tetgen.cpp

Go to the documentation of this file.
00001 
00008 // This include is here so that the chaste_libs=0 build correctly links predicates.o.
00009 #include "predicates.hpp"
00010 
00012 //                                                                           //
00013 // TetGen                                                                    //
00014 //                                                                           //
00015 // A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
00016 //                                                                           //
00017 // Version 1.4                                                               //
00018 // April 16, 2007                                                            //
00019 //                                                                           //
00020 // Copyright (C) 2002--2007                                                  //
00021 // Hang Si                                                                   //
00022 // Research Group Numerical Mathematics and Scientific Computing             //
00023 // Weierstrass Institute for Applied Analysis and Stochastics                //
00024 // Mohrenstr. 39, 10117 Berlin, Germany                                      //
00025 // si@wias-berlin.de                                                         //
00026 //                                                                           //
00027 // TetGen is freely available through the website: http://tetgen.berlios.de. //
00028 //   It may be copied, modified, and redistributed for non-commercial use.   //
00029 //   Please consult the file LICENSE for the detailed copyright notices.     //
00030 //                                                                           //
00032 
00034 //                                                                           //
00035 // tetgen.cxx                                                                //
00036 //                                                                           //
00037 // The TetGen library and program.                                           //
00038 //                                                                           //
00040 
00041 #include "tetgen.h"
00042 namespace tetgen
00043 { //Added namespace to avoid clash with triangle
00044 
00046 //                                                                           //
00047 // terminatetetgen()    Terminate TetGen with a given exit code.             //
00048 //                                                                           //
00050 
00051 void terminatetetgen(int x)
00052 {
00053 #ifdef TETLIBRARY
00054   throw x;
00055 #else
00056   exit(x);
00057 #endif // #ifdef TETLIBRARY
00058 }
00059 
00060 //
00061 // Begin of class 'tetgenio' implementation
00062 //
00063 
00065 //                                                                           //
00066 // initialize()    Initialize all variables of 'tetgenio'.                   //
00067 //                                                                           //
00068 // It is called by the only class constructor 'tetgenio()' implicitly. Thus, //
00069 // all variables are guaranteed to be initialized. Each array is initialized //
00070 // to be a 'NULL' pointer, and its length is equal zero. Some variables have //
00071 // their default value, 'firstnumber' equals zero, 'mesh_dim' equals 3,  and //
00072 // 'numberofcorners' equals 4.  Another possible use of this routine is to   //
00073 // call it before to re-use an object.                                       //
00074 //                                                                           //
00076 
00077 void tetgenio::initialize()
00078 {
00079   firstnumber = 0;              // Default item index is numbered from Zero.
00080   mesh_dim = 3;                              // Default mesh dimension is 3.
00081   useindex = true;
00082 
00083   pointlist = (REAL *) NULL;
00084   pointattributelist = (REAL *) NULL;
00085   pointmtrlist = (REAL *) NULL;
00086   pointmarkerlist = (int *) NULL;
00087   numberofpoints = 0;
00088   numberofpointattributes = 0;
00089   numberofpointmtrs = 0;
00090 
00091   tetrahedronlist = (int *) NULL;
00092   tetrahedronattributelist = (REAL *) NULL;
00093   tetrahedronvolumelist = (REAL *) NULL;
00094   neighborlist = (int *) NULL;
00095   numberoftetrahedra = 0;
00096   numberofcorners = 4;                   // Default is 4 nodes per element.
00097   numberoftetrahedronattributes = 0;
00098 
00099   trifacelist = (int *) NULL;
00100   adjtetlist = (int *) NULL;
00101   trifacemarkerlist = (int *) NULL;
00102   numberoftrifaces = 0;
00103 
00104   facetlist = (facet *) NULL;
00105   facetmarkerlist = (int *) NULL;
00106   numberoffacets = 0;
00107 
00108   edgelist = (int *) NULL;
00109   edgemarkerlist = (int *) NULL;
00110   numberofedges = 0;
00111 
00112   holelist = (REAL *) NULL;
00113   numberofholes = 0;
00114 
00115   regionlist = (REAL *) NULL;
00116   numberofregions = 0;
00117 
00118   facetconstraintlist = (REAL *) NULL;
00119   numberoffacetconstraints = 0;
00120   segmentconstraintlist = (REAL *) NULL;
00121   numberofsegmentconstraints = 0;
00122 
00123   pbcgrouplist = (pbcgroup *) NULL;
00124   numberofpbcgroups = 0;
00125 
00126   vpointlist = (REAL *) NULL;
00127   vedgelist = (voroedge *) NULL;
00128   vfacetlist = (vorofacet *) NULL;
00129   vcelllist = (int **) NULL;
00130   numberofvpoints = 0;
00131   numberofvedges = 0;
00132   numberofvfacets = 0;
00133   numberofvcells = 0;
00134 }
00135 
00137 //                                                                           //
00138 // deinitialize()    Free the memory allocated in 'tetgenio'.                //
00139 //                                                                           //
00140 // It is called by the class destructor '~tetgenio()' implicitly. Hence, the //
00141 // occupied memory by arrays of an object will be automatically released on  //
00142 // the deletion of the object. However, this routine assumes that the memory //
00143 // is allocated by C++ memory allocation operator 'new', thus it is freed by //
00144 // the C++ array deletor 'delete []'. If one uses the C/C++ library function //
00145 // 'malloc()' to allocate memory for arrays, one has to free them with the   //
00146 // 'free()' function, and call routine 'initialize()' once to disable this   //
00147 // routine on deletion of the object.                                        //
00148 //                                                                           //
00150 
00151 void tetgenio::deinitialize()
00152 {
00153   facet *f;
00154   polygon *p;
00155   pbcgroup *pg;
00156   int i, j;
00157 
00158   if (pointlist != (REAL *) NULL) {
00159     delete [] pointlist;
00160   }
00161   if (pointattributelist != (REAL *) NULL) {
00162     delete [] pointattributelist;
00163   }
00164   if (pointmtrlist != (REAL *) NULL) {
00165     delete [] pointmtrlist;
00166   }
00167   if (pointmarkerlist != (int *) NULL) {
00168     delete [] pointmarkerlist;
00169   }
00170 
00171   if (tetrahedronlist != (int *) NULL) {
00172     delete [] tetrahedronlist;
00173   }
00174   if (tetrahedronattributelist != (REAL *) NULL) {
00175     delete [] tetrahedronattributelist;
00176   }
00177   if (tetrahedronvolumelist != (REAL *) NULL) {
00178     delete [] tetrahedronvolumelist;
00179   }
00180   if (neighborlist != (int *) NULL) {
00181     delete [] neighborlist;
00182   }
00183 
00184   if (trifacelist != (int *) NULL) {
00185     delete [] trifacelist;
00186   }
00187   if (adjtetlist != (int *) NULL) {
00188     delete [] adjtetlist;
00189   }
00190   if (trifacemarkerlist != (int *) NULL) {
00191     delete [] trifacemarkerlist;
00192   }
00193 
00194   if (edgelist != (int *) NULL) {
00195     delete [] edgelist;
00196   }
00197   if (edgemarkerlist != (int *) NULL) {
00198     delete [] edgemarkerlist;
00199   }
00200 
00201   if (facetlist != (facet *) NULL) {
00202     for (i = 0; i < numberoffacets; i++) {
00203       f = &facetlist[i];
00204       for (j = 0; j < f->numberofpolygons; j++) {
00205         p = &f->polygonlist[j];
00206         delete [] p->vertexlist;
00207       }
00208       delete [] f->polygonlist;
00209       if (f->holelist != (REAL *) NULL) {
00210         delete [] f->holelist;
00211       }
00212     }
00213     delete [] facetlist;
00214   }
00215   if (facetmarkerlist != (int *) NULL) {
00216     delete [] facetmarkerlist;
00217   }
00218 
00219   if (holelist != (REAL *) NULL) {
00220     delete [] holelist;
00221   }
00222   if (regionlist != (REAL *) NULL) {
00223     delete [] regionlist;
00224   }
00225   if (facetconstraintlist != (REAL *) NULL) {
00226     delete [] facetconstraintlist;
00227   }
00228   if (segmentconstraintlist != (REAL *) NULL) {
00229     delete [] segmentconstraintlist;
00230   }
00231   if (pbcgrouplist != (pbcgroup *) NULL) {
00232     for (i = 0; i < numberofpbcgroups; i++) {
00233       pg = &(pbcgrouplist[i]);
00234       if (pg->pointpairlist != (int *) NULL) {
00235         delete [] pg->pointpairlist;
00236       }
00237     }
00238     delete [] pbcgrouplist;
00239   }
00240   if (vpointlist != (REAL *) NULL) {
00241     delete [] vpointlist;
00242   }
00243   if (vedgelist != (voroedge *) NULL) {
00244     delete [] vedgelist;
00245   }
00246   if (vfacetlist != (vorofacet *) NULL) {
00247     for (i = 0; i < numberofvfacets; i++) {
00248       delete [] vfacetlist[i].elist;
00249     }
00250     delete [] vfacetlist;
00251   }
00252   if (vcelllist != (int **) NULL) {
00253     for (i = 0; i < numberofvcells; i++) {
00254       delete [] vcelllist[i];
00255     }
00256     delete [] vcelllist;
00257   }
00258 }
00259 
00261 //                                                                           //
00262 // load_node_call()    Load a list of nodes.                                 //
00263 //                                                                           //
00264 // It is a support routine for routines: 'load_nodes()', 'load_poly()', and  //
00265 // 'load_tetmesh()'.  'infile' is the file handle contains the node list. It //
00266 // may point to a .node, or .poly or .smesh file.  'markers' indicates each  //
00267 // node contains an additional marker (integer) or not. 'infilename' is the  //
00268 // name of the file being read,  it is only appeared in error message.       //
00269 //                                                                           //
00270 // The 'firstnumber' (0 or 1) is automatically determined by the number of   //
00271 // the first index of the first point.                                       //
00272 //                                                                           //
00274 
00275 bool tetgenio::load_node_call(FILE* infile, int markers, char* infilename)
00276 {
00277   char inputline[INPUTLINESIZE];
00278   char *stringptr;
00279   REAL x, y, z, attrib;
00280   int firstnode, currentmarker;
00281   int index, attribindex;
00282   int i, j;
00283 
00284   // Initialize 'pointlist', 'pointattributelist', and 'pointmarkerlist'.
00285   pointlist = new REAL[numberofpoints * 3];
00286   if (pointlist == (REAL *) NULL) {
00287     printf("Error:  Out of memory.\n");
00288     terminatetetgen(1);
00289   }
00290   if (numberofpointattributes > 0) {
00291     pointattributelist = new REAL[numberofpoints * numberofpointattributes];
00292     if (pointattributelist == (REAL *) NULL) {
00293       printf("Error:  Out of memory.\n");
00294       terminatetetgen(1);
00295     }
00296   }
00297   if (markers) {
00298     pointmarkerlist = new int[numberofpoints];
00299     if (pointmarkerlist == (int *) NULL) {
00300       printf("Error:  Out of memory.\n");
00301       terminatetetgen(1);
00302     }
00303   }
00304 
00305   // Read the point section.
00306   index = 0;
00307   attribindex = 0;
00308   for (i = 0; i < numberofpoints; i++) {
00309     stringptr = readnumberline(inputline, infile, infilename);
00310     if (useindex) {
00311       if (i == 0) {
00312         firstnode = (int) strtol (stringptr, &stringptr, 0);
00313         if ((firstnode == 0) || (firstnode == 1)) {
00314           firstnumber = firstnode;
00315         }
00316       }
00317       stringptr = findnextnumber(stringptr);
00318     } // if (useindex)
00319     if (*stringptr == '\0') {
00320       printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
00321       break;
00322     }
00323     x = (REAL) strtod(stringptr, &stringptr);
00324     stringptr = findnextnumber(stringptr);
00325     if (*stringptr == '\0') {
00326       printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
00327       break;
00328     }
00329     y = (REAL) strtod(stringptr, &stringptr);
00330     if (mesh_dim == 3) {
00331       stringptr = findnextnumber(stringptr);
00332       if (*stringptr == '\0') {
00333         printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
00334         break;
00335       }
00336       z = (REAL) strtod(stringptr, &stringptr);
00337     } else {
00338       z = 0.0; // mesh_dim == 2;
00339     }
00340     pointlist[index++] = x;
00341     pointlist[index++] = y;
00342     pointlist[index++] = z;
00343     // Read the point attributes.
00344     for (j = 0; j < numberofpointattributes; j++) {
00345       stringptr = findnextnumber(stringptr);
00346       if (*stringptr == '\0') {
00347         attrib = 0.0;
00348       } else {
00349         attrib = (REAL) strtod(stringptr, &stringptr);
00350       }
00351       pointattributelist[attribindex++] = attrib;
00352     }
00353     if (markers) {
00354       // Read a point marker.
00355       stringptr = findnextnumber(stringptr);
00356       if (*stringptr == '\0') {
00357         currentmarker = 0;
00358       } else {
00359         currentmarker = (int) strtol (stringptr, &stringptr, 0);
00360       }
00361       pointmarkerlist[i] = currentmarker;
00362     }
00363   }
00364   if (i < numberofpoints) {
00365     // Failed to read points due to some error.
00366     delete [] pointlist;
00367     pointlist = (REAL *) NULL;
00368     if (markers) {
00369       delete [] pointmarkerlist;
00370       pointmarkerlist = (int *) NULL;
00371     }
00372     if (numberofpointattributes > 0) {
00373       delete [] pointattributelist;
00374       pointattributelist = (REAL *) NULL;
00375     }
00376     numberofpoints = 0;
00377     return false;
00378   }
00379   return true;
00380 }
00381 
00383 //                                                                           //
00384 // load_node()    Load a list of nodes from a .node file.                    //
00385 //                                                                           //
00386 // 'filename' is the inputfile without suffix. The node list is in 'filename.//
00387 // node'. On completion, the node list is returned in 'pointlist'.           //
00388 //                                                                           //
00390 
00391 bool tetgenio::load_node(char* filename)
00392 {
00393   FILE *infile;
00394   char innodefilename[FILENAMESIZE];
00395   char inputline[INPUTLINESIZE];
00396   char *stringptr;
00397   int markers;
00398 
00399   markers = 0;
00400   // Assembling the actual file names we want to open.
00401   strcpy(innodefilename, filename);
00402   strcat(innodefilename, ".node");
00403 
00404   // Try to open a .node file.
00405   infile = fopen(innodefilename, "r");
00406   if (infile == (FILE *) NULL) {
00407     printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
00408     return false;
00409   }
00410   printf("Opening %s.\n", innodefilename);
00411   // Read the first line of the file.
00412   stringptr = readnumberline(inputline, infile, innodefilename);
00413   // Is this list of points generated from rbox?
00414   stringptr = strstr(inputline, "rbox");
00415   if (stringptr == NULL) {
00416     // Read number of points, number of dimensions, number of point
00417     //   attributes, and number of boundary markers.
00418     stringptr = inputline;
00419     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00420     stringptr = findnextnumber(stringptr);
00421     if (*stringptr == '\0') {
00422       mesh_dim = 3;
00423     } else {
00424       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00425     }
00426     stringptr = findnextnumber(stringptr);
00427     if (*stringptr == '\0') {
00428       numberofpointattributes = 0;
00429     } else {
00430       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00431     }
00432     stringptr = findnextnumber(stringptr);
00433     if (*stringptr == '\0') {
00434       markers = 0;
00435     } else {
00436       markers = (int) strtol (stringptr, &stringptr, 0);
00437     }
00438   } else {
00439     // It is a rbox (qhull) input file.
00440     stringptr = inputline;
00441     // Get the dimension.
00442     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00443     // Get the number of points.
00444     stringptr = readnumberline(inputline, infile, innodefilename);
00445     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00446     // There is no index column.
00447     useindex = 0;
00448   }
00449 
00450   // if ((mesh_dim != 3) && (mesh_dim != 2)) {
00451   //   printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
00452   //   fclose(infile);
00453   //   return false;
00454   // }
00455   if (numberofpoints < (mesh_dim + 1)) {
00456     printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
00457     fclose(infile);
00458     return false;
00459   }
00460 
00461   // Load the list of nodes.
00462   if (!load_node_call(infile, markers, innodefilename)) {
00463     fclose(infile);
00464     return false;
00465   }
00466   fclose(infile);
00467   return true;
00468 }
00469 
00471 //                                                                           //
00472 // load_pbc()    Load a list of pbc groups into 'pbcgrouplist'.              //
00473 //                                                                           //
00474 // 'filename' is the filename of the original inputfile without suffix. The  //
00475 // pbc groups are found in file 'filename.pbc'.                              //
00476 //                                                                           //
00477 // This routine will be called both in load_poly() and load_tetmesh().       //
00478 //                                                                           //
00480 
00481 bool tetgenio::load_pbc(char* filename)
00482 {
00483   FILE *infile;
00484   char pbcfilename[FILENAMESIZE];
00485   char inputline[INPUTLINESIZE];
00486   char *stringptr;
00487   pbcgroup *pg;
00488   int index, p1, p2;
00489   int i, j, k;
00490 
00491   // Pbc groups are saved in file "filename.pbc".
00492   strcpy(pbcfilename, filename);
00493   strcat(pbcfilename, ".pbc");
00494   infile = fopen(pbcfilename, "r");
00495   if (infile != (FILE *) NULL) {
00496     printf("Opening %s.\n", pbcfilename);
00497   } else {
00498     // No such file. Return.
00499     return false;
00500   }
00501 
00502   // Read the number of pbc groups.
00503   stringptr = readnumberline(inputline, infile, pbcfilename);
00504   numberofpbcgroups = (int) strtol (stringptr, &stringptr, 0);
00505   if (numberofpbcgroups == 0) {
00506     // It looks this file contains no point.
00507     fclose(infile);
00508     return false;
00509   }
00510   // Initialize 'pbcgrouplist';
00511   pbcgrouplist = new pbcgroup[numberofpbcgroups];
00512 
00513   // Read the list of pbc groups.
00514   for (i = 0; i < numberofpbcgroups; i++) {
00515     pg = &(pbcgrouplist[i]);
00516     // Initialize pbcgroup i;
00517     pg->numberofpointpairs = 0;
00518     pg->pointpairlist = (int *) NULL;
00519     // Read 'fmark1', 'fmark2'.
00520     stringptr = readnumberline(inputline, infile, pbcfilename);
00521     if (*stringptr == '\0') break;
00522     pg->fmark1 = (int) strtol(stringptr, &stringptr, 0);
00523     stringptr = findnextnumber(stringptr);
00524     if (*stringptr == '\0') break;
00525     pg->fmark2 = (int) strtol(stringptr, &stringptr, 0);
00526     // Read 'transmat'.
00527     do {
00528       stringptr = readline(inputline, infile, NULL);
00529     } while ((*stringptr != '[') && (*stringptr != '\0'));
00530     if (*stringptr == '\0') break;
00531     for (j = 0; j < 4; j++) {
00532       for (k = 0; k < 4; k++) {
00533         // Read the entry of [j, k].
00534         stringptr = findnextnumber(stringptr);
00535         if (*stringptr == '\0') {
00536           // Try to read another line.
00537           stringptr = readnumberline(inputline, infile, pbcfilename);
00538           if (*stringptr == '\0') break;
00539         }
00540         pg->transmat[j][k] = (REAL) strtod(stringptr, &stringptr);
00541       }
00542       if (k < 4) break; // Not complete!
00543     }
00544     if (j < 4) break; // Not complete!
00545     // Read 'numberofpointpairs'.
00546     stringptr = readnumberline(inputline, infile, pbcfilename);
00547     if (*stringptr == '\0') break;
00548     pg->numberofpointpairs = (int) strtol(stringptr, &stringptr, 0);
00549     if (pg->numberofpointpairs > 0) {
00550       pg->pointpairlist = new int[pg->numberofpointpairs * 2];
00551       // Read the point pairs.
00552       index = 0;
00553       for (j = 0; j < pg->numberofpointpairs; j++) {
00554         stringptr = readnumberline(inputline, infile, pbcfilename);
00555         p1 = (int) strtol(stringptr, &stringptr, 0);
00556         stringptr = findnextnumber(stringptr);
00557         p2 = (int) strtol(stringptr, &stringptr, 0);
00558         pg->pointpairlist[index++] = p1;
00559         pg->pointpairlist[index++] = p2;
00560       }
00561     }
00562   }
00563   fclose(infile);
00564 
00565   if (i < numberofpbcgroups) {
00566     // Failed to read to additional points due to some error.
00567     delete [] pbcgrouplist;
00568     pbcgrouplist = (pbcgroup *) NULL;
00569     numberofpbcgroups = 0;
00570     return false;
00571   }
00572   return true;
00573 }
00574 
00576 //                                                                           //
00577 // load_var()    Load variant constraints applied on facets, segments, nodes.//
00578 //                                                                           //
00579 // 'filename' is the filename of the original inputfile without suffix. The  //
00580 // constraints are found in file 'filename.var'.                             //
00581 //                                                                           //
00583 
00584 bool tetgenio::load_var(char* filename)
00585 {
00586   FILE *infile;
00587   char varfilename[FILENAMESIZE];
00588   char inputline[INPUTLINESIZE];
00589   char *stringptr;
00590   int index;
00591   int i;
00592 
00593   // Variant constraints are saved in file "filename.var".
00594   strcpy(varfilename, filename);
00595   strcat(varfilename, ".var");
00596   infile = fopen(varfilename, "r");
00597   if (infile != (FILE *) NULL) {
00598     printf("Opening %s.\n", varfilename);
00599   } else {
00600     // No such file. Return.
00601     return false;
00602   }
00603 
00604   // Read the facet constraint section.
00605   stringptr = readnumberline(inputline, infile, varfilename);
00606   if (*stringptr != '\0') {
00607     numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0);
00608   } else {
00609     numberoffacetconstraints = 0;
00610   }
00611   if (numberoffacetconstraints > 0) {
00612     // Initialize 'facetconstraintlist'.
00613     facetconstraintlist = new REAL[numberoffacetconstraints * 2];
00614     index = 0;
00615     for (i = 0; i < numberoffacetconstraints; i++) {
00616       stringptr = readnumberline(inputline, infile, varfilename);
00617       stringptr = findnextnumber(stringptr);
00618       if (*stringptr == '\0') {
00619         printf("Error:  facet constraint %d has no facet marker.\n",
00620                firstnumber + i);
00621         break;
00622       } else {
00623         facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00624       }
00625       stringptr = findnextnumber(stringptr);
00626       if (*stringptr == '\0') {
00627         printf("Error:  facet constraint %d has no maximum area bound.\n",
00628                firstnumber + i);
00629         break;
00630       } else {
00631         facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00632       }
00633     }
00634     if (i < numberoffacetconstraints) {
00635       // This must be caused by an error.
00636       fclose(infile);
00637       return false;
00638     }
00639   }
00640 
00641   // Read the segment constraint section.
00642   stringptr = readnumberline(inputline, infile, varfilename);
00643   if (*stringptr != '\0') {
00644     numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0);
00645   } else {
00646     numberofsegmentconstraints = 0;
00647   }
00648   if (numberofsegmentconstraints > 0) {
00649     // Initialize 'segmentconstraintlist'.
00650     segmentconstraintlist = new REAL[numberofsegmentconstraints * 3];
00651     index = 0;
00652     for (i = 0; i < numberofsegmentconstraints; i++) {
00653       stringptr = readnumberline(inputline, infile, varfilename);
00654       stringptr = findnextnumber(stringptr);
00655       if (*stringptr == '\0') {
00656         printf("Error:  segment constraint %d has no frist endpoint.\n",
00657                firstnumber + i);
00658         break;
00659       } else {
00660         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00661       }
00662       stringptr = findnextnumber(stringptr);
00663       if (*stringptr == '\0') {
00664         printf("Error:  segment constraint %d has no second endpoint.\n",
00665                firstnumber + i);
00666         break;
00667       } else {
00668         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00669       }
00670       stringptr = findnextnumber(stringptr);
00671       if (*stringptr == '\0') {
00672         printf("Error:  segment constraint %d has no maximum length bound.\n",
00673                firstnumber + i);
00674         break;
00675       } else {
00676         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00677       }
00678     }
00679     if (i < numberofsegmentconstraints) {
00680       // This must be caused by an error.
00681       fclose(infile);
00682       return false;
00683     }
00684   }
00685 
00686   fclose(infile);
00687   return true;
00688 }
00689 
00691 //                                                                           //
00692 // load_mtr()    Load a size specification map from file.                    //
00693 //                                                                           //
00694 // 'filename' is the filename of the original inputfile without suffix. The  //
00695 // size map is found in file 'filename.mtr'.                                 //
00696 //                                                                           //
00698 
00699 bool tetgenio::load_mtr(char* filename)
00700 {
00701   FILE *infile;
00702   char mtrfilename[FILENAMESIZE];
00703   char inputline[INPUTLINESIZE];
00704   char *stringptr;
00705   REAL mtr;
00706   int mtrindex;
00707   int i, j;
00708 
00709   strcpy(mtrfilename, filename);
00710   strcat(mtrfilename, ".mtr");
00711   infile = fopen(mtrfilename, "r");
00712   if (infile != (FILE *) NULL) {
00713     printf("Opening %s.\n", mtrfilename);
00714   } else {
00715     // No such file. Return.
00716     return false;
00717   }
00718 
00719   // Read number of points, number of columns (1, 3, or 6).
00720   stringptr = readnumberline(inputline, infile, mtrfilename);
00721   stringptr = findnextnumber(stringptr); // Skip number of points.
00722   if (*stringptr != '\0') {
00723     numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0);
00724   }
00725   if (numberofpointmtrs == 0) {
00726     // Column number doesn't match. Set a default number (1).
00727     numberofpointmtrs = 1;
00728   }
00729 
00730   // Allocate space for pointmtrlist.
00731   pointmtrlist = new REAL[numberofpoints * numberofpointmtrs];
00732   if (pointmtrlist == (REAL *) NULL) {
00733     printf("Error:  Out of memory.\n");
00734     terminatetetgen(1);
00735   }
00736   mtrindex = 0;
00737   for (i = 0; i < numberofpoints; i++) {
00738     // Read metrics.
00739     stringptr = readnumberline(inputline, infile, mtrfilename);
00740     for (j = 0; j < numberofpointmtrs; j++) {
00741       if (*stringptr == '\0') {
00742         printf("Error:  Metric %d is missing value #%d in %s.\n",
00743                i + firstnumber, j + 1, mtrfilename);
00744         terminatetetgen(1);
00745       }
00746       mtr = (REAL) strtod(stringptr, &stringptr);
00747       pointmtrlist[mtrindex++] = mtr;
00748       stringptr = findnextnumber(stringptr);
00749     }
00750   }
00751 
00752   fclose(infile);
00753   return true;
00754 }
00755 
00757 //                                                                           //
00758 // load_poly()    Load a piecewise linear complex from a .poly or .smesh.    //
00759 //                                                                           //
00760 // 'filename' is the inputfile without suffix. The PLC is in 'filename.poly' //
00761 // or 'filename.smesh', and possibly plus 'filename.node' (when the first    //
00762 // line of the file starts with a zero).                                     //
00763 //                                                                           //
00765 
00766 bool tetgenio::load_poly(char* filename)
00767 {
00768   FILE *infile, *polyfile;
00769   char innodefilename[FILENAMESIZE];
00770   char inpolyfilename[FILENAMESIZE];
00771   char insmeshfilename[FILENAMESIZE];
00772   char inputline[INPUTLINESIZE];
00773   char *stringptr, *infilename;
00774   int smesh, markers, currentmarker;
00775   int readnodefile, index;
00776   int i, j, k;
00777 
00778   // Assembling the actual file names we want to open.
00779   strcpy(innodefilename, filename);
00780   strcpy(inpolyfilename, filename);
00781   strcpy(insmeshfilename, filename);
00782   strcat(innodefilename, ".node");
00783   strcat(inpolyfilename, ".poly");
00784   strcat(insmeshfilename, ".smesh");
00785 
00786   // First assume it is a .poly file.
00787   smesh = 0;
00788   // Try to open a .poly file.
00789   polyfile = fopen(inpolyfilename, "r");
00790   if (polyfile == (FILE *) NULL) {
00791     // .poly doesn't exist! Try to open a .smesh file.
00792     polyfile = fopen(insmeshfilename, "r");
00793     if (polyfile == (FILE *) NULL) {
00794       printf("File I/O Error:  Cannot access file %s and %s.\n",
00795              inpolyfilename, insmeshfilename);
00796       return false;
00797     } else {
00798       printf("Opening %s.\n", insmeshfilename);
00799     }
00800     smesh = 1;
00801   } else {
00802     printf("Opening %s.\n", inpolyfilename);
00803   }
00804   // Initialize the default values.
00805   mesh_dim = 3;  // Three-dimemsional accoordinates.
00806   numberofpointattributes = 0;  // no point attribute.
00807   markers = 0;  // no boundary marker.
00808   // Read number of points, number of dimensions, number of point
00809   //   attributes, and number of boundary markers.
00810   stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00811   numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00812   stringptr = findnextnumber(stringptr);
00813   if (*stringptr != '\0') {
00814     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00815   }
00816   stringptr = findnextnumber(stringptr);
00817   if (*stringptr != '\0') {
00818     numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00819   }
00820   stringptr = findnextnumber(stringptr);
00821   if (*stringptr != '\0') {
00822     markers = (int) strtol (stringptr, &stringptr, 0);
00823   }
00824   if (numberofpoints > 0) {
00825     readnodefile = 0;
00826     if (smesh) {
00827       infilename = insmeshfilename;
00828     } else {
00829       infilename = inpolyfilename;
00830     }
00831     infile = polyfile;
00832   } else {
00833     // If the .poly or .smesh file claims there are zero points, that
00834     //   means the points should be read from a separate .node file.
00835     readnodefile = 1;
00836     infilename = innodefilename;
00837   }
00838 
00839   if (readnodefile) {
00840     // Read the points from the .node file.
00841     printf("Opening %s.\n", innodefilename);
00842     infile = fopen(innodefilename, "r");
00843     if (infile == (FILE *) NULL) {
00844       printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
00845       return false;
00846     }
00847     // Initialize the default values.
00848     mesh_dim = 3;  // Three-dimemsional accoordinates.
00849     numberofpointattributes = 0;  // no point attribute.
00850     markers = 0;  // no boundary marker.
00851     // Read number of points, number of dimensions, number of point
00852     //   attributes, and number of boundary markers.
00853     stringptr = readnumberline(inputline, infile, innodefilename);
00854     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00855     stringptr = findnextnumber(stringptr);
00856     if (*stringptr != '\0') {
00857       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00858     }
00859     stringptr = findnextnumber(stringptr);
00860     if (*stringptr != '\0') {
00861       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00862     }
00863     stringptr = findnextnumber(stringptr);
00864     if (*stringptr != '\0') {
00865       markers = (int) strtol (stringptr, &stringptr, 0);
00866     }
00867   }
00868 
00869   if ((mesh_dim != 3) && (mesh_dim != 2)) {
00870     printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
00871     fclose(infile);
00872     return false;
00873   }
00874   if (numberofpoints < (mesh_dim + 1)) {
00875     printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
00876     fclose(infile);
00877     return false;
00878   }
00879 
00880   // Load the list of nodes.
00881   if (!load_node_call(infile, markers, infilename)) {
00882     fclose(infile);
00883     return false;
00884   }
00885 
00886   if (readnodefile) {
00887     fclose(infile);
00888   }
00889 
00890   facet *f;
00891   polygon *p;
00892 
00893   if (mesh_dim == 3) {
00894 
00895     // Read number of facets and number of boundary markers.
00896     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00897     numberoffacets = (int) strtol (stringptr, &stringptr, 0);
00898     if (numberoffacets <= 0) {
00899       // No facet list, return.
00900       fclose(polyfile);
00901       return true;
00902     }
00903     stringptr = findnextnumber(stringptr);
00904     if (*stringptr == '\0') {
00905       markers = 0;  // no boundary marker.
00906     } else {
00907       markers = (int) strtol (stringptr, &stringptr, 0);
00908     }
00909 
00910     // Initialize the 'facetlist', 'facetmarkerlist'.
00911     facetlist = new facet[numberoffacets];
00912     if (markers == 1) {
00913       facetmarkerlist = new int[numberoffacets];
00914     }
00915 
00916     // Read data into 'facetlist', 'facetmarkerlist'.
00917     if (smesh == 0) {
00918       // Facets are in .poly file format.
00919       for (i = 1; i <= numberoffacets; i++) {
00920         f = &(facetlist[i - 1]);
00921         init(f);
00922         f->numberofholes = 0;
00923         currentmarker = 0;
00924         // Read number of polygons, number of holes, and a boundary marker.
00925         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00926         f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
00927         stringptr = findnextnumber(stringptr);
00928         if (*stringptr != '\0') {
00929           f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
00930           if (markers == 1) {
00931             stringptr = findnextnumber(stringptr);
00932             if (*stringptr != '\0') {
00933               currentmarker = (int) strtol(stringptr, &stringptr, 0);
00934             }
00935           }
00936         }
00937         // Initialize facetmarker if it needs.
00938         if (markers == 1) {
00939           facetmarkerlist[i - 1] = currentmarker;
00940         }
00941         // Each facet should has at least one polygon.
00942         if (f->numberofpolygons <= 0) {
00943           printf("Error:  Wrong number of polygon in %d facet.\n", i);
00944           break;
00945         }
00946         // Initialize the 'f->polygonlist'.
00947         f->polygonlist = new polygon[f->numberofpolygons];
00948         // Go through all polygons, read in their vertices.
00949         for (j = 1; j <= f->numberofpolygons; j++) {
00950           p = &(f->polygonlist[j - 1]);
00951           init(p);
00952           // Read number of vertices of this polygon.
00953           stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00954           p->numberofvertices = (int) strtol(stringptr, &stringptr, 0);
00955           if (p->numberofvertices < 1) {
00956             printf("Error:  Wrong polygon %d in facet %d\n", j, i);
00957             break;
00958           }
00959           // Initialize 'p->vertexlist'.
00960           p->vertexlist = new int[p->numberofvertices];
00961           // Read all vertices of this polygon.
00962           for (k = 1; k <= p->numberofvertices; k++) {
00963             stringptr = findnextnumber(stringptr);
00964             if (*stringptr == '\0') {
00965               // Try to load another non-empty line and continue to read the
00966               //   rest of vertices.
00967               stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00968               if (*stringptr == '\0') {
00969                 printf("Error: Missing %d endpoints of polygon %d in facet %d",
00970                        p->numberofvertices - k, j, i);
00971                 break;
00972               }
00973             }
00974             p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
00975           }
00976         }
00977         if (j <= f->numberofpolygons) {
00978           // This must be caused by an error. However, there're j - 1
00979           //   polygons have been read. Reset the 'f->numberofpolygon'.
00980           if (j == 1) {
00981             // This is the first polygon.
00982             delete [] f->polygonlist;
00983           }
00984           f->numberofpolygons = j - 1;
00985           // No hole will be read even it exists.
00986           f->numberofholes = 0;
00987           break;
00988         }
00989         // If this facet has hole pints defined, read them.
00990         if (f->numberofholes > 0) {
00991           // Initialize 'f->holelist'.
00992           f->holelist = new REAL[f->numberofholes * 3];
00993           // Read the holes' coordinates.
00994           index = 0;
00995           for (j = 1; j <= f->numberofholes; j++) {
00996             stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00997             for (k = 1; k <= 3; k++) {
00998               stringptr = findnextnumber(stringptr);
00999               if (*stringptr == '\0') {
01000                 printf("Error:  Hole %d in facet %d has no coordinates", j, i);
01001                 break;
01002               }
01003               f->holelist[index++] = (REAL) strtod (stringptr, &stringptr);
01004             }
01005             if (k <= 3) {
01006               // This must be caused by an error.
01007               break;
01008             }
01009           }
01010           if (j <= f->numberofholes) {
01011             // This must be caused by an error.
01012             break;
01013           }
01014         }
01015       }
01016       if (i <= numberoffacets) {
01017         // This must be caused by an error.
01018         numberoffacets = i - 1;
01019         fclose(polyfile);
01020         return false;
01021       }
01022     } else { // poly == 0
01023       // Read the facets from a .smesh file.
01024       for (i = 1; i <= numberoffacets; i++) {
01025         f = &(facetlist[i - 1]);
01026         init(f);
01027         // Initialize 'f->facetlist'. In a .smesh file, each facetlist only
01028         //   contains exactly one polygon, no hole.
01029         f->numberofpolygons = 1;
01030         f->polygonlist = new polygon[f->numberofpolygons];
01031         p = &(f->polygonlist[0]);
01032         init(p);
01033         // Read number of vertices of this polygon.
01034         stringptr = readnumberline(inputline, polyfile, insmeshfilename);
01035         p->numberofvertices = (int) strtol (stringptr, &stringptr, 0);
01036         if (p->numberofvertices < 1) {
01037           printf("Error:  Wrong number of vertex in facet %d\n", i);
01038           break;
01039         }
01040         // Initialize 'p->vertexlist'.
01041         p->vertexlist = new int[p->numberofvertices];
01042         for (k = 1; k <= p->numberofvertices; k++) {
01043           stringptr = findnextnumber(stringptr);
01044           if (*stringptr == '\0') {
01045             // Try to load another non-empty line and continue to read the
01046             //   rest of vertices.
01047             stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01048             if (*stringptr == '\0') {
01049               printf("Error:  Missing %d endpoints in facet %d",
01050                      p->numberofvertices - k, i);
01051               break;
01052             }
01053           }
01054           p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
01055         }
01056         if (k <= p->numberofvertices) {
01057           // This must be caused by an error.
01058           break;
01059         }
01060         // Read facet's boundary marker at last.
01061         if (markers == 1) {
01062           stringptr = findnextnumber(stringptr);
01063           if (*stringptr == '\0') {
01064             currentmarker = 0;
01065           } else {
01066             currentmarker = (int) strtol(stringptr, &stringptr, 0);
01067           }
01068           facetmarkerlist[i - 1] = currentmarker;
01069         }
01070       }
01071       if (i <= numberoffacets) {
01072         // This must be caused by an error.
01073         numberoffacets = i - 1;
01074         fclose(polyfile);
01075         return false;
01076       }
01077     }
01078 
01079     // Read the hole section.
01080     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01081     if (*stringptr != '\0') {
01082       numberofholes = (int) strtol (stringptr, &stringptr, 0);
01083     } else {
01084       numberofholes = 0;
01085     }
01086     if (numberofholes > 0) {
01087       // Initialize 'holelist'.
01088       holelist = new REAL[numberofholes * 3];
01089       for (i = 0; i < 3 * numberofholes; i += 3) {
01090         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01091         stringptr = findnextnumber(stringptr);
01092         if (*stringptr == '\0') {
01093           printf("Error:  Hole %d has no x coord.\n", firstnumber + (i / 3));
01094           break;
01095         } else {
01096           holelist[i] = (REAL) strtod(stringptr, &stringptr);
01097         }
01098         stringptr = findnextnumber(stringptr);
01099         if (*stringptr == '\0') {
01100           printf("Error:  Hole %d has no y coord.\n", firstnumber + (i / 3));
01101           break;
01102         } else {
01103           holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
01104         }
01105         stringptr = findnextnumber(stringptr);
01106         if (*stringptr == '\0') {
01107           printf("Error:  Hole %d has no z coord.\n", firstnumber + (i / 3));
01108           break;
01109         } else {
01110           holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
01111         }
01112       }
01113       if (i < 3 * numberofholes) {
01114         // This must be caused by an error.
01115         fclose(polyfile);
01116         return false;
01117       }
01118     }
01119 
01120     // Read the region section.  The 'region' section is optional, if we
01121     //   don't reach the end-of-file, try read it in.
01122     stringptr = readnumberline(inputline, polyfile, NULL);
01123     if (stringptr != (char *) NULL && *stringptr != '\0') {
01124       numberofregions = (int) strtol (stringptr, &stringptr, 0);
01125     } else {
01126       numberofregions = 0;
01127     }
01128     if (numberofregions > 0) {
01129       // Initialize 'regionlist'.
01130       regionlist = new REAL[numberofregions * 5];
01131       index = 0;
01132       for (i = 0; i < numberofregions; i++) {
01133         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01134         stringptr = findnextnumber(stringptr);
01135         if (*stringptr == '\0') {
01136           printf("Error:  Region %d has no x coordinate.\n", firstnumber + i);
01137           break;
01138         } else {
01139           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01140         }
01141         stringptr = findnextnumber(stringptr);
01142         if (*stringptr == '\0') {
01143           printf("Error:  Region %d has no y coordinate.\n", firstnumber + i);
01144           break;
01145         } else {
01146           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01147         }
01148         stringptr = findnextnumber(stringptr);
01149         if (*stringptr == '\0') {
01150           printf("Error:  Region %d has no z coordinate.\n", firstnumber + i);
01151           break;
01152         } else {
01153           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01154         }
01155         stringptr = findnextnumber(stringptr);
01156         if (*stringptr == '\0') {
01157           printf("Error:  Region %d has no region attrib.\n", firstnumber + i);
01158           break;
01159         } else {
01160           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01161         }
01162         stringptr = findnextnumber(stringptr);
01163         if (*stringptr == '\0') {
01164           regionlist[index] = regionlist[index - 1];
01165         } else {
01166           regionlist[index] = (REAL) strtod(stringptr, &stringptr);
01167         }
01168         index++;
01169       }
01170       if (i < numberofregions) {
01171         // This must be caused by an error.
01172         fclose(polyfile);
01173         return false;
01174       }
01175     }
01176 
01177   } else {
01178 
01179     // Read a PSLG from Triangle's poly file.
01180     assert(mesh_dim == 2);
01181     // A PSLG is a facet of a PLC.
01182     numberoffacets = 1;
01183     // Initialize the 'facetlist'.
01184     facetlist = new facet[numberoffacets];
01185     facetmarkerlist = (int *) NULL; // No facet markers.
01186     f = &(facetlist[0]);
01187     init(f);
01188     // Read number of segments.
01189     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01190     // Segments are degenerate polygons.
01191     f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
01192     if (f->numberofpolygons > 0) {
01193       f->polygonlist = new polygon[f->numberofpolygons];
01194     }
01195     // Go through all segments, read in their vertices.
01196     for (j = 0; j < f->numberofpolygons; j++) {
01197       p = &(f->polygonlist[j]);
01198       init(p);
01199       // Read in a segment.
01200       stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01201       stringptr = findnextnumber(stringptr); // Skip its index.
01202       p->numberofvertices = 2; // A segment always has two vertices.
01203       p->vertexlist = new int[p->numberofvertices];
01204       p->vertexlist[0] = (int) strtol (stringptr, &stringptr, 0);
01205       stringptr = findnextnumber(stringptr);
01206       p->vertexlist[1] = (int) strtol (stringptr, &stringptr, 0);
01207     }
01208     // Read number of holes.
01209     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01210     f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
01211     if (f->numberofholes > 0) {
01212       // Initialize 'f->holelist'.
01213       f->holelist = new REAL[f->numberofholes * 3];
01214       // Read the holes' coordinates.
01215       for (j = 0; j < f->numberofholes; j++) {
01216         // Read a 2D hole point.
01217         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01218         stringptr = findnextnumber(stringptr); // Skip its index.
01219         f->holelist[j * 3] = (REAL) strtod (stringptr, &stringptr);
01220         stringptr = findnextnumber(stringptr);
01221         f->holelist[j * 3 + 1] = (REAL) strtod (stringptr, &stringptr);
01222         f->holelist[j * 3 + 2] = 0.0; // The z-coord.
01223       }
01224     }
01225     // The regions are skipped.
01226 
01227   }
01228 
01229   // End of reading poly/smesh file.
01230   fclose(polyfile);
01231 
01232   // Try to load a .var file if it exists.
01233   load_var(filename);
01234   // Try to load a .mtr file if it exists.
01235   load_mtr(filename);
01236   // Try to read a .pbc file if it exists.
01237   load_pbc(filename);
01238 
01239   return true;
01240 }
01241 
01243 //                                                                           //
01244 // load_off()    Load a polyhedron described in a .off file.                 //
01245 //                                                                           //
01246 // The .off format is one of file formats of the Geomview, an interactive    //
01247 // program for viewing and manipulating geometric objects.  More information //
01248 // is available form: http://www.geomview.org.                               //
01249 //                                                                           //
01250 // 'filename' is a input filename with extension .off or without extension ( //
01251 // the .off will be added in this case). On completion, the polyhedron is    //
01252 // returned in 'pointlist' and 'facetlist'.                                  //
01253 //                                                                           //
01255 
01256 bool tetgenio::load_off(char* filename)
01257 {
01258   FILE *fp;
01259   tetgenio::facet *f;
01260   tetgenio::polygon *p;
01261   char infilename[FILENAMESIZE];
01262   char buffer[INPUTLINESIZE];
01263   char *bufferp;
01264   double *coord;
01265   int nverts = 0, iverts = 0;
01266   int nfaces = 0, ifaces = 0;
01267   int nedges = 0;
01268   int line_count = 0, i;
01269 
01270   strncpy(infilename, filename, 1024 - 1);
01271   infilename[FILENAMESIZE - 1] = '\0';
01272   if (infilename[0] == '\0') {
01273     printf("Error:  No filename.\n");
01274     return false;
01275   }
01276   if (strcmp(&infilename[strlen(infilename) - 4], ".off") != 0) {
01277     strcat(infilename, ".off");
01278   }
01279 
01280   if (!(fp = fopen(infilename, "r"))) {
01281     printf("File I/O Error:  Unable to open file %s\n", infilename);
01282     return false;
01283   }
01284   printf("Opening %s.\n", infilename);
01285 
01286   // OFF requires the index starts from '0'.
01287   firstnumber = 0;
01288 
01289   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01290     // Check section
01291     if (nverts == 0) {
01292       // Read header
01293       bufferp = strstr(bufferp, "OFF");
01294       if (bufferp != NULL) {
01295         // Read mesh counts
01296         bufferp = findnextnumber(bufferp); // Skip field "OFF".
01297         if (*bufferp == '\0') {
01298           // Read a non-empty line.
01299           bufferp = readline(buffer, fp, &line_count);
01300         }
01301         if ((sscanf(bufferp, "%d%d%d", &nverts, &nfaces, &nedges) != 3)
01302             || (nverts == 0)) {
01303           printf("Syntax error reading header on line %d in file %s\n",
01304                  line_count, infilename);
01305           fclose(fp);
01306           return false;
01307         }
01308         // Allocate memory for 'tetgenio'
01309         if (nverts > 0) {
01310           numberofpoints = nverts;
01311           pointlist = new REAL[nverts * 3];
01312         }
01313         if (nfaces > 0) {
01314           numberoffacets = nfaces;
01315           facetlist = new tetgenio::facet[nfaces];
01316         }
01317       }
01318     } else if (iverts < nverts) {
01319       // Read vertex coordinates
01320       coord = &pointlist[iverts * 3];
01321       for (i = 0; i < 3; i++) {
01322         if (*bufferp == '\0') {
01323           printf("Syntax error reading vertex coords on line %d in file %s\n",
01324                  line_count, infilename);
01325           fclose(fp);
01326           return false;
01327         }
01328         coord[i] = (REAL) strtod(bufferp, &bufferp);
01329         bufferp = findnextnumber(bufferp);
01330       }
01331       iverts++;
01332     } else if (ifaces < nfaces) {
01333       // Get next face
01334       f = &facetlist[ifaces];
01335       init(f);
01336       // In .off format, each facet has one polygon, no hole.
01337       f->numberofpolygons = 1;
01338       f->polygonlist = new tetgenio::polygon[1];
01339       p = &f->polygonlist[0];
01340       init(p);
01341       // Read the number of vertices, it should be greater than 0.
01342       p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01343       if (p->numberofvertices == 0) {
01344         printf("Syntax error reading polygon on line %d in file %s\n",
01345                line_count, infilename);
01346         fclose(fp);
01347         return false;
01348       }
01349       // Allocate memory for face vertices
01350       p->vertexlist = new int[p->numberofvertices];
01351       for (i = 0; i < p->numberofvertices; i++) {
01352         bufferp = findnextnumber(bufferp);
01353         if (*bufferp == '\0') {
01354           printf("Syntax error reading polygon on line %d in file %s\n",
01355                  line_count, infilename);
01356           fclose(fp);
01357           return false;
01358         }
01359         p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01360       }
01361       ifaces++;
01362     } else {
01363       // Should never get here
01364       printf("Found extra text starting at line %d in file %s\n", line_count,
01365              infilename);
01366       break;
01367     }
01368   }
01369 
01370   // Close file
01371   fclose(fp);
01372 
01373   // Check whether read all points
01374   if (iverts != nverts) {
01375     printf("Expected %d vertices, but read only %d vertices in file %s\n",
01376            nverts, iverts, infilename);
01377     return false;
01378   }
01379 
01380   // Check whether read all faces
01381   if (ifaces != nfaces) {
01382     printf("Expected %d faces, but read only %d faces in file %s\n",
01383            nfaces, ifaces, infilename);
01384     return false;
01385   }
01386 
01387   return true;
01388 }
01389 
01391 //                                                                           //
01392 // load_ply()    Load a polyhedron described in a .ply file.                 //
01393 //                                                                           //
01394 // 'filename' is the file name with extension .ply or without extension (the //
01395 // .ply will be added in this case).                                         //
01396 //                                                                           //
01397 // This is a simplified version of reading .ply files, which only reads the  //
01398 // set of vertices and the set of faces. Other informations (such as color,  //
01399 // material, texture, etc) in .ply file are ignored. Complete routines for   //
01400 // reading and writing ,ply files are available from: http://www.cc.gatech.  //
01401 // edu/projects/large_models/ply.html.  Except the header section, ply file  //
01402 // format has exactly the same format for listing vertices and polygons as   //
01403 // off file format.                                                          //
01404 //                                                                           //
01405 // On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
01406 //                                                                           //
01408 
01409 bool tetgenio::load_ply(char* filename)
01410 {
01411   FILE *fp;
01412   tetgenio::facet *f;
01413   tetgenio::polygon *p;
01414   char infilename[FILENAMESIZE];
01415   char buffer[INPUTLINESIZE];
01416   char *bufferp, *str;
01417   double *coord;
01418   int endheader = 0, format = 0;
01419   int nverts = 0, iverts = 0;
01420   int nfaces = 0, ifaces = 0;
01421   int line_count = 0, i;
01422 
01423   strncpy(infilename, filename, FILENAMESIZE - 1);
01424   infilename[FILENAMESIZE - 1] = '\0';
01425   if (infilename[0] == '\0') {
01426     printf("Error:  No filename.\n");
01427     return false;
01428   }
01429   if (strcmp(&infilename[strlen(infilename) - 4], ".ply") != 0) {
01430     strcat(infilename, ".ply");
01431   }
01432 
01433   if (!(fp = fopen(infilename, "r"))) {
01434     printf("Error:  Unable to open file %s\n", infilename);
01435     return false;
01436   }
01437   printf("Opening %s.\n", infilename);
01438 
01439   // PLY requires the index starts from '0'.
01440   firstnumber = 0;
01441 
01442   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01443     if (!endheader) {
01444       // Find if it is the keyword "end_header".
01445       str = strstr(bufferp, "end_header");
01446       // strstr() is case sensitive.
01447       if (!str) str = strstr(bufferp, "End_header");
01448       if (!str) str = strstr(bufferp, "End_Header");
01449       if (str) {
01450         // This is the end of the header section.
01451         endheader = 1;
01452         continue;
01453       }
01454       // Parse the number of vertices and the number of faces.
01455       if (nverts == 0 || nfaces == 0) {
01456         // Find if it si the keyword "element".
01457         str = strstr(bufferp, "element");
01458         if (!str) str = strstr(bufferp, "Element");
01459         if (str) {
01460           bufferp = findnextfield(str);
01461           if (*bufferp == '\0') {
01462             printf("Syntax error reading element type on line%d in file %s\n",
01463                    line_count, infilename);
01464             fclose(fp);
01465             return false;
01466           }
01467           if (nverts == 0) {
01468             // Find if it is the keyword "vertex".
01469             str = strstr(bufferp, "vertex");
01470             if (!str) str = strstr(bufferp, "Vertex");
01471             if (str) {
01472               bufferp = findnextnumber(str);
01473               if (*bufferp == '\0') {
01474                 printf("Syntax error reading vertex number on line");
01475                 printf(" %d in file %s\n", line_count, infilename);
01476                 fclose(fp);
01477                 return false;
01478               }
01479               nverts = (int) strtol(bufferp, &bufferp, 0);
01480               // Allocate memory for 'tetgenio'
01481               if (nverts > 0) {
01482                 numberofpoints = nverts;
01483                 pointlist = new REAL[nverts * 3];
01484               }
01485             }
01486           }
01487           if (nfaces == 0) {
01488             // Find if it is the keyword "face".
01489             str = strstr(bufferp, "face");
01490             if (!str) str = strstr(bufferp, "Face");
01491             if (str) {
01492               bufferp = findnextnumber(str);
01493               if (*bufferp == '\0') {
01494                 printf("Syntax error reading face number on line");
01495                 printf(" %d in file %s\n", line_count, infilename);
01496                 fclose(fp);
01497                 return false;
01498               }
01499               nfaces = (int) strtol(bufferp, &bufferp, 0);
01500               // Allocate memory for 'tetgenio'
01501               if (nfaces > 0) {
01502                 numberoffacets = nfaces;
01503                 facetlist = new tetgenio::facet[nfaces];
01504               }
01505             }
01506           }
01507         } // It is not the string "element".
01508       }
01509       if (format == 0) {
01510         // Find the keyword "format".
01511         str = strstr(bufferp, "format");
01512         if (!str) str = strstr(bufferp, "Format");
01513         if (str) {
01514           format = 1;
01515           bufferp = findnextfield(str);
01516           // Find if it is the string "ascii".
01517           str = strstr(bufferp, "ascii");
01518           if (!str) str = strstr(bufferp, "ASCII");
01519           if (!str) {
01520             printf("This routine only reads ascii format of ply files.\n");
01521             printf("Hint: You can convert the binary to ascii format by\n");
01522             printf("  using the provided ply tools:\n");
01523             printf("  ply2ascii < %s > ascii_%s\n", infilename, infilename);
01524             fclose(fp);
01525             return false;
01526           }
01527         }
01528       }
01529     } else if (iverts < nverts) {
01530       // Read vertex coordinates
01531       coord = &pointlist[iverts * 3];
01532       for (i = 0; i < 3; i++) {
01533         if (*bufferp == '\0') {
01534           printf("Syntax error reading vertex coords on line %d in file %s\n",
01535                  line_count, infilename);
01536           fclose(fp);
01537           return false;
01538         }
01539         coord[i] = (REAL) strtod(bufferp, &bufferp);
01540         bufferp = findnextnumber(bufferp);
01541       }
01542       iverts++;
01543     } else if (ifaces < nfaces) {
01544       // Get next face
01545       f = &facetlist[ifaces];
01546       init(f);
01547       // In .off format, each facet has one polygon, no hole.
01548       f->numberofpolygons = 1;
01549       f->polygonlist = new tetgenio::polygon[1];
01550       p = &f->polygonlist[0];
01551       init(p);
01552       // Read the number of vertices, it should be greater than 0.
01553       p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01554       if (p->numberofvertices == 0) {
01555         printf("Syntax error reading polygon on line %d in file %s\n",
01556                line_count, infilename);
01557         fclose(fp);
01558         return false;
01559       }
01560       // Allocate memory for face vertices
01561       p->vertexlist = new int[p->numberofvertices];
01562       for (i = 0; i < p->numberofvertices; i++) {
01563         bufferp = findnextnumber(bufferp);
01564         if (*bufferp == '\0') {
01565           printf("Syntax error reading polygon on line %d in file %s\n",
01566                  line_count, infilename);
01567           fclose(fp);
01568           return false;
01569         }
01570         p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01571       }
01572       ifaces++;
01573     } else {
01574       // Should never get here
01575       printf("Found extra text starting at line %d in file %s\n", line_count,
01576              infilename);
01577       break;
01578     }
01579   }
01580 
01581   // Close file
01582   fclose(fp);
01583 
01584   // Check whether read all points
01585   if (iverts != nverts) {
01586     printf("Expected %d vertices, but read only %d vertices in file %s\n",
01587            nverts, iverts, infilename);
01588     return false;
01589   }
01590 
01591   // Check whether read all faces
01592   if (ifaces != nfaces) {
01593     printf("Expected %d faces, but read only %d faces in file %s\n",
01594            nfaces, ifaces, infilename);
01595     return false;
01596   }
01597 
01598   return true;
01599 }
01600 
01602 //                                                                           //
01603 // load_stl()    Load a surface mesh described in a .stl file.               //
01604 //                                                                           //
01605 // 'filename' is the file name with extension .stl or without extension (the //
01606 // .stl will be added in this case).                                         //
01607 //                                                                           //
01608 // The .stl or stereolithography format is an ASCII or binary file used in   //
01609 // manufacturing.  It is a list of the triangular surfaces that describe a   //
01610 // computer generated solid model. This is the standard input for most rapid //
01611 // prototyping machines.                                                     //
01612 //                                                                           //
01613 // On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
01614 // Note: After load_stl(), there exist many duplicated points in 'pointlist'.//
01615 // They will be unified during the Delaunay tetrahedralization process.      //
01616 //                                                                           //
01618 
01619 bool tetgenio::load_stl(char* filename)
01620 {
01621   FILE *fp;
01622   tetgenmesh::list *plist;
01623   tetgenio::facet *f;
01624   tetgenio::polygon *p;
01625   char infilename[FILENAMESIZE];
01626   char buffer[INPUTLINESIZE];
01627   char *bufferp, *str;
01628   double *coord;
01629   int solid = 0;
01630   int nverts = 0, iverts = 0;
01631   int nfaces = 0;
01632   int line_count = 0, i;
01633 
01634   strncpy(infilename, filename, FILENAMESIZE - 1);
01635   infilename[FILENAMESIZE - 1] = '\0';
01636   if (infilename[0] == '\0') {
01637     printf("Error:  No filename.\n");
01638     return false;
01639   }
01640   if (strcmp(&infilename[strlen(infilename) - 4], ".stl") != 0) {
01641     strcat(infilename, ".stl");
01642   }
01643 
01644   if (!(fp = fopen(infilename, "r"))) {
01645     printf("Error:  Unable to open file %s\n", infilename);
01646     return false;
01647   }
01648   printf("Opening %s.\n", infilename);
01649 
01650   // STL file has no number of points available. Use a list to read points.
01651   plist = new tetgenmesh::list(sizeof(double) * 3, NULL, 1024);
01652 
01653   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01654     // The ASCII .stl file must start with the lower case keyword solid and
01655     //   end with endsolid.
01656     if (solid == 0) {
01657       // Read header
01658       bufferp = strstr(bufferp, "solid");
01659       if (bufferp != NULL) {
01660         solid = 1;
01661       }
01662     } else {
01663       // We're inside the block of the solid.
01664       str = bufferp;
01665       // Is this the end of the solid.
01666       bufferp = strstr(bufferp, "endsolid");
01667       if (bufferp != NULL) {
01668         solid = 0;
01669       } else {
01670         // Read the XYZ coordinates if it is a vertex.
01671         bufferp = str;
01672         bufferp = strstr(bufferp, "vertex");
01673         if (bufferp != NULL) {
01674           coord = (double *) plist->append(NULL);
01675           for (i = 0; i < 3; i++) {
01676             bufferp = findnextnumber(bufferp);
01677             if (*bufferp == '\0') {
01678               printf("Syntax error reading vertex coords on line %d\n",
01679                    line_count);
01680               delete plist;
01681               fclose(fp);
01682               return false;
01683             }
01684             coord[i] = (REAL) strtod(bufferp, &bufferp);
01685           }
01686         }
01687       }
01688     }
01689   }
01690   fclose(fp);
01691 
01692   nverts = plist->len();
01693   // nverts should be an integer times 3 (every 3 vertices denote a face).
01694   if (nverts == 0 || (nverts % 3 != 0)) {
01695     printf("Error:  Wrong number of vertices in file %s.\n", infilename);
01696     delete plist;
01697     return false;
01698   }
01699   numberofpoints = nverts;
01700   pointlist = new REAL[nverts * 3];
01701   for (i = 0; i < nverts; i++) {
01702     coord = (double *) (* plist)[i];
01703     iverts = i * 3;
01704     pointlist[iverts] = (REAL) coord[0];
01705     pointlist[iverts + 1] = (REAL) coord[1];
01706     pointlist[iverts + 2] = (REAL) coord[2];
01707   }
01708 
01709   nfaces = (int) (nverts / 3);
01710   numberoffacets = nfaces;
01711   facetlist = new tetgenio::facet[nfaces];
01712 
01713   // Default use '1' as the array starting index.
01714   firstnumber = 1;
01715   iverts = firstnumber;
01716   for (i = 0; i < nfaces; i++) {
01717     f = &facetlist[i];
01718     init(f);
01719     // In .stl format, each facet has one polygon, no hole.
01720     f->numberofpolygons = 1;
01721     f->polygonlist = new tetgenio::polygon[1];
01722     p = &f->polygonlist[0];
01723     init(p);
01724     // Each polygon has three vertices.
01725     p->numberofvertices = 3;
01726     p->vertexlist = new int[p->numberofvertices];
01727     p->vertexlist[0] = iverts;
01728     p->vertexlist[1] = iverts + 1;
01729     p->vertexlist[2] = iverts + 2;
01730     iverts += 3;
01731   }
01732 
01733   delete plist;
01734   return true;
01735 }
01736 
01738 //                                                                           //
01739 // load_medit()    Load a surface mesh described in .mesh file.              //
01740 //                                                                           //
01741 // 'filename' is the file name with extension .mesh or without entension (   //
01742 // the .mesh will be added in this case). .mesh is the file format of Medit, //
01743 // a user-friendly interactive mesh viewing program.                         //
01744 //                                                                           //
01745 // This routine ONLY reads the sections containing vertices, triangles, and  //
01746 // quadrilaters. Other sections (such as tetrahedra, edges, ...) are ignored.//
01747 //                                                                           //
01749 
01750 bool tetgenio::load_medit(char* filename)
01751 {
01752   FILE *fp;
01753   tetgenio::facet *tmpflist, *f;
01754   tetgenio::polygon *p;
01755   char infilename[FILENAMESIZE];
01756   char buffer[INPUTLINESIZE];
01757   char *bufferp, *str;
01758   double *coord;
01759   int *tmpfmlist;
01760   int dimension = 0;
01761   int nverts = 0;
01762   int nfaces = 0;
01763   int line_count = 0;
01764   int corners = 0; // 3 (triangle) or 4 (quad).
01765   int i, j;
01766 
01767   strncpy(infilename, filename, FILENAMESIZE - 1);
01768   infilename[FILENAMESIZE - 1] = '\0';
01769   if (infilename[0] == '\0') {
01770     printf("Error:  No filename.\n");
01771     return false;
01772   }
01773   if (strcmp(&infilename[strlen(infilename) - 5], ".mesh") != 0) {
01774     strcat(infilename, ".mesh");
01775   }
01776 
01777   if (!(fp = fopen(infilename, "r"))) {
01778     printf("Error:  Unable to open file %s\n", infilename);
01779     return false;
01780   }
01781   printf("Opening %s.\n", infilename);
01782 
01783   // Default uses the index starts from '1'.
01784   firstnumber = 1;
01785 
01786   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01787     if (*bufferp == '#') continue;  // A comment line is skipped.
01788     if (dimension == 0) {
01789       // Find if it is the keyword "Dimension".
01790       str = strstr(bufferp, "Dimension");
01791       if (!str) str = strstr(bufferp, "dimension");
01792       if (!str) str = strstr(bufferp, "DIMENSION");
01793       if (str) {
01794         // Read the dimensions
01795         bufferp = findnextnumber(str); // Skip field "Dimension".
01796         if (*bufferp == '\0') {
01797           // Read a non-empty line.
01798           bufferp = readline(buffer, fp, &line_count);
01799         }
01800         dimension = (int) strtol(bufferp, &bufferp, 0);
01801         if (dimension != 2 && dimension != 3) {
01802           printf("Unknown dimension in file on line %d in file %s\n",
01803                  line_count, infilename);
01804           fclose(fp);
01805           return false;
01806         }
01807         mesh_dim = dimension;
01808       }
01809     }
01810     if (nverts == 0) {
01811       // Find if it is the keyword "Vertices".
01812       str = strstr(bufferp, "Vertices");
01813       if (!str) str = strstr(bufferp, "vertices");
01814       if (!str) str = strstr(bufferp, "VERTICES");
01815       if (str) {
01816         // Read the number of vertices.
01817         bufferp = findnextnumber(str); // Skip field "Vertices".
01818         if (*bufferp == '\0') {
01819           // Read a non-empty line.
01820           bufferp = readline(buffer, fp, &line_count);
01821         }
01822         nverts = (int) strtol(bufferp, &bufferp, 0);
01823         // Allocate memory for 'tetgenio'
01824         if (nverts > 0) {
01825           numberofpoints = nverts;
01826           pointlist = new REAL[nverts * 3];
01827         }
01828         // Read the follwoing node list.
01829         for (i = 0; i < nverts; i++) {
01830           bufferp = readline(buffer, fp, &line_count);
01831           if (bufferp == NULL) {
01832             printf("Unexpected end of file on line %d in file %s\n",
01833                    line_count, infilename);
01834             fclose(fp);
01835             return false;
01836           }
01837           // Read vertex coordinates
01838           coord = &pointlist[i * 3];
01839           for (j = 0; j < 3; j++) {
01840             if (*bufferp == '\0') {
01841               printf("Syntax error reading vertex coords on line");
01842               printf(" %d in file %s\n", line_count, infilename);
01843               fclose(fp);
01844               return false;
01845             }
01846             if ((j < 2) || (dimension == 3)) {
01847               coord[j] = (REAL) strtod(bufferp, &bufferp);
01848             } else {
01849               assert((j == 2) && (dimension == 2));
01850               coord[j] = 0.0;
01851             }
01852             bufferp = findnextnumber(bufferp);
01853           }
01854         }
01855         continue;
01856       }
01857     }
01858     if (nfaces == 0) {
01859       // Find if it is the keyword "Triangles" or "Quadrilaterals".
01860       corners = 0;
01861       str = strstr(bufferp, "Triangles");
01862       if (!str) str = strstr(bufferp, "triangles");
01863       if (!str) str = strstr(bufferp, "TRIANGLES");
01864       if (str) {
01865         corners = 3;
01866       } else {
01867         str = strstr(bufferp, "Quadrilaterals");
01868         if (!str) str = strstr(bufferp, "quadrilaterals");
01869         if (!str) str = strstr(bufferp, "QUADRILATERALS");
01870         if (str) {
01871           corners = 4;
01872         }
01873       }
01874       if (corners == 3 || corners == 4) {
01875         // Read the number of triangles (or quadrilaterals).
01876         bufferp = findnextnumber(str); // Skip field "Triangles".
01877         if (*bufferp == '\0') {
01878           // Read a non-empty line.
01879           bufferp = readline(buffer, fp, &line_count);
01880         }
01881         nfaces = strtol(bufferp, &bufferp, 0);
01882         // Allocate memory for 'tetgenio'
01883         if (nfaces > 0) {
01884           if (numberoffacets > 0) {
01885             // facetlist has already been allocated. Enlarge arrays.
01886             tmpflist = new tetgenio::facet[numberoffacets + nfaces];
01887             tmpfmlist = new int[numberoffacets + nfaces];
01888             // Copy the data of old arrays into new arrays.
01889             for (i = 0; i < numberoffacets; i++) {
01890               f = &(tmpflist[i]);
01891               tetgenio::init(f);
01892               *f = facetlist[i];
01893               tmpfmlist[i] = facetmarkerlist[i];
01894             }
01895             // Release old arrays.
01896             delete [] facetlist;
01897             delete [] facetmarkerlist;
01898             // Remember the new arrays.
01899             facetlist = tmpflist;
01900             facetmarkerlist = tmpfmlist;
01901           } else {
01902             // This is the first time to allocate facetlist.
01903             facetlist = new tetgenio::facet[nfaces];
01904             facetmarkerlist = new int[nfaces];
01905           }
01906         }
01907         // Read the following list of faces.
01908         for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
01909           bufferp = readline(buffer, fp, &line_count);
01910           if (bufferp == NULL) {
01911             printf("Unexpected end of file on line %d in file %s\n",
01912                    line_count, infilename);
01913             fclose(fp);
01914             return false;
01915           }
01916           f = &facetlist[i];
01917           tetgenio::init(f);
01918           // In .mesh format, each facet has one polygon, no hole.
01919           f->numberofpolygons = 1;
01920           f->polygonlist = new tetgenio::polygon[1];
01921           p = &f->polygonlist[0];
01922           tetgenio::init(p);
01923           p->numberofvertices = corners;
01924           // Allocate memory for face vertices
01925           p->vertexlist = new int[p->numberofvertices];
01926           // Read the vertices of the face.
01927           for (j = 0; j < corners; j++) {
01928             if (*bufferp == '\0') {
01929               printf("Syntax error reading face on line %d in file %s\n",
01930                      line_count, infilename);
01931               fclose(fp);
01932               return false;
01933             }
01934             p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0);
01935             if (firstnumber == 1) {
01936               // Check if a '0' index appears.
01937               if (p->vertexlist[j] == 0) {
01938                 // The first index is set to be 0.
01939                 firstnumber = 0;
01940               }
01941             }
01942             bufferp = findnextnumber(bufferp);
01943           }
01944           // Read the marker of the face if it exists.
01945           facetmarkerlist[i] = 0;
01946           if (*bufferp != '\0') {
01947             facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
01948           }
01949         }
01950         // Have read in a list of triangles/quads.
01951         numberoffacets += nfaces;
01952         nfaces = 0;
01953       }
01954     }
01955     // if (nverts > 0 && nfaces > 0) break; // Ignore other data.
01956   }
01957 
01958   // Close file
01959   fclose(fp);
01960 
01961   return true;
01962 }
01963 
01965 //                                                                           //
01966 // load_plc()    Load a piecewise linear complex from file.                  //
01967 //                                                                           //
01968 // This is main entrance for loading plcs from different file formats into   //
01969 // tetgenio.  'filename' is the input file name without extention. 'object'  //
01970 // indicates which file format is used to describ the plc.                   //
01971 //                                                                           //
01973 
01974 bool tetgenio::load_plc(char* filename, int object)
01975 {
01976   enum tetgenbehavior::objecttype type;
01977 
01978   type = (enum tetgenbehavior::objecttype) object;
01979   switch (type) {
01980   case tetgenbehavior::NODES:
01981     return load_node(filename);
01982   case tetgenbehavior::POLY:
01983     return load_poly(filename);
01984   case tetgenbehavior::OFF:
01985     return load_off(filename);
01986   case tetgenbehavior::PLY:
01987     return load_ply(filename);
01988   case tetgenbehavior::STL:
01989     return load_stl(filename);
01990   case tetgenbehavior::MEDIT:
01991     return load_medit(filename);
01992   default:
01993     return load_poly(filename);
01994   }
01995 }
01996 
01998 //                                                                           //
01999 // load_tetmesh()    Load a tetrahedral mesh from files.                     //
02000 //                                                                           //
02001 // 'filename' is the inputfile without suffix.  The nodes of the tetrahedral //
02002 // mesh is in "filename.node",  the elements is in "filename.ele", if the    //
02003 // "filename.face" and "filename.vol" exists, they will also be read.        //
02004 //                                                                           //
02006 
02007 bool tetgenio::load_tetmesh(char* filename)
02008 {
02009   FILE *infile;
02010   char innodefilename[FILENAMESIZE];
02011   char inelefilename[FILENAMESIZE];
02012   char infacefilename[FILENAMESIZE];
02013   char inedgefilename[FILENAMESIZE];
02014   char involfilename[FILENAMESIZE];
02015   char inputline[INPUTLINESIZE];
02016   char *stringptr, *infilename;
02017   REAL attrib, volume;
02018   int volelements;
02019   int markers, corner;
02020   int index, attribindex;
02021   int i, j;
02022 
02023   markers = 0;
02024 
02025   // Assembling the actual file names we want to open.
02026   strcpy(innodefilename, filename);
02027   strcpy(inelefilename, filename);
02028   strcpy(infacefilename, filename);
02029   strcpy(inedgefilename, filename);
02030   strcpy(involfilename, filename);
02031   strcat(innodefilename, ".node");
02032   strcat(inelefilename, ".ele");
02033   strcat(infacefilename, ".face");
02034   strcat(inedgefilename, ".edge");
02035   strcat(involfilename, ".vol");
02036 
02037   // Read the points from a .node file.
02038   infilename = innodefilename;
02039   printf("Opening %s.\n", infilename);
02040   infile = fopen(infilename, "r");
02041   if (infile == (FILE *) NULL) {
02042     printf("File I/O Error:  Cannot access file %s.\n", infilename);
02043     return false;
02044   }
02045   // Read the first line of the file.
02046   stringptr = readnumberline(inputline, infile, infilename);
02047   // Is this list of points generated from rbox?
02048   stringptr = strstr(inputline, "rbox");
02049   if (stringptr == NULL) {
02050     // Read number of points, number of dimensions, number of point
02051     //   attributes, and number of boundary markers.
02052     stringptr = inputline;
02053     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02054     stringptr = findnextnumber(stringptr);
02055     if (*stringptr == '\0') {
02056       mesh_dim = 3;
02057     } else {
02058       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02059     }
02060     stringptr = findnextnumber(stringptr);
02061     if (*stringptr == '\0') {
02062       numberofpointattributes = 0;
02063     } else {
02064       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
02065     }
02066     stringptr = findnextnumber(stringptr);
02067     if (*stringptr == '\0') {
02068       markers = 0;  // Default value.
02069     } else {
02070       markers = (int) strtol (stringptr, &stringptr, 0);
02071     }
02072   } else {
02073     // It is a rbox (qhull) input file.
02074     stringptr = inputline;
02075     // Get the dimension.
02076     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02077     // Get the number of points.
02078     stringptr = readnumberline(inputline, infile, infilename);
02079     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02080     // There is no index column.
02081     useindex = 0;
02082   }
02083 
02084   // Load the list of nodes.
02085   if (!load_node_call(infile, markers, infilename)) {
02086     fclose(infile);
02087     return false;
02088   }
02089   fclose(infile);
02090 
02091   // Read the elements from an .ele file.
02092   if (mesh_dim == 3) {
02093     infilename = inelefilename;
02094     infile = fopen(infilename, "r");
02095     if (infile != (FILE *) NULL) {
02096       printf("Opening %s.\n", infilename);
02097       // Read number of elements, number of corners (4 or 10), number of
02098       //   element attributes.
02099       stringptr = readnumberline(inputline, infile, infilename);
02100       numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0);
02101       stringptr = findnextnumber(stringptr);
02102       if (*stringptr == '\0') {
02103         numberofcorners = 4;  // Default read 4 nodes per element.
02104       } else {
02105         numberofcorners = (int) strtol(stringptr, &stringptr, 0);
02106       }
02107       stringptr = findnextnumber(stringptr);
02108       if (*stringptr == '\0') {
02109         numberoftetrahedronattributes = 0; // Default no attribute.
02110       } else {
02111         numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0);
02112       }
02113       if (numberofcorners != 4 && numberofcorners != 10) {
02114         printf("Error:  Wrong number of corners %d (should be 4 or 10).\n",
02115                numberofcorners);
02116         fclose(infile);
02117         return false;
02118       }
02119       // Allocate memory for tetrahedra.
02120       if (numberoftetrahedra > 0) {
02121         tetrahedronlist = new int[numberoftetrahedra * numberofcorners];
02122         if (tetrahedronlist == (int *) NULL) {
02123           printf("Error:  Out of memory.\n");
02124           terminatetetgen(1);
02125         }
02126         // Allocate memory for output tetrahedron attributes if necessary.
02127         if (numberoftetrahedronattributes > 0) {
02128           tetrahedronattributelist = new REAL[numberoftetrahedra *
02129                                           numberoftetrahedronattributes];
02130           if (tetrahedronattributelist == (REAL *) NULL) {
02131             printf("Error:  Out of memory.\n");
02132             terminatetetgen(1);
02133           }
02134         }
02135       }
02136       // Read the list of tetrahedra.
02137       index = 0;
02138       attribindex = 0;
02139       for (i = 0; i < numberoftetrahedra; i++) {
02140         // Read tetrahedron index and the tetrahedron's corners.
02141         stringptr = readnumberline(inputline, infile, infilename);
02142         for (j = 0; j < numberofcorners; j++) {
02143           stringptr = findnextnumber(stringptr);
02144           if (*stringptr == '\0') {
02145             printf("Error:  Tetrahedron %d is missing vertex %d in %s.\n",
02146                    i + firstnumber, j + 1, infilename);
02147             terminatetetgen(1);
02148           }
02149           corner = (int) strtol(stringptr, &stringptr, 0);
02150           if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02151             printf("Error:  Tetrahedron %d has an invalid vertex index.\n",
02152                    i + firstnumber);
02153             terminatetetgen(1);
02154           }
02155           tetrahedronlist[index++] = corner;
02156         }
02157         // Read the tetrahedron's attributes.
02158         for (j = 0; j < numberoftetrahedronattributes; j++) {
02159           stringptr = findnextnumber(stringptr);
02160           if (*stringptr == '\0') {
02161             attrib = 0.0;
02162           } else {
02163             attrib = (REAL) strtod(stringptr, &stringptr);
02164           }
02165           tetrahedronattributelist[attribindex++] = attrib;
02166         }
02167       }
02168       fclose(infile);
02169     }
02170   } // if (meshdim == 3)
02171 
02172   // Read the hullfaces or subfaces from a .face file if it exists.
02173   if (mesh_dim == 3) {
02174     infilename = infacefilename;
02175   } else {
02176     infilename = inelefilename;
02177   }
02178   infile = fopen(infilename, "r");
02179   if (infile != (FILE *) NULL) {
02180     printf("Opening %s.\n", infilename);
02181     // Read number of faces, boundary markers.
02182     stringptr = readnumberline(inputline, infile, infilename);
02183     numberoftrifaces = (int) strtol (stringptr, &stringptr, 0);
02184     stringptr = findnextnumber(stringptr);
02185     if (mesh_dim == 2) {
02186       // Skip a number.
02187       stringptr = findnextnumber(stringptr);
02188     }
02189     if (*stringptr == '\0') {
02190       markers = 0;  // Default there is no marker per face.
02191     } else {
02192       markers = (int) strtol (stringptr, &stringptr, 0);
02193     }
02194     if (numberoftrifaces > 0) {
02195       trifacelist = new int[numberoftrifaces * 3];
02196       if (trifacelist == (int *) NULL) {
02197         printf("Error:  Out of memory.\n");
02198         terminatetetgen(1);
02199       }
02200       if (markers) {
02201         trifacemarkerlist = new int[numberoftrifaces * 3];
02202         if (trifacemarkerlist == (int *) NULL) {
02203           printf("Error:  Out of memory.\n");
02204           terminatetetgen(1);
02205         }
02206       }
02207     }
02208     // Read the list of faces.
02209     index = 0;
02210     for (i = 0; i < numberoftrifaces; i++) {
02211       // Read face index and the face's three corners.
02212       stringptr = readnumberline(inputline, infile, infilename);
02213       for (j = 0; j < 3; j++) {
02214         stringptr = findnextnumber(stringptr);
02215         if (*stringptr == '\0') {
02216           printf("Error:  Face %d is missing vertex %d in %s.\n",
02217                  i + firstnumber, j + 1, infilename);
02218           terminatetetgen(1);
02219         }
02220         corner = (int) strtol(stringptr, &stringptr, 0);
02221         if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02222           printf("Error:  Face %d has an invalid vertex index.\n",
02223                  i + firstnumber);
02224           terminatetetgen(1);
02225         }
02226         trifacelist[index++] = corner;
02227       }
02228       // Read the boundary marker if it exists.
02229       if (markers) {
02230         stringptr = findnextnumber(stringptr);
02231         if (*stringptr == '\0') {
02232           attrib = 0.0;
02233         } else {
02234           attrib = (REAL) strtod(stringptr, &stringptr);
02235         }
02236         trifacemarkerlist[i] = (int) attrib;
02237       }
02238     }
02239     fclose(infile);
02240   }
02241 
02242   // Read the boundary edges from a .edge file if it exists.
02243   infilename = inedgefilename;
02244   infile = fopen(infilename, "r");
02245   if (infile != (FILE *) NULL) {
02246     printf("Opening %s.\n", infilename);
02247     // Read number of boundary edges.
02248     stringptr = readnumberline(inputline, infile, infilename);
02249     numberofedges = (int) strtol (stringptr, &stringptr, 0);
02250     if (numberofedges > 0) {
02251       edgelist = new int[numberofedges * 2];
02252       if (edgelist == (int *) NULL) {
02253         printf("Error:  Out of memory.\n");
02254         terminatetetgen(1);
02255       }
02256     }
02257     // Read the list of faces.
02258     index = 0;
02259     for (i = 0; i < numberofedges; i++) {
02260       // Read face index and the edge's two endpoints.
02261       stringptr = readnumberline(inputline, infile, infilename);
02262       for (j = 0; j < 2; j++) {
02263         stringptr = findnextnumber(stringptr);
02264         if (*stringptr == '\0') {
02265           printf("Error:  Edge %d is missing vertex %d in %s.\n",
02266                  i + firstnumber, j + 1, infilename);
02267           terminatetetgen(1);
02268         }
02269         corner = (int) strtol(stringptr, &stringptr, 0);
02270         if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02271           printf("Error:  Edge %d has an invalid vertex index.\n",
02272                  i + firstnumber);
02273           terminatetetgen(1);
02274         }
02275         edgelist[index++] = corner;
02276       }
02277     }
02278     fclose(infile);
02279   }
02280 
02281   // Read the volume constraints from a .vol file if it exists.
02282   infilename = involfilename;
02283   infile = fopen(infilename, "r");
02284   if (infile != (FILE *) NULL) {
02285     printf("Opening %s.\n", infilename);
02286     // Read number of tetrahedra.
02287     stringptr = readnumberline(inputline, infile, infilename);
02288     volelements = (int) strtol (stringptr, &stringptr, 0);
02289     if (volelements != numberoftetrahedra) {
02290       printf("Warning:  %s and %s disagree on number of tetrahedra.\n",
02291              inelefilename, involfilename);
02292       volelements = 0;
02293     }
02294     if (volelements > 0) {
02295       tetrahedronvolumelist = new REAL[volelements];
02296       if (tetrahedronvolumelist == (REAL *) NULL) {
02297         printf("Error:  Out of memory.\n");
02298         terminatetetgen(1);
02299       }
02300     }
02301     // Read the list of volume constraints.
02302     for (i = 0; i < volelements; i++) {
02303       stringptr = readnumberline(inputline, infile, infilename);
02304       stringptr = findnextnumber(stringptr);
02305       if (*stringptr == '\0') {
02306         volume = -1.0; // No constraint on this tetrahedron.
02307       } else {
02308         volume = (REAL) strtod(stringptr, &stringptr);
02309       }
02310       tetrahedronvolumelist[i] = volume;
02311     }
02312     fclose(infile);
02313   }
02314 
02315   // Try to load a .mtr file if it exists.
02316   load_mtr(filename);
02317   // Try to read a .pbc file if it exists.
02318   load_pbc(filename);
02319 
02320   return true;
02321 }
02322 
02324 //                                                                           //
02325 // load_voronoi()    Load a Voronoi diagram from files.                      //
02326 //                                                                           //
02327 // 'filename' is the inputfile without suffix.  The Voronoi diagram is read  //
02328 // from files: filename.v.node, filename.v.edge, and filename.v.face.        //
02329 //                                                                           //
02331 
02332 bool tetgenio::load_voronoi(char* filename)
02333 {
02334   FILE *infile;
02335   char innodefilename[FILENAMESIZE];
02336   char inedgefilename[FILENAMESIZE];
02337   char inputline[INPUTLINESIZE];
02338   char *stringptr, *infilename;
02339   voroedge *vedge;
02340   REAL x, y, z;
02341   int firstnode, corner;
02342   int index;
02343   int i, j;
02344 
02345   // Assembling the actual file names we want to open.
02346   strcpy(innodefilename, filename);
02347   strcpy(inedgefilename, filename);
02348   strcat(innodefilename, ".v.node");
02349   strcat(inedgefilename, ".v.edge");
02350 
02351   // Read the points from a .v.node file.
02352   infilename = innodefilename;
02353   printf("Opening %s.\n", infilename);
02354   infile = fopen(infilename, "r");
02355   if (infile == (FILE *) NULL) {
02356     printf("File I/O Error:  Cannot access file %s.\n", infilename);
02357     return false;
02358   }
02359   // Read the first line of the file.
02360   stringptr = readnumberline(inputline, infile, infilename);
02361   // Is this list of points generated from rbox?
02362   stringptr = strstr(inputline, "rbox");
02363   if (stringptr == NULL) {
02364     // Read number of points, number of dimensions, number of point
02365     //   attributes, and number of boundary markers.
02366     stringptr = inputline;
02367     numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02368     stringptr = findnextnumber(stringptr);
02369     if (*stringptr == '\0') {
02370       mesh_dim = 3;  // Default.
02371     } else {
02372       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02373     }
02374     useindex = 1;  // There is an index column.
02375   } else {
02376     // It is a rbox (qhull) input file.
02377     stringptr = inputline;
02378     // Get the dimension.
02379     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02380     // Get the number of points.
02381     stringptr = readnumberline(inputline, infile, infilename);
02382     numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02383     useindex = 0;  // No index column.
02384   }
02385   // Initialize 'vpointlist'.
02386   vpointlist = new REAL[numberofvpoints * 3];
02387   if (vpointlist == (REAL *) NULL) {
02388     printf("Error:  Out of memory.\n");
02389     terminatetetgen(1);
02390   }
02391   // Read the point section.
02392   index = 0;
02393   for (i = 0; i < numberofvpoints; i++) {
02394     stringptr = readnumberline(inputline, infile, infilename);
02395     if (useindex) {
02396       if (i == 0) {
02397         firstnode = (int) strtol (stringptr, &stringptr, 0);
02398         if ((firstnode == 0) || (firstnode == 1)) {
02399           firstnumber = firstnode;
02400         }
02401       }
02402       stringptr = findnextnumber(stringptr);
02403     } // if (useindex)
02404     if (*stringptr == '\0') {
02405       printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
02406       terminatetetgen(1);
02407     }
02408     x = (REAL) strtod(stringptr, &stringptr);
02409     stringptr = findnextnumber(stringptr);
02410     if (*stringptr == '\0') {
02411       printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
02412       terminatetetgen(1);
02413     }
02414     y = (REAL) strtod(stringptr, &stringptr);
02415     if (mesh_dim == 3) {
02416       stringptr = findnextnumber(stringptr);
02417       if (*stringptr == '\0') {
02418         printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
02419         terminatetetgen(1);
02420       }
02421       z = (REAL) strtod(stringptr, &stringptr);
02422     } else {
02423       z = 0.0; // mesh_dim == 2;
02424     }
02425     vpointlist[index++] = x;
02426     vpointlist[index++] = y;
02427     vpointlist[index++] = z;
02428   }
02429   fclose(infile);
02430 
02431   // Read the Voronoi edges from a .v.edge file if it exists.
02432   infilename = inedgefilename;
02433   infile = fopen(infilename, "r");
02434   if (infile != (FILE *) NULL) {
02435     printf("Opening %s.\n", infilename);
02436     // Read number of boundary edges.
02437     stringptr = readnumberline(inputline, infile, infilename);
02438     numberofvedges = (int) strtol (stringptr, &stringptr, 0);
02439     if (numberofvedges > 0) {
02440       vedgelist = new voroedge[numberofvedges];
02441     }
02442     // Read the list of faces.
02443     index = 0;
02444     for (i = 0; i < numberofvedges; i++) {
02445       // Read edge index and the edge's two endpoints.
02446       stringptr = readnumberline(inputline, infile, infilename);
02447       vedge = &(vedgelist[i]);
02448       for (j = 0; j < 2; j++) {
02449         stringptr = findnextnumber(stringptr);
02450         if (*stringptr == '\0') {
02451           printf("Error:  Edge %d is missing vertex %d in %s.\n",
02452                  i + firstnumber, j + 1, infilename);
02453           terminatetetgen(1);
02454         }
02455         corner = (int) strtol(stringptr, &stringptr, 0);
02456         j == 0 ? vedge->v1 = corner : vedge->v2 = corner;
02457       }
02458       if (vedge->v2 < 0) {
02459         for (j = 0; j < mesh_dim; j++) {
02460           stringptr = findnextnumber(stringptr);
02461           if (*stringptr == '\0') {
02462             printf("Error:  Edge %d is missing normal in %s.\n",
02463                    i + firstnumber, infilename);
02464             terminatetetgen(1);
02465           }
02466           vedge->vnormal[j] = (REAL) strtod(stringptr, &stringptr);
02467         }
02468         if (mesh_dim == 2) {
02469           vedge->vnormal[2] = 0.0;
02470         }
02471       } else {
02472         vedge->vnormal[0] = 0.0;
02473         vedge->vnormal[1] = 0.0;
02474         vedge->vnormal[2] = 0.0;
02475       }
02476     }
02477     fclose(infile);
02478   }
02479 
02480   return true;
02481 }
02482 
02484 //                                                                           //
02485 // save_nodes()    Save points to a .node file.                              //
02486 //                                                                           //
02487 // 'filename' is a string containing the file name without suffix.           //
02488 //                                                                           //
02490 
02491 void tetgenio::save_nodes(char* filename)
02492 {
02493   FILE *fout;
02494   char outnodefilename[FILENAMESIZE];
02495   char outmtrfilename[FILENAMESIZE];
02496   int i, j;
02497 
02498   sprintf(outnodefilename, "%s.node", filename);
02499   printf("Saving nodes to %s\n", outnodefilename);
02500   fout = fopen(outnodefilename, "w");
02501   fprintf(fout, "%d  %d  %d  %d\n", numberofpoints, mesh_dim,
02502           numberofpointattributes, pointmarkerlist != NULL ? 1 : 0);
02503   for (i = 0; i < numberofpoints; i++) {
02504     if (mesh_dim == 2) {
02505       fprintf(fout, "%d  %.16g  %.16g", i + firstnumber, pointlist[i * 2],
02506               pointlist[i * 2 + 1]);
02507     } else {
02508       fprintf(fout, "%d  %.16g  %.16g  %.16g", i + firstnumber,
02509               pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
02510     }
02511     for (j = 0; j < numberofpointattributes; j++) {
02512       fprintf(fout, "  %.16g",
02513               pointattributelist[i * numberofpointattributes + j]);
02514     }
02515     if (pointmarkerlist != NULL) {
02516       fprintf(fout, "  %d", pointmarkerlist[i]);
02517     }
02518     fprintf(fout, "\n");
02519   }
02520   fclose(fout);
02521 
02522   // If the point metrics exist, output them to a .mtr file.
02523   if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
02524     sprintf(outmtrfilename, "%s.mtr", filename);
02525     printf("Saving metrics to %s\n", outmtrfilename);
02526     fout = fopen(outmtrfilename, "w");
02527     fprintf(fout, "%d  %d\n", numberofpoints, numberofpointmtrs);
02528     for (i = 0; i < numberofpoints; i++) {
02529       for (j = 0; j < numberofpointmtrs; j++) {
02530         fprintf(fout, "%.16g ", pointmtrlist[i * numberofpointmtrs + j]);
02531       }
02532       fprintf(fout, "\n");
02533     }
02534     fclose(fout);
02535   }
02536 }
02537 
02539 //                                                                           //
02540 // save_elements()    Save elements to a .ele file.                          //
02541 //                                                                           //
02542 // 'filename' is a string containing the file name without suffix.           //
02543 //                                                                           //
02545 
02546 void tetgenio::save_elements(char* filename)
02547 {
02548   FILE *fout;
02549   char outelefilename[FILENAMESIZE];
02550   int i, j;
02551 
02552   sprintf(outelefilename, "%s.ele", filename);
02553   printf("Saving elements to %s\n", outelefilename);
02554   fout = fopen(outelefilename, "w");
02555   fprintf(fout, "%d  %d  %d\n", numberoftetrahedra, numberofcorners,
02556           numberoftetrahedronattributes);
02557   for (i = 0; i < numberoftetrahedra; i++) {
02558     fprintf(fout, "%d", i + firstnumber);
02559     for (j = 0; j < numberofcorners; j++) {
02560       fprintf(fout, "  %5d", tetrahedronlist[i * numberofcorners + j]);
02561     }
02562     for (j = 0; j < numberoftetrahedronattributes; j++) {
02563       fprintf(fout, "  %g",
02564         tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
02565     }
02566     fprintf(fout, "\n");
02567   }
02568 
02569   fclose(fout);
02570 }
02571 
02573 //                                                                           //
02574 // save_faces()    Save faces to a .face file.                               //
02575 //                                                                           //
02576 // 'filename' is a string containing the file name without suffix.           //
02577 //                                                                           //
02579 
02580 void tetgenio::save_faces(char* filename)
02581 {
02582   FILE *fout;
02583   char outfacefilename[FILENAMESIZE];
02584   int i;
02585 
02586   sprintf(outfacefilename, "%s.face", filename);
02587   printf("Saving faces to %s\n", outfacefilename);
02588   fout = fopen(outfacefilename, "w");
02589   fprintf(fout, "%d  %d\n", numberoftrifaces,
02590           trifacemarkerlist != NULL ? 1 : 0);
02591   for (i = 0; i < numberoftrifaces; i++) {
02592     fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber, trifacelist[i * 3],
02593             trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
02594     if (trifacemarkerlist != NULL) {
02595       fprintf(fout, "  %d", trifacemarkerlist[i]);
02596     }
02597     fprintf(fout, "\n");
02598   }
02599 
02600   fclose(fout);
02601 }
02602 
02604 //                                                                           //
02605 // save_edges()    Save egdes to a .edge file.                               //
02606 //                                                                           //
02607 // 'filename' is a string containing the file name without suffix.           //
02608 //                                                                           //
02610 
02611 void tetgenio::save_edges(char* filename)
02612 {
02613   FILE *fout;
02614   char outedgefilename[FILENAMESIZE];
02615   int i;
02616 
02617   sprintf(outedgefilename, "%s.edge", filename);
02618   printf("Saving edges to %s\n", outedgefilename);
02619   fout = fopen(outedgefilename, "w");
02620   fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02621   for (i = 0; i < numberofedges; i++) {
02622     fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
02623             edgelist[i * 2 + 1]);
02624     if (edgemarkerlist != NULL) {
02625       fprintf(fout, "  %d", edgemarkerlist[i]);
02626     }
02627     fprintf(fout, "\n");
02628   }
02629 
02630   fclose(fout);
02631 }
02632 
02634 //                                                                           //
02635 // save_neighbors()    Save egdes to a .neigh file.                          //
02636 //                                                                           //
02637 // 'filename' is a string containing the file name without suffix.           //
02638 //                                                                           //
02640 
02641 void tetgenio::save_neighbors(char* filename)
02642 {
02643   FILE *fout;
02644   char outneighborfilename[FILENAMESIZE];
02645   int i;
02646 
02647   sprintf(outneighborfilename, "%s.neigh", filename);
02648   printf("Saving neighbors to %s\n", outneighborfilename);
02649   fout = fopen(outneighborfilename, "w");
02650   fprintf(fout, "%d  %d\n", numberoftetrahedra, mesh_dim + 1);
02651   for (i = 0; i < numberoftetrahedra; i++) {
02652     if (mesh_dim == 2) {
02653       fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber,  neighborlist[i * 3],
02654               neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]);
02655     } else {
02656       fprintf(fout, "%d  %5d  %5d  %5d  %5d", i + firstnumber,
02657               neighborlist[i * 4], neighborlist[i * 4 + 1],
02658               neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]);
02659     }
02660     fprintf(fout, "\n");
02661   }
02662 
02663   fclose(fout);
02664 }
02665 
02667 //                                                                           //
02668 // save_poly()    Save segments or facets to a .poly file.                   //
02669 //                                                                           //
02670 // 'filename' is a string containing the file name without suffix.  It only  //
02671 // save the facets, holes and regions.  The nodes are saved in a .node file  //
02672 // by routine save_nodes().                                                  //
02673 //                                                                           //
02675 
02676 void tetgenio::save_poly(char* filename)
02677 {
02678   FILE *fout;
02679   facet *f;
02680   polygon *p;
02681   char outpolyfilename[FILENAMESIZE];
02682   int i, j, k;
02683 
02684   sprintf(outpolyfilename, "%s.poly", filename);
02685   printf("Saving poly to %s\n", outpolyfilename);
02686   fout = fopen(outpolyfilename, "w");
02687 
02688   // The zero indicates that the vertices are in a separate .node file.
02689   //   Followed by number of dimensions, number of vertex attributes,
02690   //   and number of boundary markers (zero or one).
02691   fprintf(fout, "%d  %d  %d  %d\n", 0, mesh_dim, numberofpointattributes,
02692           pointmarkerlist != NULL ? 1 : 0);
02693 
02694   // Save segments or facets.
02695   if (mesh_dim == 2) {
02696     // Number of segments, number of boundary markers (zero or one).
02697     fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02698     for (i = 0; i < numberofedges; i++) {
02699       fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
02700               edgelist[i * 2 + 1]);
02701       if (edgemarkerlist != NULL) {
02702         fprintf(fout, "  %d", edgemarkerlist[i]);
02703       }
02704       fprintf(fout, "\n");
02705     }
02706   } else {
02707     // Number of facets, number of boundary markers (zero or one).
02708     fprintf(fout, "%d  %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0);
02709     for (i = 0; i < numberoffacets; i++) {
02710       f = &(facetlist[i]);
02711       fprintf(fout, "%d  %d  %d  # %d\n", f->numberofpolygons,f->numberofholes,
02712             facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber);
02713       // Output polygons of this facet.
02714       for (j = 0; j < f->numberofpolygons; j++) {
02715         p = &(f->polygonlist[j]);
02716         fprintf(fout, "%d  ", p->numberofvertices);
02717         for (k = 0; k < p->numberofvertices; k++) {
02718           if (((k + 1) % 10) == 0) {
02719             fprintf(fout, "\n  ");
02720           }
02721           fprintf(fout, "  %d", p->vertexlist[k]);
02722         }
02723         fprintf(fout, "\n");
02724       }
02725       // Output holes of this facet.
02726       for (j = 0; j < f->numberofholes; j++) {
02727         fprintf(fout, "%d  %.12g  %.12g  %.12g\n", j + firstnumber,
02728            f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]);
02729       }
02730     }
02731   }
02732 
02733   // Save holes.
02734   fprintf(fout, "%d\n", numberofholes);
02735   for (i = 0; i < numberofholes; i++) {
02736     // Output x, y coordinates.
02737     fprintf(fout, "%d  %.12g  %.12g", i + firstnumber, holelist[i * mesh_dim],
02738             holelist[i * mesh_dim + 1]);
02739     if (mesh_dim == 3) {
02740       // Output z coordinate.
02741       fprintf(fout, "  %.12g", holelist[i * mesh_dim + 2]);
02742     }
02743     fprintf(fout, "\n");
02744   }
02745 
02746   // Save regions.
02747   fprintf(fout, "%d\n", numberofregions);
02748   for (i = 0; i < numberofregions; i++) {
02749     if (mesh_dim == 2) {
02750       // Output the index, x, y coordinates, attribute (region number)
02751       //   and maximum area constraint (maybe -1).
02752       fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
02753               regionlist[i * 4], regionlist[i * 4 + 1],
02754               regionlist[i * 4 + 2], regionlist[i * 4 + 3]);
02755     } else {
02756       // Output the index, x, y, z coordinates, attribute (region number)
02757       //   and maximum volume constraint (maybe -1).
02758       fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
02759               regionlist[i * 5], regionlist[i * 5 + 1],
02760               regionlist[i * 5 + 2], regionlist[i * 5 + 3],
02761               regionlist[i * 5 + 4]);
02762     }
02763   }
02764 
02765   fclose(fout);
02766 }
02767 
02769 //                                                                           //
02770 // readline()   Read a nonempty line from a file.                            //
02771 //                                                                           //
02772 // A line is considered "nonempty" if it contains something more than white  //
02773 // spaces.  If a line is considered empty, it will be dropped and the next   //
02774 // line will be read, this process ends until reaching the end-of-file or a  //
02775 // non-empty line.  Return NULL if it is the end-of-file, otherwise, return  //
02776 // a pointer to the first non-whitespace character of the line.              //
02777 //                                                                           //
02779 
02780 char* tetgenio::readline(char *string, FILE *infile, int *linenumber)
02781 {
02782   char *result;
02783 
02784   // Search for a non-empty line.
02785   do {
02786     result = fgets(string, INPUTLINESIZE - 1, infile);
02787     if (linenumber) (*linenumber)++;
02788     if (result == (char *) NULL) {
02789       return (char *) NULL;
02790     }
02791     // Skip white spaces.
02792     while ((*result == ' ') || (*result == '\t')) result++;
02793     // If it's end of line, read another line and try again.
02794   } while (*result == '\0');
02795   return result;
02796 }
02797 
02799 //                                                                           //
02800 // findnextfield()   Find the next field of a string.                        //
02801 //                                                                           //
02802 // Jumps past the current field by searching for whitespace or a comma, then //
02803 // jumps past the whitespace or the comma to find the next field.            //
02804 //                                                                           //
02806 
02807 char* tetgenio::findnextfield(char *string)
02808 {
02809   char *result;
02810 
02811   result = string;
02812   // Skip the current field.  Stop upon reaching whitespace or a comma.
02813   while ((*result != '\0') && (*result != ' ') &&  (*result != '\t') &&
02814          (*result != ',') && (*result != ';')) {
02815     result++;
02816   }
02817   // Now skip the whitespace or the comma, stop at anything else that looks
02818   //   like a character, or the end of a line.
02819   while ((*result == ' ') || (*result == '\t') || (*result == ',') ||
02820          (*result == ';')) {
02821     result++;
02822   }
02823   return result;
02824 }
02825 
02827 //                                                                           //
02828 // readnumberline()   Read a nonempty number line from a file.               //
02829 //                                                                           //
02830 // A line is considered "nonempty" if it contains something that looks like  //
02831 // a number.  Comments (prefaced by `#') are ignored.                        //
02832 //                                                                           //
02834 
02835 char* tetgenio::readnumberline(char *string, FILE *infile, char *infilename)
02836 {
02837   char *result;
02838 
02839   // Search for something that looks like a number.
02840   do {
02841     result = fgets(string, INPUTLINESIZE, infile);
02842     if (result == (char *) NULL) {
02843       if (infilename != (char *) NULL) {
02844         printf("  Error:  Unexpected end of file in %s.\n", infilename);
02845         terminatetetgen(1);
02846       }
02847       return result;
02848     }
02849     // Skip anything that doesn't look like a number, a comment,
02850     //   or the end of a line.
02851     while ((*result != '\0') && (*result != '#')
02852            && (*result != '.') && (*result != '+') && (*result != '-')
02853            && ((*result < '0') || (*result > '9'))) {
02854       result++;
02855     }
02856     // If it's a comment or end of line, read another line and try again.
02857   } while ((*result == '#') || (*result == '\0'));
02858   return result;
02859 }
02860 
02862 //                                                                           //
02863 // findnextnumber()   Find the next field of a number string.                //
02864 //                                                                           //
02865 // Jumps past the current field by searching for whitespace or a comma, then //
02866 // jumps past the whitespace or the comma to find the next field that looks  //
02867 // like a number.                                                            //
02868 //                                                                           //
02870 
02871 char* tetgenio::findnextnumber(char *string)
02872 {
02873   char *result;
02874 
02875   result = string;
02876   // Skip the current field.  Stop upon reaching whitespace or a comma.
02877   while ((*result != '\0') && (*result != '#') && (*result != ' ') &&
02878          (*result != '\t') && (*result != ',')) {
02879     result++;
02880   }
02881   // Now skip the whitespace and anything else that doesn't look like a
02882   //   number, a comment, or the end of a line.
02883   while ((*result != '\0') && (*result != '#')
02884          && (*result != '.') && (*result != '+') && (*result != '-')
02885          && ((*result < '0') || (*result > '9'))) {
02886     result++;
02887   }
02888   // Check for a comment (prefixed with `#').
02889   if (*result == '#') {
02890     *result = '\0';
02891   }
02892   return result;
02893 }
02894 
02895 //
02896 // End of class 'tetgenio' implementation
02897 //
02898 
02899 static REAL PI = 3.14159265358979323846264338327950288419716939937510582;
02900 
02901 //
02902 // Begin of class 'tetgenbehavior' implementation
02903 //
02904 
02906 //                                                                           //
02907 // tetgenbehavior()    Initialize veriables of 'tetgenbehavior'.             //
02908 //                                                                           //
02910 
02911 tetgenbehavior::tetgenbehavior()
02912 {
02913   // Initialize command line switches.
02914   plc = 0;
02915   quality = 0;
02916   refine = 0;
02917   coarse = 0;
02918   metric = 0;
02919   minratio = 2.0;
02920   goodratio = 0.0;
02921   minangle = 20.0;
02922   goodangle = 0.0;
02923   maxdihedral = 165.0;
02924   mindihedral = 5.0;
02925   varvolume = 0;
02926   fixedvolume = 0;
02927   maxvolume = -1.0;
02928   regionattrib = 0;
02929   insertaddpoints = 0;
02930   diagnose = 0;
02931   offcenter = 0;
02932   conformdel = 0;
02933   alpha1 = sqrt(2.0);
02934   alpha2 = 1.0;
02935   alpha3 = 0.6;
02936   zeroindex = 0;
02937   facesout = 0;
02938   edgesout = 0;
02939   neighout = 0;
02940   voroout = 0;
02941   meditview = 0;
02942   gidview = 0;
02943   geomview = 0;
02944   optlevel = 3;
02945   optpasses = 3;
02946   order = 1;
02947   nojettison = 0;
02948   nobound = 0;
02949   nonodewritten = 0;
02950   noelewritten = 0;
02951   nofacewritten = 0;
02952   noiterationnum = 0;
02953   nobisect = 0;
02954   noflip = 0;
02955   steiner = -1;
02956   fliprepair = 1;
02957   nomerge = 0;
02958   docheck = 0;
02959   quiet = 0;
02960   verbose = 0;
02961   useshelles = 0;
02962   epsilon = 1.0e-8;
02963   epsilon2 = 1.0e-5;
02964   object = NONE;
02965   // Initialize strings
02966   commandline[0] = '\0';
02967   infilename[0] = '\0';
02968   outfilename[0] = '\0';
02969   addinfilename[0] = '\0';
02970   bgmeshfilename[0] = '\0';
02971 }
02972 
02974 //                                                                           //
02975 // versioninfo()    Print the version information of TetGen.                 //
02976 //                                                                           //
02978 
02979 void tetgenbehavior::versioninfo()
02980 {
02981   printf("Version 1.4.2 (April 16, 2007).\n");
02982   printf("\n");
02983   printf("Copyright (C) 2002 - 2007\n");
02984   printf("Hang Si\n");
02985   printf("Mohrenstr. 39, 10117 Berlin, Germany\n");
02986   printf("si@wias-berlin.de\n");
02987 }
02988 
02990 //                                                                           //
02991 // syntax()    Print list of command line switches and exit the program.     //
02992 //                                                                           //
02994 
02995 void tetgenbehavior::syntax()
02996 {
02997   printf("  tetgen [-prq_Ra_AiMYS_T_dzo_fenvgGOJBNEFICQVh] input_file\n");
02998   printf("    -p  Tetrahedralizes a piecewise linear complex (PLC).\n");
02999   printf("    -r  Reconstructs a previously generated mesh.\n");
03000   printf("    -q  Quality mesh generation (adding new mesh points to ");
03001   printf("improve mesh quality).\n");
03002   printf("    -R  Mesh coarsening (deleting redundant mesh points).\n");
03003   printf("    -a  Applies a maximum tetrahedron volume constraint.\n");
03004   printf("    -A  Assigns attributes to identify tetrahedra in different ");
03005   printf("regions.\n");
03006   printf("    -i  Inserts a list of additional points into mesh.\n");
03007   printf("    -M  Does not merge coplanar facets.\n");
03008   printf("    -Y  Suppresses boundary facets/segments splitting.\n");
03009   printf("    -S  Specifies maximum number of added points.\n");
03010   printf("    -T  Sets a tolerance for coplanar test (default 1e-8).\n");
03011   printf("    -d  Detects self-intersections of facets of the PLC.\n");
03012   printf("    -z  Numbers all output items starting from zero.\n");
03013   printf("    -o2 Generates second-order subparametric elements.\n");
03014   printf("    -f  Outputs all faces to .face file.");
03015   printf("file.\n");
03016   printf("    -e  Outputs all edges to .edge file.\n");
03017   printf("    -n  Outputs tetrahedra neighbors to .neigh file.\n");
03018   printf("    -v  Outputs Voronoi diagram to files.\n");
03019   printf("    -g  Outputs mesh to .mesh file for viewing by Medit.\n");
03020   printf("    -G  Outputs mesh to .msh file for viewing by Gid.\n");
03021   printf("    -O  Outputs mesh to .off file for viewing by Geomview.\n");
03022   printf("    -J  No jettison of unused vertices from output .node file.\n");
03023   printf("    -B  Suppresses output of boundary information.\n");
03024   printf("    -N  Suppresses output of .node file.\n");
03025   printf("    -E  Suppresses output of .ele file.\n");
03026   printf("    -F  Suppresses output of .face file.\n");
03027   printf("    -I  Suppresses mesh iteration numbers.\n");
03028   printf("    -C  Checks the consistency of the final mesh.\n");
03029   printf("    -Q  Quiet:  No terminal output except errors.\n");
03030   printf("    -V  Verbose:  Detailed information, more terminal output.\n");
03031   printf("    -h  Help:  A brief instruction for using TetGen.\n");
03032 }
03033 
03035 //                                                                           //
03036 // usage()    Print a brief instruction for using TetGen.                    //
03037 //                                                                           //
03039 
03040 void tetgenbehavior::usage()
03041 {
03042   printf("TetGen\n");
03043   printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
03044   printf("Triangulator\n");
03045   versioninfo();
03046   printf("\n");
03047   printf("What Can TetGen Do?\n");
03048   printf("\n");
03049   printf("  TetGen generates exact Delaunay tetrahedralizations, exact\n");
03050   printf("  constrained Delaunay tetrahedralizations, and quality ");
03051   printf("tetrahedral\n  meshes. The latter are nicely graded and whose ");
03052   printf("tetrahedra have\n  radius-edge ratio bounded, thus are suitable ");
03053   printf("for finite element and\n  finite volume analysis.\n");
03054   printf("\n");
03055   printf("Command Line Syntax:\n");
03056   printf("\n");
03057   printf("  Below is the command line syntax of TetGen with a list of ");
03058   printf("short\n");
03059   printf("  descriptions. Underscores indicate that numbers may optionally\n");
03060   printf("  follow certain switches.  Do not leave any space between a ");
03061   printf("switch\n");
03062   printf("  and its numeric parameter.  \'input_file\' contains input data\n");
03063   printf("  depending on the switches you supplied which may be a ");
03064   printf("  piecewise\n");
03065   printf("  linear complex or a list of nodes.  File formats and detailed\n");
03066   printf("  description of command line switches are found in user's ");
03067   printf("manual.\n");
03068   printf("\n");
03069   syntax();
03070   printf("\n");
03071   printf("Examples of How to Use TetGen:\n");
03072   printf("\n");
03073   printf("  \'tetgen object\' reads vertices from object.node, and writes ");
03074   printf("their\n  Delaunay tetrahedralization to object.1.node and ");
03075   printf("object.1.ele.\n");
03076   printf("\n");
03077   printf("  \'tetgen -p object\' reads a PLC from object.poly or object.");
03078   printf("smesh (and\n  possibly object.node) and writes its constrained ");
03079   printf("Delaunay\n  tetrahedralization to object.1.node, object.1.ele and ");
03080   printf("object.1.face.\n");
03081   printf("\n");
03082   printf("  \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
03083   printf("  object.smesh (and possibly object.node), generates a mesh ");
03084   printf("whose\n  tetrahedra have radius-edge ratio smaller than 1.414 and ");
03085   printf("have volume\n  of 0.1 or less, and writes the mesh to ");
03086   printf("object.1.node, object.1.ele\n  and object.1.face.\n");
03087   printf("\n");
03088   printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
03089 }
03090 
03092 //                                                                           //
03093 // parse_commandline()    Read the command line, identify switches, and set  //
03094 //                        up options and file names.                         //
03095 //                                                                           //
03096 // 'argc' and 'argv' are the same parameters passed to the function main()   //
03097 // of a C/C++ program. They together represent the command line user invoked //
03098 // from an environment in which TetGen is running.                           //
03099 //                                                                           //
03100 // When TetGen is invoked from an environment. 'argc' is nonzero, switches   //
03101 // and input filename should be supplied as zero-terminated strings in       //
03102 // argv[0] through argv[argc - 1] and argv[0] shall be the name used to      //
03103 // invoke TetGen, i.e. "tetgen".  Switches are previously started with a     //
03104 // dash '-' to identify them from the input filename.                        //
03105 //                                                                           //
03106 // When TetGen is called from within another program. 'argc' is set to zero. //
03107 // switches are given in one zero-terminated string (no previous dash is     //
03108 // required.), and 'argv' is a pointer points to this string.  No input      //
03109 // filename is required (usually the input data has been directly created by //
03110 // user in the 'tetgenio' structure).  A default filename 'tetgen-tmpfile'   //
03111 // will be created for debugging output purpose.                             //
03112 //                                                                           //
03114 
03115 bool tetgenbehavior::parse_commandline(int argc, char **argv)
03116 {
03117   int startindex;
03118   int increment;
03119   int meshnumber;
03120   int scount;
03121   int i, j, k;
03122   char workstring[1024];
03123 
03124   // First determine the input style of the switches.
03125   if (argc == 0) {
03126     startindex = 0;                    // Switches are given without a dash.
03127     argc = 1;                    // For running the following for-loop once.
03128     commandline[0] = '\0';
03129   } else {
03130     startindex = 1;
03131     strcpy(commandline, argv[0]);
03132     strcat(commandline, " ");
03133   }
03134 
03135   // Rcount used to count the number of '-R' be used.
03136   scount = 0;
03137 
03138   for (i = startindex; i < argc; i++) {
03139     // Remember the command line switches.
03140     strcat(commandline, argv[i]);
03141     strcat(commandline, " ");
03142     if (startindex == 1) {
03143       // Is this string a filename?
03144       if (argv[i][0] != '-') {
03145         strncpy(infilename, argv[i], 1024 - 1);
03146         infilename[1024 - 1] = '\0';
03147         // Go to the next string directly.
03148         continue;
03149       }
03150     }
03151     // Parse the individual switch from the string.
03152     for (j = startindex; argv[i][j] != '\0'; j++) {
03153       if (argv[i][j] == 'p') {
03154         plc = 1;
03155       } else if (argv[i][j] == 'r') {
03156         refine = 1;
03157       } else if (argv[i][j] == 'R') {
03158         coarse = 1;
03159       } else if (argv[i][j] == 'q') {
03160         quality++;
03161         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03162             (argv[i][j + 1] == '.')) {
03163           k = 0;
03164           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03165                  (argv[i][j + 1] == '.')) {
03166             j++;
03167             workstring[k] = argv[i][j];
03168             k++;
03169           }
03170           workstring[k] = '\0';
03171           if (quality == 1) {
03172             minratio = (REAL) strtod(workstring, (char **) NULL);
03173           } else if (quality == 2) {
03174             mindihedral = (REAL) strtod(workstring, (char **) NULL);
03175           } else if (quality == 3) {
03176             maxdihedral = (REAL) strtod(workstring, (char **) NULL);
03177           } else if (quality == 4) {
03178             alpha2 = (REAL) strtod(workstring, (char **) NULL);
03179           } else if (quality == 5) {
03180             alpha1 = (REAL) strtod(workstring, (char **) NULL);
03181           }
03182         }
03183       } else if (argv[i][j] == 'm') {
03184         metric++;
03185         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03186             (argv[i][j + 1] == '.')) {
03187           k = 0;
03188           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03189                  (argv[i][j + 1] == '.')) {
03190             j++;
03191             workstring[k] = argv[i][j];
03192             k++;
03193           }
03194           workstring[k] = '\0';
03195           if (metric == 1) {
03196             alpha1 = (REAL) strtod(workstring, (char **) NULL);
03197           } else if (metric == 2) {
03198             alpha2 = (REAL) strtod(workstring, (char **) NULL);
03199           }
03200         }
03201       } else if (argv[i][j] == 'a') {
03202         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03203             (argv[i][j + 1] == '.')) {
03204           fixedvolume = 1;
03205           k = 0;
03206           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03207                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03208                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03209             j++;
03210             workstring[k] = argv[i][j];
03211             k++;
03212           }
03213           workstring[k] = '\0';
03214           maxvolume = (REAL) strtod(workstring, (char **) NULL);
03215         } else {
03216           varvolume = 1;
03217         }
03218       } else if (argv[i][j] == 'A') {
03219         regionattrib++;
03220       } else if (argv[i][j] == 'i') {
03221         insertaddpoints = 1;
03222       } else if (argv[i][j] == 'd') {
03223         diagnose = 1;
03224       } else if (argv[i][j] == 'z') {
03225         zeroindex = 1;
03226       } else if (argv[i][j] == 'f') {
03227         facesout = 1;
03228       } else if (argv[i][j] == 'e') {
03229         edgesout++;
03230       } else if (argv[i][j] == 'n') {
03231         neighout++;
03232       } else if (argv[i][j] == 'v') {
03233         voroout = 1;
03234       } else if (argv[i][j] == 'g') {
03235         meditview = 1;
03236       } else if (argv[i][j] == 'G') {
03237         gidview = 1;
03238       } else if (argv[i][j] == 'O') {
03239         geomview = 1;
03240       } else if (argv[i][j] == 'M') {
03241         nomerge = 1;
03242       } else if (argv[i][j] == 'Y') {
03243         nobisect++;
03244       } else if (argv[i][j] == 'J') {
03245         nojettison = 1;
03246       } else if (argv[i][j] == 'B') {
03247         nobound = 1;
03248       } else if (argv[i][j] == 'N') {
03249         nonodewritten = 1;
03250       } else if (argv[i][j] == 'E') {
03251         noelewritten = 1;
03252       } else if (argv[i][j] == 'F') {
03253         nofacewritten = 1;
03254       } else if (argv[i][j] == 'I') {
03255         noiterationnum = 1;
03256       } else if (argv[i][j] == 'o') {
03257         if (argv[i][j + 1] == '2') {
03258           j++;
03259           order = 2;
03260         }
03261       } else if (argv[i][j] == 'S') {
03262         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03263             (argv[i][j + 1] == '.')) {
03264           k = 0;
03265           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03266                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03267                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03268             j++;
03269             workstring[k] = argv[i][j];
03270             k++;
03271           }
03272           workstring[k] = '\0';
03273           steiner = (int) strtol(workstring, (char **) NULL, 0);
03274         }
03275       } else if (argv[i][j] == 's') {
03276         scount++;
03277         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03278             (argv[i][j + 1] == '.')) {
03279           k = 0;
03280           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03281                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03282                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03283             j++;
03284             workstring[k] = argv[i][j];
03285             k++;
03286           }
03287           workstring[k] = '\0';
03288           if (scount == 1) {
03289             optlevel = (int) strtol(workstring, (char **) NULL, 0);
03290           } else if (scount == 2) {
03291             optpasses = (int) strtol(workstring, (char **) NULL, 0);
03292           }
03293         }
03294       } else if (argv[i][j] == 'D') {
03295         conformdel++;
03296       } else if (argv[i][j] == 'T') {
03297         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03298             (argv[i][j + 1] == '.')) {
03299           k = 0;
03300           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03301                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03302                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03303             j++;
03304             workstring[k] = argv[i][j];
03305             k++;
03306           }
03307           workstring[k] = '\0';
03308           epsilon = (REAL) strtod(workstring, (char **) NULL);
03309         }
03310       } else if (argv[i][j] == 'C') {
03311         docheck++;
03312       } else if (argv[i][j] == 'X') {
03313         fliprepair = 0;
03314       } else if (argv[i][j] == 'Q') {
03315         quiet = 1;
03316       } else if (argv[i][j] == 'V') {
03317         verbose++;
03318       // } else if (argv[i][j] == 'v') {
03319         // versioninfo();
03320         // terminatetetgen(0);
03321       } else if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
03322                  (argv[i][j] == '?')) {
03323         usage();
03324         terminatetetgen(0);
03325       } else {
03326         printf("Warning:  Unknown switch -%c.\n", argv[i][j]);
03327       }
03328     }
03329   }
03330 
03331   if (startindex == 0) {
03332     // Set a temporary filename for debugging output.
03333     strcpy(infilename, "tetgen-tmpfile");
03334   } else {
03335     if (infilename[0] == '\0') {
03336       // No input file name. Print the syntax and exit.
03337       syntax();
03338       terminatetetgen(0);
03339     }
03340     // Recognize the object from file extension if it is available.
03341     if (!strcmp(&infilename[strlen(infilename) - 5], ".node")) {
03342       infilename[strlen(infilename) - 5] = '\0';
03343       object = NODES;
03344     } else if (!strcmp(&infilename[strlen(infilename) - 5], ".poly")) {
03345       infilename[strlen(infilename) - 5] = '\0';
03346       object = POLY;
03347       plc = 1;
03348     } else if (!strcmp(&infilename[strlen(infilename) - 6], ".smesh")) {
03349       infilename[strlen(infilename) - 6] = '\0';
03350       object = POLY;
03351       plc = 1;
03352     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".off")) {
03353       infilename[strlen(infilename) - 4] = '\0';
03354       object = OFF;
03355       plc = 1;
03356     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ply")) {
03357       infilename[strlen(infilename) - 4] = '\0';
03358       object = PLY;
03359       plc = 1;
03360     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".stl")) {
03361       infilename[strlen(infilename) - 4] = '\0';
03362       object = STL;
03363       plc = 1;
03364     } else if (!strcmp(&infilename[strlen(infilename) - 5], ".mesh")) {
03365       infilename[strlen(infilename) - 5] = '\0';
03366       object = MEDIT;
03367       plc = 1;
03368     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ele")) {
03369       infilename[strlen(infilename) - 4] = '\0';
03370       object = MESH;
03371       refine = 1;
03372     }
03373   }
03374   plc = plc || diagnose;
03375   useshelles = plc || refine || coarse || quality;
03376   goodratio = minratio;
03377   goodratio *= goodratio;
03378 
03379   // Detect improper combinations of switches.
03380   if (plc && refine) {
03381     printf("Error:  Switch -r cannot use together with -p.\n");
03382     return false;
03383   }
03384   if (refine && (plc || noiterationnum)) {
03385     printf("Error:  Switches %s cannot use together with -r.\n",
03386            "-p, -d, and -I");
03387     return false;
03388   }
03389   if (diagnose && (quality || insertaddpoints || (order == 2) || neighout
03390       || docheck)) {
03391     printf("Error:  Switches %s cannot use together with -d.\n",
03392            "-q, -i, -o2, -n, and -C");
03393     return false;
03394   }
03395 
03396   // Be careful not to allocate space for element area constraints that
03397   //   will never be assigned any value (other than the default -1.0).
03398   if (!refine && !plc) {
03399     varvolume = 0;
03400   }
03401   // Be careful not to add an extra attribute to each element unless the
03402   //   input supports it (PLC in, but not refining a preexisting mesh).
03403   if (refine || !plc) {
03404     regionattrib = 0;
03405   }
03406   // If '-a' or '-aa' is in use, enable '-q' option too.
03407   if (fixedvolume || varvolume) {
03408     if (quality == 0) {
03409       quality = 1;
03410     }
03411   }
03412   // Calculate the goodangle for testing bad subfaces.
03413   goodangle = cos(minangle * PI / 180.0);
03414   goodangle *= goodangle;
03415 
03416   increment = 0;
03417   strcpy(workstring, infilename);
03418   j = 1;
03419   while (workstring[j] != '\0') {
03420     if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
03421       increment = j + 1;
03422     }
03423     j++;
03424   }
03425   meshnumber = 0;
03426   if (increment > 0) {
03427     j = increment;
03428     do {
03429       if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
03430         meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
03431       } else {
03432         increment = 0;
03433       }
03434       j++;
03435     } while (workstring[j] != '\0');
03436   }
03437   if (noiterationnum) {
03438     strcpy(outfilename, infilename);
03439   } else if (increment == 0) {
03440     strcpy(outfilename, infilename);
03441     strcat(outfilename, ".1");
03442   } else {
03443     workstring[increment] = '%';
03444     workstring[increment + 1] = 'd';
03445     workstring[increment + 2] = '\0';
03446     sprintf(outfilename, workstring, meshnumber + 1);
03447   }
03448   // Additional input file name has the end ".a".
03449   strcpy(addinfilename, infilename);
03450   strcat(addinfilename, ".a");
03451   // Background filename has the form "*.b.ele", "*.b.node", ...
03452   strcpy(bgmeshfilename, infilename);
03453   strcat(bgmeshfilename, ".b");
03454 
03455   return true;
03456 }
03457 
03458 //
03459 // End of class 'tetgenbehavior' implementation
03460 //
03461 
03462 //
03463 // Begin of class 'tetgenmesh' implementation
03464 //
03465 
03466 //
03467 // Begin of class 'list', 'memorypool' and 'link' implementation
03468 //
03469 
03470 // Following are predefined compare functions for primitive data types.
03471 //   These functions take two pointers of the corresponding date type,
03472 //   perform the comparation. Return -1, 0 or 1 indicating the default
03473 //   linear order of two operators.
03474 
03475 // Compare two 'integers'.
03476 int tetgenmesh::compare_2_ints(const void* x, const void* y) {
03477   if (* (int *) x < * (int *) y) {
03478     return -1;
03479   } else if (* (int *) x > * (int *) y) {
03480     return 1;
03481   } else {
03482     return 0;
03483   }
03484 }
03485 
03486 // Compare two 'longs'.  Note: in 64-bit machine the 'long' type is 64-bit
03487 //   (8-byte) where the 'int' only 32-bit (4-byte).
03488 int tetgenmesh::compare_2_longs(const void* x, const void* y) {
03489   if (* (long *) x < * (long *) y) {
03490     return -1;
03491   } else if (* (long *) x > * (long *) y) {
03492     return 1;
03493   } else {
03494     return 0;
03495   }
03496 }
03497 
03498 // Compare two 'unsigned longs'.
03499 int tetgenmesh::compare_2_unsignedlongs(const void* x, const void* y) {
03500   if (* (unsigned long *) x < * (unsigned long *) y) {
03501     return -1;
03502   } else if (* (unsigned long *) x > * (unsigned long *) y) {
03503     return 1;
03504   } else {
03505     return 0;
03506   }
03507 }
03508 
03510 //                                                                           //
03511 // set_compfunc()    Determine the size of primitive data types and set the  //
03512 //                   corresponding predefined linear order functions.        //
03513 //                                                                           //
03514 // 'str' is a zero-end string indicating a primitive data type, like 'int',  //
03515 // 'long' or 'unsigned long'.  Every string ending with a '*' is though as a //
03516 // type of pointer and the type 'unsign long' is used for it.                //
03517 //                                                                           //
03518 // When the type of 'str' is determined, the size of this type (in byte) is  //
03519 // returned in 'itbytes', and the pointer of corresponding predefined linear //
03520 // order functions is returned in 'pcomp'.                                   //
03521 //                                                                           //
03523 
03524 void tetgenmesh::set_compfunc(char* str, int* itbytes, compfunc* pcomp)
03525 {
03526   // First figure out whether it is a pointer or not.
03527   if (str[strlen(str) - 1] == '*') {
03528     *itbytes = sizeof(unsigned long);
03529     *pcomp = &compare_2_unsignedlongs;
03530     return;
03531   }
03532   // Then determine other types.
03533   if (strcmp(str, "int") == 0) {
03534     *itbytes = sizeof(int);
03535     *pcomp = &compare_2_ints;
03536   } else if (strcmp(str, "long") == 0) {
03537     *itbytes = sizeof(long);
03538     *pcomp = &compare_2_longs;
03539   } else if (strcmp(str, "unsigned long") == 0) {
03540     *itbytes = sizeof(unsigned long);
03541     *pcomp = &compare_2_unsignedlongs;
03542   } else {
03543     // It is an unknown type.
03544     printf("Error in set_compfunc():  unknown type %s.\n", str);
03545     terminatetetgen(1);
03546   }
03547 }
03548 
03550 //                                                                           //
03551 // listinit()    Initialize a list for storing a data type.                  //
03552 //                                                                           //
03553 // Determine the size of each item, set the maximum size allocated at onece, //
03554 // set the expand size in case the list is full, and set the linear order    //
03555 // function if it is provided (default is NULL).                             //
03556 //                                                                           //
03558 
03559 void tetgenmesh::list::
03560 listinit(int itbytes, compfunc pcomp, int mitems,int exsize)
03561 {
03562 #ifdef SELF_CHECK
03563   assert(itbytes > 0 && mitems > 0 && exsize > 0);
03564 #endif
03565   itembytes = itbytes;
03566   comp = pcomp;
03567   maxitems = mitems;
03568   expandsize = exsize;
03569   base = (char *) malloc(maxitems * itembytes);
03570   if (base == (char *) NULL) {
03571     printf("Error:  Out of memory.\n");
03572     terminatetetgen(1);
03573   }
03574   items = 0;
03575 }
03576 
03578 //                                                                           //
03579 // append()    Add a new item at the end of the list.                        //
03580 //                                                                           //
03581 // A new space at the end of this list will be allocated for storing the new //
03582 // item. If the memory is not sufficient, reallocation will be performed. If //
03583 // 'appitem' is not NULL, the contents of this pointer will be copied to the //
03584 // new allocated space.  Returns the pointer to the new allocated space.     //
03585 //                                                                           //
03587 
03588 void* tetgenmesh::list::append(void *appitem)
03589 {
03590   // Do we have enough space?
03591   if (items == maxitems) {
03592     char* newbase = (char *) realloc(base, (maxitems + expandsize) *
03593                                      itembytes);
03594     if (newbase == (char *) NULL) {
03595       printf("Error:  Out of memory.\n");
03596       terminatetetgen(1);
03597     }
03598     base = newbase;
03599     maxitems += expandsize;
03600   }
03601   if (appitem != (void *) NULL) {
03602     memcpy(base + items * itembytes, appitem, itembytes);
03603   }
03604   items++;
03605   return (void *) (base + (items - 1) * itembytes);
03606 }
03607 
03609 //                                                                           //
03610 // insert()    Insert an item before 'pos' (range from 0 to items - 1).      //
03611 //                                                                           //
03612 // A new space will be inserted at the position 'pos', that is, items lie    //
03613 // after pos (including the item at pos) will be moved one space downwords.  //
03614 // If 'insitem' is not NULL, its contents will be copied into the new        //
03615 // inserted space. Return a pointer to the new inserted space.               //
03616 //                                                                           //
03618 
03619 void* tetgenmesh::list::insert(int pos, void* insitem)
03620 {
03621   if (pos >= items) {
03622     return append(insitem);
03623   }
03624   // Do we have enough space.
03625   if (items == maxitems) {
03626     char* newbase = (char *) realloc(base, (maxitems + expandsize) *
03627                                      itembytes);
03628     if (newbase == (char *) NULL) {
03629       printf("Error:  Out of memory.\n");
03630       terminatetetgen(1);
03631     }
03632     base = newbase;
03633     maxitems += expandsize;
03634   }
03635   // Do block move.
03636   memmove(base + (pos + 1) * itembytes,   // dest
03637           base + pos * itembytes,         // src
03638           (items - pos) * itembytes);     // size in bytes
03639   // Insert the item.
03640   if (insitem != (void *) NULL) {
03641     memcpy(base + pos * itembytes, insitem, itembytes);
03642   }
03643   items++;
03644   return (void *) (base + pos * itembytes);
03645 }
03646 
03648 //                                                                           //
03649 // del()    Delete an item at 'pos' (range from 0 to items - 1).             //
03650 //                                                                           //
03651 // The space at 'pos' will be overlapped by other item. If 'order' is 1, the //
03652 // remaining items of the list have the same order as usual, i.e., items lie //
03653 // after pos will be moved one space upwords. If 'order' is 0, the last item //
03654 // of the list will be moved up to pos.                                      //
03655 //                                                                           //
03657 
03658 void tetgenmesh::list::del(int pos, int order)
03659 {
03660   // If 'pos' is the last item of the list, nothing need to do.
03661   if (pos >= 0 && pos < items - 1) {
03662     if (order == 1) {
03663       // Do block move.
03664       memmove(base + pos * itembytes,       // dest
03665               base + (pos + 1) * itembytes, // src
03666               (items - pos - 1) * itembytes);
03667     } else {
03668       // Use the last item to overlap the del item.
03669       memcpy(base + pos * itembytes, // item at pos
03670              base + (items - 1) * itembytes, // item at last
03671              itembytes);
03672     }
03673   }
03674   if (items > 0) {
03675     items--;
03676   }
03677 }
03678 
03680 //                                                                           //
03681 // hasitem()    Search in this list to find if 'checkitem' exists.           //
03682 //                                                                           //
03683 // This routine assumes that a linear order function has been set.  It loops //
03684 // through the entire list, compares each item to 'checkitem'. If it exists, //
03685 // return its position (between 0 to items - 1), otherwise, return -1.       //
03686 //                                                                           //
03688 
03689 int tetgenmesh::list::hasitem(void* checkitem)
03690 {
03691   int i;
03692 
03693   for (i = 0; i < items; i++) {
03694     if (comp != (compfunc) NULL) {
03695       if ((* comp)((void *)(base + i * itembytes), checkitem) == 0) {
03696         return i;
03697       }
03698     }
03699   }
03700   return -1;
03701 }
03702 
03704 //                                                                           //
03705 // sort()    Sort the items with respect to a linear order function.         //
03706 //                                                                           //
03707 // Uses QuickSort routines (qsort) of the standard C/C++ library (stdlib.h). //
03708 //                                                                           //
03710 
03711 void tetgenmesh::list::sort()
03712 {
03713   qsort((void *) base, (size_t) items, (size_t) itembytes, comp);
03714 }
03715 
03717 //                                                                           //
03718 // memorypool()   The constructors of memorypool.                            //
03719 //                                                                           //
03721 
03722 tetgenmesh::memorypool::memorypool()
03723 {
03724   firstblock = nowblock = (void **) NULL;
03725   nextitem = (void *) NULL;
03726   deaditemstack = (void *) NULL;
03727   pathblock = (void **) NULL;
03728   pathitem = (void *) NULL;
03729   itemwordtype = POINTER;
03730   alignbytes = 0;
03731   itembytes = itemwords = 0;
03732   itemsperblock = 0;
03733   items = maxitems = 0l;
03734   unallocateditems = 0;
03735   pathitemsleft = 0;
03736 }
03737 
03738 tetgenmesh::memorypool::
03739 memorypool(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03740 {
03741   poolinit(bytecount, itemcount, wtype, alignment);
03742 }
03743 
03745 //                                                                           //
03746 // ~memorypool()   Free to the operating system all memory taken by a pool.  //
03747 //                                                                           //
03749 
03750 tetgenmesh::memorypool::~memorypool()
03751 {
03752   while (firstblock != (void **) NULL) {
03753     nowblock = (void **) *(firstblock);
03754     free(firstblock);
03755     firstblock = nowblock;
03756   }
03757 }
03758 
03760 //                                                                           //
03761 // poolinit()    Initialize a pool of memory for allocation of items.        //
03762 //                                                                           //
03763 // A `pool' is created whose records have size at least `bytecount'.  Items  //
03764 // will be allocated in `itemcount'-item blocks.  Each item is assumed to be //
03765 // a collection of words, and either pointers or floating-point values are   //
03766 // assumed to be the "primary" word type.  (The "primary" word type is used  //
03767 // to determine alignment of items.)  If `alignment' isn't zero, all items   //
03768 // will be `alignment'-byte aligned in memory.  `alignment' must be either a //
03769 // multiple or a factor of the primary word size;  powers of two are safe.   //
03770 // `alignment' is normally used to create a few unused bits at the bottom of //
03771 // each item's pointer, in which information may be stored.                  //
03772 //                                                                           //
03774 
03775 void tetgenmesh::memorypool::
03776 poolinit(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03777 {
03778   int wordsize;
03779 
03780   // Initialize values in the pool.
03781   itemwordtype = wtype;
03782   wordsize = (itemwordtype == POINTER) ? sizeof(void *) : sizeof(REAL);
03783   // Find the proper alignment, which must be at least as large as:
03784   //   - The parameter `alignment'.
03785   //   - The primary word type, to avoid unaligned accesses.
03786   //   - sizeof(void *), so the stack of dead items can be maintained
03787   //       without unaligned accesses.
03788   if (alignment > wordsize) {
03789     alignbytes = alignment;
03790   } else {
03791     alignbytes = wordsize;
03792   }
03793   if ((int) sizeof(void *) > alignbytes) {
03794     alignbytes = (int) sizeof(void *);
03795   }
03796   itemwords = ((bytecount + alignbytes - 1) /  alignbytes)
03797             * (alignbytes / wordsize);
03798   itembytes = itemwords * wordsize;
03799   itemsperblock = itemcount;
03800 
03801   // Allocate a block of items.  Space for `itemsperblock' items and one
03802   //   pointer (to point to the next block) are allocated, as well as space
03803   //   to ensure alignment of the items.
03804   firstblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *)
03805                                 + alignbytes);
03806   if (firstblock == (void **) NULL) {
03807     printf("Error:  Out of memory.\n");
03808     terminatetetgen(1);
03809   }
03810   // Set the next block pointer to NULL.
03811   *(firstblock) = (void *) NULL;
03812   restart();
03813 }
03814 
03816 //                                                                           //
03817 // restart()   Deallocate all items in this pool.                            //
03818 //                                                                           //
03819 // The pool is returned to its starting state, except that no memory is      //
03820 // freed to the operating system.  Rather, the previously allocated blocks   //
03821 // are ready to be reused.                                                   //
03822 //                                                                           //
03824 
03825 void tetgenmesh::memorypool::restart()
03826 {
03827   unsigned long alignptr;
03828 
03829   items = 0;
03830   maxitems = 0;
03831 
03832   // Set the currently active block.
03833   nowblock = firstblock;
03834   // Find the first item in the pool.  Increment by the size of (void *).
03835   alignptr = (unsigned long) (nowblock + 1);
03836   // Align the item on an `alignbytes'-byte boundary.
03837   nextitem = (void *)
03838     (alignptr + (unsigned long) alignbytes -
03839      (alignptr % (unsigned long) alignbytes));
03840   // There are lots of unallocated items left in this block.
03841   unallocateditems = itemsperblock;
03842   // The stack of deallocated items is empty.
03843   deaditemstack = (void *) NULL;
03844 }
03845 
03847 //                                                                           //
03848 // alloc()   Allocate space for an item.                                     //
03849 //                                                                           //
03851 
03852 void* tetgenmesh::memorypool::alloc()
03853 {
03854   void *newitem;
03855   void **newblock;
03856   unsigned long alignptr;
03857 
03858   // First check the linked list of dead items.  If the list is not
03859   //   empty, allocate an item from the list rather than a fresh one.
03860   if (deaditemstack != (void *) NULL) {
03861     newitem = deaditemstack;                     // Take first item in list.
03862     deaditemstack = * (void **) deaditemstack;
03863   } else {
03864     // Check if there are any free items left in the current block.
03865     if (unallocateditems == 0) {
03866       // Check if another block must be allocated.
03867       if (*nowblock == (void *) NULL) {
03868         // Allocate a new block of items, pointed to by the previous block.
03869         newblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *)
03870                                     + alignbytes);
03871         if (newblock == (void **) NULL) {
03872           printf("Error:  Out of memory.\n");
03873           terminatetetgen(1);
03874         }
03875         *nowblock = (void *) newblock;
03876         // The next block pointer is NULL.
03877         *newblock = (void *) NULL;
03878       }
03879       // Move to the new block.
03880       nowblock = (void **) *nowblock;
03881       // Find the first item in the block.
03882       //   Increment by the size of (void *).
03883       alignptr = (unsigned long) (nowblock + 1);
03884       // Align the item on an `alignbytes'-byte boundary.
03885       nextitem = (void *)
03886         (alignptr + (unsigned long) alignbytes -
03887          (alignptr % (unsigned long) alignbytes));
03888       // There are lots of unallocated items left in this block.
03889       unallocateditems = itemsperblock;
03890     }
03891     // Allocate a new item.
03892     newitem = nextitem;
03893     // Advance `nextitem' pointer to next free item in block.
03894     if (itemwordtype == POINTER) {
03895       nextitem = (void *) ((void **) nextitem + itemwords);
03896     } else {
03897       nextitem = (void *) ((REAL *) nextitem + itemwords);
03898     }
03899     unallocateditems--;
03900     maxitems++;
03901   }
03902   items++;
03903   return newitem;
03904 }
03905 
03907 //                                                                           //
03908 // dealloc()   Deallocate space for an item.                                 //
03909 //                                                                           //
03910 // The deallocated space is stored in a queue for later reuse.               //
03911 //                                                                           //
03913 
03914 void tetgenmesh::memorypool::dealloc(void *dyingitem)
03915 {
03916   // Push freshly killed item onto stack.
03917   *((void **) dyingitem) = deaditemstack;
03918   deaditemstack = dyingitem;
03919   items--;
03920 }
03921 
03923 //                                                                           //
03924 // traversalinit()   Prepare to traverse the entire list of items.           //
03925 //                                                                           //
03926 // This routine is used in conjunction with traverse().                      //
03927 //                                                                           //
03929 
03930 void tetgenmesh::memorypool::traversalinit()
03931 {
03932   unsigned long alignptr;
03933 
03934   // Begin the traversal in the first block.
03935   pathblock = firstblock;
03936   // Find the first item in the block.  Increment by the size of (void *).
03937   alignptr = (unsigned long) (pathblock + 1);
03938   // Align with item on an `alignbytes'-byte boundary.
03939   pathitem = (void *)
03940     (alignptr + (unsigned long) alignbytes -
03941      (alignptr % (unsigned long) alignbytes));
03942   // Set the number of items left in the current block.
03943   pathitemsleft = itemsperblock;
03944 }
03945 
03947 //                                                                           //
03948 // traverse()   Find the next item in the list.                              //
03949 //                                                                           //
03950 // This routine is used in conjunction with traversalinit().  Be forewarned  //
03951 // that this routine successively returns all items in the list, including   //
03952 // deallocated ones on the deaditemqueue. It's up to you to figure out which //
03953 // ones are actually dead.  It can usually be done more space-efficiently by //
03954 // a routine that knows something about the structure of the item.           //
03955 //                                                                           //
03957 
03958 void* tetgenmesh::memorypool::traverse()
03959 {
03960   void *newitem;
03961   unsigned long alignptr;
03962 
03963   // Stop upon exhausting the list of items.
03964   if (pathitem == nextitem) {
03965     return (void *) NULL;
03966   }
03967   // Check whether any untraversed items remain in the current block.
03968   if (pathitemsleft == 0) {
03969     // Find the next block.
03970     pathblock = (void **) *pathblock;
03971     // Find the first item in the block.  Increment by the size of (void *).
03972     alignptr = (unsigned long) (pathblock + 1);
03973     // Align with item on an `alignbytes'-byte boundary.
03974     pathitem = (void *)
03975       (alignptr + (unsigned long) alignbytes -
03976        (alignptr % (unsigned long) alignbytes));
03977     // Set the number of items left in the current block.
03978     pathitemsleft = itemsperblock;
03979   }
03980   newitem = pathitem;
03981   // Find the next item in the block.
03982   if (itemwordtype == POINTER) {
03983     pathitem = (void *) ((void **) pathitem + itemwords);
03984   } else {
03985     pathitem = (void *) ((REAL *) pathitem + itemwords);
03986   }
03987   pathitemsleft--;
03988   return newitem;
03989 }
03990 
03992 //                                                                           //
03993 // linkinit()    Initialize a link for storing items.                        //
03994 //                                                                           //
03995 // The input parameters are the size of each item, a pointer of a linear     //
03996 // order function and the number of items allocating in one memory bulk.     //
03997 //                                                                           //
03999 
04000 void tetgenmesh::link::linkinit(int bytecount, compfunc pcomp, int itemcount)
04001 {
04002 #ifdef SELF_CHECK
04003   assert(bytecount > 0 && itemcount > 0);
04004 #endif
04005   // Remember the real size of each item.
04006   linkitembytes = bytecount;
04007   // Set the linear order function for this link.
04008   comp = pcomp;
04009 
04010   // Call the constructor of 'memorypool' to initialize its variables.
04011   //   like: itembytes, itemwords, items, ... Each node has size
04012   //   bytecount + 2 * sizeof(void **), and total 'itemcount + 2' (because
04013   //   link has additional two nodes 'head' and 'tail').
04014   poolinit(bytecount + 2 * sizeof(void **), itemcount + 2, POINTER, 0);
04015 
04016   // Initial state of this link.
04017   head = (void **) alloc();
04018   tail = (void **) alloc();
04019   *head = (void *) tail;
04020   *(head + 1) = NULL;
04021   *tail = NULL;
04022   *(tail + 1) = (void *) head;
04023   nextlinkitem = *head;
04024   curpos = 1;
04025   linkitems = 0;
04026 }
04027 
04029 //                                                                           //
04030 // clear()   Deallocate all nodes in this link.                              //
04031 //                                                                           //
04032 // The link is returned to its starting state, except that no memory is      //
04033 // freed to the operating system.  Rather, the previously allocated blocks   //
04034 // are ready to be reused.                                                   //
04035 //                                                                           //
04037 
04038 void tetgenmesh::link::clear()
04039 {
04040   // Reset the pool.
04041   restart();
04042 
04043   // Initial state of this link.
04044   head = (void **) alloc();
04045   tail = (void **) alloc();
04046   *head = (void *) tail;
04047   *(head + 1) = NULL;
04048   *tail = NULL;
04049   *(tail + 1) = (void *) head;
04050   nextlinkitem = *head;
04051   curpos = 1;
04052   linkitems = 0;
04053 }
04054 
04056 //                                                                           //
04057 // move()    Causes 'nextlinkitem' to traverse the specified number of nodes,//
04058 //           updates 'curpos' to be the node to which 'nextlinkitem' points. //
04059 //                                                                           //
04060 // 'numberofnodes' is a number indicating how many nodes need be traversed   //
04061 // (not counter the current node) need be traversed. It may be positive(move //
04062 // forward) or negative (move backward).  Return TRUE if it is successful.   //
04063 //                                                                           //
04065 
04066 bool tetgenmesh::link::move(int numberofnodes)
04067 {
04068   void **nownode;
04069   int i;
04070 
04071   nownode = (void **) nextlinkitem;
04072   if (numberofnodes > 0) {
04073     // Move forward.
04074     i = 0;
04075     while ((i < numberofnodes) && *nownode) {
04076       nownode = (void **) *nownode;
04077       i++;
04078     }
04079     if (*nownode == NULL) return false;
04080     nextlinkitem = (void *) nownode;
04081     curpos += numberofnodes;
04082   } else if (numberofnodes < 0) {
04083     // Move backward.
04084     i = 0;
04085     numberofnodes = -numberofnodes;
04086     while ((i < numberofnodes) && *(nownode + 1)) {
04087       nownode = (void **) *(nownode + 1);
04088       i++;
04089     }
04090     if (*(nownode + 1) == NULL) return false;
04091     nextlinkitem = (void *) nownode;
04092     curpos -= numberofnodes;
04093   }
04094   return true;
04095 }
04096 
04098 //                                                                           //
04099 // locate()    Locates the node at the specified position.                   //
04100 //                                                                           //
04101 // The number 'pos' (between 1 and 'linkitems') indicates the location. This //
04102 // routine first decides the shortest path traversing from 'curpos' to 'pos',//
04103 // i.e., from head, tail or 'curpos'.   Routine 'move()' is called to really //
04104 // traverse the link. If success, 'nextlinkitem' points to the node, 'curpos'//
04105 // and 'pos' are equal. Otherwise, return FALSE.                             //
04106 //                                                                           //
04108 
04109 bool tetgenmesh::link::locate(int pos)
04110 {
04111   int headdist, taildist, curdist;
04112   int abscurdist, mindist;
04113 
04114   if (pos < 1 || pos > linkitems) return false;
04115 
04116   headdist = pos - 1;
04117   taildist = linkitems - pos;
04118   curdist = pos - curpos;
04119   abscurdist = curdist >= 0 ? curdist : -curdist;
04120 
04121   if (headdist > taildist) {
04122     if (taildist > abscurdist) {
04123       mindist = curdist;
04124     } else {
04125       // taildist <= abs(curdist)
04126       mindist = -taildist;
04127       goend();
04128     }
04129   } else {
04130     // headdist <= taildist
04131     if (headdist > abscurdist) {
04132       mindist = curdist;
04133     } else {
04134       // headdist <= abs(curdist)
04135       mindist = headdist;
04136       rewind();
04137     }
04138   }
04139 
04140   return move(mindist);
04141 }
04142 
04144 //                                                                           //
04145 // add()    Add a node at the end of this link.                              //
04146 //                                                                           //
04147 // A new node is appended to the end of the link.  If 'newitem' is not NULL, //
04148 // its conents will be copied to the data slot of the new node. Returns the  //
04149 // pointer to the newest added node.                                         //
04150 //                                                                           //
04152 
04153 void* tetgenmesh::link::add(void* newitem)
04154 {
04155   void **newnode = tail;
04156   if (newitem != (void *) NULL) {
04157     memcpy((void *)(newnode + 2), newitem, linkitembytes);
04158   }
04159   tail = (void **) alloc();
04160   *tail = NULL;
04161   *newnode = (void*) tail;
04162   *(tail + 1) = (void*) newnode;
04163   linkitems++;
04164   return (void *)(newnode + 2);
04165 }
04166 
04168 //                                                                           //
04169 // insert()    Inserts a node before the specified position.                 //
04170 //                                                                           //
04171 // 'pos' (between 1 and 'linkitems') indicates the inserting position.  This //
04172 // routine inserts a new node before the node of 'pos'.  If 'newitem' is not //
04173 // NULL,  its conents will be copied into the data slot of the new node.  If //
04174 // 'pos' is larger than 'linkitems', it is equal as 'add()'.  A pointer to   //
04175 // the newest inserted item is returned.                                     //
04176 //                                                                           //
04178 
04179 void* tetgenmesh::link::insert(int pos, void* insitem)
04180 {
04181   if (!locate(pos)) {
04182     return add(insitem);
04183   }
04184 
04185   void **nownode = (void **) nextlinkitem;
04186 
04187   // Insert a node before 'nownode'.
04188   void **newnode = (void **) alloc();
04189   if (insitem != (void *) NULL) {
04190     memcpy((void *)(newnode + 2), insitem, linkitembytes);
04191   }
04192 
04193   *(void **)(*(nownode + 1)) = (void *) newnode;
04194   *newnode = (void *) nownode;
04195   *(newnode + 1) = *(nownode + 1);
04196   *(nownode + 1) = (void *) newnode;
04197 
04198   linkitems++;
04199 
04200   nextlinkitem = (void *) newnode;
04201   return (void *)(newnode + 2);
04202 }
04203 
04205 //                                                                           //
04206 // del()    Delete a node.                                                   //
04207 //                                                                           //
04208 // Returns a pointer of the deleted data. If you try to delete a non-existed //
04209 // node (e.g. link is empty or a wrong index is given) return NULL.          //
04210 //                                                                           //
04212 
04213 void* tetgenmesh::link::deletenode(void** deadnode)
04214 {
04215   void **nextnode = (void **) *deadnode;
04216   void **prevnode = (void **) *(deadnode + 1);
04217   *prevnode = (void *) nextnode;
04218   *(nextnode + 1) = (void *) prevnode;
04219 
04220   dealloc((void *) deadnode);
04221   linkitems--;
04222 
04223   nextlinkitem = (void *) nextnode;
04224   return (void *)(deadnode + 2);
04225 }
04226 
04228 //                                                                           //
04229 // del()    Delete a node at the specified position.                         //
04230 //                                                                           //
04231 // 'pos' between 1 and 'linkitems'.  Returns a pointer of the deleted data.  //
04232 // If you try to delete a non-existed node (e.g. link is empty or a wrong    //
04233 // index is given) return NULL.                                              //
04234 //                                                                           //
04236 
04237 void* tetgenmesh::link::del(int pos)
04238 {
04239   if (!locate(pos) || (linkitems == 0)) {
04240     return (void *) NULL;
04241   }
04242   return deletenode((void **) nextlinkitem);
04243 }
04244 
04246 //                                                                           //
04247 // getitem()    The link traversal routine.                                  //
04248 //                                                                           //
04249 // Returns the node to which 'nextlinkitem' points. Returns a 'NULL' if the  //
04250 // end of the link is reaching.  Both 'nextlinkitem' and 'curpos' will be    //
04251 // updated after this operation.                                             //
04252 //                                                                           //
04254 
04255 void* tetgenmesh::link::getitem()
04256 {
04257   if (nextlinkitem == (void *) tail) return NULL;
04258   void **nownode = (void **) nextlinkitem;
04259   nextlinkitem = *nownode;
04260   curpos += 1;
04261   return (void *)(nownode + 2);
04262 }
04263 
04265 //                                                                           //
04266 // getnitem()    Returns the node at a specified position.                   //
04267 //                                                                           //
04268 // 'pos' between 1 and 'linkitems'. After this operation, 'nextlinkitem' and //
04269 // 'curpos' will be updated to indicate this node.                           //
04270 //                                                                           //
04272 
04273 void* tetgenmesh::link::getnitem(int pos)
04274 {
04275   if (!locate(pos)) return NULL;
04276   return (void *)((void **) nextlinkitem + 2);
04277 }
04278 
04280 //                                                                           //
04281 // hasitem()    Search in this link to find if 'checkitem' exists.           //
04282 //                                                                           //
04283 // If 'checkitem' exists, return its position (between 1 to 'linkitems'),    //
04284 // otherwise, return -1. This routine requires the linear order function has //
04285 // been set.                                                                 //
04286 //                                                                           //
04288 
04289 int tetgenmesh::link::hasitem(void* checkitem)
04290 {
04291   void *pathitem;
04292   int count;
04293 
04294   rewind();
04295   pathitem = getitem();
04296   count = 0;
04297   while (pathitem) {
04298     count ++;
04299     if (comp) {
04300       if ((* comp)(pathitem, checkitem) == 0) {
04301         return count;
04302       }
04303     }
04304     pathitem = getitem();
04305   }
04306   return -1;
04307 }
04308 
04309 //
04310 // End of class 'list', 'memorypool' and 'link' implementation
04311 //
04312 
04313 //
04314 // Begin of mesh manipulation primitives
04315 //
04316 
04317 //
04318 // Begin of tables initialization.
04319 //
04320 
04321 // For enumerating three edges of a triangle.
04322 
04323 int tetgenmesh::plus1mod3[3] = {1, 2, 0};
04324 int tetgenmesh::minus1mod3[3] = {2, 0, 1};
04325 
04326 // Table 've' takes an edge version as input, returns the next edge version
04327 //   in the same edge ring.
04328 
04329 int tetgenmesh::ve[6] = { 2, 5, 4, 1, 0, 3 };
04330 
04331 // Tables 'vo', 'vd' and 'va' take an edge version, return the positions of
04332 //   the origin, destination and apex in the triangle.
04333 
04334 int tetgenmesh::vo[6] = { 0, 1, 1, 2, 2, 0 };
04335 int tetgenmesh::vd[6] = { 1, 0, 2, 1, 0, 2 };
04336 int tetgenmesh::va[6] = { 2, 2, 0, 0, 1, 1 };
04337 
04338 // The following tables are for tetrahedron primitives (operate on trifaces).
04339 
04340 // For 'org()', 'dest()' and 'apex()'.  Use 'loc' as the first index and
04341 //   'ver' as the second index.
04342 
04343 int tetgenmesh::locver2org[4][6]  = {
04344   {0, 1, 1, 2, 2, 0},
04345   {0, 3, 3, 1, 1, 0},
04346   {1, 3, 3, 2, 2, 1},
04347   {2, 3, 3, 0, 0, 2}
04348 };
04349 int tetgenmesh::locver2dest[4][6] = {
04350   {1, 0, 2, 1, 0, 2},
04351   {3, 0, 1, 3, 0, 1},
04352   {3, 1, 2, 3, 1, 2},
04353   {3, 2, 0, 3, 2, 0}
04354 };
04355 int tetgenmesh::locver2apex[4][6] = {
04356   {2, 2, 0, 0, 1, 1},
04357   {1, 1, 0, 0, 3, 3},
04358   {2, 2, 1, 1, 3, 3},
04359   {0, 0, 2, 2, 3, 3}
04360 };
04361 
04362 // For oppo() primitives, use 'loc' as the index.
04363 
04364 int tetgenmesh::loc2oppo[4] = { 3, 2, 0, 1 };
04365 
04366 // For fnext() primitive.  Use 'loc' as the first index and 'ver' as the
04367 //   second index. Returns a new 'loc' and new 'ver' in an array. (It is
04368 //   only valid for edge version equals one of {0, 2, 4}.)
04369 
04370 int tetgenmesh::locver2nextf[4][6][2] = {
04371   { {1, 5}, {-1, -1}, {2, 5}, {-1, -1}, {3, 5}, {-1, -1} },
04372   { {3, 3}, {-1, -1}, {2, 1}, {-1, -1}, {0, 1}, {-1, -1} },
04373   { {1, 3}, {-1, -1}, {3, 1}, {-1, -1}, {0, 3}, {-1, -1} },
04374   { {2, 3}, {-1, -1}, {1, 1}, {-1, -1}, {0, 5}, {-1, -1} }
04375 };
04376 
04377 // The edge number (from 0 to 5) of a tet is defined as follows:
04378 //   0 - (v0, v1), 1 - (v1, v2), 2 - (v2, v0)
04379 //   3 - (v3, v0), 4 - (v3, v1), 5 - (v3, v2).
04380 
04381 int tetgenmesh::locver2edge[4][6] = {
04382   {0, 0, 1, 1, 2, 2},
04383   {3, 3, 4, 4, 0, 0},
04384   {4, 4, 5, 5, 1, 1},
04385   {5, 5, 3, 3, 2, 2}
04386 };
04387 
04388 int tetgenmesh::edge2locver[6][2] = {
04389   {0, 0}, // 0  v0 -> v1
04390   {0, 2}, // 1  v1 -> v2
04391   {0, 4}, // 2  v2 -> v1
04392   {1, 0}, // 3  v0 -> v3
04393   {1, 2}, // 4  v1 -> v3
04394   {2, 2}  // 5  v2 -> v3
04395 };
04396 
04397 //
04398 // End of tables initialization.
04399 //
04400 
04401 // Some macros for convenience
04402 
04403 #define Div2  >> 1
04404 #define Mod2  & 01
04405 
04406 // NOTE: These bit operators should only be used in macros below.
04407 
04408 // Get orient(Range from 0 to 2) from face version(Range from 0 to 5).
04409 
04410 #define Orient(V)   ((V) Div2)
04411 
04412 // Determine edge ring(0 or 1) from face version(Range from 0 to 5).
04413 
04414 #define EdgeRing(V) ((V) Mod2)
04415 
04416 //
04417 // Begin of primitives for tetrahedra
04418 //
04419 
04420 // Each tetrahedron contains four pointers to its neighboring tetrahedra,
04421 //   with face indices.  To save memory, both information are kept in a
04422 //   single pointer. To make this possible, all tetrahedra are aligned to
04423 //   eight-byte boundaries, so that the last three bits of each pointer are
04424 //   zeros. A face index (in the range 0 to 3) is compressed into the last
04425 //   two bits of each pointer by the function 'encode()'.  The function
04426 //   'decode()' decodes a pointer, extracting a face index and a pointer to
04427 //   the beginning of a tetrahedron.
04428 
04429 inline void tetgenmesh::decode(tetrahedron ptr, triface& t) {
04430   t.loc = (int) ((unsigned long) (ptr) & (unsigned long) 3l);
04431   t.tet = (tetrahedron *) ((unsigned long) (ptr) & ~(unsigned long) 7l);
04432 }
04433 
04434 inline tetgenmesh::tetrahedron tetgenmesh::encode(triface& t) {
04435   return (tetrahedron) ((unsigned long) t.tet | (unsigned long) t.loc);
04436 }
04437 
04438 // sym() finds the abutting tetrahedron on the same face.
04439 
04440 inline void tetgenmesh::sym(triface& t1, triface& t2) {
04441   tetrahedron ptr = t1.tet[t1.loc];
04442   decode(ptr, t2);
04443 }
04444 
04445 inline void tetgenmesh::symself(triface& t) {
04446   tetrahedron ptr = t.tet[t.loc];
04447   decode(ptr, t);
04448 }
04449 
04450 // Bond two tetrahedra together at their faces.
04451 
04452 inline void tetgenmesh::bond(triface& t1, triface& t2) {
04453   t1.tet[t1.loc] = encode(t2);
04454   t2.tet[t2.loc] = encode(t1);
04455 }
04456 
04457 // Dissolve a bond (from one side).  Note that the other tetrahedron will
04458 //   still think it is connected to this tetrahedron.  Usually, however,
04459 //   the other tetrahedron is being deleted entirely, or bonded to another
04460 //   tetrahedron, so it doesn't matter.
04461 
04462 inline void tetgenmesh::dissolve(triface& t) {
04463   t.tet[t.loc] = (tetrahedron) dummytet;
04464 }
04465 
04466 // These primitives determine or set the origin, destination, apex or
04467 //   opposition of a tetrahedron with respect to 'loc' and 'ver'.
04468 
04469 inline tetgenmesh::point tetgenmesh::org(triface& t) {
04470   return (point) t.tet[locver2org[t.loc][t.ver] + 4];
04471 }
04472 
04473 inline tetgenmesh::point tetgenmesh::dest(triface& t) {
04474   return (point) t.tet[locver2dest[t.loc][t.ver] + 4];
04475 }
04476 
04477 inline tetgenmesh::point tetgenmesh::apex(triface& t) {
04478   return (point) t.tet[locver2apex[t.loc][t.ver] + 4];
04479 }
04480 
04481 inline tetgenmesh::point tetgenmesh::oppo(triface& t) {
04482   return (point) t.tet[loc2oppo[t.loc] + 4];
04483 }
04484 
04485 inline void tetgenmesh::setorg(triface& t, point pointptr) {
04486   t.tet[locver2org[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04487 }
04488 
04489 inline void tetgenmesh::setdest(triface& t, point pointptr) {
04490   t.tet[locver2dest[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04491 }
04492 
04493 inline void tetgenmesh::setapex(triface& t, point pointptr) {
04494   t.tet[locver2apex[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04495 }
04496 
04497 inline void tetgenmesh::setoppo(triface& t, point pointptr) {
04498   t.tet[loc2oppo[t.loc] + 4] = (tetrahedron) pointptr;
04499 }
04500 
04501 // These primitives were drived from Mucke's triangle-edge data structure
04502 //   to change face-edge relation in a tetrahedron (esym, enext and enext2)
04503 //   or between two tetrahedra (fnext).
04504 
04505 // If e0 = e(i, j), e1 = e(j, i), that is e0 and e1 are the two directions
04506 //   of the same undirected edge of a face. e0.sym() = e1 and vice versa.
04507 
04508 inline void tetgenmesh::esym(triface& t1, triface& t2) {
04509   t2.tet = t1.tet;
04510   t2.loc = t1.loc;
04511   t2.ver = t1.ver + (EdgeRing(t1.ver) ? -1 : 1);
04512 }
04513 
04514 inline void tetgenmesh::esymself(triface& t) {
04515   t.ver += (EdgeRing(t.ver) ? -1 : 1);
04516 }
04517 
04518 // If e0 and e1 are both in the same edge ring of a face, e1 = e0.enext().
04519 
04520 inline void tetgenmesh::enext(triface& t1, triface& t2) {
04521   t2.tet = t1.tet;
04522   t2.loc = t1.loc;
04523   t2.ver = ve[t1.ver];
04524 }
04525 
04526 inline void tetgenmesh::enextself(triface& t) {
04527   t.ver = ve[t.ver];
04528 }
04529 
04530 // enext2() is equal to e2 = e0.enext().enext()
04531 
04532 inline void tetgenmesh::enext2(triface& t1, triface& t2) {
04533   t2.tet = t1.tet;
04534   t2.loc = t1.loc;
04535   t2.ver = ve[ve[t1.ver]];
04536 }
04537 
04538 inline void tetgenmesh::enext2self(triface& t) {
04539   t.ver = ve[ve[t.ver]];
04540 }
04541 
04542 // If f0 and f1 are both in the same face ring of a face, f1 = f0.fnext().
04543 //   If f1 exists, return true. Otherwise, return false, i.e., f0 is a
04544 //   boundary or hull face.
04545 
04546 inline bool tetgenmesh::fnext(triface& t1, triface& t2)
04547 {
04548   // Get the next face.
04549   t2.loc = locver2nextf[t1.loc][t1.ver][0];
04550   // Is the next face in the same tet?
04551   if (t2.loc != -1) {
04552     // It's in the same tet. Get the edge version.
04553     t2.ver = locver2nextf[t1.loc][t1.ver][1];
04554     t2.tet = t1.tet;
04555   } else {
04556     // The next face is in the neigbhour of 't1'.
04557     sym(t1, t2);
04558     if (t2.tet != dummytet) {
04559       // Find the corresponding edge in t2.
04560       point torg;
04561       int tloc, tver, i;
04562       t2.ver = 0;
04563       torg = org(t1);
04564       for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04565         enextself(t2);
04566       }
04567       // Go to the next face in t2.
04568       tloc = t2.loc;
04569       tver = t2.ver;
04570       t2.loc = locver2nextf[tloc][tver][0];
04571       t2.ver = locver2nextf[tloc][tver][1];
04572     }
04573   }
04574   return t2.tet != dummytet;
04575 }
04576 
04577 inline bool tetgenmesh::fnextself(triface& t1)
04578 {
04579   triface t2;
04580 
04581   // Get the next face.
04582   t2.loc = locver2nextf[t1.loc][t1.ver][0];
04583   // Is the next face in the same tet?
04584   if (t2.loc != -1) {
04585     // It's in the same tet. Get the edge version.
04586     t2.ver = locver2nextf[t1.loc][t1.ver][1];
04587     t1.loc = t2.loc;
04588     t1.ver = t2.ver;
04589   } else {
04590     // The next face is in the neigbhour of 't1'.
04591     sym(t1, t2);
04592     if (t2.tet != dummytet) {
04593       // Find the corresponding edge in t2.
04594       point torg;
04595       int i;
04596       t2.ver = 0;
04597       torg = org(t1);
04598       for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04599         enextself(t2);
04600       }
04601       t1.loc = locver2nextf[t2.loc][t2.ver][0];
04602       t1.ver = locver2nextf[t2.loc][t2.ver][1];
04603       t1.tet = t2.tet;
04604     }
04605   }
04606   return t2.tet != dummytet;
04607 }
04608 
04609 // enextfnext() and enext2fnext() are combination primitives of enext(),
04610 //   enext2() and fnext().
04611 
04612 inline void tetgenmesh::enextfnext(triface& t1, triface& t2) {
04613   enext(t1, t2);
04614   fnextself(t2);
04615 }
04616 
04617 inline void tetgenmesh::enextfnextself(triface& t) {
04618   enextself(t);
04619   fnextself(t);
04620 }
04621 
04622 inline void tetgenmesh::enext2fnext(triface& t1, triface& t2) {
04623   enext2(t1, t2);
04624   fnextself(t2);
04625 }
04626 
04627 inline void tetgenmesh::enext2fnextself(triface& t) {
04628   enext2self(t);
04629   fnextself(t);
04630 }
04631 
04632 // Primitives to infect or cure a tetrahedron with the virus.   The last
04633 //   third bit of the pointer is marked for infection.  These rely on the
04634 //   assumption that all tetrahedron are aligned to eight-byte boundaries.
04635 
04636 inline void tetgenmesh::infect(triface& t) {
04637   t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] | (unsigned long) 4l);
04638 }
04639 
04640 inline void tetgenmesh::uninfect(triface& t) {
04641   t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] & ~ (unsigned long) 4l);
04642 }
04643 
04644 // Test a tetrahedron for viral infection.
04645 
04646 inline bool tetgenmesh::infected(triface& t) {
04647   return (((unsigned long) t.tet[0] & (unsigned long) 4l) != 0);
04648 }
04649 
04650 // Check or set a tetrahedron's attributes.
04651 
04652 inline REAL tetgenmesh::elemattribute(tetrahedron* ptr, int attnum) {
04653   return ((REAL *) (ptr))[elemattribindex + attnum];
04654 }
04655 
04656 inline void tetgenmesh::
04657 setelemattribute(tetrahedron* ptr, int attnum, REAL value){
04658   ((REAL *) (ptr))[elemattribindex + attnum] = value;
04659 }
04660 
04661 // Check or set a tetrahedron's maximum volume bound.
04662 
04663 inline REAL tetgenmesh::volumebound(tetrahedron* ptr) {
04664   return ((REAL *) (ptr))[volumeboundindex];
04665 }
04666 
04667 inline void tetgenmesh::setvolumebound(tetrahedron* ptr, REAL value) {
04668   ((REAL *) (ptr))[volumeboundindex] = value;
04669 }
04670 
04671 //
04672 // End of primitives for tetrahedra
04673 //
04674 
04675 //
04676 // Begin of primitives for subfaces/subsegments
04677 //
04678 
04679 // Each subface contains three pointers to its neighboring subfaces, with
04680 //   edge versions.  To save memory, both information are kept in a single
04681 //   pointer. To make this possible, all subfaces are aligned to eight-byte
04682 //   boundaries, so that the last three bits of each pointer are zeros. An
04683 //   edge version (in the range 0 to 5) is compressed into the last three
04684 //   bits of each pointer by 'sencode()'.  'sdecode()' decodes a pointer,
04685 //   extracting an edge version and a pointer to the beginning of a subface.
04686 
04687 inline void tetgenmesh::sdecode(shellface sptr, face& s) {
04688   s.shver = (int) ((unsigned long) (sptr) & (unsigned long) 7l);
04689   s.sh = (shellface *) ((unsigned long) (sptr) & ~ (unsigned long) 7l);
04690 }
04691 
04692 inline tetgenmesh::shellface tetgenmesh::sencode(face& s) {
04693   return (shellface) ((unsigned long) s.sh | (unsigned long) s.shver);
04694 }
04695 
04696 // spivot() finds the other subface (from this subface) that shares the
04697 //   same edge.
04698 
04699 inline void tetgenmesh::spivot(face& s1, face& s2) {
04700   shellface sptr = s1.sh[Orient(s1.shver)];
04701   sdecode(sptr, s2);
04702 }
04703 
04704 inline void tetgenmesh::spivotself(face& s) {
04705   shellface sptr = s.sh[Orient(s.shver)];
04706   sdecode(sptr, s);
04707 }
04708 
04709 // sbond() bonds two subfaces together, i.e., after bonding, both faces
04710 //   are pointing to each other.
04711 
04712 inline void tetgenmesh::sbond(face& s1, face& s2) {
04713   s1.sh[Orient(s1.shver)] = sencode(s2);
04714   s2.sh[Orient(s2.shver)] = sencode(s1);
04715 }
04716 
04717 // sbond1() only bonds s2 to s1, i.e., after bonding, s1 is pointing to s2,
04718 //   but s2 is not pointing to s1.
04719 
04720 inline void tetgenmesh::sbond1(face& s1, face& s2) {
04721   s1.sh[Orient(s1.shver)] = sencode(s2);
04722 }
04723 
04724 // Dissolve a subface bond (from one side).  Note that the other subface
04725 //   will still think it's connected to this subface.
04726 
04727 inline void tetgenmesh::sdissolve(face& s) {
04728   s.sh[Orient(s.shver)] = (shellface) dummysh;
04729 }
04730 
04731 // These primitives determine or set the origin, destination, or apex
04732 //   of a subface with respect to the edge version.
04733 
04734 inline tetgenmesh::point tetgenmesh::sorg(face& s) {
04735   return (point) s.sh[3 + vo[s.shver]];
04736 }
04737 
04738 inline tetgenmesh::point tetgenmesh::sdest(face& s) {
04739   return (point) s.sh[3 + vd[s.shver]];
04740 }
04741 
04742 inline tetgenmesh::point tetgenmesh::sapex(face& s) {
04743   return (point) s.sh[3 + va[s.shver]];
04744 }
04745 
04746 inline void tetgenmesh::setsorg(face& s, point pointptr) {
04747   s.sh[3 + vo[s.shver]] = (shellface) pointptr;
04748 }
04749 
04750 inline void tetgenmesh::setsdest(face& s, point pointptr) {
04751   s.sh[3 + vd[s.shver]] = (shellface) pointptr;
04752 }
04753 
04754 inline void tetgenmesh::setsapex(face& s, point pointptr) {
04755   s.sh[3 + va[s.shver]] = (shellface) pointptr;
04756 }
04757 
04758 // These primitives were drived from Mucke[2]'s triangle-edge data structure
04759 //   to change face-edge relation in a subface (sesym, senext and senext2).
04760 
04761 inline void tetgenmesh::sesym(face& s1, face& s2) {
04762   s2.sh = s1.sh;
04763   s2.shver = s1.shver + (EdgeRing(s1.shver) ? -1 : 1);
04764 }
04765 
04766 inline void tetgenmesh::sesymself(face& s) {
04767   s.shver += (EdgeRing(s.shver) ? -1 : 1);
04768 }
04769 
04770 inline void tetgenmesh::senext(face& s1, face& s2) {
04771   s2.sh = s1.sh;
04772   s2.shver = ve[s1.shver];
04773 }
04774 
04775 inline void tetgenmesh::senextself(face& s) {
04776   s.shver = ve[s.shver];
04777 }
04778 
04779 inline void tetgenmesh::senext2(face& s1, face& s2) {
04780   s2.sh = s1.sh;
04781   s2.shver = ve[ve[s1.shver]];
04782 }
04783 
04784 inline void tetgenmesh::senext2self(face& s) {
04785   s.shver = ve[ve[s.shver]];
04786 }
04787 
04788 // If f0 and f1 are both in the same face ring, then f1 = f0.fnext(),
04789 
04790 inline void tetgenmesh::sfnext(face& s1, face& s2) {
04791   getnextsface(&s1, &s2);
04792 }
04793 
04794 inline void tetgenmesh::sfnextself(face& s) {
04795   getnextsface(&s, NULL);
04796 }
04797 
04798 // These primitives read or set a pointer of the badface structure.  The
04799 //   pointer is stored sh[11].
04800 
04801 inline tetgenmesh::badface* tetgenmesh::shell2badface(face& s) {
04802   return (badface*) s.sh[11];
04803 }
04804 
04805 inline void tetgenmesh::setshell2badface(face& s, badface* value) {
04806   s.sh[11] = (shellface) value;
04807 }
04808 
04809 // Check or set a subface's maximum area bound.
04810 
04811 inline REAL tetgenmesh::areabound(face& s) {
04812   return ((REAL *) (s.sh))[areaboundindex];
04813 }
04814 
04815 inline void tetgenmesh::setareabound(face& s, REAL value) {
04816   ((REAL *) (s.sh))[areaboundindex] = value;
04817 }
04818 
04819 // These two primitives read or set a shell marker.  Shell markers are used
04820 //   to hold user boundary information.
04821 
04822 inline int tetgenmesh::shellmark(face& s) {
04823   return ((int *) (s.sh))[shmarkindex];
04824 }
04825 
04826 inline void tetgenmesh::setshellmark(face& s, int value) {
04827   ((int *) (s.sh))[shmarkindex] = value;
04828 }
04829 
04830 // These two primitives set or read the type of the subface or subsegment.
04831 
04832 inline enum tetgenmesh::shestype tetgenmesh::shelltype(face& s) {
04833   return (enum shestype) ((int *) (s.sh))[shmarkindex + 1];
04834 }
04835 
04836 inline void tetgenmesh::setshelltype(face& s, enum shestype value) {
04837   ((int *) (s.sh))[shmarkindex + 1] = (int) value;
04838 }
04839 
04840 // These two primitives set or read the pbc group of the subface.
04841 
04842 inline int tetgenmesh::shellpbcgroup(face& s) {
04843   return ((int *) (s.sh))[shmarkindex + 2];
04844 }
04845 
04846 inline void tetgenmesh::setshellpbcgroup(face& s, int value) {
04847   ((int *) (s.sh))[shmarkindex + 2] = value;
04848 }
04849 
04850 // Primitives to infect or cure a subface with the virus. These rely on the
04851 //   assumption that all tetrahedra are aligned to eight-byte boundaries.
04852 
04853 inline void tetgenmesh::sinfect(face& s) {
04854   s.sh[6] = (shellface) ((unsigned long) s.sh[6] | (unsigned long) 4l);
04855 }
04856 
04857 inline void tetgenmesh::suninfect(face& s) {
04858   s.sh[6] = (shellface)((unsigned long) s.sh[6] & ~(unsigned long) 4l);
04859 }
04860 
04861 // Test a subface for viral infection.
04862 
04863 inline bool tetgenmesh::sinfected(face& s) {
04864   return (((unsigned long) s.sh[6] & (unsigned long) 4l) != 0);
04865 }
04866 
04867 //
04868 // End of primitives for subfaces/subsegments
04869 //
04870 
04871 //
04872 // Begin of primitives for interacting between tetrahedra and subfaces
04873 //
04874 
04875 // tspivot() finds a subface abutting on this tetrahdera.
04876 
04877 inline void tetgenmesh::tspivot(triface& t, face& s) {
04878   shellface sptr = (shellface) t.tet[8 + t.loc];
04879   sdecode(sptr, s);
04880 }
04881 
04882 // stpivot() finds a tetrahedron abutting a subface.
04883 
04884 inline void tetgenmesh::stpivot(face& s, triface& t) {
04885   tetrahedron ptr = (tetrahedron) s.sh[6 + EdgeRing(s.shver)];
04886   decode(ptr, t);
04887 }
04888 
04889 // tsbond() bond a tetrahedron to a subface.
04890 
04891 inline void tetgenmesh::tsbond(triface& t, face& s) {
04892   t.tet[8 + t.loc] = (tetrahedron) sencode(s);
04893   s.sh[6 + EdgeRing(s.shver)] = (shellface) encode(t);
04894 }
04895 
04896 // tsdissolve() dissolve a bond (from the tetrahedron side).
04897 
04898 inline void tetgenmesh::tsdissolve(triface& t) {
04899   t.tet[8 + t.loc] = (tetrahedron) dummysh;
04900 }
04901 
04902 // stdissolve() dissolve a bond (from the subface side).
04903 
04904 inline void tetgenmesh::stdissolve(face& s) {
04905   s.sh[6 + EdgeRing(s.shver)] = (shellface) dummytet;
04906 }
04907 
04908 //
04909 // End of primitives for interacting between tetrahedra and subfaces
04910 //
04911 
04912 //
04913 // Begin of primitives for interacting between subfaces and subsegs
04914 //
04915 
04916 // sspivot() finds a subsegment abutting a subface.
04917 
04918 inline void tetgenmesh::sspivot(face& s, face& edge) {
04919   shellface sptr = (shellface) s.sh[8 + Orient(s.shver)];
04920   sdecode(sptr, edge);
04921 }
04922 
04923 // ssbond() bond a subface to a subsegment.
04924 
04925 inline void tetgenmesh::ssbond(face& s, face& edge) {
04926   s.sh[8 + Orient(s.shver)] = sencode(edge);
04927   edge.sh[0] = sencode(s);
04928 }
04929 
04930 // ssdisolve() dissolve a bond (from the subface side)
04931 
04932 inline void tetgenmesh::ssdissolve(face& s) {
04933   s.sh[8 + Orient(s.shver)] = (shellface) dummysh;
04934 }
04935 
04936 //
04937 // End of primitives for interacting between subfaces and subsegs
04938 //
04939 
04940 //
04941 // Begin of primitives for interacting between tet and subsegs.
04942 //
04943 
04944 inline void tetgenmesh::tsspivot1(triface& t, face& seg)
04945 {
04946   shellface sptr = (shellface) t.tet[8 + locver2edge[t.loc][t.ver]];
04947   sdecode(sptr, seg);
04948 }
04949 
04950 // Only bond/dissolve at tet's side, but not vice versa.
04951 
04952 inline void tetgenmesh::tssbond1(triface& t, face& seg)
04953 {
04954   t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) sencode(seg);
04955 }
04956 
04957 inline void tetgenmesh::tssdissolve1(triface& t)
04958 {
04959   t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) dummysh;
04960 }
04961 
04962 //
04963 // End of primitives for interacting between tet and subsegs.
04964 //
04965 
04966 //
04967 // Begin of primitives for points
04968 //
04969 
04970 inline int tetgenmesh::pointmark(point pt) {
04971   return ((int *) (pt))[pointmarkindex];
04972 }
04973 
04974 inline void tetgenmesh::setpointmark(point pt, int value) {
04975   ((int *) (pt))[pointmarkindex] = value;
04976 }
04977 
04978 // These two primitives set and read the type of the point.
04979 
04980 inline enum tetgenmesh::verttype tetgenmesh::pointtype(point pt) {
04981   return (enum verttype) ((int *) (pt))[pointmarkindex + 1];
04982 }
04983 
04984 inline void tetgenmesh::setpointtype(point pt, enum verttype value) {
04985   ((int *) (pt))[pointmarkindex + 1] = (int) value;
04986 }
04987 
04988 // These following primitives set and read a pointer to a tetrahedron
04989 //   a subface/subsegment, a point, or a tet of background mesh.
04990 
04991 inline tetgenmesh::tetrahedron tetgenmesh::point2tet(point pt) {
04992   return ((tetrahedron *) (pt))[point2simindex];
04993 }
04994 
04995 inline void tetgenmesh::setpoint2tet(point pt, tetrahedron value) {
04996   ((tetrahedron *) (pt))[point2simindex] = value;
04997 }
04998 
04999 inline tetgenmesh::shellface tetgenmesh::point2sh(point pt) {
05000   return (shellface) ((tetrahedron *) (pt))[point2simindex + 1];
05001 }
05002 
05003 inline void tetgenmesh::setpoint2sh(point pt, shellface value) {
05004   ((tetrahedron *) (pt))[point2simindex + 1] = (tetrahedron) value;
05005 }
05006 
05007 inline tetgenmesh::point tetgenmesh::point2ppt(point pt) {
05008   return (point) ((tetrahedron *) (pt))[point2simindex + 2];
05009 }
05010 
05011 inline void tetgenmesh::setpoint2ppt(point pt, point value) {
05012   ((tetrahedron *) (pt))[point2simindex + 2] = (tetrahedron) value;
05013 }
05014 
05015 inline tetgenmesh::tetrahedron tetgenmesh::point2bgmtet(point pt) {
05016   return ((tetrahedron *) (pt))[point2simindex + 3];
05017 }
05018 
05019 inline void tetgenmesh::setpoint2bgmtet(point pt, tetrahedron value) {
05020   ((tetrahedron *) (pt))[point2simindex + 3] = value;
05021 }
05022 
05023 // These primitives set and read a pointer to its pbc point.
05024 
05025 inline tetgenmesh::point tetgenmesh::point2pbcpt(point pt) {
05026   return (point) ((tetrahedron *) (pt))[point2pbcptindex];
05027 }
05028 
05029 inline void tetgenmesh::setpoint2pbcpt(point pt, point value) {
05030   ((tetrahedron *) (pt))[point2pbcptindex] = (tetrahedron) value;
05031 }
05032 
05033 //
05034 // End of primitives for points
05035 //
05036 
05037 //
05038 // Begin of advanced primitives
05039 //
05040 
05041 // adjustedgering() adjusts the edge version so that it belongs to the
05042 //   indicated edge ring.  The 'direction' only can be 0(CCW) or 1(CW).
05043 //   If the edge is not in the wanted edge ring, reverse it.
05044 
05045 inline void tetgenmesh::adjustedgering(triface& t, int direction) {
05046   if (EdgeRing(t.ver) != direction) {
05047     esymself(t);
05048   }
05049 }
05050 
05051 inline void tetgenmesh::adjustedgering(face& s, int direction) {
05052   if (EdgeRing(s.shver) != direction) {
05053     sesymself(s);
05054   }
05055 }
05056 
05057 // isdead() returns TRUE if the tetrahedron or subface has been dealloced.
05058 
05059 inline bool tetgenmesh::isdead(triface* t) {
05060   if (t->tet == (tetrahedron *) NULL) return true;
05061   else return t->tet[4] == (tetrahedron) NULL;
05062 }
05063 
05064 inline bool tetgenmesh::isdead(face* s) {
05065   if (s->sh == (shellface *) NULL) return true;
05066   else return s->sh[3] == (shellface) NULL;
05067 }
05068 
05069 // isfacehaspoint() returns TRUE if the 'testpoint' is one of the vertices
05070 //   of the tetface 't' subface 's'.
05071 
05072 inline bool tetgenmesh::isfacehaspoint(triface* t, point testpoint) {
05073   return ((org(*t) == testpoint) || (dest(*t) == testpoint) ||
05074           (apex(*t) == testpoint));
05075 }
05076 
05077 inline bool tetgenmesh::isfacehaspoint(face* s, point testpoint) {
05078   return (s->sh[3] == (shellface) testpoint) ||
05079          (s->sh[4] == (shellface) testpoint) ||
05080          (s->sh[5] == (shellface) testpoint);
05081 }
05082 
05083 // isfacehasedge() returns TRUE if the edge (given by its two endpoints) is
05084 //   one of the three edges of the subface 's'.
05085 
05086 inline bool tetgenmesh::isfacehasedge(face* s, point tend1, point tend2) {
05087   return (isfacehaspoint(s, tend1) && isfacehaspoint(s, tend2));
05088 }
05089 
05090 // issymexist() returns TRUE if the adjoining tetrahedron is not 'duumytet'.
05091 
05092 inline bool tetgenmesh::issymexist(triface* t) {
05093   tetrahedron *ptr = (tetrahedron *)
05094     ((unsigned long)(t->tet[t->loc]) & ~(unsigned long)7l);
05095   return ptr != dummytet;
05096 }
05097 
05099 //                                                                           //
05100 // getnextsface()    Finds the next subface in the face ring.                //
05101 //                                                                           //
05102 // For saving space in the data structure of subface, there only exists one  //
05103 // face ring around a segment (see programming manual).  This routine imple- //
05104 // ments the double face ring as desired in Muecke's data structure.         //
05105 //                                                                           //
05107 
05108 void tetgenmesh::getnextsface(face* s1, face* s2)
05109 {
05110   face neighsh, spinsh;
05111   face testseg;
05112 
05113   sspivot(*s1, testseg);
05114   if (testseg.sh != dummysh) {
05115     testseg.shver = 0;
05116     if (sorg(testseg) == sorg(*s1)) {
05117       spivot(*s1, neighsh);
05118     } else {
05119       spinsh = *s1;
05120       do {
05121         neighsh = spinsh;
05122         spivotself(spinsh);
05123       } while (spinsh.sh != s1->sh);
05124     }
05125   } else {
05126     spivot(*s1, neighsh);
05127   }
05128   if (sorg(neighsh) != sorg(*s1)) {
05129     sesymself(neighsh);
05130   }
05131   if (s2 != (face *) NULL) {
05132     *s2 = neighsh;
05133   } else {
05134     *s1 = neighsh;
05135   }
05136 }
05137 
05139 //                                                                           //
05140 // tsspivot()    Finds a subsegment abutting on a tetrahderon's edge.        //
05141 //                                                                           //
05142 // The edge is represented in the primary edge of 'checkedge'. If there is a //
05143 // subsegment bonded at this edge, it is returned in handle 'checkseg', the  //
05144 // edge direction of 'checkseg' is conformed to 'checkedge'. If there isn't, //
05145 // set 'checkseg.sh = dummysh' to indicate it is not a subsegment.           //
05146 //                                                                           //
05147 // To find whether an edge of a tetrahedron is a subsegment or not. First we //
05148 // need find a subface around this edge to see if it contains a subsegment.  //
05149 // The reason is there is no direct connection between a tetrahedron and its //
05150 // adjoining subsegments.                                                    //
05151 //                                                                           //
05153 
05154 void tetgenmesh::tsspivot(triface* checkedge, face* checkseg)
05155 {
05156   triface spintet;
05157   face parentsh;
05158   point tapex;
05159   int hitbdry;
05160 
05161   spintet = *checkedge;
05162   tapex = apex(*checkedge);
05163   hitbdry = 0;
05164   do {
05165     tspivot(spintet, parentsh);
05166     // Does spintet have a (non-fake) subface attached?
05167     if ((parentsh.sh != dummysh) && (sapex(parentsh) != NULL)) {
05168       // Find a subface! Find the edge in it.
05169       findedge(&parentsh, org(*checkedge), dest(*checkedge));
05170       sspivot(parentsh, *checkseg);
05171       if (checkseg->sh != dummysh) {
05172         // Find a subsegment! Correct its edge direction before return.
05173         if (sorg(*checkseg) != org(*checkedge)) {
05174           sesymself(*checkseg);
05175         }
05176       }
05177       return;
05178     }
05179     if (!fnextself(spintet)) {
05180       hitbdry++;
05181       if (hitbdry < 2) {
05182         esym(*checkedge, spintet);
05183         if (!fnextself(spintet)) {
05184           hitbdry++;
05185         }
05186       }
05187     }
05188   } while ((apex(spintet) != tapex) && (hitbdry < 2));
05189   // Not find.
05190   checkseg->sh = dummysh;
05191 }
05192 
05194 //                                                                           //
05195 // sstpivot()    Finds a tetrahedron abutting a subsegment.                  //
05196 //                                                                           //
05197 // This is the inverse operation of 'tsspivot()'.  One subsegment shared by  //
05198 // arbitrary number of tetrahedron, the returned tetrahedron is not unique.  //
05199 // The edge direction of the returned tetrahedron is conformed to the given  //
05200 // subsegment.                                                               //
05201 //                                                                           //
05203 
05204 void tetgenmesh::sstpivot(face* checkseg, triface* retedge)
05205 {
05206   face parentsh;
05207 
05208   // Get the subface which holds the subsegment.
05209   sdecode(checkseg->sh[0], parentsh);
05210 #ifdef SELF_CHECK
05211   assert(parentsh.sh != dummysh);
05212 #endif
05213   // Get a tetraheron to which the subface attches.
05214   stpivot(parentsh, *retedge);
05215   if (retedge->tet == dummytet) {
05216     sesymself(parentsh);
05217     stpivot(parentsh, *retedge);
05218 #ifdef SELF_CHECK
05219     assert(retedge->tet != dummytet);
05220 #endif
05221   }
05222   // Correct the edge direction before return.
05223   findedge(retedge, sorg(*checkseg), sdest(*checkseg));
05224 }
05225 
05227 //                                                                           //
05228 // findorg()    Finds a point in the given handle (tetrahedron or subface).  //
05229 //                                                                           //
05230 // If 'dorg' is a one of vertices of the given handle,  set the origin of    //
05231 // this handle be that point and return TRUE.  Otherwise, return FALSE and   //
05232 // 'tface' remains unchanged.                                                //
05233 //                                                                           //
05235 
05236 bool tetgenmesh::findorg(triface* tface, point dorg)
05237 {
05238   if (org(*tface) == dorg) {
05239     return true;
05240   } else {
05241     if (dest(*tface) == dorg) {
05242       enextself(*tface);
05243       return true;
05244     } else {
05245       if (apex(*tface) == dorg) {
05246         enext2self(*tface);
05247         return true;
05248       } else {
05249         if (oppo(*tface) == dorg) {
05250           // Keep 'tface' referring to the same tet after fnext().
05251           adjustedgering(*tface, CCW);
05252           fnextself(*tface);
05253           enext2self(*tface);
05254           return true;
05255         }
05256       }
05257     }
05258   }
05259   return false;
05260 }
05261 
05262 bool tetgenmesh::findorg(face* sface, point dorg)
05263 {
05264   if (sorg(*sface) == dorg) {
05265     return true;
05266   } else {
05267     if (sdest(*sface) == dorg) {
05268       senextself(*sface);
05269       return true;
05270     } else {
05271       if (sapex(*sface) == dorg) {
05272         senext2self(*sface);
05273         return true;
05274       }
05275     }
05276   }
05277   return false;
05278 }
05279 
05281 //                                                                           //
05282 // findedge()    Find an edge in the given handle (tetrahedron or subface).  //
05283 //                                                                           //
05284 // The edge is given in two points 'eorg' and 'edest'.  It is assumed that   //
05285 // the edge must exist in the given handle (tetrahedron or subface).  This   //
05286 // routine sets the right edge version for the input handle.                 //
05287 //                                                                           //
05289 
05290 void tetgenmesh::findedge(triface* tface, point eorg, point edest)
05291 {
05292   int i;
05293 
05294   for (i = 0; i < 3; i++) {
05295     if (org(*tface) == eorg) {
05296       if (dest(*tface) == edest) {
05297         // Edge is found, return.
05298         return;
05299       }
05300     } else {
05301       if (org(*tface) == edest) {
05302         if (dest(*tface) == eorg) {
05303           // Edge is found, inverse the direction and return.
05304           esymself(*tface);
05305           return;
05306         }
05307       }
05308     }
05309     enextself(*tface);
05310   }
05311   // It should never be here.
05312   printf("Internalerror in findedge():  Unable to find an edge in tet.\n");
05313   internalerror();
05314 }
05315 
05316 void tetgenmesh::findedge(face* sface, point eorg, point edest)
05317 {
05318   int i;
05319 
05320   for (i = 0; i < 3; i++) {
05321     if (sorg(*sface) == eorg) {
05322       if (sdest(*sface) == edest) {
05323         // Edge is found, return.
05324         return;
05325       }
05326     } else {
05327       if (sorg(*sface) == edest) {
05328         if (sdest(*sface) == eorg) {
05329           // Edge is found, inverse the direction and return.
05330           sesymself(*sface);
05331           return;
05332         }
05333       }
05334     }
05335     senextself(*sface);
05336   }
05337   printf("Internalerror in findedge():  Unable to find an edge in subface.\n");
05338   internalerror();
05339 }
05340 
05342 //                                                                           //
05343 // findface()    Find the face has the given origin, destination and apex.   //
05344 //                                                                           //
05345 // On input, 'fface' is a handle which may contain the three corners or may  //
05346 // not or may be dead.  On return, it represents exactly the face with the   //
05347 // given origin, destination and apex.                                       //
05348 //                                                                           //
05350 
05351 void tetgenmesh::findface(triface *fface, point forg, point fdest, point fapex)
05352 {
05353   triface spintet;
05354   enum finddirectionresult collinear;
05355   int hitbdry;
05356 
05357   if (!isdead(fface)) {
05358     // First check the easiest case, that 'fface' is just the right one.
05359     if (org(*fface) == forg && dest(*fface) == fdest &&
05360         apex(*fface) == fapex) return;
05361   } else {
05362     // The input handle is dead, use the 'recenttet' if it is alive.
05363     if (!isdead(&recenttet)) *fface = recenttet;
05364   }
05365 
05366   if (!isdead(fface)) {
05367     if (!findorg(fface, forg)) {
05368       // 'forg' is not a corner of 'fface', locate it.
05369       preciselocate(forg, fface, tetrahedrons->items);
05370     }
05371     // It is possible that forg is not found in a non-convex mesh.
05372     if (org(*fface) == forg) {
05373       collinear = finddirection(fface, fdest, tetrahedrons->items);
05374       if (collinear == RIGHTCOLLINEAR) {
05375         // fdest is just the destination.
05376       } else if (collinear == LEFTCOLLINEAR) {
05377         enext2self(*fface);
05378         esymself(*fface);
05379       } else if (collinear == TOPCOLLINEAR) {
05380         fnextself(*fface);
05381         enext2self(*fface);
05382         esymself(*fface);
05383       }
05384     }
05385     // It is possible taht fdest is not found in a non-convex mesh.
05386     if ((org(*fface) == forg) && (dest(*fface) == fdest)) {
05387       // Find the apex of 'fapex'.
05388       spintet = *fface;
05389       hitbdry = 0;
05390       do {
05391         if (apex(spintet) == fapex) {
05392           // We have done. Be careful the edge direction of 'spintet',
05393           //   it may reversed because of hitting boundary once.
05394           if (org(spintet) != org(*fface)) {
05395             esymself(spintet);
05396           }
05397           *fface = spintet;
05398           return;
05399         }
05400         if (!fnextself(spintet)) {
05401           hitbdry ++;
05402           if (hitbdry < 2) {
05403             esym(*fface, spintet);
05404             if (!fnextself(spintet)) {
05405               hitbdry ++;
05406             }
05407           }
05408         }
05409       } while (hitbdry < 2 && apex(spintet) != apex(*fface));
05410       // It is possible that fapex is not found in a non-convex mesh.
05411     }
05412   }
05413 
05414   if (isdead(fface) || (org(*fface) != forg) || (dest(*fface) != fdest) ||
05415       (apex(*fface) != fapex)) {
05416     // Too bad, the input handle is useless. We have to find a handle
05417     //   for 'fface' contains the 'forg' and 'fdest'. Here a brute force
05418     //   search is performed.
05419     if (b->verbose > 1) {
05420       printf("Warning in findface():  Perform a brute-force searching.\n");
05421     }
05422     enum verttype forgty, fdestty, fapexty;
05423     int share, i;
05424     forgty = pointtype(forg);
05425     fdestty = pointtype(fdest);
05426     fapexty = pointtype(fapex);
05427     setpointtype(forg, DEADVERTEX);
05428     setpointtype(fdest, DEADVERTEX);
05429     setpointtype(fapex, DEADVERTEX);
05430     tetrahedrons->traversalinit();
05431     fface->tet = tetrahedrontraverse();
05432     while (fface->tet != (tetrahedron *) NULL) {
05433       share = 0;
05434       for (i = 0; i < 4; i++) {
05435         if (pointtype((point) fface->tet[4 + i]) == DEADVERTEX) share ++;
05436       }
05437       if (share == 3) {
05438         // Found! Set the correct face and desired corners.
05439         if (pointtype((point) fface->tet[4]) != DEADVERTEX) {
05440           fface->loc = 2;
05441         } else if (pointtype((point) fface->tet[5]) != DEADVERTEX) {
05442           fface->loc = 3;
05443         } else if (pointtype((point) fface->tet[6]) != DEADVERTEX) {
05444           fface->loc = 1;
05445         } else { // pointtype((point) fface->tet[7]) != DEADVERTEX
05446           fface->loc = 0;
05447         }
05448         findedge(fface, forg, fdest);
05449         break;
05450       }
05451       fface->tet = tetrahedrontraverse();
05452     }
05453     setpointtype(forg, forgty);
05454     setpointtype(fdest, fdestty);
05455     setpointtype(fapex, fapexty);
05456     if (fface->tet == (tetrahedron *) NULL) {
05457       // It is impossible to reach here.
05458       printf("Internal error:  Fail to find the indicated face.\n");
05459       internalerror();
05460     }
05461   }
05462 }
05463 
05465 //                                                                           //
05466 // getonextseg()    Get the next SEGMENT counterclockwise with the same org. //
05467 //                                                                           //
05468 // 's' is a subface. This routine reteuns the segment which is counterclock- //
05469 // wise with the origin of s.                                                //
05470 //                                                                           //
05472 
05473 void tetgenmesh::getonextseg(face* s, face* lseg)
05474 {
05475   face checksh, checkseg;
05476   point forg;
05477 
05478   forg = sorg(*s);
05479   checksh = *s;
05480   do {
05481     // Go to the edge at forg's left side.
05482     senext2self(checksh);
05483     // Check if there is a segment attaching this edge.
05484     sspivot(checksh, checkseg);
05485     if (checkseg.sh != dummysh) break;
05486     // No segment! Go to the neighbor of this subface.
05487     spivotself(checksh);
05488 #ifdef SELF_CHECK
05489     // It should always meet a segment before come back.
05490     assert(checksh.sh != s->sh);
05491 #endif
05492     if (sorg(checksh) != forg) {
05493       sesymself(checksh);
05494 #ifdef SELF_CHECK
05495       assert(sorg(checksh) == forg);
05496 #endif
05497     }
05498   } while (true);
05499   if (sorg(checkseg) != forg) sesymself(checkseg);
05500   *lseg = checkseg;
05501 }
05502 
05504 //                                                                           //
05505 // getseghasorg()    Get the segment containing the given point.             //
05506 //                                                                           //
05507 // 'dorg' is an endpoint of a segment S. 'sseg' is a subsegment of S. This   //
05508 // routine search a subsegment (along sseg) of S containing dorg. On return, //
05509 // 'sseg' contains 'dorg' as its origin.                                     //
05510 //                                                                           //
05512 
05513 void tetgenmesh::getseghasorg(face* sseg, point dorg)
05514 {
05515   face nextseg;
05516   point checkpt;
05517 
05518   nextseg = *sseg;
05519   checkpt = sorg(nextseg);
05520   while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05521     // Search dorg along the original direction of sseg.
05522     senext2self(nextseg);
05523     spivotself(nextseg);
05524     nextseg.shver = 0;
05525     if (sdest(nextseg) != checkpt) sesymself(nextseg);
05526     checkpt = sorg(nextseg);
05527   }
05528   if (checkpt == dorg) {
05529     *sseg = nextseg;
05530     return;
05531   }
05532   nextseg = *sseg;
05533   checkpt = sdest(nextseg);
05534   while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05535     // Search dorg along the destinational direction of sseg.
05536     senextself(nextseg);
05537     spivotself(nextseg);
05538     nextseg.shver = 0;
05539     if (sorg(nextseg) != checkpt) sesymself(nextseg);
05540     checkpt = sdest(nextseg);
05541   }
05542   if (checkpt == dorg) {
05543     sesym(nextseg, *sseg);
05544     return;
05545   }
05546   // Should never be here.
05547   printf("Internalerror in getseghasorg():  Unable to find the subseg.\n");
05548   internalerror();
05549 }
05550 
05552 //                                                                           //
05553 // getsubsegfarorg()    Get the origin of the parent segment of a subseg.    //
05554 //                                                                           //
05556 
05557 tetgenmesh::point tetgenmesh::getsubsegfarorg(face* sseg)
05558 {
05559   face prevseg;
05560   point checkpt;
05561 
05562   checkpt = sorg(*sseg);
05563   senext2(*sseg, prevseg);
05564   spivotself(prevseg);
05565   // Search dorg along the original direction of sseg.
05566   while (prevseg.sh != dummysh) {
05567     prevseg.shver = 0;
05568     if (sdest(prevseg) != checkpt) sesymself(prevseg);
05569     checkpt = sorg(prevseg);
05570     senext2self(prevseg);
05571     spivotself(prevseg);
05572   }
05573   return checkpt;
05574 }
05575 
05577 //                                                                           //
05578 // getsubsegfardest()    Get the dest. of the parent segment of a subseg.    //
05579 //                                                                           //
05581 
05582 tetgenmesh::point tetgenmesh::getsubsegfardest(face* sseg)
05583 {
05584   face nextseg;
05585   point checkpt;
05586 
05587   checkpt = sdest(*sseg);
05588   senext(*sseg, nextseg);
05589   spivotself(nextseg);
05590   // Search dorg along the destinational direction of sseg.
05591   while (nextseg.sh != dummysh) {
05592     nextseg.shver = 0;
05593     if (sorg(nextseg) != checkpt) sesymself(nextseg);
05594     checkpt = sdest(nextseg);
05595     senextself(nextseg);
05596     spivotself(nextseg);
05597   }
05598   return checkpt;
05599 }
05600 
05602 //                                                                           //
05603 // printtet()    Print out the details of a tetrahedron on screen.           //
05604 //                                                                           //
05605 // It's also used when the highest level of verbosity (`-VVV') is specified. //
05606 //                                                                           //
05608 
05609 void tetgenmesh::printtet(triface* tface)
05610 {
05611   triface tmpface, prtface;
05612   point tmppt;
05613   face tmpsh;
05614   int facecount;
05615 
05616   printf("Tetra x%lx with loc(%i) and ver(%i):",
05617          (unsigned long)(tface->tet), tface->loc, tface->ver);
05618   if (infected(*tface)) {
05619     printf(" (infected)");
05620   }
05621   printf("\n");
05622 
05623   tmpface = *tface;
05624   facecount = 0;
05625   while(facecount < 4) {
05626     tmpface.loc = facecount;
05627     sym(tmpface, prtface);
05628     if(prtface.tet == dummytet) {
05629       printf("      [%i] Outer space.\n", facecount);
05630     } else {
05631       printf("      [%i] x%lx  loc(%i).", facecount,
05632              (unsigned long)(prtface.tet), prtface.loc);
05633       if (infected(prtface)) {
05634         printf(" (infected)");
05635       }
05636       printf("\n");
05637     }
05638     facecount ++;
05639   }
05640 
05641   tmppt = org(*tface);
05642   if(tmppt == (point) NULL) {
05643     printf("      Org [%i] NULL\n", locver2org[tface->loc][tface->ver]);
05644   } else {
05645     printf("      Org [%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05646            locver2org[tface->loc][tface->ver], (unsigned long)(tmppt),
05647            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05648   }
05649   tmppt = dest(*tface);
05650   if(tmppt == (point) NULL) {
05651     printf("      Dest[%i] NULL\n", locver2dest[tface->loc][tface->ver]);
05652   } else {
05653     printf("      Dest[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05654            locver2dest[tface->loc][tface->ver], (unsigned long)(tmppt),
05655            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05656   }
05657   tmppt = apex(*tface);
05658   if(tmppt == (point) NULL) {
05659     printf("      Apex[%i] NULL\n", locver2apex[tface->loc][tface->ver]);
05660   } else {
05661     printf("      Apex[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05662            locver2apex[tface->loc][tface->ver], (unsigned long)(tmppt),
05663            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05664   }
05665   tmppt = oppo(*tface);
05666   if(tmppt == (point) NULL) {
05667     printf("      Oppo[%i] NULL\n", loc2oppo[tface->loc]);
05668   } else {
05669     printf("      Oppo[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05670            loc2oppo[tface->loc], (unsigned long)(tmppt),
05671            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05672   }
05673 
05674   if (b->useshelles) {
05675     tmpface = *tface;
05676     facecount = 0;
05677     while(facecount < 6) {
05678       tmpface.loc = facecount;
05679       tspivot(tmpface, tmpsh);
05680       if(tmpsh.sh != dummysh) {
05681         printf("      [%i] x%lx  ID(%i) ", facecount,
05682                (unsigned long)(tmpsh.sh), shellmark(tmpsh));
05683         if (sorg(tmpsh) == (point) NULL) {
05684           printf("(fake)");
05685         }
05686         printf("\n");
05687       }
05688       facecount ++;
05689     }
05690   }
05691 }
05692 
05694 //                                                                           //
05695 // printsh()    Print out the details of a subface or subsegment on screen.  //
05696 //                                                                           //
05697 // It's also used when the highest level of verbosity (`-VVV') is specified. //
05698 //                                                                           //
05700 
05701 void tetgenmesh::printsh(face* sface)
05702 {
05703   face prtsh;
05704   triface prttet;
05705   point printpoint;
05706 
05707   if (sapex(*sface) != NULL) {
05708     printf("subface x%lx, ver %d, mark %d:",
05709            (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05710   } else {
05711     printf("Subsegment x%lx, ver %d, mark %d:",
05712            (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05713   }
05714   if (sinfected(*sface)) {
05715     printf(" (infected)");
05716   }
05717   if (shell2badface(*sface)) {
05718     printf(" (queued)");
05719   }
05720   if (sapex(*sface) != NULL) {
05721     if (shelltype(*sface) == SHARP) {
05722       printf(" (sharp)");
05723     }
05724   } else {
05725     if (shelltype(*sface) == SHARP) {
05726       printf(" (sharp)");
05727     }
05728   }
05729   if (checkpbcs) {
05730     if (shellpbcgroup(*sface) >= 0) {
05731       printf(" (pbc %d)", shellpbcgroup(*sface));
05732     }
05733   }
05734   printf("\n");
05735 
05736   sdecode(sface->sh[0], prtsh);
05737   if (prtsh.sh == dummysh) {
05738     printf("      [0] = No shell\n");
05739   } else {
05740     printf("      [0] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05741   }
05742   sdecode(sface->sh[1], prtsh);
05743   if (prtsh.sh == dummysh) {
05744     printf("      [1] = No shell\n");
05745   } else {
05746     printf("      [1] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05747   }
05748   sdecode(sface->sh[2], prtsh);
05749   if (prtsh.sh == dummysh) {
05750     printf("      [2] = No shell\n");
05751   } else {
05752     printf("      [2] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05753   }
05754 
05755   printpoint = sorg(*sface);
05756   if (printpoint == (point) NULL)
05757     printf("      Org [%d] = NULL\n", vo[sface->shver]);
05758   else
05759     printf("      Org [%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05760            vo[sface->shver], (unsigned long)(printpoint), printpoint[0],
05761            printpoint[1], printpoint[2], pointmark(printpoint));
05762   printpoint = sdest(*sface);
05763   if (printpoint == (point) NULL)
05764     printf("      Dest[%d] = NULL\n", vd[sface->shver]);
05765   else
05766     printf("      Dest[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05767             vd[sface->shver], (unsigned long)(printpoint), printpoint[0],
05768             printpoint[1], printpoint[2], pointmark(printpoint));
05769 
05770   if (sapex(*sface) != NULL) {
05771     printpoint = sapex(*sface);
05772     if (printpoint == (point) NULL)
05773       printf("      Apex[%d] = NULL\n", va[sface->shver]);
05774     else
05775       printf("      Apex[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05776              va[sface->shver], (unsigned long)(printpoint), printpoint[0],
05777              printpoint[1], printpoint[2], pointmark(printpoint));
05778 
05779     decode(sface->sh[6], prttet);
05780     if (prttet.tet == dummytet) {
05781       printf("      [6] = Outer space\n");
05782     } else {
05783       printf("      [6] = x%lx  %d\n",
05784              (unsigned long)(prttet.tet), prttet.loc);
05785     }
05786     decode(sface->sh[7], prttet);
05787     if (prttet.tet == dummytet) {
05788       printf("      [7] = Outer space\n");
05789     } else {
05790       printf("      [7] = x%lx  %d\n",
05791              (unsigned long)(prttet.tet), prttet.loc);
05792     }
05793 
05794     sdecode(sface->sh[8], prtsh);
05795     if (prtsh.sh == dummysh) {
05796       printf("      [8] = No subsegment\n");
05797     } else {
05798       printf("      [8] = x%lx  %d\n",
05799              (unsigned long)(prtsh.sh), prtsh.shver);
05800     }
05801     sdecode(sface->sh[9], prtsh);
05802     if (prtsh.sh == dummysh) {
05803       printf("      [9] = No subsegment\n");
05804     } else {
05805       printf("      [9] = x%lx  %d\n",
05806              (unsigned long)(prtsh.sh), prtsh.shver);
05807     }
05808     sdecode(sface->sh[10], prtsh);
05809     if (prtsh.sh == dummysh) {
05810       printf("      [10]= No subsegment\n");
05811     } else {
05812       printf("      [10]= x%lx  %d\n",
05813              (unsigned long)(prtsh.sh), prtsh.shver);
05814     }
05815   }
05816 }
05817 
05818 //
05819 // End of advanced primitives
05820 //
05821 
05822 //
05823 // End of mesh manipulation primitives
05824 //
05825 
05826 //
05827 // Begin of mesh items searching routines
05828 //
05829 
05831 //                                                                           //
05832 // makepoint2tetmap()    Construct a mapping from points to tetrahedra.      //
05833 //                                                                           //
05834 // Traverses all the tetrahedra,  provides each corner of each tetrahedron   //
05835 // with a pointer to that tetrahedera.  Some pointers will be overwritten by //
05836 // other pointers because each point may be a corner of several tetrahedra,  //
05837 // but in the end every point will point to a tetrahedron that contains it.  //
05838 //                                                                           //
05840 
05841 void tetgenmesh::makepoint2tetmap()
05842 {
05843   triface tetloop;
05844   point pointptr;
05845 
05846   if (b->verbose > 0) {
05847     printf("  Constructing mapping from points to tetrahedra.\n");
05848   }
05849 
05850   // Initialize the point2tet field of each point.
05851   points->traversalinit();
05852   pointptr = pointtraverse();
05853   while (pointptr != (point) NULL) {
05854     setpoint2tet(pointptr, (tetrahedron) NULL);
05855     pointptr = pointtraverse();
05856   }
05857 
05858   tetrahedrons->traversalinit();
05859   tetloop.tet = tetrahedrontraverse();
05860   while (tetloop.tet != (tetrahedron *) NULL) {
05861     // Check all four points of the tetrahedron.
05862     tetloop.loc = 0;
05863     pointptr = org(tetloop);
05864     setpoint2tet(pointptr, encode(tetloop));
05865     pointptr = dest(tetloop);
05866     setpoint2tet(pointptr, encode(tetloop));
05867     pointptr = apex(tetloop);
05868     setpoint2tet(pointptr, encode(tetloop));
05869     pointptr = oppo(tetloop);
05870     setpoint2tet(pointptr, encode(tetloop));
05871     // Get the next tetrahedron in the list.
05872     tetloop.tet = tetrahedrontraverse();
05873   }
05874 }
05875 
05877 //                                                                           //
05878 // makeindex2pointmap()    Create a map from index to vertices.              //
05879 //                                                                           //
05880 // 'idx2verlist' returns the created map.  Traverse all vertices, a pointer  //
05881 // to each vertex is set into the array.  The pointer to the first vertex is //
05882 // saved in 'idx2verlist[0]'.  Don't forget to minus 'in->firstnumber' when  //
05883 // to get the vertex form its index.                                         //
05884 //                                                                           //
05886 
05887 void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
05888 {
05889   point pointloop;
05890   int idx;
05891 
05892   if (b->verbose > 0) {
05893     printf("  Constructing mapping from indices to points.\n");
05894   }
05895 
05896   idx2verlist = new point[points->items];
05897 
05898   points->traversalinit();
05899   pointloop = pointtraverse();
05900   idx = 0;
05901   while (pointloop != (point) NULL) {
05902     idx2verlist[idx] = pointloop;
05903     idx++;
05904     pointloop = pointtraverse();
05905   }
05906 }
05907 
05909 //                                                                           //
05910 // makesegmentmap()    Create a map from vertices (their indices) to         //
05911 //                     segments incident at the same vertices.               //
05912 //                                                                           //
05913 // Two arrays 'idx2seglist' and 'segsperverlist' together return the map.    //
05914 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
05915 // number of segments.  idx2seglist contains row information and             //
05916 // segsperverlist contains all (non-zero) elements.  The i-th entry of       //
05917 // idx2seglist is the starting position of i-th row's (non-zero) elements in //
05918 // segsperverlist.  The number of elements of i-th row is calculated by the  //
05919 // (i+1)-th entry minus i-th entry of idx2seglist.                           //
05920 //                                                                           //
05921 // NOTE: These two arrays will be created inside this routine, don't forget  //
05922 // to free them after using.                                                 //
05923 //                                                                           //
05925 
05926 void tetgenmesh::makesegmentmap(int*& idx2seglist, shellface**& segsperverlist)
05927 {
05928   shellface *shloop;
05929   int i, j, k;
05930 
05931   if (b->verbose > 0) {
05932     printf("  Constructing mapping from points to segments.\n");
05933   }
05934 
05935   // Create and initialize 'idx2seglist'.
05936   idx2seglist = new int[points->items + 1];
05937   for (i = 0; i < points->items + 1; i++) idx2seglist[i] = 0;
05938 
05939   // Loop the set of segments once, counter the number of segments sharing
05940   //   each vertex.
05941   subsegs->traversalinit();
05942   shloop = shellfacetraverse(subsegs);
05943   while (shloop != (shellface *) NULL) {
05944     // Increment the number of sharing segments for each endpoint.
05945     for (i = 0; i < 2; i++) {
05946       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05947       idx2seglist[j]++;
05948     }
05949     shloop = shellfacetraverse(subsegs);
05950   }
05951 
05952   // Calculate the total length of array 'facesperverlist'.
05953   j = idx2seglist[0];
05954   idx2seglist[0] = 0;  // Array starts from 0 element.
05955   for (i = 0; i < points->items; i++) {
05956     k = idx2seglist[i + 1];
05957     idx2seglist[i + 1] = idx2seglist[i] + j;
05958     j = k;
05959   }
05960   // The total length is in the last unit of idx2seglist.
05961   segsperverlist = new shellface*[idx2seglist[i]];
05962   // Loop the set of segments again, set the info. of segments per vertex.
05963   subsegs->traversalinit();
05964   shloop = shellfacetraverse(subsegs);
05965   while (shloop != (shellface *) NULL) {
05966     for (i = 0; i < 2; i++) {
05967       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05968       segsperverlist[idx2seglist[j]] = shloop;
05969       idx2seglist[j]++;
05970     }
05971     shloop = shellfacetraverse(subsegs);
05972   }
05973   // Contents in 'idx2seglist' are shifted, now shift them back.
05974   for (i = points->items - 1; i >= 0; i--) {
05975     idx2seglist[i + 1] = idx2seglist[i];
05976   }
05977   idx2seglist[0] = 0;
05978 }
05979 
05981 //                                                                           //
05982 // makesubfacemap()    Create a map from vertices (their indices) to         //
05983 //                     subfaces incident at the same vertices.               //
05984 //                                                                           //
05985 // Two arrays 'idx2facelist' and 'facesperverlist' together return the map.  //
05986 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
05987 // number of subfaces.  idx2facelist contains row information and            //
05988 // facesperverlist contains all (non-zero) elements.  The i-th entry of      //
05989 // idx2facelist is the starting position of i-th row's(non-zero) elements in //
05990 // facesperverlist.  The number of elements of i-th row is calculated by the //
05991 // (i+1)-th entry minus i-th entry of idx2facelist.                          //
05992 //                                                                           //
05993 // NOTE: These two arrays will be created inside this routine, don't forget  //
05994 // to free them after using.                                                 //
05995 //                                                                           //
05997 
05998 void tetgenmesh::
05999 makesubfacemap(int*& idx2facelist, shellface**& facesperverlist)
06000 {
06001   shellface *shloop;
06002   int i, j, k;
06003 
06004   if (b->verbose > 0) {
06005     printf("  Constructing mapping from points to subfaces.\n");
06006   }
06007 
06008   // Create and initialize 'idx2facelist'.
06009   idx2facelist = new int[points->items + 1];
06010   for (i = 0; i < points->items + 1; i++) idx2facelist[i] = 0;
06011 
06012   // Loop the set of subfaces once, counter the number of subfaces sharing
06013   //   each vertex.
06014   subfaces->traversalinit();
06015   shloop = shellfacetraverse(subfaces);
06016   while (shloop != (shellface *) NULL) {
06017     // Increment the number of sharing segments for each endpoint.
06018     for (i = 0; i < 3; i++) {
06019       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06020       idx2facelist[j]++;
06021     }
06022     shloop = shellfacetraverse(subfaces);
06023   }
06024 
06025   // Calculate the total length of array 'facesperverlist'.
06026   j = idx2facelist[0];
06027   idx2facelist[0] = 0;  // Array starts from 0 element.
06028   for (i = 0; i < points->items; i++) {
06029     k = idx2facelist[i + 1];
06030     idx2facelist[i + 1] = idx2facelist[i] + j;
06031     j = k;
06032   }
06033   // The total length is in the last unit of idx2facelist.
06034   facesperverlist = new shellface*[idx2facelist[i]];
06035   // Loop the set of segments again, set the info. of segments per vertex.
06036   subfaces->traversalinit();
06037   shloop = shellfacetraverse(subfaces);
06038   while (shloop != (shellface *) NULL) {
06039     for (i = 0; i < 3; i++) {
06040       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06041       facesperverlist[idx2facelist[j]] = shloop;
06042       idx2facelist[j]++;
06043     }
06044     shloop = shellfacetraverse(subfaces);
06045   }
06046   // Contents in 'idx2facelist' are shifted, now shift them back.
06047   for (i = points->items - 1; i >= 0; i--) {
06048     idx2facelist[i + 1] = idx2facelist[i];
06049   }
06050   idx2facelist[0] = 0;
06051 }
06052 
06054 //                                                                           //
06055 // maketetrahedronmap()    Create a map from vertices (their indices) to     //
06056 //                         tetrahedra incident at the same vertices.         //
06057 //                                                                           //
06058 // Two arrays 'idx2tetlist' and 'tetsperverlist' together return the map.    //
06059 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
06060 // number of tetrahedra.  idx2tetlist contains row information and           //
06061 // tetsperverlist contains all (non-zero) elements.  The i-th entry of       //
06062 // idx2tetlist is the starting position of i-th row's (non-zero) elements in //
06063 // tetsperverlist.  The number of elements of i-th row is calculated by the  //
06064 // (i+1)-th entry minus i-th entry of idx2tetlist.                           //
06065 //                                                                           //
06066 // NOTE: These two arrays will be created inside this routine, don't forget  //
06067 // to free them after using.                                                 //
06068 //                                                                           //
06070 
06071 void tetgenmesh::
06072 maketetrahedronmap(int*& idx2tetlist, tetrahedron**& tetsperverlist)
06073 {
06074   tetrahedron *tetloop;
06075   int i, j, k;
06076 
06077   if (b->verbose > 0) {
06078     printf("  Constructing mapping from points to tetrahedra.\n");
06079   }
06080 
06081   // Create and initialize 'idx2tetlist'.
06082   idx2tetlist = new int[points->items + 1];
06083   for (i = 0; i < points->items + 1; i++) idx2tetlist[i] = 0;
06084 
06085   // Loop the set of tetrahedra once, counter the number of tetrahedra
06086   //   sharing each vertex.
06087   tetrahedrons->traversalinit();
06088   tetloop = tetrahedrontraverse();
06089   while (tetloop != (tetrahedron *) NULL) {
06090     // Increment the number of sharing tetrahedra for each endpoint.
06091     for (i = 0; i < 4; i++) {
06092       j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06093       idx2tetlist[j]++;
06094     }
06095     tetloop = tetrahedrontraverse();
06096   }
06097 
06098   // Calculate the total length of array 'tetsperverlist'.
06099   j = idx2tetlist[0];
06100   idx2tetlist[0] = 0;  // Array starts from 0 element.
06101   for (i = 0; i < points->items; i++) {
06102     k = idx2tetlist[i + 1];
06103     idx2tetlist[i + 1] = idx2tetlist[i] + j;
06104     j = k;
06105   }
06106   // The total length is in the last unit of idx2tetlist.
06107   tetsperverlist = new tetrahedron*[idx2tetlist[i]];
06108   // Loop the set of tetrahedra again, set the info. of tet. per vertex.
06109   tetrahedrons->traversalinit();
06110   tetloop = tetrahedrontraverse();
06111   while (tetloop != (tetrahedron *) NULL) {
06112     for (i = 0; i < 4; i++) {
06113       j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06114       tetsperverlist[idx2tetlist[j]] = tetloop;
06115       idx2tetlist[j]++;
06116     }
06117     tetloop = tetrahedrontraverse();
06118   }
06119   // Contents in 'idx2tetlist' are shifted, now shift them back.
06120   for (i = points->items - 1; i >= 0; i--) {
06121     idx2tetlist[i + 1] = idx2tetlist[i];
06122   }
06123   idx2tetlist[0] = 0;
06124 }
06125 
06126 //
06127 // End of mesh items searching routines
06128 //
06129 
06130 //
06131 // Begin of linear algebra functions
06132 //
06133 
06134 // dot() returns the dot product: v1 dot v2.
06135 
06136 inline REAL tetgenmesh::dot(REAL* v1, REAL* v2)
06137 {
06138   return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
06139 }
06140 
06141 // cross() computes the cross product: n = v1 cross v2.
06142 
06143 inline void tetgenmesh::cross(REAL* v1, REAL* v2, REAL* n)
06144 {
06145   n[0] =   v1[1] * v2[2] - v2[1] * v1[2];
06146   n[1] = -(v1[0] * v2[2] - v2[0] * v1[2]);
06147   n[2] =   v1[0] * v2[1] - v2[0] * v1[1];
06148 }
06149 
06150 // initm44() initializes a 4x4 matrix.
06151 static void initm44(REAL a00, REAL a01, REAL a02, REAL a03,
06152                     REAL a10, REAL a11, REAL a12, REAL a13,
06153                     REAL a20, REAL a21, REAL a22, REAL a23,
06154                     REAL a30, REAL a31, REAL a32, REAL a33,
06155                     REAL M[4][4])
06156 {
06157   M[0][0] = a00; M[0][1] = a01; M[0][2] = a02; M[0][3] = a03;
06158   M[1][0] = a10; M[1][1] = a11; M[1][2] = a12; M[1][3] = a13;
06159   M[2][0] = a20; M[2][1] = a21; M[2][2] = a22; M[2][3] = a23;
06160   M[3][0] = a30; M[3][1] = a31; M[3][2] = a32; M[3][3] = a33;
06161 }
06162 
06163 // m4xm4() multiplies 2 4x4 matrics:  m1 = m1 * m2.
06164 static void m4xm4(REAL m1[4][4], REAL m2[4][4])
06165 {
06166   REAL tmp[4];
06167   int i, j;
06168 
06169   for (i = 0; i < 4; i++) {   // i-th row
06170     for (j = 0; j < 4; j++) { // j-th col
06171       tmp[j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j]
06172              + m1[i][2] * m2[2][j] + m1[i][3] * m2[3][j];
06173     }
06174     for (j = 0; j < 4; j++)
06175       m1[i][j] = tmp[j];
06176   }
06177 }
06178 
06179 // m4xv4() multiplies a 4x4 matrix and 4x1 vector: v2 = m * v1
06180 static void m4xv4(REAL v2[4], REAL m[4][4], REAL v1[4])
06181 {
06182   v2[0] = m[0][0]*v1[0] + m[0][1]*v1[1] + m[0][2]*v1[2] + m[0][3]*v1[3];
06183   v2[1] = m[1][0]*v1[0] + m[1][1]*v1[1] + m[1][2]*v1[2] + m[1][3]*v1[3];
06184   v2[2] = m[2][0]*v1[0] + m[2][1]*v1[1] + m[2][2]*v1[2] + m[2][3]*v1[3];
06185   v2[3] = m[3][0]*v1[0] + m[3][1]*v1[1] + m[3][2]*v1[2] + m[3][3]*v1[3];
06186 }
06187 
06189 //                                                                           //
06190 // lu_decmp()    Compute the LU decomposition of a matrix.                   //
06191 //                                                                           //
06192 // Compute the LU decomposition of a (non-singular) square matrix A using    //
06193 // partial pivoting and implicit row exchanges.  The result is:              //
06194 //     A = P * L * U,                                                        //
06195 // where P is a permutation matrix, L is unit lower triangular, and U is     //
06196 // upper triangular.  The factored form of A is used in combination with     //
06197 // 'lu_solve()' to solve linear equations: Ax = b, or invert a matrix.       //
06198 //                                                                           //
06199 // The inputs are a square matrix 'lu[N..n+N-1][N..n+N-1]', it's size is 'n'.//
06200 // On output, 'lu' is replaced by the LU decomposition of a rowwise permuta- //
06201 // tion of itself, 'ps[N..n+N-1]' is an output vector that records the row   //
06202 // permutation effected by the partial pivoting, effectively,  'ps' array    //
06203 // tells the user what the permutation matrix P is; 'd' is output as +1/-1   //
06204 // depending on whether the number of row interchanges was even or odd,      //
06205 // respectively.                                                             //
06206 //                                                                           //
06207 // Return true if the LU decomposition is successfully computed, otherwise,  //
06208 // return false in case that A is a singular matrix.                         //
06209 //                                                                           //
06211 
06212 bool tetgenmesh::lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N)
06213 {
06214   REAL scales[4];
06215   REAL pivot, biggest, mult, tempf;
06216   int pivotindex = 0;
06217   int i, j, k;
06218 
06219   *d = 1.0;                                      // No row interchanges yet.
06220 
06221   for (i = N; i < n + N; i++) {                             // For each row.
06222     // Find the largest element in each row for row equilibration
06223     biggest = 0.0;
06224     for (j = N; j < n + N; j++)
06225       if (biggest < (tempf = fabs(lu[i][j])))
06226         biggest  = tempf;
06227     if (biggest != 0.0)
06228       scales[i] = 1.0 / biggest;
06229     else {
06230       scales[i] = 0.0;
06231       return false;                            // Zero row: singular matrix.
06232     }
06233     ps[i] = i;                                 // Initialize pivot sequence.
06234   }
06235 
06236   for (k = N; k < n + N - 1; k++) {                      // For each column.
06237     // Find the largest element in each column to pivot around.
06238     biggest = 0.0;
06239     for (i = k; i < n + N; i++) {
06240       if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
06241         biggest = tempf;
06242         pivotindex = i;
06243       }
06244     }
06245     if (biggest == 0.0) {
06246       return false;                         // Zero column: singular matrix.
06247     }
06248     if (pivotindex != k) {                         // Update pivot sequence.
06249       j = ps[k];
06250       ps[k] = ps[pivotindex];
06251       ps[pivotindex] = j;
06252       *d = -(*d);                          // ...and change the parity of d.
06253     }
06254 
06255     // Pivot, eliminating an extra variable  each time
06256     pivot = lu[ps[k]][k];
06257     for (i = k + 1; i < n + N; i++) {
06258       lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
06259       if (mult != 0.0) {
06260         for (j = k + 1; j < n + N; j++)
06261           lu[ps[i]][j] -= mult * lu[ps[k]][j];
06262       }
06263     }
06264   }
06265 
06266   // (lu[ps[n + N - 1]][n + N - 1] == 0.0) ==> A is singular.
06267   return lu[ps[n + N - 1]][n + N - 1] != 0.0;
06268 }
06269 
06271 //                                                                           //
06272 // lu_solve()    Solves the linear equation:  Ax = b,  after the matrix A    //
06273 //               has been decomposed into the lower and upper triangular     //
06274 //               matrices L and U, where A = LU.                             //
06275 //                                                                           //
06276 // 'lu[N..n+N-1][N..n+N-1]' is input, not as the matrix 'A' but rather as    //
06277 // its LU decomposition, computed by the routine 'lu_decmp'; 'ps[N..n+N-1]'  //
06278 // is input as the permutation vector returned by 'lu_decmp';  'b[N..n+N-1]' //
06279 // is input as the right-hand side vector, and returns with the solution     //
06280 // vector. 'lu', 'n', and 'ps' are not modified by this routine and can be   //
06281 // left in place for successive calls with different right-hand sides 'b'.   //
06282 //                                                                           //
06284 
06285 void tetgenmesh::lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N)
06286 {
06287   int i, j;
06288   REAL X[4], dot;
06289 
06290   for (i = N; i < n + N; i++) X[i] = 0.0;
06291 
06292   // Vector reduction using U triangular matrix.
06293   for (i = N; i < n + N; i++) {
06294     dot = 0.0;
06295     for (j = N; j < i + N; j++)
06296       dot += lu[ps[i]][j] * X[j];
06297     X[i] = b[ps[i]] - dot;
06298   }
06299 
06300   // Back substitution, in L triangular matrix.
06301   for (i = n + N - 1; i >= N; i--) {
06302     dot = 0.0;
06303     for (j = i + 1; j < n + N; j++)
06304       dot += lu[ps[i]][j] * X[j];
06305     X[i] = (X[i] - dot) / lu[ps[i]][i];
06306   }
06307 
06308   for (i = N; i < n + N; i++) b[i] = X[i];
06309 }
06310 
06311 //
06312 // End of linear algebra functions
06313 //
06314 
06315 //
06316 // Begin of geometric tests
06317 //
06318 
06319 // All the following routines require the input objects are not degenerate.
06320 //   i.e., a triangle must has three non-collinear corners; an edge must
06321 //   has two identical endpoints.  Degenerate cases should have to detect
06322 //   first and then handled as special cases.
06323 
06325 //                                                                           //
06326 // edge_vert_col_inter()    Test whether an edge (ab) and a collinear vertex //
06327 //                          (p) are intersecting or not.                     //
06328 //                                                                           //
06329 // Possible cases are p is coincident to a (p = a), or to b (p = b), or p is //
06330 // inside ab (a < p < b), or outside ab (p < a or p > b). These cases can be //
06331 // quickly determined by comparing the corresponding coords of a, b, and p   //
06332 // (which are not all equal).                                                //
06333 //                                                                           //
06334 // The return value indicates one of the three cases: DISJOINT, SHAREVERTEX  //
06335 // (p = a or p = b), and INTERSECT (a < p < b).                              //
06336 //                                                                           //
06338 
06339 enum tetgenmesh::interresult tetgenmesh::edge_vert_col_inter(REAL* A, REAL* B,
06340   REAL* P)
06341 {
06342   int i = 0;
06343   do {
06344     if (A[i] < B[i]) {
06345       if (P[i] < A[i]) {
06346         return DISJOINT;
06347       } else if (P[i] > A[i]) {
06348         if (P[i] < B[i]) {
06349           return INTERSECT;
06350         } else if (P[i] > B[i]) {
06351           return DISJOINT;
06352         } else {
06353           // assert(P[i] == B[i]);
06354           return SHAREVERTEX;
06355         }
06356       } else {
06357         // assert(P[i] == A[i]);
06358         return SHAREVERTEX;
06359       }
06360     } else if (A[i] > B[i]) {
06361       if (P[i] < B[i]) {
06362         return DISJOINT;
06363       } else if (P[i] > B[i]) {
06364         if (P[i] < A[i]) {
06365           return INTERSECT;
06366         } else if (P[i] > A[i]) {
06367           return DISJOINT;
06368         } else {
06369           // assert(P[i] == A[i]);
06370           return SHAREVERTEX;
06371         }
06372       } else {
06373         // assert(P[i] == B[i]);
06374         return SHAREVERTEX;
06375       }
06376     }
06377     // i-th coordinates are equal, try i+1-th;
06378     i++;
06379   } while (i < 3);
06380   // Should never be here.
06381   return DISJOINT;
06382 }
06383 
06385 //                                                                           //
06386 // edge_edge_cop_inter()    Test whether two coplanar edges (ab, and pq) are //
06387 //                          intersecting or not.                             //
06388 //                                                                           //
06389 // Possible cases are ab and pq are disjointed, or proper intersecting (int- //
06390 // ersect at a point other than their endpoints), or both collinear and int- //
06391 // ersecting, or sharing at a common endpoint, or are coincident.            //
06392 //                                                                           //
06393 // A reference point R is required, which is exactly not coplanar with these //
06394 // two edges.  Since the caller knows these two edges are coplanar, it must  //
06395 // be able to provide (or calculate) such a point.                           //
06396 //                                                                           //
06397 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06398 // SHAREEDGE, and INTERSECT.                                                 //
06399 //                                                                           //
06401 
06402 enum tetgenmesh::interresult tetgenmesh:: edge_edge_cop_inter(REAL* A, REAL* B,
06403   REAL* P, REAL* Q, REAL* R)
06404 {
06405   REAL s1, s2, s3, s4;
06406 
06407 #ifdef SELF_CHECK
06408   assert(R != NULL);
06409 #endif
06410   s1 = orient3d(A, B, R, P);
06411   s2 = orient3d(A, B, R, Q);
06412   if (s1 * s2 > 0.0) {
06413     // Both p and q are at the same side of ab.
06414     return DISJOINT;
06415   }
06416   s3 = orient3d(P, Q, R, A);
06417   s4 = orient3d(P, Q, R, B);
06418   if (s3 * s4 > 0.0) {
06419     // Both a and b are at the same side of pq.
06420     return DISJOINT;
06421   }
06422 
06423   // Possible degenerate cases are:
06424   //   (1) Only one of p and q is collinear with ab;
06425   //   (2) Both p and q are collinear with ab;
06426   //   (3) Only one of a and b is collinear with pq.
06427   enum interresult abp, abq;
06428   enum interresult pqa, pqb;
06429 
06430   if (s1 == 0.0) {
06431     // p is collinear with ab.
06432     abp = edge_vert_col_inter(A, B, P);
06433     if (abp == INTERSECT) {
06434       // p is inside ab.
06435       return INTERSECT;
06436     }
06437     if (s2 == 0.0) {
06438       // q is collinear with ab. Case (2).
06439       abq = edge_vert_col_inter(A, B, Q);
06440       if (abq == INTERSECT) {
06441         // q is inside ab.
06442         return INTERSECT;
06443       }
06444       if (abp == SHAREVERTEX && abq == SHAREVERTEX) {
06445         // ab and pq are identical.
06446         return SHAREEDGE;
06447       }
06448       pqa = edge_vert_col_inter(P, Q, A);
06449       if (pqa == INTERSECT) {
06450         // a is inside pq.
06451         return INTERSECT;
06452       }
06453       pqb = edge_vert_col_inter(P, Q, B);
06454       if (pqb == INTERSECT) {
06455         // b is inside pq.
06456         return INTERSECT;
06457       }
06458       if (abp == SHAREVERTEX || abq == SHAREVERTEX) {
06459         // either p or q is coincident with a or b.
06460 #ifdef SELF_CHECK
06461         // ONLY one case is possible, otherwise, shoule be SHAREEDGE.
06462         assert(abp ^ abq);
06463 #endif
06464         return SHAREVERTEX;
06465       }
06466       // The last case. They are disjointed.
06467 #ifdef SELF_CHECK
06468       assert((abp == DISJOINT) && (abp == abq && abq == pqa && pqa == pqb));
06469 #endif
06470       return DISJOINT;
06471     } else {
06472       // p is collinear with ab. Case (1).
06473 #ifdef SELF_CHECK
06474       assert(abp == SHAREVERTEX || abp == DISJOINT);
06475 #endif
06476       return abp;
06477     }
06478   }
06479   // p is NOT collinear with ab.
06480   if (s2 == 0.0) {
06481     // q is collinear with ab. Case (1).
06482     abq = edge_vert_col_inter(A, B, Q);
06483 #ifdef SELF_CHECK
06484     assert(abq == SHAREVERTEX || abq == DISJOINT || abq == INTERSECT);
06485 #endif
06486     return abq;
06487   }
06488 
06489   // We have found p and q are not collinear with ab. However, it is still
06490   //   possible that a or b is collinear with pq (ONLY one of a and b).
06491   if (s3 == 0.0) {
06492     // a is collinear with pq. Case (3).
06493 #ifdef SELF_CHECK
06494     assert(s4 != 0.0);
06495 #endif
06496     pqa = edge_vert_col_inter(P, Q, A);
06497 #ifdef SELF_CHECK
06498     // This case should have been detected in above.
06499     assert(pqa != SHAREVERTEX);
06500     assert(pqa == INTERSECT || pqa == DISJOINT);
06501 #endif
06502     return pqa;
06503   }
06504   if (s4 == 0.0) {
06505     // b is collinear with pq. Case (3).
06506 #ifdef SELF_CHECK
06507     assert(s3 != 0.0);
06508 #endif
06509     pqb = edge_vert_col_inter(P, Q, B);
06510 #ifdef SELF_CHECK
06511     // This case should have been detected in above.
06512     assert(pqb != SHAREVERTEX);
06513     assert(pqb == INTERSECT || pqb == DISJOINT);
06514 #endif
06515     return pqb;
06516   }
06517 
06518   // ab and pq are intersecting properly.
06519   return INTERSECT;
06520 }
06521 
06523 //                                                                           //
06524 // Notations                                                                 //
06525 //                                                                           //
06526 // Let ABC be the plane passes through a, b, and c;  ABC+ be the halfspace   //
06527 // including the set of all points x, such that orient3d(a, b, c, x) > 0;    //
06528 // ABC- be the other halfspace, such that for each point x in ABC-,          //
06529 // orient3d(a, b, c, x) < 0.  For the set of x which are on ABC, orient3d(a, //
06530 // b, c, x) = 0.                                                             //
06531 //                                                                           //
06533 
06535 //                                                                           //
06536 // tri_vert_copl_inter()    Test whether a triangle (abc) and a coplanar     //
06537 //                          point (p) are intersecting or not.               //
06538 //                                                                           //
06539 // Possible cases are p is inside abc, or on an edge of, or coincident with  //
06540 // a vertex of, or outside abc.                                              //
06541 //                                                                           //
06542 // A reference point R is required. R is exactly not coplanar with abc and p.//
06543 // Since the caller knows they are coplanar, it must be able to provide (or  //
06544 // calculate) such a point.                                                  //
06545 //                                                                           //
06546 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06547 // and INTERSECT.                                                            //
06548 //                                                                           //
06550 
06551 enum tetgenmesh::interresult tetgenmesh::tri_vert_cop_inter(REAL* A, REAL* B,
06552   REAL* C, REAL* P, REAL* R)
06553 {
06554   REAL s1, s2, s3;
06555   int sign;
06556 
06557 #ifdef SELF_CHECK
06558   assert(R != (REAL *) NULL);
06559 #endif
06560   // Adjust the orientation of a, b, c and r, so that we can assume that
06561   //   r is strictly in ABC- (i.e., r is above ABC wrt. right-hand rule).
06562   s1 = orient3d(A, B, C, R);
06563 #ifdef SELF_CHECK
06564   assert(s1 != 0.0);
06565 #endif
06566   sign = s1 < 0.0 ? 1 : -1;
06567 
06568   // Test starts from here.
06569   s1 = orient3d(A, B, R, P) * sign;
06570   if (s1 < 0.0) {
06571     // p is in ABR-.
06572     return DISJOINT;
06573   }
06574   s2 = orient3d(B, C, R, P) * sign;
06575   if (s2 < 0.0) {
06576     // p is in BCR-.
06577     return DISJOINT;
06578   }
06579   s3 = orient3d(C, A, R, P) * sign;
06580   if (s3 < 0.0) {
06581     // p is in CAR-.
06582     return DISJOINT;
06583   }
06584   if (s1 == 0.0) {
06585     // p is on ABR.
06586     if (s2 == 0.0) {
06587       // p is on BCR.
06588 #ifdef SELF_CHECK
06589       assert(s3 > 0.0);
06590 #endif
06591       // p is coincident with b.
06592       return SHAREVERTEX;
06593     }
06594     if (s3 == 0.0) {
06595       // p is on CAR.
06596       // p is coincident with a.
06597       return SHAREVERTEX;
06598     }
06599     // p is on edge ab.
06600     return INTERSECT;
06601   }
06602   // p is in ABR+.
06603   if (s2 == 0.0) {
06604     // p is on BCR.
06605     if (s3 == 0.0) {
06606       // p is on CAR.
06607       // p is coincident with c.
06608       return SHAREVERTEX;
06609     }
06610     // p is on edge bc.
06611     return INTERSECT;
06612   }
06613   if (s3 == 0.0) {
06614     // p is on CAR.
06615     // p is on edge ca.
06616     return INTERSECT;
06617   }
06618 
06619   // p is strictly inside abc.
06620   return INTERSECT;
06621 }
06622 
06624 //                                                                           //
06625 // tri_edge_cop_inter()    Test whether a triangle (abc) and a coplanar edge //
06626 //                         (pq) are intersecting or not.                     //
06627 //                                                                           //
06628 // A reference point R is required. R is exactly not coplanar with abc and   //
06629 // pq.  Since the caller knows they are coplanar, it must be able to provide //
06630 // (or calculate) such a point.                                              //
06631 //                                                                           //
06632 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06633 // SHAREEDGE, and INTERSECT.                                                 //
06634 //                                                                           //
06636 
06637 enum tetgenmesh::interresult tetgenmesh::tri_edge_cop_inter(REAL* A, REAL* B,
06638   REAL* C, REAL* P, REAL* Q, REAL* R)
06639 {
06640   enum interresult abpq, bcpq, capq;
06641   enum interresult abcp, abcq;
06642 
06643   // Test if pq is intersecting one of edges of abc.
06644   abpq = edge_edge_cop_inter(A, B, P, Q, R);
06645   if (abpq == INTERSECT || abpq == SHAREEDGE) {
06646     return abpq;
06647   }
06648   bcpq = edge_edge_cop_inter(B, C, P, Q, R);
06649   if (bcpq == INTERSECT || bcpq == SHAREEDGE) {
06650     return bcpq;
06651   }
06652   capq = edge_edge_cop_inter(C, A, P, Q, R);
06653   if (capq == INTERSECT || capq == SHAREEDGE) {
06654     return capq;
06655   }
06656 
06657   // Test if p and q is inside abc.
06658   abcp = tri_vert_cop_inter(A, B, C, P, R);
06659   if (abcp == INTERSECT) {
06660     return INTERSECT;
06661   }
06662   abcq = tri_vert_cop_inter(A, B, C, Q, R);
06663   if (abcq == INTERSECT) {
06664     return INTERSECT;
06665   }
06666 
06667   // Combine the test results of edge intersectings and triangle insides
06668   //   to detect whether abc and pq are sharing vertex or disjointed.
06669   if (abpq == SHAREVERTEX) {
06670     // p or q is coincident with a or b.
06671 #ifdef SELF_CHECK
06672     assert(abcp ^ abcq);
06673 #endif
06674     return SHAREVERTEX;
06675   }
06676   if (bcpq == SHAREVERTEX) {
06677     // p or q is coincident with b or c.
06678 #ifdef SELF_CHECK
06679     assert(abcp ^ abcq);
06680 #endif
06681     return SHAREVERTEX;
06682   }
06683   if (capq == SHAREVERTEX) {
06684     // p or q is coincident with c or a.
06685 #ifdef SELF_CHECK
06686     assert(abcp ^ abcq);
06687 #endif
06688     return SHAREVERTEX;
06689   }
06690 
06691   // They are disjointed.
06692   return DISJOINT;
06693 }
06694 
06696 //                                                                           //
06697 // tri_edge_inter_tail()    Test whether a triangle (abc) and an edge (pq)   //
06698 //                          are intersecting or not.                         //
06699 //                                                                           //
06700 // s1 and s2 are results of pre-performed orientation tests. s1 = orient3d(  //
06701 // a, b, c, p); s2 = orient3d(a, b, c, q).  To separate this routine from    //
06702 // tri_edge_inter() can save two orientation tests in tri_tri_inter().       //
06703 //                                                                           //
06704 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06705 // SHAREEDGE, and INTERSECT.                                                 //
06706 //                                                                           //
06708 
06709 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter_tail(REAL* A, REAL* B,
06710   REAL* C, REAL* P, REAL* Q, REAL s1, REAL s2)
06711 {
06712   REAL s3, s4, s5;
06713   int sign;
06714 
06715   if (s1 * s2 > 0.0) {
06716     // p, q are at the same halfspace of ABC, no intersection.
06717     return DISJOINT;
06718   }
06719 
06720   if (s1 * s2 < 0.0) {
06721     // p, q are both not on ABC (and not sharing vertices, edges of abc).
06722     // Adjust the orientation of a, b, c and p, so that we can assume that
06723     //   p is strictly in ABC-, and q is strictly in ABC+.
06724     sign = s1 < 0.0 ? 1 : -1;
06725     s3 = orient3d(A, B, P, Q) * sign;
06726     if (s3 < 0.0) {
06727       // q is at ABP-.
06728       return DISJOINT;
06729     }
06730     s4 = orient3d(B, C, P, Q) * sign;
06731     if (s4 < 0.0) {
06732       // q is at BCP-.
06733       return DISJOINT;
06734     }
06735     s5 = orient3d(C, A, P, Q) * sign;
06736     if (s5 < 0.0) {
06737       // q is at CAP-.
06738       return DISJOINT;
06739     }
06740     if (s3 == 0.0) {
06741       // q is on ABP.
06742       if (s4 == 0.0) {
06743         // q is on BCP (and q must in CAP+).
06744 #ifdef SELF_CHECK
06745         assert(s5 > 0.0);
06746 #endif
06747         // pq intersects abc at vertex b.
06748         return SHAREVERTEX;
06749       }
06750       if (s5 == 0.0) {
06751         // q is on CAP (and q must in BCP+).
06752         // pq intersects abc at vertex a.
06753         return SHAREVERTEX;
06754       }
06755       // q in both BCP+ and CAP+.
06756       // pq crosses ab properly.
06757       return INTERSECT;
06758     }
06759     // q is in ABP+;
06760     if (s4 == 0.0) {
06761       // q is on BCP.
06762       if (s5 == 0.0) {
06763         // q is on CAP.
06764         // pq intersects abc at vertex c.
06765         return SHAREVERTEX;
06766       }
06767       // pq crosses bc properly.
06768       return INTERSECT;
06769     }
06770     // q is in BCP+;
06771     if (s5 == 0.0) {
06772       // q is on CAP.
06773       // pq crosses ca properly.
06774       return INTERSECT;
06775     }
06776     // q is in CAP+;
06777     // pq crosses abc properly.
06778     return INTERSECT;
06779   }
06780 
06781   if (s1 != 0.0 || s2 != 0.0) {
06782     // Either p or q is coplanar with abc. ONLY one of them is possible.
06783     if (s1 == 0.0) {
06784       // p is coplanar with abc, q can be used as reference point.
06785 #ifdef SELF_CHECK
06786       assert(s2 != 0.0);
06787 #endif
06788       return tri_vert_cop_inter(A, B, C, P, Q);
06789     } else {
06790       // q is coplanar with abc, p can be used as reference point.
06791 #ifdef SELF_CHECK
06792       assert(s2 == 0.0);
06793 #endif
06794       return tri_vert_cop_inter(A, B, C, Q, P);
06795     }
06796   }
06797 
06798   // pq is coplanar with abc.  Calculate a point which is exactly not
06799   //   coplanar with a, b, and c.
06800   REAL R[3], N[3];
06801   REAL ax, ay, az, bx, by, bz;
06802 
06803   ax = A[0] - B[0];
06804   ay = A[1] - B[1];
06805   az = A[2] - B[2];
06806   bx = A[0] - C[0];
06807   by = A[1] - C[1];
06808   bz = A[2] - C[2];
06809   N[0] = ay * bz - by * az;
06810   N[1] = az * bx - bz * ax;
06811   N[2] = ax * by - bx * ay;
06812   // The normal should not be a zero vector (otherwise, abc are collinear).
06813 #ifdef SELF_CHECK
06814   assert((fabs(N[0]) + fabs(N[1]) + fabs(N[2])) > 0.0);
06815 #endif
06816   // The reference point R is lifted from A to the normal direction with
06817   //   a distance d = average edge length of the triangle abc.
06818   R[0] = N[0] + A[0];
06819   R[1] = N[1] + A[1];
06820   R[2] = N[2] + A[2];
06821   // Becareful the case: if the non-zero component(s) in N is smaller than
06822   //   the machine epsilon (i.e., 2^(-16) for double), R will exactly equal
06823   //   to A due to the round-off error.  Do check if it is.
06824   if (R[0] == A[0] && R[1] == A[1] && R[2] == A[2]) {
06825     int i, j;
06826     for (i = 0; i < 3; i++) {
06827 #ifdef SELF_CHECK
06828       assert (R[i] == A[i]);
06829 #endif
06830       j = 2;
06831       do {
06832         if (N[i] > 0.0) {
06833           N[i] += (j * macheps);
06834         } else {
06835           N[i] -= (j * macheps);
06836         }
06837         R[i] = N[i] + A[i];
06838         j *= 2;
06839       } while (R[i] == A[i]);
06840     }
06841   }
06842 
06843   return tri_edge_cop_inter(A, B, C, P, Q, R);
06844 }
06845 
06847 //                                                                           //
06848 // tri_edge_inter()    Test whether a triangle (abc) and an edge (pq) are    //
06849 //                     intersecting or not.                                  //
06850 //                                                                           //
06851 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06852 // SHAREEDGE, and INTERSECT.                                                 //
06853 //                                                                           //
06855 
06856 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter(REAL* A, REAL* B,
06857   REAL* C, REAL* P, REAL* Q)
06858 {
06859   REAL s1, s2;
06860 
06861   // Test the locations of p and q with respect to ABC.
06862   s1 = orient3d(A, B, C, P);
06863   s2 = orient3d(A, B, C, Q);
06864 
06865   return tri_edge_inter_tail(A, B, C, P, Q, s1, s2);
06866 }
06867 
06869 //                                                                           //
06870 // tri_tri_inter()    Test whether two triangle (abc) and (opq) are          //
06871 //                    intersecting or not.                                   //
06872 //                                                                           //
06873 // The return value indicates one of the five cases: DISJOINT, SHAREVERTEX,  //
06874 // SHAREEDGE, SHAREFACE, and INTERSECT.                                      //
06875 //                                                                           //
06877 
06878 enum tetgenmesh::interresult tetgenmesh::tri_tri_inter(REAL* A, REAL* B,
06879   REAL* C, REAL* O, REAL* P, REAL* Q)
06880 {
06881   REAL s_o, s_p, s_q;
06882   REAL s_a, s_b, s_c;
06883 
06884   s_o = orient3d(A, B, C, O);
06885   s_p = orient3d(A, B, C, P);
06886   s_q = orient3d(A, B, C, Q);
06887   if ((s_o * s_p > 0.0) && (s_o * s_q > 0.0)) {
06888     // o, p, q are all in the same halfspace of ABC.
06889     return DISJOINT;
06890   }
06891 
06892   s_a = orient3d(O, P, Q, A);
06893   s_b = orient3d(O, P, Q, B);
06894   s_c = orient3d(O, P, Q, C);
06895   if ((s_a * s_b > 0.0) && (s_a * s_c > 0.0)) {
06896     // a, b, c are all in the same halfspace of OPQ.
06897     return DISJOINT;
06898   }
06899 
06900   enum interresult abcop, abcpq, abcqo;
06901   int shareedge = 0;
06902 
06903   abcop = tri_edge_inter_tail(A, B, C, O, P, s_o, s_p);
06904   if (abcop == INTERSECT) {
06905     return INTERSECT;
06906   } else if (abcop == SHAREEDGE) {
06907     shareedge++;
06908   }
06909   abcpq = tri_edge_inter_tail(A, B, C, P, Q, s_p, s_q);
06910   if (abcpq == INTERSECT) {
06911     return INTERSECT;
06912   } else if (abcpq == SHAREEDGE) {
06913     shareedge++;
06914   }
06915   abcqo = tri_edge_inter_tail(A, B, C, Q, O, s_q, s_o);
06916   if (abcqo == INTERSECT) {
06917     return INTERSECT;
06918   } else if (abcqo == SHAREEDGE) {
06919     shareedge++;
06920   }
06921   if (shareedge == 3) {
06922     // opq are coincident with abc.
06923     return SHAREFACE;
06924   }
06925 #ifdef SELF_CHECK
06926   // It is only possible either no share edge or one.
06927   assert(shareedge == 0 || shareedge == 1);
06928 #endif
06929 
06930   // Continue to detect whether opq and abc are intersecting or not.
06931   enum interresult opqab, opqbc, opqca;
06932 
06933   opqab = tri_edge_inter_tail(O, P, Q, A, B, s_a, s_b);
06934   if (opqab == INTERSECT) {
06935     return INTERSECT;
06936   }
06937   opqbc = tri_edge_inter_tail(O, P, Q, B, C, s_b, s_c);
06938   if (opqbc == INTERSECT) {
06939     return INTERSECT;
06940   }
06941   opqca = tri_edge_inter_tail(O, P, Q, C, A, s_c, s_a);
06942   if (opqca == INTERSECT) {
06943     return INTERSECT;
06944   }
06945 
06946   // At this point, two triangles are not intersecting and not coincident.
06947   //   They may be share an edge, or share a vertex, or disjoint.
06948   if (abcop == SHAREEDGE) {
06949 #ifdef SELF_CHECK
06950     assert(abcpq == SHAREVERTEX && abcqo == SHAREVERTEX);
06951 #endif
06952     // op is coincident with an edge of abc.
06953     return SHAREEDGE;
06954   }
06955   if (abcpq == SHAREEDGE) {
06956 #ifdef SELF_CHECK
06957     assert(abcop == SHAREVERTEX && abcqo == SHAREVERTEX);
06958 #endif
06959     // pq is coincident with an edge of abc.
06960     return SHAREEDGE;
06961   }
06962   if (abcqo == SHAREEDGE) {
06963 #ifdef SELF_CHECK
06964     assert(abcop == SHAREVERTEX && abcpq == SHAREVERTEX);
06965 #endif
06966     // qo is coincident with an edge of abc.
06967     return SHAREEDGE;
06968   }
06969 
06970   // They may share a vertex or disjoint.
06971   if (abcop == SHAREVERTEX) {
06972     // o or p is coincident with a vertex of abc.
06973     if (abcpq == SHAREVERTEX) {
06974       // p is the coincident vertex.
06975 #ifdef SELF_CHECK
06976       assert(abcqo != SHAREVERTEX);
06977 #endif
06978     } else {
06979       // o is the coincident vertex.
06980 #ifdef SELF_CHECK
06981       assert(abcqo == SHAREVERTEX);
06982 #endif
06983     }
06984     return SHAREVERTEX;
06985   }
06986   if (abcpq == SHAREVERTEX) {
06987     // q is the coincident vertex.
06988 #ifdef SELF_CHECK
06989     assert(abcqo == SHAREVERTEX);
06990 #endif
06991     return SHAREVERTEX;
06992   }
06993 
06994   // They are disjoint.
06995   return DISJOINT;
06996 }
06997 
06999 //                                                                           //
07000 // insphere_sos()    Insphere test with symbolic perturbation.               //
07001 //                                                                           //
07002 // The input points a, b, c, and d should be non-coplanar. They must be ord- //
07003 // ered so that they have a positive orientation (as defined by orient3d()), //
07004 // or the sign of the result will be reversed.                               //
07005 //                                                                           //
07006 // Return a positive value if the point e lies inside the circumsphere of a, //
07007 // b, c, and d; a negative value if it lies outside.                         //
07008 //                                                                           //
07010 
07011 REAL tetgenmesh::insphere_sos(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
07012   int ia, int ib, int ic, int id, int ie)
07013 {
07014   REAL det;
07015 
07016   det = insphere(pa, pb, pc, pd, pe);
07017   if (det != 0.0) {
07018     return det;
07019   }
07020 
07021   // det = 0.0, use symbolic perturbation.
07022   REAL *p[5], *tmpp;
07023   REAL sign, det_c, det_d;
07024   int idx[5], perm, tmp;
07025   int n, i, j;
07026 
07027   p[0] = pa; idx[0] = ia;
07028   p[1] = pb; idx[1] = ib;
07029   p[2] = pc; idx[2] = ic;
07030   p[3] = pd; idx[3] = id;
07031   p[4] = pe; idx[4] = ie;
07032 
07033   // Bubble sort the points by the increasing order of the indices.
07034   n = 5;
07035   perm = 0; // The number of total swaps.
07036   for (i = 0; i < n - 1; i++) {
07037     for (j = 0; j < n - 1 - i; j++) {
07038       if (idx[j + 1] < idx[j]) {  // compare the two neighbors.
07039         tmp = idx[j];         // swap idx[j] and idx[j + 1]
07040         idx[j] = idx[j + 1];
07041         idx[j + 1] = tmp;
07042         tmpp = p[j];         // swap p[j] and p[j + 1]
07043         p[j] = p[j + 1];
07044         p[j + 1] = tmpp;
07045         perm++;
07046       }
07047     }
07048   }
07049 
07050   sign = (perm % 2 == 0) ? 1.0 : -1.0;
07051   det_c = orient3d(p[1], p[2], p[3], p[4]); // orient3d(b, c, d, e)
07052   if (det_c != 0.0) {
07053     return sign * det_c;
07054   }
07055   det_d = orient3d(p[0], p[2], p[3], p[4]); // orient3d(a, c, d, e)
07056   return -sign * det_d;
07057 }
07058 
07060 //                                                                           //
07061 // iscollinear()    Check if three points are approximately collinear.       //
07062 //                                                                           //
07063 // 'eps' is a relative error tolerance.  The collinearity is determined by   //
07064 // the value q = cos(theta), where theta is the angle between two vectors    //
07065 // A->B and A->C.  They're collinear if 1.0 - q <= epspp.                    //
07066 //                                                                           //
07068 
07069 bool tetgenmesh::iscollinear(REAL* A, REAL* B, REAL* C, REAL eps)
07070 {
07071   REAL abx, aby, abz;
07072   REAL acx, acy, acz;
07073   REAL Lv, Lw, dd;
07074   REAL d, q;
07075 
07076   // Limit of two closed points.
07077   q = longest * eps;
07078   q *= q;
07079 
07080   abx = A[0] - B[0];
07081   aby = A[1] - B[1];
07082   abz = A[2] - B[2];
07083   acx = A[0] - C[0];
07084   acy = A[1] - C[1];
07085   acz = A[2] - C[2];
07086   Lv = abx * abx + aby * aby + abz * abz;
07087   // Is AB (nearly) indentical?
07088   if (Lv < q) return true;
07089   Lw = acx * acx + acy * acy + acz * acz;
07090   // Is AC (nearly) indentical?
07091   if (Lw < q) return true;
07092   dd = abx * acx + aby * acy + abz * acz;
07093 
07094   d = (dd * dd) / (Lv * Lw);
07095   if (d > 1.0) d = 1.0; // Rounding.
07096   q = 1.0 - sqrt(d); // Notice 0 < q < 1.0.
07097 
07098   return q <= eps;
07099 }
07100 
07102 //                                                                           //
07103 // iscoplanar()    Check if four points are approximately coplanar.          //
07104 //                                                                           //
07105 // 'vol6' is six times of the signed volume of the tetrahedron formed by the //
07106 // four points. 'eps' is the relative error tolerance.  The coplanarity is   //
07107 // determined by the value: q = fabs(vol6) / L^3,  where L is the average    //
07108 // edge length of the tet. They're coplanar if q <= eps.                     //
07109 //                                                                           //
07111 
07112 bool tetgenmesh::
07113 iscoplanar(REAL* k, REAL* l, REAL* m, REAL* n, REAL vol6, REAL eps)
07114 {
07115   REAL L, q;
07116   REAL x, y, z;
07117 
07118   if (vol6 == 0.0) return true;
07119 
07120   x = k[0] - l[0];
07121   y = k[1] - l[1];
07122   z = k[2] - l[2];
07123   L = sqrt(x * x + y * y + z * z);
07124   x = l[0] - m[0];
07125   y = l[1] - m[1];
07126   z = l[2] - m[2];
07127   L += sqrt(x * x + y * y + z * z);
07128   x = m[0] - k[0];
07129   y = m[1] - k[1];
07130   z = m[2] - k[2];
07131   L += sqrt(x * x + y * y + z * z);
07132   x = k[0] - n[0];
07133   y = k[1] - n[1];
07134   z = k[2] - n[2];
07135   L += sqrt(x * x + y * y + z * z);
07136   x = l[0] - n[0];
07137   y = l[1] - n[1];
07138   z = l[2] - n[2];
07139   L += sqrt(x * x + y * y + z * z);
07140   x = m[0] - n[0];
07141   y = m[1] - n[1];
07142   z = m[2] - n[2];
07143   L += sqrt(x * x + y * y + z * z);
07144 #ifdef SELF_CHECK
07145   assert(L > 0.0);
07146 #endif
07147   L /= 6.0;
07148   q = fabs(vol6) / (L * L * L);
07149 
07150   return q <= eps;
07151 }
07152 
07154 //                                                                           //
07155 // iscospheric()    Check if five points are approximately coplanar.         //
07156 //                                                                           //
07157 // 'vol24' is the 24 times of the signed volume of the 4-dimensional simplex //
07158 // formed by the five points. 'eps' is the relative tolerance. The cosphere  //
07159 // case is determined by the value: q = fabs(vol24) / L^4,  where L is the   //
07160 // average edge length of the simplex. They're cosphere if q <= eps.         //
07161 //                                                                           //
07163 
07164 bool tetgenmesh::
07165 iscospheric(REAL* k, REAL* l, REAL* m, REAL* n, REAL* o, REAL vol24, REAL eps)
07166 {
07167   REAL L, q;
07168 
07169   // A 4D simplex has 10 edges.
07170   L = distance(k, l);
07171   L += distance(l, m);
07172   L += distance(m, k);
07173   L += distance(k, n);
07174   L += distance(l, n);
07175   L += distance(m, n);
07176   L += distance(k, o);
07177   L += distance(l, o);
07178   L += distance(m, o);
07179   L += distance(n, o);
07180 #ifdef SELF_CHECK
07181   assert(L > 0.0);
07182 #endif
07183   L /= 10.0;
07184   q = fabs(vol24) / (L * L * L * L);
07185 
07186   return q < eps;
07187 }
07188 
07189 //
07190 // End of geometric tests
07191 //
07192 
07193 //
07194 // Begin of Geometric quantities calculators
07195 //
07196 
07197 // distance() computs the Euclidean distance between two points.
07198 inline REAL tetgenmesh::distance(REAL* p1, REAL* p2)
07199 {
07200   return sqrt((p2[0] - p1[0]) * (p2[0] - p1[0]) +
07201               (p2[1] - p1[1]) * (p2[1] - p1[1]) +
07202               (p2[2] - p1[2]) * (p2[2] - p1[2]));
07203 }
07204 
07206 //                                                                           //
07207 // shortdistance()    Returns the shortest distance from point p to a line   //
07208 //                    defined by two points e1 and e2.                       //
07209 //                                                                           //
07210 // First compute the projection length l_p of the vector v1 = p - e1 along   //
07211 // the vector v2 = e2 - e1. Then Pythagoras' Theorem is used to compute the  //
07212 // shortest distance.                                                        //
07213 //                                                                           //
07214 // This routine allows that p is collinear with the line. In this case, the  //
07215 // return value is zero. The two points e1 and e2 should not be identical.   //
07216 //                                                                           //
07218 
07219 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2)
07220 {
07221   REAL v1[3], v2[3];
07222   REAL len, l_p;
07223 
07224   v1[0] = e2[0] - e1[0];
07225   v1[1] = e2[1] - e1[1];
07226   v1[2] = e2[2] - e1[2];
07227   v2[0] = p[0] - e1[0];
07228   v2[1] = p[1] - e1[1];
07229   v2[2] = p[2] - e1[2];
07230 
07231   len = sqrt(dot(v1, v1));
07232 #ifdef SELF_CHECK
07233   assert(len != 0.0);
07234 #endif
07235   v1[0] /= len;
07236   v1[1] /= len;
07237   v1[2] /= len;
07238   l_p = dot(v1, v2);
07239 
07240   return sqrt(dot(v2, v2) - l_p * l_p);
07241 }
07242 
07244 //                                                                           //
07245 // shortdistance()    Returns the shortest distance from point p to a face.  //
07246 //                                                                           //
07248 
07249 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2, REAL* e3)
07250 {
07251   REAL prj[3];
07252 
07253   projpt2face(p, e1, e2, e3, prj);
07254   return distance(p, prj);
07255 }
07256 
07258 //                                                                           //
07259 // interiorangle()    Return the interior angle (0 - 2 * PI) between vectors //
07260 //                    o->p1 and o->p2.                                       //
07261 //                                                                           //
07262 // 'n' is the normal of the plane containing face (o, p1, p2).  The interior //
07263 // angle is the total angle rotating from o->p1 around n to o->p2.  Exchange //
07264 // the position of p1 and p2 will get the complement angle of the other one. //
07265 // i.e., interiorangle(o, p1, p2) = 2 * PI - interiorangle(o, p2, p1).  Set  //
07266 // 'n' be NULL if you only want the interior angle between 0 - PI.           //
07267 //                                                                           //
07269 
07270 REAL tetgenmesh::interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n)
07271 {
07272   REAL v1[3], v2[3], np[3];
07273   REAL theta, costheta, lenlen;
07274   REAL ori, len1, len2;
07275 
07276   // Get the interior angle (0 - PI) between o->p1, and o->p2.
07277   v1[0] = p1[0] - o[0];
07278   v1[1] = p1[1] - o[1];
07279   v1[2] = p1[2] - o[2];
07280   v2[0] = p2[0] - o[0];
07281   v2[1] = p2[1] - o[1];
07282   v2[2] = p2[2] - o[2];
07283   len1 = sqrt(dot(v1, v1));
07284   len2 = sqrt(dot(v2, v2));
07285   lenlen = len1 * len2;
07286 #ifdef SELF_CHECK
07287   assert(lenlen != 0.0);
07288 #endif
07289   costheta = dot(v1, v2) / lenlen;
07290   if (costheta > 1.0) {
07291     costheta = 1.0; // Roundoff.
07292   } else if (costheta < -1.0) {
07293     costheta = -1.0; // Roundoff.
07294   }
07295   theta = acos(costheta);
07296   if (n != NULL) {
07297     // Get a point above the face (o, p1, p2);
07298     np[0] = o[0] + n[0];
07299     np[1] = o[1] + n[1];
07300     np[2] = o[2] + n[2];
07301     // Adjust theta (0 - 2 * PI).
07302     ori = orient3d(p1, o, np, p2);
07303     if (ori > 0.0) {
07304       theta = 2 * PI - theta;
07305     }
07306   }
07307 
07308   return theta;
07309 }
07310 
07312 //                                                                           //
07313 // projpt2edge()    Return the projection point from a point to an edge.     //
07314 //                                                                           //
07316 
07317 void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj)
07318 {
07319   REAL v1[3], v2[3];
07320   REAL len, l_p;
07321 
07322   v1[0] = e2[0] - e1[0];
07323   v1[1] = e2[1] - e1[1];
07324   v1[2] = e2[2] - e1[2];
07325   v2[0] = p[0] - e1[0];
07326   v2[1] = p[1] - e1[1];
07327   v2[2] = p[2] - e1[2];
07328 
07329   len = sqrt(dot(v1, v1));
07330 #ifdef SELF_CHECK
07331   assert(len != 0.0);
07332 #endif
07333   v1[0] /= len;
07334   v1[1] /= len;
07335   v1[2] /= len;
07336   l_p = dot(v1, v2);
07337 
07338   prj[0] = e1[0] + l_p * v1[0];
07339   prj[1] = e1[1] + l_p * v1[1];
07340   prj[2] = e1[2] + l_p * v1[2];
07341 }
07342 
07344 //                                                                           //
07345 // projpt2face()    Return the projection point from a point to a face.      //
07346 //                                                                           //
07348 
07349 void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj)
07350 {
07351   REAL fnormal[3], v1[3];
07352   REAL len, dist;
07353 
07354   // Get the unit face normal.
07355   facenormal(f1, f2, f3, fnormal, &len);
07356 #ifdef SELF_CHECK
07357   assert(len > 0.0);
07358 #endif
07359   fnormal[0] /= len;
07360   fnormal[1] /= len;
07361   fnormal[2] /= len;
07362   // Get the vector v1 = |p - f1|.
07363   v1[0] = p[0] - f1[0];
07364   v1[1] = p[1] - f1[1];
07365   v1[2] = p[2] - f1[2];
07366   // Get the project distance.
07367   dist = dot(fnormal, v1);
07368 
07369   // Get the project point.
07370   prj[0] = p[0] - dist * fnormal[0];
07371   prj[1] = p[1] - dist * fnormal[1];
07372   prj[2] = p[2] - dist * fnormal[2];
07373 }
07374 
07376 //                                                                           //
07377 // facenormal()    Calculate the normal of a face given by three points.     //
07378 //                                                                           //
07379 // In general, the face normal can be calculate by the cross product of any  //
07380 // pair of the three edge vectors.  However, if the three points are nearly  //
07381 // collinear, the rounding error may harm the result. To choose a good pair  //
07382 // of vectors is helpful to reduce the error.                                //
07383 //                                                                           //
07385 
07386 void tetgenmesh::facenormal(REAL* pa, REAL* pb, REAL* pc, REAL* n, REAL* nlen)
07387 {
07388   REAL v1[3], v2[3];
07389 
07390   v1[0] = pb[0] - pa[0];
07391   v1[1] = pb[1] - pa[1];
07392   v1[2] = pb[2] - pa[2];
07393   v2[0] = pc[0] - pa[0];
07394   v2[1] = pc[1] - pa[1];
07395   v2[2] = pc[2] - pa[2];
07396 
07397   cross(v1, v2, n);
07398   if (nlen != (REAL *) NULL) {
07399     *nlen = sqrt(dot(n, n));
07400   }
07401 }
07402 
07404 //                                                                           //
07405 // edgeorthonormal()    Return the unit normal of an edge in a given plane.  //
07406 //                                                                           //
07407 // The edge is from e1 to e2,  the plane is defined by given an additional   //
07408 // point op, which is non-collinear with the edge.  In addition, the side of //
07409 // the edge in which op lies defines the positive position of the normal.    //
07410 //                                                                           //
07411 // Let v1 be the unit vector from e1 to e2, v2 be the unit edge vector from  //
07412 // e1 to op, fn be the unit face normal calculated by fn = v1 x v2. Then the //
07413 // unit edge normal of e1e2 pointing to op is n = fn x v1.  Note, we should  //
07414 // not change the position of fn and v1, otherwise, we get the edge normal   //
07415 // pointing to the other side of op.                                         //
07416 //                                                                           //
07418 
07419 void tetgenmesh::edgeorthonormal(REAL* e1, REAL* e2, REAL* op, REAL* n)
07420 {
07421   REAL v1[3], v2[3], fn[3];
07422   REAL len;
07423 
07424   // Get the edge vector v1.
07425   v1[0] = e2[0] - e1[0];
07426   v1[1] = e2[1] - e1[1];
07427   v1[2] = e2[2] - e1[2];
07428   // Get the edge vector v2.
07429   v2[0] = op[0] - e1[0];
07430   v2[1] = op[1] - e1[1];
07431   v2[2] = op[2] - e1[2];
07432   // Get the face normal fn = v1 x v2.
07433   cross(v1, v2, fn);
07434   // Get the edge normal n pointing to op. n = fn x v1.
07435   cross(fn, v1, n);
07436   // Normalize the vector.
07437   len = sqrt(dot(n, n));
07438   n[0] /= len;
07439   n[1] /= len;
07440   n[2] /= len;
07441 }
07442 
07444 //                                                                           //
07445 // facedihedral()    Return the dihedral angle (in radian) between two       //
07446 //                   adjoining faces.                                        //
07447 //                                                                           //
07448 // 'pa', 'pb' are the shared edge of these two faces, 'pc1', and 'pc2' are   //
07449 // apexes of these two faces.  Return the angle (between 0 to 2*pi) between  //
07450 // the normal of face (pa, pb, pc1) and normal of face (pa, pb, pc2).        //
07451 //                                                                           //
07453 
07454 REAL tetgenmesh::facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2)
07455 {
07456   REAL n1[3], n2[3];
07457   REAL n1len, n2len;
07458   REAL costheta, ori;
07459   REAL theta;
07460 
07461   facenormal(pa, pb, pc1, n1, &n1len);
07462   facenormal(pa, pb, pc2, n2, &n2len);
07463   costheta = dot(n1, n2) / (n1len * n2len);
07464   // Be careful rounding error!
07465   if (costheta > 1.0) {
07466     costheta = 1.0;
07467   } else if (costheta < -1.0) {
07468     costheta = -1.0;
07469   }
07470   theta = acos(costheta);
07471   ori = orient3d(pa, pb, pc1, pc2);
07472   if (ori > 0.0) {
07473     theta = 2 * PI - theta;
07474   }
07475 
07476   return theta;
07477 }
07478 
07480 //                                                                           //
07481 // tetalldihedral()    Get all (six) dihedral angles of a tet.               //
07482 //                                                                           //
07483 // The tet is given by its four corners a, b, c, and d. If 'cosdd' is not    //
07484 // NULL, it returns the cosines of the 6 dihedral angles, the corresponding  //
07485 // edges are: ab, bc, ca, ad, bd, and cd. If 'cosmaxd' (or 'cosmind') is not //
07486 // NULL, it returns the cosine of the maximal (or minimal) dihedral angle.   //
07487 //                                                                           //
07489 
07490 void tetgenmesh::tetalldihedral(point pa, point pb, point pc, point pd,
07491   REAL* cosdd, REAL* cosmaxd, REAL* cosmind)
07492 {
07493   REAL N[4][3], cosd, len;
07494   int f1, f2, i, j;
07495 
07496   f1=0;
07497   f2=0;
07498 
07499   // Get four normals of faces of the tet.
07500   tetallnormal(pa, pb, pc, pd, N, NULL);
07501   // Normalize the normals.
07502   for (i = 0; i < 4; i++) {
07503     len = sqrt(dot(N[i], N[i]));
07504     if (len != 0.0) {
07505       for (j = 0; j < 3; j++) N[i][j] /= len;
07506     }
07507   }
07508 
07509   for (i = 0; i < 6; i++) {
07510     switch (i) {
07511     case 0: f1 = 2; f2 = 3; break; // edge ab.
07512     case 1: f1 = 0; f2 = 3; break; // edge bc.
07513     case 2: f1 = 1; f2 = 3; break; // edge ca.
07514     case 3: f1 = 1; f2 = 2; break; // edge ad.
07515     case 4: f1 = 2; f2 = 0; break; // edge bd.
07516     case 5: f1 = 0; f2 = 1; break; // edge cd.
07517     }
07518     cosd = -dot(N[f1], N[f2]);
07519     if (cosdd) cosdd[i] = cosd;
07520     if (i == 0) {
07521       if (cosmaxd) *cosmaxd = cosd;
07522       if (cosmind) *cosmind = cosd;
07523     } else {
07524       if (cosmaxd) *cosmaxd = cosd < *cosmaxd ? cosd : *cosmaxd;
07525       if (cosmind) *cosmind = cosd > *cosmind ? cosd : *cosmind;
07526     }
07527   }
07528 }
07529 
07531 //                                                                           //
07532 // tetallnormal()    Get the in-noramls of the four faces of a given tet.    //
07533 //                                                                           //
07534 // Let tet be abcd. N[4][3] returns the four normals, which are: N[0] cbd,   //
07535 // N[1] acd, N[2] bad, N[3] abc. These normals are unnormalized.             //
07536 //                                                                           //
07538 
07539 void tetgenmesh::tetallnormal(point pa, point pb, point pc, point pd,
07540   REAL N[4][3], REAL* volume)
07541 {
07542   REAL A[4][4], rhs[4], D;
07543   int indx[4];
07544   int i, j;
07545 
07546   // get the entries of A[3][3].
07547   for (i = 0; i < 3; i++) A[0][i] = pa[i] - pd[i];  // d->a vec
07548   for (i = 0; i < 3; i++) A[1][i] = pb[i] - pd[i];  // d->b vec
07549   for (i = 0; i < 3; i++) A[2][i] = pc[i] - pd[i];  // d->c vec
07550   // Compute the inverse of matrix A, to get 3 normals of the 4 faces.
07551   lu_decmp(A, 3, indx, &D, 0);     // Decompose the matrix just once.
07552   if (volume != NULL) {
07553     // Get the volume of the tet.
07554     *volume = fabs((A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2])) / 6.0;
07555   }
07556   for (j = 0; j < 3; j++) {
07557     for (i = 0; i < 3; i++) rhs[i] = 0.0;
07558     rhs[j] = 1.0;  // Positive means the inside direction
07559     lu_solve(A, 3, indx, rhs, 0);
07560     for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07561   }
07562   // Get the fourth normal by summing up the first three.
07563   for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07564 }
07565 
07567 //                                                                           //
07568 // tetaspectratio()    Calculate the aspect ratio of the tetrahedron.        //
07569 //                                                                           //
07570 // The aspect ratio of a tet is R/h, where R is the circumradius and h is    //
07571 // the shortest height of the tet.                                           //
07572 //                                                                           //
07574 
07575 REAL tetgenmesh::tetaspectratio(point pa, point pb, point pc, point pd)
07576 {
07577   REAL vda[3], vdb[3], vdc[3];
07578   REAL N[4][3], A[4][4], rhs[4], D;
07579   REAL H[4], volume, radius2, minheightinv;
07580   int indx[4];
07581   int i, j;
07582 
07583   // Set the matrix A = [vda, vdb, vdc]^T.
07584   for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
07585   for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
07586   for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
07587   // Lu-decompose the matrix A.
07588   lu_decmp(A, 3, indx, &D, 0);
07589   // Get the volume of abcd.
07590   volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
07591   // Check if it is zero.
07592   if (volume == 0.0) return 1.0e+200; // A degenerate tet.
07593   // if (volume < 0.0) volume = -volume;
07594   // Check the radiu-edge ratio of the tet.
07595   rhs[0] = 0.5 * dot(vda, vda);
07596   rhs[1] = 0.5 * dot(vdb, vdb);
07597   rhs[2] = 0.5 * dot(vdc, vdc);
07598   lu_solve(A, 3, indx, rhs, 0);
07599   // Get the circumcenter.
07600   // for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
07601   // Get the square of the circumradius.
07602   radius2 = dot(rhs, rhs);
07603 
07604   // Compute the 4 face normals (N[0], ..., N[3]).
07605   for (j = 0; j < 3; j++) {
07606     for (i = 0; i < 3; i++) rhs[i] = 0.0;
07607     rhs[j] = 1.0;  // Positive means the inside direction
07608     lu_solve(A, 3, indx, rhs, 0);
07609     for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07610   }
07611   // Get the fourth normal by summing up the first three.
07612   for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07613   // Normalized the normals.
07614   for (i = 0; i < 4; i++) {
07615     // H[i] is the inverse of the height of its corresponding face.
07616     H[i] = sqrt(dot(N[i], N[i]));
07617     // if (H[i] > 0.0) {
07618     //   for (j = 0; j < 3; j++) N[i][j] /= H[i];
07619     // }
07620   }
07621   // Get the radius of the inscribed sphere.
07622   // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]);
07623   // Get the biggest H[i] (corresponding to the smallest height).
07624   minheightinv = H[0];
07625   for (i = 1; i < 3; i++) {
07626     if (H[i] > minheightinv) minheightinv = H[i];
07627   }
07628 
07629   return sqrt(radius2) * minheightinv;
07630 }
07631 
07633 //                                                                           //
07634 // circumsphere()    Calculate the smallest circumsphere (center and radius) //
07635 //                   of the given three or four points.                      //
07636 //                                                                           //
07637 // The circumsphere of four points (a tetrahedron) is unique if they are not //
07638 // degenerate. If 'pd = NULL', the smallest circumsphere of three points is  //
07639 // the diametral sphere of the triangle if they are not degenerate.          //
07640 //                                                                           //
07641 // Return TRUE if the input points are not degenerate and the circumcenter   //
07642 // and circumradius are returned in 'cent' and 'radius' respectively if they //
07643 // are not NULLs. Otherwise, return FALSE indicated the points are degenrate.//
07644 //                                                                           //
07646 
07647 bool tetgenmesh::
07648 circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* cent, REAL* radius)
07649 {
07650   REAL A[4][4], rhs[4], D;
07651   int indx[4];
07652 
07653   // Compute the coefficient matrix A (3x3).
07654   A[0][0] = pb[0] - pa[0];
07655   A[0][1] = pb[1] - pa[1];
07656   A[0][2] = pb[2] - pa[2];
07657   A[1][0] = pc[0] - pa[0];
07658   A[1][1] = pc[1] - pa[1];
07659   A[1][2] = pc[2] - pa[2];
07660   if (pd != NULL) {
07661     A[2][0] = pd[0] - pa[0];
07662     A[2][1] = pd[1] - pa[1];
07663     A[2][2] = pd[2] - pa[2];
07664   } else {
07665     cross(A[0], A[1], A[2]);
07666   }
07667 
07668   // Compute the right hand side vector b (3x1).
07669   rhs[0] = 0.5 * dot(A[0], A[0]);
07670   rhs[1] = 0.5 * dot(A[1], A[1]);
07671   if (pd != NULL) {
07672     rhs[2] = 0.5 * dot(A[2], A[2]);
07673   } else {
07674     rhs[2] = 0.0;
07675   }
07676 
07677   // Solve the 3 by 3 equations use LU decomposition with partial pivoting
07678   //   and backward and forward substitute..
07679   if (!lu_decmp(A, 3, indx, &D, 0)) {
07680     if (radius != (REAL *) NULL) *radius = 0.0;
07681     return false;
07682   }
07683   lu_solve(A, 3, indx, rhs, 0);
07684   if (cent != (REAL *) NULL) {
07685     cent[0] = pa[0] + rhs[0];
07686     cent[1] = pa[1] + rhs[1];
07687     cent[2] = pa[2] + rhs[2];
07688   }
07689   if (radius != (REAL *) NULL) {
07690     *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
07691   }
07692   return true;
07693 }
07694 
07696 //                                                                           //
07697 // inscribedsphere()    Compute the radius and center of the biggest         //
07698 //                      inscribed sphere of a given tetrahedron.             //
07699 //                                                                           //
07700 // The tetrahedron is given by its four points, it must not be degenerate.   //
07701 // The center and radius are returned in 'cent' and 'radius' respectively if //
07702 // they are not NULLs.                                                       //
07703 //                                                                           //
07704 // Geometrical fact. For any simplex in d dimension,                         //
07705 //   r/h1 + r/h2 + ... r/hn = 1 (n <= d + 1);                                //
07706 // where r is the radius of inscribed ball, and h is the height of each side //
07707 // of the simplex. The value of 'r/h' is just the barycenter coordinates of  //
07708 // each vertex of the simplex. Therefore, we can compute the radius and      //
07709 // center of the smallest inscribed ball as following equations:             //
07710 //   r = 1.0 / (1/h1 + 1/h2 + ... + 1/hn);          (1)                      //
07711 //   C = r/h1 * P1 + r/h2 * P2 + ... + r/hn * Pn;   (2)                      //
07712 // where C is the vector of center, P1, P2, .. Pn are vectors of vertices.   //
07713 // Here (2) contains n linear equations with n variables.  (h, P) must be a  //
07714 // pair, h is the height from P to its opposite face.                        //
07715 //                                                                           //
07717 
07718 void tetgenmesh::inscribedsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
07719   REAL* cent, REAL* radius)
07720 {
07721   REAL N[4][3], H[4]; // Normals (colume vectors) and heights of each face.
07722   REAL rd;
07723   int i;
07724 
07725   // Get the all normals of the tet.
07726   tetallnormal(pa, pb, pc, pd, N, NULL);
07727   for (i = 0; i < 4; i++) {
07728     // H[i] is the inverse of height of its corresponding face.
07729     H[i] = sqrt(dot(N[i], N[i]));
07730   }
07731   // Compute the radius use eq. (1).
07732   rd = 1.0 / (H[0] + H[1] + H[2] + H[3]);
07733   if (radius != (REAL*) NULL) *radius = rd;
07734   if (cent != (REAL*) NULL) {
07735     // Compute the center use eq. (2).
07736     cent[0] = rd * (H[0] * pa[0] + H[1] * pb[0] + H[2] * pc[0] + H[3] * pd[0]);
07737     cent[1] = rd * (H[0] * pa[1] + H[1] * pb[1] + H[2] * pc[1] + H[3] * pd[1]);
07738     cent[2] = rd * (H[0] * pa[2] + H[1] * pb[2] + H[2] * pc[2] + H[3] * pd[2]);
07739   }
07740 }
07741 
07743 //                                                                           //
07744 // rotatepoint()    Create a point by rotating an existing point.            //
07745 //                                                                           //
07746 // Create a 3D point by rotating point 'p' with an angle 'rotangle' (in arc  //
07747 // degree) around a rotating axis given by a vector from point 'p1' to 'p2'. //
07748 // The rotation is according with right-hand rule, i.e., use your right-hand //
07749 // to grab the axis with your thumber pointing to its positive direction,    //
07750 // your fingers indicate the rotating direction.                             //
07751 //                                                                           //
07752 // The rotating steps are the following:                                     //
07753 //   1. Translate vector 'p1->p2' to origin, M1;                             //
07754 //   2. Rotate vector around the Y-axis until it lies in the YZ plane, M2;   //
07755 //   3. Rotate vector around the X-axis until it lies on the Z axis, M3;     //
07756 //   4. Perform the rotation of 'p' around the z-axis, M4;                   //
07757 //   5. Undo Step 3, M5;                                                     //
07758 //   6. Undo Step 2, M6;                                                     //
07759 //   7. Undo Step 1, M7;                                                     //
07760 // Use matrix multiplication to combine the above sequences, we get:         //
07761 //   p0' = T * p0, where T = M7 * M6 * M5 * M4 * M3 * M2 * M1                //
07762 //                                                                           //
07764 
07765 void tetgenmesh::rotatepoint(REAL* p, REAL rotangle, REAL* p1, REAL* p2)
07766 {
07767   REAL T[4][4], pp0[4], p0t[4], p2t[4];
07768   REAL roty, rotx, alphaR, projlen;
07769   REAL dx, dy, dz;
07770 
07771   initm44(1, 0, 0, -p1[0],
07772           0, 1, 0, -p1[1],
07773           0, 0, 1, -p1[2],
07774           0, 0, 0, 1, T);
07775   pp0[0] = p[0]; pp0[1] = p[1]; pp0[2] = p[2]; pp0[3] = 1.0;
07776   m4xv4(p0t, T, pp0); // Step 1
07777   pp0[0] = p2[0]; pp0[1] = p2[1]; pp0[2] = p2[2]; pp0[3] = 1.0;
07778   m4xv4(p2t, T, pp0); // Step 1
07779 
07780   // Get the rotation angle around y-axis;
07781   dx = p2t[0];
07782   dz = p2t[2];
07783   projlen = sqrt(dx * dx + dz * dz);
07784   if (projlen <= (b->epsilon * 1e-2) * longest) {
07785     roty = 0;
07786   } else {
07787     roty = acos(dz / projlen);
07788     if (dx < 0) {
07789       roty = -roty;
07790     }
07791   }
07792 
07793   initm44(cos(-roty), 0, sin(-roty), 0,
07794           0, 1, 0, 0,
07795           -sin(-roty), 0, cos(-roty), 0,
07796           0, 0, 0, 1, T);
07797   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07798   m4xv4(p0t, T, pp0); // Step 2
07799   pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
07800   m4xv4(p2t, T, pp0); // Step 2
07801 
07802   // Get the rotation angle around x-axis
07803   dy = p2t[1];
07804   dz = p2t[2];
07805   projlen = sqrt(dy * dy + dz * dz);
07806   if (projlen <= (b->epsilon * 1e-2) * longest) {
07807     rotx = 0;
07808   } else {
07809     rotx = acos(dz / projlen);
07810     if (dy < 0) {
07811       rotx = -rotx;
07812     }
07813   }
07814 
07815   initm44(1, 0, 0, 0,
07816           0, cos(rotx), -sin(rotx), 0,
07817           0, sin(rotx), cos(rotx), 0,
07818           0, 0, 0, 1, T);
07819   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07820   m4xv4(p0t, T, pp0); // Step 3
07821   // pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
07822   // m4xv4(p2t, T, pp0); // Step 3
07823 
07824   alphaR = rotangle;
07825   initm44(cos(alphaR), -sin(alphaR), 0, 0,
07826           sin(alphaR), cos(alphaR), 0, 0,
07827           0, 0, 1, 0,
07828           0, 0, 0, 1, T);
07829   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07830   m4xv4(p0t, T, pp0); // Step 4
07831 
07832   initm44(1, 0, 0, 0,
07833           0, cos(-rotx), -sin(-rotx), 0,
07834           0, sin(-rotx), cos(-rotx), 0,
07835           0, 0, 0, 1, T);
07836   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07837   m4xv4(p0t, T, pp0); // Step 5
07838 
07839   initm44(cos(roty), 0, sin(roty), 0,
07840           0, 1, 0, 0,
07841           -sin(roty), 0, cos(roty), 0,
07842           0, 0, 0, 1, T);
07843   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07844   m4xv4(p0t, T, pp0); // Step 6
07845 
07846   initm44(1, 0, 0, p1[0],
07847           0, 1, 0, p1[1],
07848           0, 0, 1, p1[2],
07849           0, 0, 0, 1, T);
07850   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07851   m4xv4(p0t, T, pp0); // Step 7
07852 
07853   p[0] = p0t[0];
07854   p[1] = p0t[1];
07855   p[2] = p0t[2];
07856 }
07857 
07859 //                                                                           //
07860 // spherelineint()    3D line sphere (or circle) intersection.               //
07861 //                                                                           //
07862 // The line is given by two points p1, and p2, the sphere is centered at c   //
07863 // with radius r.  This function returns a pointer array p which first index //
07864 // indicates the number of intersection point, followed by coordinate pairs. //
07865 //                                                                           //
07866 // The following code are adapted from: http://astronomy.swin.edu.au/pbourke //
07867 // /geometry/sphereline. Paul Bourke pbourke@swin.edu.au                     //
07868 //                                                                           //
07870 
07871 void tetgenmesh::spherelineint(REAL* p1, REAL* p2, REAL* C, REAL R, REAL p[7])
07872 {
07873   REAL x1, y1, z1; //  P1 coordinates (point of line)
07874   REAL x2, y2, z2; //  P2 coordinates (point of line)
07875   REAL x3, y3, z3, r; //  P3 coordinates and radius (sphere)
07876   REAL a, b, c, mu, i ;
07877 
07878   x1 = p1[0]; y1 = p1[1]; z1 = p1[2];
07879   x2 = p2[0]; y2 = p2[1]; z2 = p2[2];
07880   x3 = C[0];  y3 = C[1];  z3 = C[2];
07881   r = R;
07882 
07883   a =   (x2 - x1) * (x2 - x1)
07884       + (y2 - y1) * (y2 - y1)
07885       + (z2 - z1) * (z2 - z1);
07886   b = 2 * ( (x2 - x1) * (x1 - x3)
07887           + (y2 - y1) * (y1 - y3)
07888           + (z2 - z1) * (z1 - z3) ) ;
07889   c =   (x3 * x3) + (y3 * y3) + (z3 * z3)
07890       + (x1 * x1) + (y1 * y1) + (z1 * z1)
07891       - 2 * (x3 * x1 + y3 * y1 + z3 * z1) - (r * r) ;
07892   i = b * b - 4 * a * c ;
07893 
07894   if (i < 0.0) {
07895     // no intersection
07896     p[0] = 0.0;
07897   } else if (i == 0.0) {
07898     // one intersection
07899     p[0] = 1.0;
07900     mu = -b / (2 * a) ;
07901     p[1] = x1 + mu * (x2 - x1);
07902     p[2] = y1 + mu * (y2 - y1);
07903     p[3] = z1 + mu * (z2 - z1);
07904   } else {
07905     // two intersections
07906     p[0] = 2.0;
07907     // first intersection
07908     mu = (-b + sqrt((b * b) - 4 * a * c)) / (2 * a);
07909     p[1] = x1 + mu * (x2 - x1);
07910     p[2] = y1 + mu * (y2 - y1);
07911     p[3] = z1 + mu * (z2 - z1);
07912     // second intersection
07913     mu = (-b - sqrt((b * b) - 4 * a * c)) / (2 * a);
07914     p[4] = x1 + mu * (x2 - x1);
07915     p[5] = y1 + mu * (y2 - y1);
07916     p[6] = z1 + mu * (z2 - z1);
07917   }
07918 }
07919 
07921 //                                                                           //
07922 // linelineint()    Calculate the shortest line between two lines in 3D.     //
07923 //                                                                           //
07924 // Two 3D lines generally don't intersect at a point, they may be parallel ( //
07925 // no intersections), or coincident (infinite intersections) but most often  //
07926 // only their projections onto a plane intersect. If they don't exactly int- //
07927 // ersect at a point they can be connected by a line segment, the shortest   //
07928 // segment is unique and is often considered to be their intersection in 3D. //
07929 //                                                                           //
07930 // The following code are adapted from: http://astronomy.swin.edu.au/pbourke //
07931 // /geometry/lineline3d. Paul Bourke pbourke@swin.edu.au                     //
07932 //                                                                           //
07933 // Calculate the line segment PaPb that is the shortest route between two    //
07934 // lines P1P2 and P3P4. This function returns a pointer array p which first  //
07935 // index indicates there exists solution or not, 0 means no solution, 1 meas //
07936 // has solution followed by two coordinate pairs.                            //
07937 //                                                                           //
07939 
07940 void tetgenmesh::linelineint(REAL *p1,REAL *p2, REAL *p3, REAL *p4, REAL p[7])
07941 {
07942   REAL p13[3], p43[3], p21[3];
07943   REAL d1343, d4321, d1321, d4343, d2121;
07944   REAL numer, denom;
07945   REAL mua, mub;
07946 
07947   p13[0] = p1[0] - p3[0];
07948   p13[1] = p1[1] - p3[1];
07949   p13[2] = p1[2] - p3[2];
07950   p43[0] = p4[0] - p3[0];
07951   p43[1] = p4[1] - p3[1];
07952   p43[2] = p4[2] - p3[2];
07953   if (p43[0] == 0.0 && p43[1] == 0.0 && p43[2] == 0.0) {
07954     p[0] = 0.0;
07955     return;
07956   }
07957 
07958   p21[0] = p2[0] - p1[0];
07959   p21[1] = p2[1] - p1[1];
07960   p21[2] = p2[2] - p1[2];
07961   if (p21[0] == 0.0 && p21[1] == 0.0 && p21[2] == 0.0) {
07962     p[0] = 0.0;
07963     return;
07964   }
07965 
07966   d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
07967   d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
07968   d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
07969   d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
07970   d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
07971 
07972   denom = d2121 * d4343 - d4321 * d4321;
07973   if (denom == 0.0) {
07974     p[0] = 0.0;
07975     return;
07976   }
07977   numer = d1343 * d4321 - d1321 * d4343;
07978   mua = numer / denom;
07979   mub = (d1343 + d4321 * mua) / d4343;
07980 
07981   p[0] = 1.0;
07982   p[1] = p1[0] + mua * p21[0];
07983   p[2] = p1[1] + mua * p21[1];
07984   p[3] = p1[2] + mua * p21[2];
07985   p[4] = p3[0] + mub * p43[0];
07986   p[5] = p3[1] + mub * p43[1];
07987   p[6] = p3[2] + mub * p43[2];
07988 }
07989 
07991 //                                                                           //
07992 // planelineint()    Calculate the intersection of a line and a plane.       //
07993 //                                                                           //
07994 // The equation of a plane (points P are on the plane with normal N and P3   //
07995 // on the plane) can be written as: N dot (P - P3) = 0. The equation of the  //
07996 // line (points P on the line passing through P1 and P2) can be written as:  //
07997 // P = P1 + u (P2 - P1). The intersection of these two occurs when:          //
07998 //   N dot (P1 + u (P2 - P1)) = N dot P3.                                    //
07999 // Solving for u gives:                                                      //
08000 //         N dot (P3 - P1)                                                   //
08001 //   u = ------------------.                                                 //
08002 //         N dot (P2 - P1)                                                   //
08003 // If the denominator is 0 then N (the normal to the plane) is perpendicular //
08004 // to the line.  Thus the line is either parallel to the plane and there are //
08005 // no solutions or the line is on the plane in which case there are an infi- //
08006 // nite number of solutions.                                                 //
08007 //                                                                           //
08008 // The plane is given by three points pa, pb, and pc, e1 and e2 defines the  //
08009 // line. If u is non-zero, The intersection point (if exists) returns in ip. //
08010 //                                                                           //
08012 
08013 void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
08014   REAL* ip, REAL* u)
08015 {
08016   REAL n[3], det, det1;
08017 
08018   // Calculate N.
08019   facenormal(pa, pb, pc, n, NULL);
08020   // Calculate N dot (e2 - e1).
08021   det = n[0] * (e2[0] - e1[0]) + n[1] * (e2[1] - e1[1])
08022       + n[2] * (e2[2] - e1[2]);
08023   if (det != 0.0) {
08024     // Calculate N dot (pa - e1)
08025     det1 = n[0] * (pa[0] - e1[0]) + n[1] * (pa[1] - e1[1])
08026          + n[2] * (pa[2] - e1[2]);
08027     *u = det1 / det;
08028     ip[0] = e1[0] + *u * (e2[0] - e1[0]);
08029     ip[1] = e1[1] + *u * (e2[1] - e1[1]);
08030     ip[2] = e1[2] + *u * (e2[2] - e1[2]);
08031   } else {
08032     *u = 0.0;
08033   }
08034 }
08035 
08036 //
08037 // End of Geometric quantities calculators
08038 //
08039 
08040 //
08041 // Begin of memory management routines
08042 //
08043 
08045 //                                                                           //
08046 // dummyinit()    Initialize the tetrahedron that fills "outer space" and    //
08047 //                the omnipresent subface.                                   //
08048 //                                                                           //
08049 // The tetrahedron that fills "outer space" called 'dummytet', is pointed to //
08050 // by every tetrahedron and subface on a boundary (be it outer or inner) of  //
08051 // the tetrahedralization. Also, 'dummytet' points to one of the tetrahedron //
08052 // on the convex hull(until the holes and concavities are carved), making it //
08053 // possible to find a starting tetrahedron for point location.               //
08054 //                                                                           //
08055 // The omnipresent subface,'dummysh', is pointed to by every tetrahedron or  //
08056 // subface that doesn't have a full complement of real subface to point to.  //
08057 //                                                                           //
08059 
08060 void tetgenmesh::dummyinit(int tetwords, int shwords)
08061 {
08062   unsigned long alignptr;
08063 
08064   // Set up 'dummytet', the 'tetrahedron' that occupies "outer space".
08065   dummytetbase = (tetrahedron *) new char[tetwords * sizeof(tetrahedron)
08066                                           + tetrahedrons->alignbytes];
08067   // Align 'dummytet' on a 'tetrahedrons->alignbytes'-byte boundary.
08068   alignptr = (unsigned long) dummytetbase;
08069   dummytet = (tetrahedron *)
08070     (alignptr + (unsigned long) tetrahedrons->alignbytes
08071      - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08072   // Initialize the four adjoining tetrahedra to be "outer space". These
08073   //   will eventually be changed by various bonding operations, but their
08074   //   values don't really matter, as long as they can legally be
08075   //   dereferenced.
08076   dummytet[0] = (tetrahedron) dummytet;
08077   dummytet[1] = (tetrahedron) dummytet;
08078   dummytet[2] = (tetrahedron) dummytet;
08079   dummytet[3] = (tetrahedron) dummytet;
08080   // Four null vertex points.
08081   dummytet[4] = (tetrahedron) NULL;
08082   dummytet[5] = (tetrahedron) NULL;
08083   dummytet[6] = (tetrahedron) NULL;
08084   dummytet[7] = (tetrahedron) NULL;
08085 
08086   if (b->useshelles) {
08087     // Set up 'dummysh', the omnipresent "subface" pointed to by any
08088     //   tetrahedron side or subface end that isn't attached to a real
08089     //   subface.
08090     dummyshbase = (shellface *) new char[shwords * sizeof(shellface)
08091                                          + subfaces->alignbytes];
08092     // Align 'dummysh' on a 'subfaces->alignbytes'-byte boundary.
08093     alignptr = (unsigned long) dummyshbase;
08094     dummysh = (shellface *)
08095       (alignptr + (unsigned long) subfaces->alignbytes
08096        - (alignptr % (unsigned long) subfaces->alignbytes));
08097     // Initialize the three adjoining subfaces to be the omnipresent
08098     //   subface. These will eventually be changed by various bonding
08099     //   operations, but their values don't really matter, as long as they
08100     //   can legally be dereferenced.
08101     dummysh[0] = (shellface) dummysh;
08102     dummysh[1] = (shellface) dummysh;
08103     dummysh[2] = (shellface) dummysh;
08104     // Three null vertex points.
08105     dummysh[3] = (shellface) NULL;
08106     dummysh[4] = (shellface) NULL;
08107     dummysh[5] = (shellface) NULL;
08108     // Initialize the two adjoining tetrahedra to be "outer space".
08109     dummysh[6] = (shellface) dummytet;
08110     dummysh[7] = (shellface) dummytet;
08111     // Initialize the three adjoining subsegments to be "out boundary".
08112     dummysh[8]  = (shellface) dummysh;
08113     dummysh[9]  = (shellface) dummysh;
08114     dummysh[10] = (shellface) dummysh;
08115     // Initialize the pointer to badface structure.
08116     dummysh[11] = (shellface) NULL;
08117     // Initialize the four adjoining subfaces of 'dummytet' to be the
08118     //   omnipresent subface.
08119     dummytet[8 ] = (tetrahedron) dummysh;
08120     dummytet[9 ] = (tetrahedron) dummysh;
08121     dummytet[10] = (tetrahedron) dummysh;
08122     dummytet[11] = (tetrahedron) dummysh;
08123   }
08124 }
08125 
08127 //                                                                           //
08128 // initializepools()    Calculate the sizes of the point, tetrahedron, and   //
08129 //                      subface. Initialize their memory pools.              //
08130 //                                                                           //
08131 // This routine also computes the indices 'pointmarkindex', 'point2simindex',//
08132 // and 'point2pbcptindex' used to find values within each point;  computes   //
08133 // indices 'highorderindex', 'elemattribindex', and 'volumeboundindex' used  //
08134 // to find values within each tetrahedron.                                   //
08135 //                                                                           //
08136 // There are two types of boundary elements, which are subfaces and subsegs, //
08137 // they are stored in seperate pools. However, the data structures of them   //
08138 // are the same.  A subsegment can be regarded as a degenerate subface, i.e.,//
08139 // one of its three corners is not used. We set the apex of it be 'NULL' to  //
08140 // distinguish it's a subsegment.                                            //
08141 //                                                                           //
08143 
08144 void tetgenmesh::initializepools()
08145 {
08146   enum wordtype wtype;
08147   int pointsize, elesize, shsize;
08148 
08149   // Default checkpbc = 0;
08150   if ((b->plc || b->refine) && (in->pbcgrouplist != NULL)) {
08151     checkpbcs = 1;
08152   }
08153   // Default varconstraint = 0;
08154   if (in->segmentconstraintlist || in->facetconstraintlist) {
08155     varconstraint = 1;
08156   }
08157 
08158   // The index within each point at which its metric tensor is found. It is
08159   //   saved directly after the list of point attributes.
08160   pointmtrindex = 3 + in->numberofpointattributes;
08161   // Decide the size (1, 3, or 6) of the metric tensor.
08162   if (b->metric) {
08163     // For '-m' option. A tensor field is provided (*.mtr or *.b.mtr file).
08164     if (bgm != (tetgenmesh *) NULL) {
08165       // A background mesh is allocated. It may not exist though.
08166       sizeoftensor = (bgm->in != (tetgenio *) NULL) ?
08167         bgm->in->numberofpointmtrs : in->numberofpointmtrs;
08168     } else {
08169       // No given background mesh - Itself is a background mesh.
08170       sizeoftensor = in->numberofpointmtrs;
08171     }
08172     // Make sure sizeoftensor is at least 1.
08173     sizeoftensor = (sizeoftensor > 0) ? sizeoftensor : 1;
08174   } else {
08175     // For '-q' option. Make sure to have space for saving a scalar value.
08176     sizeoftensor = b->quality ? 1 : 0;
08177   }
08178   // The index within each point at which an element pointer is found, where
08179   //   the index is measured in pointers. Ensure the index is aligned to a
08180   //   sizeof(tetrahedron)-byte address.
08181   point2simindex = ((pointmtrindex + sizeoftensor) * sizeof(REAL)
08182                  + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08183   if (b->plc || b->refine) {
08184     // Increase the point size by three pointers, which are:
08185     //   - a pointer to a tet, read by point2tet();
08186     //   - a pointer to a subface/subsegment , read by point2sh();
08187     //   - a pointer to a parent point, read by point2ppt()).
08188     if (b->metric) {
08189       // Increase one pointer to a tet of the background mesh.
08190       pointsize = (point2simindex + 4) * sizeof(tetrahedron);
08191     } else {
08192       pointsize = (point2simindex + 3) * sizeof(tetrahedron);
08193     }
08194     // The index within each point at which a pbc point is found.
08195     point2pbcptindex = (pointsize + sizeof(tetrahedron) - 1)
08196                      / sizeof(tetrahedron);
08197     if (checkpbcs) {
08198       // Increase the size by one pointer to a corresponding pbc point,
08199       //   read by point2pbcpt().
08200       pointsize = (point2pbcptindex + 1) * sizeof(tetrahedron);
08201     }
08202   } else {
08203     pointsize = point2simindex * sizeof(tetrahedron);
08204   }
08205   // The index within each point at which the boundary marker is found,
08206   //   Ensure the point marker is aligned to a sizeof(int)-byte address.
08207   pointmarkindex = (pointsize + sizeof(int) - 1) / sizeof(int);
08208   // Now point size is the ints (inidcated by pointmarkindex) plus:
08209   //   - an integer for boundary marker;
08210   //   - an integer for vertex type;
08211   pointsize = (pointmarkindex + 2) * sizeof(int);
08212   // Decide the wordtype used in vertex pool.
08213   wtype = (sizeof(REAL) >= sizeof(tetrahedron)) ? FLOATINGPOINT : POINTER;
08214   // Initialize the pool of vertices.
08215   points = new memorypool(pointsize, VERPERBLOCK, wtype, 0);
08216 
08217   // The number of bytes occupied by a tetrahedron.  There are four pointers
08218   //   to other tetrahedra, four pointers to corners, and possibly four
08219   //   pointers to subfaces.
08220   elesize = (8 + b->useshelles * 6) * sizeof(tetrahedron);
08221   // If Voronoi diagram is wanted, make sure we have additional space.
08222   if (b->voroout && (b->useshelles == 0)) {
08223     elesize = (8 + 4) * sizeof(tetrahedron);
08224   }
08225   // The index within each element at which its attributes are found, where
08226   //   the index is measured in REALs.
08227   elemattribindex = (elesize + sizeof(REAL) - 1) / sizeof(REAL);
08228   // The index within each element at which the maximum voulme bound is
08229   //   found, where the index is measured in REALs.  Note that if the
08230   //   `b->regionattrib' flag is set, an additional attribute will be added.
08231   volumeboundindex = elemattribindex + in->numberoftetrahedronattributes
08232                    + (b->regionattrib > 0);
08233   // If element attributes or an constraint are needed, increase the number
08234   //   of bytes occupied by an element.
08235   if (b->varvolume) {
08236     elesize = (volumeboundindex + 1) * sizeof(REAL);
08237   } else if (in->numberoftetrahedronattributes + b->regionattrib > 0) {
08238     elesize = volumeboundindex * sizeof(REAL);
08239   }
08240   // If element neighbor graph is requested (-n switch), an additional
08241   //   integer is allocated for each element.
08242   elemmarkerindex = (elesize + sizeof(int) - 1) / sizeof(int);
08243   if (b->neighout || b->voroout) {
08244     elesize = (elemmarkerindex + 1) * sizeof(int);
08245   }
08246   // If -o2 switch is used, an additional pointer pointed to the list of
08247   //   higher order nodes is allocated for each element.
08248   highorderindex = (elesize + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08249   if (b->order == 2) {
08250     elesize = (highorderindex + 1) * sizeof(tetrahedron);
08251   }
08252   // Having determined the memory size of an element, initialize the pool.
08253   tetrahedrons = new memorypool(elesize, ELEPERBLOCK, POINTER, 8);
08254 
08255   if (b->useshelles) {
08256     // The number of bytes occupied by a subface.  The list of pointers
08257     //   stored in a subface are: three to other subfaces, three to corners,
08258     //   three to subsegments, two to tetrahedra, and one to a badface.
08259     shsize = 12 * sizeof(shellface);
08260     // The index within each subface at which the maximum area bound is
08261     //   found, where the index is measured in REALs.
08262     areaboundindex = (shsize + sizeof(REAL) - 1) / sizeof(REAL);
08263     // If -q switch is in use, increase the number of bytes occupied by
08264     //   a subface for saving maximum area bound.
08265     if (b->quality && varconstraint) {
08266       shsize = (areaboundindex + 1) * sizeof(REAL);
08267     } else {
08268       shsize = areaboundindex * sizeof(REAL);
08269     }
08270     // The index within subface at which the facet marker is found. Ensure
08271     //   the marker is aligned to a sizeof(int)-byte address.
08272     shmarkindex = (shsize + sizeof(int) - 1) / sizeof(int);
08273     // Increase the number of bytes by two or three integers, one for facet
08274     //   marker, one for shellface type, and optionally one for pbc group.
08275     shsize = (shmarkindex + 2 + checkpbcs) * sizeof(int);
08276     // Initialize the pool of subfaces. Each subface record is eight-byte
08277     //   aligned so it has room to store an edge version (from 0 to 5) in
08278     //   the least three bits.
08279     subfaces = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08280     // Initialize the pool of subsegments. The subsegment's record is same
08281     //   with subface.
08282     subsegs = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08283     // Initialize the "outer space" tetrahedron and omnipresent subface.
08284     dummyinit(tetrahedrons->itemwords, subfaces->itemwords);
08285   } else {
08286     // Initialize the "outer space" tetrahedron.
08287     dummyinit(tetrahedrons->itemwords, 0);
08288   }
08289 }
08290 
08292 //                                                                           //
08293 // tetrahedrondealloc()    Deallocate space for a tet., marking it dead.     //
08294 //                                                                           //
08296 
08297 void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
08298 {
08299   // Set tetrahedron's vertices to NULL. This makes it possible to detect
08300   //   dead tetrahedra when traversing the list of all tetrahedra.
08301   dyingtetrahedron[4] = (tetrahedron) NULL;
08302   dyingtetrahedron[5] = (tetrahedron) NULL;
08303   dyingtetrahedron[6] = (tetrahedron) NULL;
08304   dyingtetrahedron[7] = (tetrahedron) NULL;
08305   tetrahedrons->dealloc((void *) dyingtetrahedron);
08306 }
08307 
08309 //                                                                           //
08310 // tetrahedrontraverse()    Traverse the tetrahedra, skipping dead ones.     //
08311 //                                                                           //
08313 
08314 tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse()
08315 {
08316   tetrahedron *newtetrahedron;
08317 
08318   do {
08319     newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
08320     if (newtetrahedron == (tetrahedron *) NULL) {
08321       return (tetrahedron *) NULL;
08322     }
08323   } while (newtetrahedron[7] == (tetrahedron) NULL);      // Skip dead ones.
08324   return newtetrahedron;
08325 }
08326 
08328 //                                                                           //
08329 // shellfacedealloc()    Deallocate space for a shellface, marking it dead.  //
08330 //                       Used both for dealloc a subface and subsegment.     //
08331 //                                                                           //
08333 
08334 void tetgenmesh::shellfacedealloc(memorypool *pool, shellface *dyingsh)
08335 {
08336   // Set shellface's vertices to NULL. This makes it possible to detect dead
08337   //   shellfaces when traversing the list of all shellfaces.
08338   dyingsh[3] = (shellface) NULL;
08339   dyingsh[4] = (shellface) NULL;
08340   dyingsh[5] = (shellface) NULL;
08341   pool->dealloc((void *) dyingsh);
08342 }
08343 
08345 //                                                                           //
08346 // shellfacetraverse()    Traverse the subfaces, skipping dead ones. Used    //
08347 //                        for both subfaces and subsegments pool traverse.   //
08348 //                                                                           //
08350 
08351 tetgenmesh::shellface* tetgenmesh::shellfacetraverse(memorypool *pool)
08352 {
08353   shellface *newshellface;
08354 
08355   do {
08356     newshellface = (shellface *) pool->traverse();
08357     if (newshellface == (shellface *) NULL) {
08358       return (shellface *) NULL;
08359     }
08360   } while (newshellface[3] == (shellface) NULL);          // Skip dead ones.
08361   return newshellface;
08362 }
08363 
08365 //                                                                           //
08366 // badfacedealloc()    Deallocate space for a badface, marking it dead.      //
08367 //                                                                           //
08369 
08370 void tetgenmesh::badfacedealloc(memorypool *pool, badface *dying)
08371 {
08372   // Set badface's forg to NULL. This makes it possible to detect dead
08373   //   ones when traversing the list of all items.
08374   dying->forg = (point) NULL;
08375   pool->dealloc((void *) dying);
08376 }
08377 
08379 //                                                                           //
08380 // badfacetraverse()    Traverse the pools, skipping dead ones.              //
08381 //                                                                           //
08383 
08384 tetgenmesh::badface* tetgenmesh::badfacetraverse(memorypool *pool)
08385 {
08386   badface *newsh;
08387 
08388   do {
08389     newsh = (badface *) pool->traverse();
08390     if (newsh == (badface *) NULL) {
08391       return (badface *) NULL;
08392     }
08393   } while (newsh->forg == (point) NULL);               // Skip dead ones.
08394   return newsh;
08395 }
08396 
08398 //                                                                           //
08399 // pointdealloc()    Deallocate space for a point, marking it dead.          //
08400 //                                                                           //
08402 
08403 void tetgenmesh::pointdealloc(point dyingpoint)
08404 {
08405   // Mark the point as dead. This  makes it possible to detect dead points
08406   //   when traversing the list of all points.
08407   setpointtype(dyingpoint, DEADVERTEX);
08408   points->dealloc((void *) dyingpoint);
08409 }
08410 
08412 //                                                                           //
08413 // pointtraverse()    Traverse the points, skipping dead ones.               //
08414 //                                                                           //
08416 
08417 tetgenmesh::point tetgenmesh::pointtraverse()
08418 {
08419   point newpoint;
08420 
08421   do {
08422     newpoint = (point) points->traverse();
08423     if (newpoint == (point) NULL) {
08424       return (point) NULL;
08425     }
08426   } while (pointtype(newpoint) == DEADVERTEX);            // Skip dead ones.
08427   return newpoint;
08428 }
08429 
08431 //                                                                           //
08432 // maketetrahedron()    Create a new tetrahedron.                            //
08433 //                                                                           //
08435 
08436 void tetgenmesh::maketetrahedron(triface *newtet)
08437 {
08438   newtet->tet = (tetrahedron *) tetrahedrons->alloc();
08439   // Initialize the four adjoining tetrahedra to be "outer space".
08440   newtet->tet[0] = (tetrahedron) dummytet;
08441   newtet->tet[1] = (tetrahedron) dummytet;
08442   newtet->tet[2] = (tetrahedron) dummytet;
08443   newtet->tet[3] = (tetrahedron) dummytet;
08444   // Four NULL vertices.
08445   newtet->tet[4] = (tetrahedron) NULL;
08446   newtet->tet[5] = (tetrahedron) NULL;
08447   newtet->tet[6] = (tetrahedron) NULL;
08448   newtet->tet[7] = (tetrahedron) NULL;
08449   // Initialize the four adjoining subfaces to be the omnipresent subface.
08450   if (b->useshelles) {
08451     newtet->tet[8 ] = (tetrahedron) dummysh;
08452     newtet->tet[9 ] = (tetrahedron) dummysh;
08453     newtet->tet[10] = (tetrahedron) dummysh;
08454     newtet->tet[11] = (tetrahedron) dummysh;
08455     newtet->tet[12] = (tetrahedron) dummysh;
08456     newtet->tet[13] = (tetrahedron) dummysh;
08457   }
08458   for (int i = 0; i < in->numberoftetrahedronattributes; i++) {
08459     setelemattribute(newtet->tet, i, 0.0);
08460   }
08461   if (b->varvolume) {
08462     setvolumebound(newtet->tet, -1.0);
08463   }
08464   // Initialize the location and version to be Zero.
08465   newtet->loc = 0;
08466   newtet->ver = 0;
08467 }
08468 
08470 //                                                                           //
08471 // makeshellface()    Create a new shellface with version zero. Used for     //
08472 //                    both subfaces and seusegments.                         //
08473 //                                                                           //
08475 
08476 void tetgenmesh::makeshellface(memorypool *pool, face *newface)
08477 {
08478   newface->sh = (shellface *) pool->alloc();
08479   //Initialize the three adjoining subfaces to be the omnipresent subface.
08480   newface->sh[0] = (shellface) dummysh;
08481   newface->sh[1] = (shellface) dummysh;
08482   newface->sh[2] = (shellface) dummysh;
08483   // Three NULL vertices.
08484   newface->sh[3] = (shellface) NULL;
08485   newface->sh[4] = (shellface) NULL;
08486   newface->sh[5] = (shellface) NULL;
08487   // Initialize the two adjoining tetrahedra to be "outer space".
08488   newface->sh[6] = (shellface) dummytet;
08489   newface->sh[7] = (shellface) dummytet;
08490   // Initialize the three adjoining subsegments to be the omnipresent
08491   //   subsegments.
08492   newface->sh [8] = (shellface) dummysh;
08493   newface->sh [9] = (shellface) dummysh;
08494   newface->sh[10] = (shellface) dummysh;
08495   // Initialize the pointer to badface structure.
08496   newface->sh[11] = (shellface) NULL;
08497   if (b->quality && varconstraint) {
08498     // Initialize the maximum area bound.
08499     setareabound(*newface, 0.0);
08500   }
08501   // Set the boundary marker to zero.
08502   setshellmark(*newface, 0);
08503   // Set the type.
08504   setshelltype(*newface, NSHARP);
08505   if (checkpbcs) {
08506     // Set the pbcgroup be ivalid.
08507     setshellpbcgroup(*newface, -1);
08508   }
08509   // Initialize the version to be Zero.
08510   newface->shver = 0;
08511 }
08512 
08514 //                                                                           //
08515 // makepoint()    Create a new point.                                        //
08516 //                                                                           //
08518 
08519 void tetgenmesh::makepoint(point* pnewpoint)
08520 {
08521   int ptmark, i;
08522 
08523   *pnewpoint = (point) points->alloc();
08524   // Initialize three coordinates.
08525   (*pnewpoint)[0] = 0.0;
08526   (*pnewpoint)[1] = 0.0;
08527   (*pnewpoint)[2] = 0.0;
08528   // Initialize the list of user-defined attributes.
08529   for (i = 0; i < in->numberofpointattributes; i++) {
08530     (*pnewpoint)[3 + i] = 0.0;
08531   }
08532   // Initialize the metric tensor.
08533   for (i = 0; i < sizeoftensor; i++) {
08534     (*pnewpoint)[pointmtrindex + i] = 0.0;
08535   }
08536   if (b->plc || b->refine) {
08537     // Initialize the point-to-simplex filed.
08538     setpoint2tet(*pnewpoint, NULL);
08539     setpoint2sh(*pnewpoint, NULL);
08540     setpoint2ppt(*pnewpoint, NULL);
08541     if (b->metric) {
08542       setpoint2bgmtet(*pnewpoint, NULL);
08543     }
08544     if (checkpbcs) {
08545       // Initialize the other pointer to its pbc point.
08546       setpoint2pbcpt(*pnewpoint, NULL);
08547     }
08548   }
08549   // Initialize the point marker (starting from in->firstnumber).
08550   ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
08551   setpointmark(*pnewpoint, ptmark);
08552   // Initialize the point type.
08553   setpointtype(*pnewpoint, UNUSEDVERTEX);
08554 }
08555 
08556 //
08557 // End of memory management routines
08558 //
08559 
08560 //
08561 // Begin of point location routines
08562 //
08563 
08565 //                                                                           //
08566 // randomnation()    Generate a random number between 0 and 'choices' - 1.   //
08567 //                                                                           //
08569 
08570 unsigned long tetgenmesh::randomnation(unsigned int choices)
08571 {
08572   unsigned long newrandom;
08573 
08574   if (choices >= 714025l) {
08575     newrandom = (randomseed * 1366l + 150889l) % 714025l;
08576     randomseed = (newrandom * 1366l + 150889l) % 714025l;
08577     newrandom = newrandom * (choices / 714025l) + randomseed;
08578     if (newrandom >= choices) {
08579       return newrandom - choices;
08580     } else {
08581       return newrandom;
08582     }
08583   } else {
08584     randomseed = (randomseed * 1366l + 150889l) % 714025l;
08585     return randomseed % choices;
08586   }
08587   // Old function.
08588   // randomseed = (randomseed * 1366l + 150889l) % 714025l;
08589   // return randomseed / (714025l / choices + 1);
08590 }
08591 
08593 //                                                                           //
08594 // distance2()    Returns the square "distance" of a tetrahedron to point p. //
08595 //                                                                           //
08597 
08598 REAL tetgenmesh::distance2(tetrahedron* tetptr, point p)
08599 {
08600   point p1, p2, p3, p4;
08601   REAL dx, dy, dz;
08602 
08603   p1 = (point) tetptr[4];
08604   p2 = (point) tetptr[5];
08605   p3 = (point) tetptr[6];
08606   p4 = (point) tetptr[7];
08607 
08608   dx = p[0] - 0.25 * (p1[0] + p2[0] + p3[0] + p4[0]);
08609   dy = p[1] - 0.25 * (p1[1] + p2[1] + p3[1] + p4[1]);
08610   dz = p[2] - 0.25 * (p1[2] + p2[2] + p3[2] + p4[2]);
08611 
08612   return dx * dx + dy * dy + dz * dz;
08613 }
08614 
08616 //                                                                           //
08617 // preciselocate()    Find a simplex containing a given point.               //
08618 //                                                                           //
08619 // This routine implements the simple Walk-through point location algorithm. //
08620 // Begins its search from 'searchtet', assume there is a line segment L from //
08621 // a vertex of 'searchtet' to the query point 'searchpt', and simply walk    //
08622 // towards 'searchpt' by traversing all faces intersected by L.              //
08623 //                                                                           //
08624 // On completion, 'searchtet' is a tetrahedron that contains 'searchpt'. The //
08625 // returned value indicates one of the following cases:                      //
08626 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchtet' //
08627 //     is a handle whose origin is the existing vertex.                      //
08628 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchtet' is a    //
08629 //     handle whose primary edge is the edge on which the point lies.        //
08630 //   - Returns ONFACE if the point lies strictly within a face. 'searchtet'  //
08631 //     is a handle whose primary face is the face on which the point lies.   //
08632 //   - Returns INTETRAHEDRON if the point lies strictly in a tetrahededron.  //
08633 //     'searchtet' is a handle on the tetrahedron that contains the point.   //
08634 //   - Returns OUTSIDE if the point lies outside the mesh. 'searchtet' is a  //
08635 //     handle whose location is the face the point is to 'above' of.         //
08636 //                                                                           //
08637 // WARNING: This routine is designed for convex triangulations, and will not //
08638 // generally work after the holes and concavities have been carved.          //
08639 //                                                                           //
08640 // If 'maxtetnumber' > 0, stop the searching process if the number of passed //
08641 // tets is larger than it and return OUTSIDE.                                //
08642 //                                                                           //
08644 
08645 enum tetgenmesh::locateresult tetgenmesh::preciselocate(point searchpt,
08646   triface* searchtet, long maxtetnumber)
08647 {
08648   triface backtracetet;
08649   triface walkthroface;
08650   point forg, fdest, fapex, toppo;
08651   REAL ori1, ori2, ori3, ori4;
08652   long tetnumber;
08653   int side;
08654 
08655   if (isdead(searchtet)) searchtet->tet = dummytet;
08656   if (searchtet->tet == dummytet) {
08657     searchtet->loc = 0;
08658     symself(*searchtet);
08659   }
08660   // 'searchtet' should be a valid tetrahedron now.
08661 #ifdef SELF_CHECK
08662   // assert(!isdead(searchtet) && (searchtet->tet != dummytet));
08663 #endif
08664   if (isdead(searchtet)) {
08665     printf("Warning:  Point location failed.\n");
08666     return OUTSIDE;
08667   }
08668 
08669   searchtet->ver = 0; // Keep in CCW edge ring.
08670   // Find a face of 'searchtet' such that the 'searchpt' lies strictly
08671   //   above it.  Such face should always exist.
08672   for (searchtet->loc = 0; searchtet->loc < 4; searchtet->loc++) {
08673     forg = org(*searchtet);
08674     fdest = dest(*searchtet);
08675     fapex = apex(*searchtet);
08676     ori1 = orient3d(forg, fdest, fapex, searchpt);
08677     if (ori1 < 0.0) break;
08678   }
08679 #ifdef SELF_CHECK
08680   assert(searchtet->loc < 4);
08681 #endif
08682 
08683   // Define 'tetnumber' for exit the loop when it's running endless.
08684   tetnumber = 0l;
08685   while ((maxtetnumber > 0l) && (tetnumber <= maxtetnumber)) {
08686     // Check if we are reaching the boundary of the triangulation.
08687     if (searchtet->tet == dummytet) {
08688       *searchtet = backtracetet;
08689       return OUTSIDE;
08690     }
08691     // Initialize the face for returning the walk-through face.
08692     walkthroface.tet = (tetrahedron *) NULL;
08693     // Adjust the edge ring, so that 'ori1 < 0.0' holds.
08694     searchtet->ver = 0;
08695     // 'toppo' remains unchange for the following orientation tests.
08696     toppo = oppo(*searchtet);
08697     // Check the three sides of 'searchtet' to find the face through which
08698     //   we can walk next.
08699     for (side = 0; side < 3; side++) {
08700       forg = org(*searchtet);
08701       fdest = dest(*searchtet);
08702       ori2 = orient3d(forg, fdest, toppo, searchpt);
08703       if (ori2 == 0.0) {
08704         // They are coplanar, check if 'searchpt' lies inside, or on an edge,
08705         //   or coindice with a vertex of face (forg, fdest, toppo).
08706         fapex = apex(*searchtet);
08707         ori3 = orient3d(fdest, fapex, toppo, searchpt);
08708         if (ori3 < 0.0) {
08709           // Outside the face (fdest, fapex, toppo), walk through it.
08710           enextself(*searchtet);
08711           fnext(*searchtet, walkthroface);
08712           break;
08713         }
08714         ori4 = orient3d(fapex, forg, toppo, searchpt);
08715         if (ori4 < 0.0) {
08716           // Outside the face (fapex, forg, toppo), walk through it.
08717           enext2self(*searchtet);
08718           fnext(*searchtet, walkthroface);
08719           break;
08720         }
08721         // Remember, ori1 < 0.0, which means 'searchpt' will not on edge
08722         //   (forg, fdest) or on vertex forg or fdest.
08723 #ifdef SELF_CHECK
08724         assert(ori1 < 0.0);
08725 #endif
08726         // The rest possible cases are:
08727         //   (1) 'searchpt' lies on edge (fdest, toppo);
08728         //   (2) 'searchpt' lies on edge (toppo, forg);
08729         //   (3) 'searchpt' coincident with toppo;
08730         //   (4) 'searchpt' lies inside face (forg, fdest, toppo).
08731         fnextself(*searchtet);
08732         if (ori3 == 0.0) {
08733           if (ori4 == 0.0) {
08734             // Case (4).
08735             enext2self(*searchtet);
08736             return ONVERTEX;
08737           } else {
08738             // Case (1).
08739             enextself(*searchtet);
08740             return ONEDGE;
08741           }
08742         }
08743         if (ori4 == 0.0) {
08744           // Case (2).
08745           enext2self(*searchtet);
08746           return ONEDGE;
08747         }
08748         // Case (4).
08749         return ONFACE;
08750       } else if (ori2 < 0.0) {
08751         // Outside the face (forg, fdest, toppo), walk through it.
08752         fnext(*searchtet, walkthroface);
08753         break;
08754       }
08755       // Go to check next side.
08756       enextself(*searchtet);
08757     }
08758     if (side >= 3) {
08759       // Found! Inside tetrahedron.
08760       return INTETRAHEDRON;
08761     }
08762     // We walk through the face 'walkthroface' and continue the searching.
08763 #ifdef SELF_CHECK
08764     assert(walkthroface.tet != (tetrahedron *) NULL);
08765 #endif
08766     // Store the face handle in 'backtracetet' before we take the real walk.
08767     //   So we are able to restore the handle to 'searchtet' if we are
08768     //   reaching the outer boundary.
08769     backtracetet = walkthroface;
08770     sym(walkthroface, *searchtet);
08771     tetnumber++;
08772   }
08773 
08774   // Should never be here.
08775   // printf("Internal error in preciselocate(): Point location failed.\n");
08776   // internalerror();
08777   return OUTSIDE;
08778 }
08779 
08781 //                                                                           //
08782 // locate()    Find a simplex containing a given point.                      //
08783 //                                                                           //
08784 // This routine implements Muecke's Jump-and-walk point location algorithm.  //
08785 // It improves the simple walk-through by "jumping" to a good starting point //
08786 // via random sampling.  Searching begins from one of handles:  the input    //
08787 // 'searchtet', a recently encountered tetrahedron 'recenttet',  or from one //
08788 // chosen from a random sample.  The choice is made by determining which one //
08789 // 's barycenter is closest to the point we are searcing for.  Having chosen //
08790 // the starting tetrahedron, the simple Walk-through algorithm is used to do //
08791 // the real walking.                                                         //
08792 //                                                                           //
08793 // The return value indicates the location of the 'searchpt' (INTETRAHEDRON, //
08794 // or ONFACE, ...). 'searchtet' is adjusted to a tetrahedron corresponding   //
08795 // to that value. See the introduction part of preciselocate() for detail.   //
08796 //                                                                           //
08797 // WARNING: This routine is designed for convex triangulations, and will not //
08798 // generally work after the holes and concavities have been carved.          //
08799 //                                                                           //
08801 
08802 enum tetgenmesh::locateresult tetgenmesh::locate(point searchpt,
08803   triface *searchtet)
08804 {
08805   tetrahedron *firsttet, *tetptr;
08806   void **sampleblock;
08807   long sampleblocks, samplesperblock, samplenum;
08808   long tetblocks, i, j;
08809   unsigned long alignptr;
08810   REAL searchdist, dist;
08811 
08812   // 'searchtet' should be a valid tetrahedron.
08813   if (isdead(searchtet)) {
08814     searchtet->tet = dummytet;
08815   }
08816   if (searchtet->tet == dummytet) {
08817     // This is an 'Outer Space' handle, get a hull tetrahedron.
08818     searchtet->loc = 0;
08819     symself(*searchtet);
08820   }
08821 #ifdef SELF_CHECK
08822   // assert(!isdead(searchtet));
08823 #endif
08824   if (isdead(searchtet)) {
08825     printf("Warning:  Point location failed.\n");
08826     return OUTSIDE;
08827   }
08828 
08829   // Get the distance from the suggested starting tet to the point we seek.
08830   searchdist = distance2(searchtet->tet, searchpt);
08831 
08832   // If a recently encountered tetrahedron has been recorded and has not
08833   //   been deallocated, test it as a good starting point.
08834   if (!isdead(&recenttet) && (recenttet.tet != searchtet->tet)) {
08835     dist = distance2(recenttet.tet, searchpt);
08836     if (dist < searchdist) {
08837       *searchtet = recenttet;
08838       searchdist = dist;
08839     }
08840   }
08841 
08842   // Select "good" candidate using k random samples, taking the closest one.
08843   //   The number of random samples taken is proportional to the fourth root
08844   //   of the number of tetrahedra in the mesh. The next bit of code assumes
08845   //   that the number of tetrahedra increases monotonically.
08846   while (SAMPLEFACTOR * samples * samples * samples * samples <
08847          tetrahedrons->items) {
08848     samples++;
08849   }
08850   // Find how much blocks in current tet pool.
08851   tetblocks = (tetrahedrons->maxitems + ELEPERBLOCK - 1) / ELEPERBLOCK;
08852   // Find the average samles per block. Each block at least have 1 sample.
08853   samplesperblock = 1 + (samples / tetblocks);
08854   sampleblocks = samples / samplesperblock;
08855   sampleblock = tetrahedrons->firstblock;
08856   for (i = 0; i < sampleblocks; i++) {
08857     alignptr = (unsigned long) (sampleblock + 1);
08858     firsttet = (tetrahedron *)
08859                (alignptr + (unsigned long) tetrahedrons->alignbytes
08860                - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08861     for (j = 0; j < samplesperblock; j++) {
08862       if (i == tetblocks - 1) {
08863         // This is the last block.
08864         samplenum = randomnation((int)
08865                       (tetrahedrons->maxitems - (i * ELEPERBLOCK)));
08866       } else {
08867         samplenum = randomnation(ELEPERBLOCK);
08868       }
08869       tetptr = (tetrahedron *)
08870                (firsttet + (samplenum * tetrahedrons->itemwords));
08871       if (tetptr[4] != (tetrahedron) NULL) {
08872         dist = distance2(tetptr, searchpt);
08873         if (dist < searchdist) {
08874           searchtet->tet = tetptr;
08875           searchdist = dist;
08876         }
08877       }
08878     }
08879     sampleblock = (void **) *sampleblock;
08880   }
08881 
08882   // Call simple walk-through to locate the point.
08883   return preciselocate(searchpt, searchtet, tetrahedrons->items);
08884 }
08885 
08887 //                                                                           //
08888 // adjustlocate()    Adjust the precise location of a vertex.                //
08889 //                                                                           //
08890 // 'precise' is the value returned from preciselocate().  It indicates the   //
08891 // exact location of the point 'searchpt' with respect to the tetrahedron    //
08892 // 'searchtet'.  'epspp' is a given relative tolerance.                      //
08893 //                                                                           //
08894 // This routine re-evaluates the orientations of searchpt with respect to    //
08895 // the four sides of searchtet. Detects the coplanarities by additinal tests //
08896 // which are based on the given tolerance. If 'precise' is ONFACE or ONEDGE, //
08897 // we can save one or two orientation tests.                                 //
08898 //                                                                           //
08899 // The return value indicates the location of the 'searchpt' (INTETRAHEDRON, //
08900 // or ONFACE, ...). 'searchtet' is adjusted to a tetrahedron corresponding   //
08901 // to that value. See the introduction part of preciselocate() for detail.   //
08902 //                                                                           //
08903 // WARNING:  This routine detect degenerate case using relative tolerance.   //
08904 // It is better used after locate() or preciselocate().  For general inputs, //
08905 // it may not able to tell the correct location.                             //
08906 //                                                                           //
08908 
08909 enum tetgenmesh::locateresult tetgenmesh::adjustlocate(point searchpt,
08910   triface* searchtet, enum locateresult precise, REAL epspp)
08911 {
08912   point torg, tdest, tapex, toppo;
08913   REAL s1, s2, s3, s4;
08914 
08915   // For the given 'searchtet', the orientations tests are:
08916   //  s1: (tdest, torg, tapex, searchpt);
08917   //  s2: (torg, tdest, toppo, searchpt);
08918   //  s3: (tdest, tapex, toppo, searchpt);
08919   //  s4: (tapex, torg, toppo, searchpt);
08920   adjustedgering(*searchtet, CCW);
08921   torg = org(*searchtet);
08922   tdest = dest(*searchtet);
08923   tapex = apex(*searchtet);
08924   toppo = oppo(*searchtet);
08925 
08926   switch (precise) {
08927   case ONVERTEX:
08928     // This case we don't need do any further test.
08929     return ONVERTEX;
08930   case ONEDGE:
08931     // (torg, tdest);
08932     s1 = 0.0;
08933     s2 = 0.0;
08934     break;
08935   case ONFACE:
08936     // (tdest, torg, tapex);
08937     s1 = 0.0;
08938     s2 = orient3d(torg, tdest, toppo, searchpt);
08939     break;
08940   default: // INTETRAHEDRON or OUTSIDE
08941     s1 = orient3d(tdest, torg, tapex, searchpt);
08942     s2 = orient3d(torg, tdest, toppo, searchpt);
08943   }
08944 
08945   if (s1 != 0.0) {
08946     if (iscoplanar(tdest, torg, tapex, searchpt, s1, epspp)) {
08947       s1 = 0.0;
08948     }
08949   }
08950   if (s1 < 0.0) {
08951     return OUTSIDE;
08952   }
08953 
08954   if (s2 != 0.0) {
08955     if (iscoplanar(torg, tdest, toppo, searchpt, s2, epspp)) {
08956       s2 = 0.0;
08957     }
08958   }
08959   if (s2 < 0.0) {
08960     fnextself(*searchtet);
08961     return OUTSIDE;
08962   }
08963 
08964   s3 = orient3d(tdest, tapex, toppo, searchpt);
08965   if (s3 != 0.0) {
08966     if (iscoplanar(tdest, tapex, toppo, searchpt, s3, epspp)) {
08967       s3 = 0.0;
08968     }
08969   }
08970   if (s3 < 0.0) {
08971     enextfnextself(*searchtet);
08972     return OUTSIDE;
08973   }
08974 
08975   s4 = orient3d(tapex, torg, toppo, searchpt);
08976   if (s4 != 0.0) {
08977     if (iscoplanar(tapex, torg, toppo, searchpt, s4, epspp)) {
08978       s4 = 0.0;
08979     }
08980   }
08981   if (s4 < 0.0) {
08982     enext2fnextself(*searchtet);
08983     return OUTSIDE;
08984   }
08985 
08986   // Determine degenerate cases.
08987   if (s1 == 0.0) {
08988     if (s2 == 0.0) {
08989       if (s3 == 0.0) {
08990         // On tdest.
08991         enextself(*searchtet);
08992         return ONVERTEX;
08993       }
08994       if (s4 == 0.0) {
08995         // On torg.
08996         return ONVERTEX;
08997       }
08998       // On edge (torg, tdest).
08999       return ONEDGE;
09000     }
09001     if (s3 == 0.0) {
09002       if (s4 == 0.0) {
09003         // On tapex.
09004         enext2self(*searchtet);
09005         return ONVERTEX;
09006       }
09007       // On edge (tdest, tapex).
09008       enextself(*searchtet);
09009       return ONEDGE;
09010     }
09011     if (s4 == 0.0) {
09012       // On edge (tapex, torg).
09013       enext2self(*searchtet);
09014       return ONEDGE;
09015     }
09016     // On face (torg, tdest, tapex).
09017     return ONFACE;
09018   }
09019   if (s2 == 0.0) {
09020     fnextself(*searchtet);
09021     if (s3 == 0.0) {
09022       if (s4 == 0.0) {
09023         // On toppo.
09024         enext2self(*searchtet);
09025         return ONVERTEX;
09026       }
09027       // On edge (tdest, toppo).
09028       enextself(*searchtet);
09029       return ONEDGE;
09030     }
09031     if (s4 == 0.0) {
09032       // On edge (toppo, torg).
09033       enext2self(*searchtet);
09034       return ONEDGE;
09035     }
09036     // On face (torg, tdest, toppo).
09037     return ONFACE;
09038   }
09039   if (s3 == 0.0) {
09040     enextfnextself(*searchtet);
09041     if (s4 == 0.0) {
09042       // On edge (tapex, toppo).
09043       enextself(*searchtet);
09044       return ONEDGE;
09045     }
09046     // On face (tdest, tapex, toppo).
09047     return ONFACE;
09048   }
09049   if (s4 == 0.0) {
09050     enext2fnextself(*searchtet);
09051     // On face (tapex, torg, toppo).
09052     return ONFACE;
09053   }
09054 
09055   // Inside tetrahedron.
09056   return INTETRAHEDRON;
09057 }
09058 
09060 //                                                                           //
09061 // hullwalk()    Find a tetrahedron on the hull to continue search.          //
09062 //                                                                           //
09064 
09065 enum tetgenmesh::locateresult tetgenmesh::hullwalk(point searchpt,
09066   triface *hulltet)
09067 {
09068   list* travtetlist;
09069   triface travtet, neightet;
09070   point pa, pb, pc;
09071   enum locateresult loc;
09072   REAL ori;
09073   int i;
09074 
09075   travtetlist = new list(sizeof(triface), NULL, 256);
09076   travtet = *hulltet;
09077   infect(travtet);
09078   travtetlist->append(&travtet);
09079 
09080   loc = OUTSIDE;
09081   for (i = 0; i < travtetlist->len(); i++) {
09082     travtet = * (triface *)(* travtetlist)[i];
09083     // Choose the CCW-edgering in face.
09084     travtet.ver = 0;
09085     // Look for a side where pt lies below it.
09086     for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09087       pa = org(travtet);
09088       pb = dest(travtet);
09089       pc = apex(travtet);
09090       ori = orient3d(pa, pb, pc, searchpt);
09091       if (ori > 0.0) break;
09092     }
09093     // Is pt above all (or coplanar with some of) the four sides?
09094     if (travtet.loc == 4) {
09095       hulltet->tet = travtet.tet;
09096       loc = adjustlocate(searchpt, hulltet, INTETRAHEDRON, b->epsilon);
09097       assert(loc != OUTSIDE);
09098     } else { // ori > 0.0
09099       // pt is below (behind) this side. We want to walk through it.
09100       sym(travtet, neightet);
09101       if (neightet.tet == dummytet) {
09102         // This is a hull side. Is p approximately on this side.
09103         loc = adjustlocate(searchpt, &travtet, OUTSIDE, b->epsilon);
09104       }
09105       if (loc == OUTSIDE) {
09106         // Let's collect all the neighbors for next searching.
09107         for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09108           sym(travtet, neightet);
09109           if ((neightet.tet != dummytet) && !infected(neightet)) {
09110             // Neighbor exists and not visited.
09111             infect(neightet);
09112             travtetlist->append(&neightet);
09113           }
09114         } // for (travtet.loc = 0;
09115       } // if (loc == OUTSIDE)
09116     } // if (travtet.loc == 4)
09117     if (loc != OUTSIDE) break;
09118   } // for (i = 0; i < travtetlist->len(); i++)
09119 
09120   // Uninfect traversed tets.
09121   for (i = 0; i < travtetlist->len(); i++) {
09122     travtet = * (triface *)(* travtetlist)[i];
09123     uninfect(travtet);
09124   }
09125 
09126   delete travtetlist;
09127   return loc;
09128 }
09129 
09131 //                                                                           //
09132 // locatesub()    Find a point in the surface mesh of a facet.               //
09133 //                                                                           //
09134 // Searching begins from the input 'searchsh', it should be a handle on the  //
09135 // convex hull of the facet triangulation.                                   //
09136 //                                                                           //
09137 // If 'stopatseg' is nonzero, the search will stop if it tries to walk       //
09138 // through a subsegment, and will return OUTSIDE.                            //
09139 //                                                                           //
09140 // On completion, 'searchsh' is a subface that contains 'searchpt'.          //
09141 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchsh'  //
09142 //     is a handle whose origin is the existing vertex.                      //
09143 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchsh' is a     //
09144 //     handle whose primary edge is the edge on which the point lies.        //
09145 //   - Returns ONFACE if the point lies strictly within a subface.           //
09146 //     'searchsh' is a handle on which the point lies.                       //
09147 //   - Returns OUTSIDE if the point lies outside the triangulation.          //
09148 //                                                                           //
09149 // WARNING: This routine is designed for convex triangulations, and will not //
09150 // not generally work after the holes and concavities have been carved.      //
09151 //                                                                           //
09153 
09154 enum tetgenmesh::locateresult tetgenmesh::locatesub(point searchpt,
09155   face* searchsh, int stopatseg, REAL epspp)
09156 {
09157   face backtracksh, spinsh, checkedge;
09158   point forg, fdest, fapex;
09159   REAL orgori, destori;
09160   REAL ori, sign;
09161   int moveleft, i;
09162 
09163   if (searchsh->sh == dummysh) {
09164     searchsh->shver = 0;
09165     spivotself(*searchsh);
09166 #ifdef SELF_CHECK
09167     assert(searchsh->sh != dummysh);
09168 #endif
09169   }
09170   // Find the sign to simulate that abovepoint is 'above' the facet.
09171   adjustedgering(*searchsh, CCW);
09172   forg = sorg(*searchsh);
09173   fdest = sdest(*searchsh);
09174   fapex = sapex(*searchsh);
09175   ori = orient3d(forg, fdest, fapex, abovepoint);
09176   sign = ori > 0.0 ? -1 : 1;
09177 
09178   // Orient 'searchsh' so that 'searchpt' is below it (i.e., searchpt has
09179   //   CCW orientation with respect to searchsh in plane).  Such edge
09180   //   should always exist. Save it as (forg, fdest).
09181   for (i = 0; i < 3; i++) {
09182     forg = sorg(*searchsh);
09183     fdest = sdest(*searchsh);
09184     ori = orient3d(forg, fdest, abovepoint, searchpt) * sign;
09185     if (ori > 0.0) break;
09186     senextself(*searchsh);
09187   }
09188 #ifdef SELF_CHECK
09189   assert(i < 3);
09190 #endif
09191 
09192   while (1) {
09193     fapex = sapex(*searchsh);
09194     // Check whether the apex is the point we seek.
09195     if (fapex[0] == searchpt[0] && fapex[1] == searchpt[1] &&
09196         fapex[2] == searchpt[2]) {
09197       senext2self(*searchsh);
09198       return ONVERTEX;
09199     }
09200     // Does the point lie on the other side of the line defined by the
09201     //   triangle edge opposite the triangle's destination?
09202     destori = orient3d(forg, fapex, abovepoint, searchpt) * sign;
09203     if (epspp > 0.0) {
09204       if (iscoplanar(forg, fapex, abovepoint, searchpt, destori, epspp)) {
09205         destori = 0.0;
09206       }
09207     }
09208     // Does the point lie on the other side of the line defined by the
09209     //   triangle edge opposite the triangle's origin?
09210     orgori = orient3d(fapex, fdest, abovepoint, searchpt) * sign;
09211     if (epspp > 0.0) {
09212       if (iscoplanar(fapex, fdest, abovepoint, searchpt, orgori, epspp)) {
09213         orgori = 0.0;
09214       }
09215     }
09216     if (destori > 0.0) {
09217       moveleft = 1;
09218     } else {
09219       if (orgori > 0.0) {
09220         moveleft = 0;
09221       } else {
09222         // The point must be on the boundary of or inside this triangle.
09223         if (destori == 0.0) {
09224           senext2self(*searchsh);
09225           return ONEDGE;
09226         }
09227         if (orgori == 0.0) {
09228           senextself(*searchsh);
09229           return ONEDGE;
09230         }
09231         return ONFACE;
09232       }
09233     }
09234     // Move to another triangle.  Leave a trace `backtracksh' in case
09235     //   walking off a boundary of the triangulation.
09236     if (moveleft) {
09237       senext2(*searchsh, backtracksh);
09238       fdest = fapex;
09239     } else {
09240       senext(*searchsh, backtracksh);
09241       forg = fapex;
09242     }
09243     // Check if we meet a segment.
09244     sspivot(backtracksh, checkedge);
09245     if (checkedge.sh != dummysh) {
09246       if (stopatseg) {
09247         // The flag indicates we should not cross a segment. Stop.
09248         *searchsh = backtracksh;
09249         return OUTSIDE;
09250       }
09251       // Try to walk through a segment. We need to find a coplanar subface
09252       //   sharing this segment to get into.
09253       spinsh = backtracksh;
09254       do {
09255         spivotself(spinsh);
09256         if (spinsh.sh == backtracksh.sh) {
09257           // Turn back, no coplanar subface is found.
09258           break;
09259         }
09260         // Are they belong to the same facet.
09261         if (shellmark(spinsh) == shellmark(backtracksh)) {
09262           // Find a coplanar subface. Walk into it.
09263           *searchsh = spinsh;
09264           break;
09265         }
09266         // Are they (nearly) coplanar?
09267         ori = orient3d(forg, fdest, sapex(backtracksh), sapex(spinsh));
09268         if (iscoplanar(forg, fdest, sapex(backtracksh), sapex(spinsh), ori,
09269                        b->epsilon)) {
09270           // Find a coplanar subface. Walk into it.
09271           *searchsh = spinsh;
09272           break;
09273         }
09274       } while (spinsh.sh != backtracksh.sh);
09275     } else {
09276       spivot(backtracksh, *searchsh);
09277     }
09278     // Check for walking right out of the triangulation.
09279     if ((searchsh->sh == dummysh) || (searchsh->sh == backtracksh.sh)) {
09280       // Go back to the last triangle.
09281       *searchsh = backtracksh;
09282       return OUTSIDE;
09283     }
09284     // To keep the same orientation wrt abovepoint.
09285     if (sorg(*searchsh) != forg) sesymself(*searchsh);
09286 #ifdef SELF_CHECK
09287     assert((sorg(*searchsh) == forg) && (sdest(*searchsh) == fdest));
09288 #endif
09289   }
09290 }
09291 
09293 //                                                                           //
09294 // adjustlocatesub()    Adjust the precise location of a vertex.             //
09295 //                                                                           //
09296 // 'precise' is the precise location (returned from locatesub()) of 'searcht'//
09297 // with respect to 'searchsh'. 'epspp' is the given relative tolerance.      //
09298 //                                                                           //
09299 // This routine re-evaluates the orientations of 'searchpt' with respect to  //
09300 // the three edges of 'searchsh'. Detects the collinearities by additinal    //
09301 // tests based on the given tolerance. If 'precise' is ONEDGE, one can save  //
09302 // one orientation test for the current edge of 'searchsh'.                  //
09303 //                                                                           //
09304 // On completion, 'searchsh' is a subface contains 'searchpt'. The returned  //
09305 // value indicates one of the following cases:                               //
09306 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchsh'  //
09307 //     is a handle whose origin is the existing vertex.                      //
09308 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchsh' is a     //
09309 //     handle whose primary edge is the edge on which the point lies.        //
09310 //   - Returns ONFACE if the point lies strictly within a subface.           //
09311 //     'searchsh' is a handle on which the point lies.                       //
09312 //   - Returns OUTSIDE if the point lies outside 'searchsh'.                 //
09313 //                                                                           //
09315 
09316 enum tetgenmesh::locateresult tetgenmesh::
09317 adjustlocatesub(point searchpt, face* searchsh, enum locateresult precise,
09318                 REAL epspp)
09319 {
09320   point pa, pb, pc;
09321   bool s1, s2, s3;
09322 
09323   pa = sorg(*searchsh);
09324   pb = sdest(*searchsh);
09325   pc = sapex(*searchsh);
09326 
09327   if (precise == ONEDGE) {
09328     s1 = true;
09329   } else {
09330     s1 = iscollinear(pa, pb, searchpt, epspp);
09331   }
09332   s2 = iscollinear(pb, pc, searchpt, epspp);
09333   s3 = iscollinear(pc, pa, searchpt, epspp);
09334   if (s1) {
09335     if (s2) {
09336       // on vertex pb.
09337 #ifdef SELF_CHECK
09338       assert(!s3);
09339 #endif
09340       senextself(*searchsh);
09341       return ONVERTEX;
09342     } else if (s3) {
09343       // on vertex pa.
09344       return ONVERTEX;
09345     } else {
09346       // on edge pa->pb.
09347       return ONEDGE;
09348     }
09349   } else if (s2) {
09350     if (s3) {
09351       // on vertex pc.
09352       senext2self(*searchsh);
09353       return ONVERTEX;
09354     } else {
09355       // on edge pb->pc.
09356       senextself(*searchsh);
09357       return ONEDGE;
09358     }
09359   } else if (s3) {
09360     // on edge pc->pa.
09361     senext2self(*searchsh);
09362     return ONEDGE;
09363   } else {
09364     return precise;
09365   }
09366 }
09367 
09369 //                                                                           //
09370 // locateseg()    Find a point in subsegments.                               //
09371 //                                                                           //
09372 // Searching begins from the input 'searchseg', it should be a subsegment of //
09373 // the whole segment.                                                        //
09374 //                                                                           //
09375 // On completion, 'searchseg' is a subsegment that contains 'searchpt'.      //
09376 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchseg' //
09377 //     is a handle whose origin is the existing vertex.                      //
09378 //   - Returns ONEDGE if the point lies inside 'searchseg'.                  //
09379 //   - Returns OUTSIDE if the point lies outside the segment.                //
09380 //                                                                           //
09382 
09383 enum tetgenmesh::locateresult tetgenmesh::
09384 locateseg(point searchpt, face* searchseg)
09385 {
09386   face backtraceseg;
09387   point pa, pb;
09388   REAL dx, dy, dz;
09389   int moveleft;
09390   int i;
09391 
09392   moveleft = 0;
09393   while (1) {
09394     searchseg->shver = 0;
09395     pa = sorg(*searchseg);
09396     pb = sdest(*searchseg);
09397     // Find the biggest difference in x, y, and z coordinates of a and b.
09398     dx = fabs(pb[0] - pa[0]);
09399     dy = fabs(pb[1] - pa[1]);
09400     dz = fabs(pb[2] - pa[2]);
09401     if (dx > dy) {
09402       if (dx > dz) {
09403         i = 0;
09404       } else {
09405         i = 2;
09406       }
09407     } else {
09408       if (dy > dz) {
09409         i = 1;
09410       } else {
09411         i = 2;
09412       }
09413     }
09414     if (pa[i] < pb[i]) {
09415       if (searchpt[i] < pa[i]) {
09416         moveleft = 1;
09417       } else if (searchpt[i] > pa[i]) {
09418         if (searchpt[i] < pb[i]) {
09419           return ONEDGE;
09420         } else if (searchpt[i] > pb[i]) {
09421           moveleft = 0;
09422         } else {
09423 #ifdef SELF_CHECK
09424           assert(searchpt[i] == pb[i]);
09425 #endif
09426           sesymself(*searchseg);
09427           return ONVERTEX;
09428         }
09429       } else {
09430 #ifdef SELF_CHECK
09431         assert(searchpt[i] == pa[i]);
09432 #endif
09433         return ONVERTEX;
09434       }
09435     } else if (pa[i] > pb[i]) {
09436       if (searchpt[i] < pb[i]) {
09437         moveleft = 0;
09438       } else if (searchpt[i] > pb[i]) {
09439         if (searchpt[i] < pa[i]) {
09440           return ONEDGE;
09441         } else if (searchpt[i] > pa[i]) {
09442           moveleft = 1;
09443         } else {
09444 #ifdef SELF_CHECK
09445           assert(searchpt[i] == pa[i]);
09446 #endif
09447           return ONVERTEX;
09448         }
09449       } else {
09450 #ifdef SELF_CHECK
09451         assert(searchpt[i] == pb[i]);
09452 #endif
09453         sesymself(*searchseg);
09454         return ONVERTEX;
09455       }
09456     }
09457     backtraceseg = *searchseg;
09458     if (moveleft) {
09459       senext2self(*searchseg);
09460     } else {
09461       senextself(*searchseg);
09462     }
09463     spivotself(*searchseg);
09464     if (searchseg->sh == dummysh) {
09465       *searchseg = backtraceseg;
09466       break;
09467     }
09468   }
09469 
09470   return OUTSIDE;
09471 }
09472 
09474 //                                                                           //
09475 // adjustlocateseg()    Adjust the precise location of a vertex on segment.  //
09476 //                                                                           //
09477 // 'searchpt' is either inside or ouside the segment 'searchseg'. It will be //
09478 // adjusted to on vertex if it is very close to an endpoint of 'searchseg'.  //
09479 // 'epspp' is the given relative tolerance.                                  //
09480 //                                                                           //
09482 
09483 enum tetgenmesh::locateresult tetgenmesh::
09484 adjustlocateseg(point searchpt, face* searchseg, enum locateresult precise,
09485                 REAL epspp)
09486 {
09487   point pa, pb;
09488   REAL L, d, r;
09489 
09490   pa = sorg(*searchseg);
09491   pb = sdest(*searchseg);
09492   L = distance(pa, pb);
09493 
09494   // Is searchpt approximate to pa?
09495   d = distance(pa, searchpt);
09496   r = d / L;
09497   if (r <= epspp) {
09498     return ONVERTEX;
09499   }
09500   // Is searchpt approximate to pb?
09501   d = distance(pb, searchpt);
09502   r = d / L;
09503   if (r <= epspp) {
09504     sesymself(*searchseg);
09505     return ONVERTEX;
09506   }
09507 
09508   return precise;
09509 }
09510 
09511 //
09512 // End of point location routines
09513 //
09514 
09515 //
09516 // Begin of mesh transformation routines
09517 //
09518 
09520 //                                                                           //
09521 // Flip operations                                                           //
09522 //                                                                           //
09523 // If abc is a hull face, it is unflipable, and is locally Delaunay.  In the //
09524 // following, we assume abc is an interior face, and the other tetrahedron   //
09525 // adjoining at abc is bace.                                                 //
09526 //                                                                           //
09527 // If the convex hull CH of the set {a, b, c, d, e} only has four vertices,  //
09528 // i.e., one vertex lies inside CH, then abc is unflipable, and is locally   //
09529 // Delaunay. If CH is the vertex set itself, we have the following cases to  //
09530 // determine whether abc is flipable or not.                                 //
09531 //                                                                           //
09532 // If no four points of {a, b, c, d, e} are coplanar, a 2-to-3 flip can be   //
09533 // applied to abc if the edge de crosses the triangle abc; a 3-to-2 flip can //
09534 // be applied to abc if ab crosses cde, and abde exists, otherwise, face abc //
09535 // is unflipable, i.e., the tetrahedron abde is not present.                 //
09536 //                                                                           //
09537 // If four points of {a, b, c, d, e} are coplanar (two faces are coplanar).  //
09538 // Assume faces abd and abe are coplanar (it is impossible be abc). If a, b, //
09539 // d, e form a non-convex quadrilateral, then abc is unflipable, furthermore,//
09540 // it is locally Delaunay.  Assume they are convex quadrilateral, if abd and //
09541 // abe are hull faces, a 2-to-2 flip can be applied to abc;  if abd and abe  //
09542 // are interior faces,  assume two tetrahedra adjoining abd and abe at the   //
09543 // opposite sides are abdg and abef, respectively.  If g = f, a 4-to-4 flip  //
09544 // can be applied to abc, otherwise, abc is unflipable.                      //
09545 //                                                                           //
09546 // There are other cases which can cause abc unflipable. If abc is a subface,//
09547 // a 2-to-3 flip is forbidden;  if ab is a subsegment, flips 3-to-2, 2-to-2, //
09548 // and 4-to-4 are forbidden.                                                 //
09549 //                                                                           //
09551 
09553 //                                                                           //
09554 // categorizeface()    Determine the flip type of a given face.              //
09555 //                                                                           //
09556 // On input, 'horiz' represents the face abc we want to flip (imagine it is  //
09557 // parallel to the horizon).  Let the tet above it be abcd.                  //
09558 //                                                                           //
09559 // This routine determines the suitable type of flip operation for 'horiz'.  //
09560 //   - Returns T23 if a 2-to-3 flip is applicable. 'horiz' is same as input. //
09561 //   - Returns T32 if a 3-to-2 flip is applicable. 'horiz' returns the edge  //
09562 //     of abc which is the flipable.                                         //
09563 //   - Returns T22 if a 2-to-2 or 4-to-4 flip is applicable. 'horiz' returns //
09564 //     the edge of abc which is flipable.                                    //
09565 //   - Returns N32 indicates it is unflipable due to the absence of a tet.   //
09566 //     'horize' returns the unflipable edge.                                 //
09567 //   - Returns N40 indicates it is unflipable and is locally Delaunay.       //
09568 //   - Returns FORBIDDENFACE indicates abc is a subface.                     //
09569 //   - Returns FORBIDDENEDGE indicates the flipable edge of abc is a segment.//
09570 //     'horize' returns the flipable edge.                                   //
09571 //                                                                           //
09572 // Given a face abc, with two adjoining tetrahedra abcd and bace.  If abc is //
09573 // flipable, i.e., T23, T32, T22 or T44, its flip type can be determined by  //
09574 // doing five orientation tests: two tests for determining that d, e lie on  //
09575 // the different sides of abc, three tests for determining if the edge de    //
09576 // intersects the face abc.  However, if we use the neighbor information of  //
09577 // the mesh data structure, we can reduce the five orientation tests to at   //
09578 // most three tests, that is, the two tests for determining whether d and e  //
09579 // lie on the different sides of abc can be saved.                           //
09580 //                                                                           //
09582 
09583 enum tetgenmesh::fliptype tetgenmesh::categorizeface(triface& horiz)
09584 {
09585   triface symhoriz, casing;
09586   face checksh, checkseg;
09587   face cassh1, cassh2;
09588   point pa, pb, pc, pd, pe, pf, pg;
09589   point abdoppo, bcdoppo, cadoppo;
09590   REAL ori1, ori2, ori3;
09591   int adjtet;
09592 
09593   sym(horiz, symhoriz);
09594   if (symhoriz.tet == dummytet) {
09595     // A hull face is unflipable and locally Delaunay.
09596     return N40;
09597   }
09598 
09599   adjustedgering(horiz, CCW);
09600   findedge(&symhoriz, dest(horiz), org(horiz));
09601   pa = org(horiz);
09602   pb = dest(horiz);
09603   pc = apex(horiz);
09604   pd = oppo(horiz);
09605   pe = oppo(symhoriz);
09606 
09607   // Find the number of adjacent tetrahedra of abc, which have d, e, and one
09608   //   of corners of abc as their corners. This number can be 0, 1 and 2.
09609   abdoppo = bcdoppo = cadoppo = (point) NULL;
09610   adjtet = 0;
09611   fnext(horiz, casing); // at edge 'ab'.
09612   symself(casing);
09613   if (casing.tet != dummytet) {
09614     abdoppo = oppo(casing);
09615     if (abdoppo == pe) adjtet++;
09616   }
09617   enextfnext(horiz, casing); // at edge 'bc'.
09618   symself(casing);
09619   if (casing.tet != dummytet) {
09620     bcdoppo = oppo(casing);
09621     if (bcdoppo == pe) adjtet++;
09622   }
09623   enext2fnext(horiz, casing); // at edge 'ca'.
09624   symself(casing);
09625   if (casing.tet != dummytet) {
09626     cadoppo = oppo(casing);
09627     if (cadoppo == pe) adjtet++;
09628   }
09629 
09630   if (adjtet == 0) {
09631     // No adjacent tetrahedron. Types T23, T22 and T44 are possible.
09632     ori1 = orient3d(pa, pb, pd, pe);
09633     if (checksubfaces && ori1 != 0.0) {
09634       // Check if abd and abe are both boundary faces?
09635       fnext(horiz, casing);
09636       tspivot(casing, cassh1);
09637       fnext(symhoriz, casing);
09638       tspivot(casing, cassh2);
09639       if ((cassh1.sh != dummysh) && (cassh2.sh != dummysh)) {
09640         // abd and abe are both boundary faces. Check if ab is a segment.
09641         findedge(&cassh1, pa, pb);
09642         sspivot(cassh1, checkseg);
09643         if (checkseg.sh == dummysh) {
09644           // ab is not a segment - abd and abe belong to the same facet.
09645           //   The four points are forced to be coplanar.
09646           ori1 = 0.0;
09647         } else {
09648           // ab is a segment - abd and abe belong to two different facets.
09649           //   In principle, a, b, c and d can form a tetrahedron (since
09650           //   ori1 != 0.0).  However, we should avoid to create a very
09651           //   flat one which may form a sequence of extremely badly-shaped
09652           //   or even wrong orientational tets. Test with a larger epsilon.
09653           if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09654         }
09655       } else {
09656         // abd and abe are not both boundary faces. Check if abd and bae
09657         //   are approximately coplanar with respect to the epsilon.
09658         if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon)) ori1 = 0.0;
09659       }
09660     }
09661     if (ori1 < 0.0) {
09662       // e lies above abd, unflipable, tet abde is not present.
09663 #ifdef SELF_CHECK
09664       if (!nonconvex) {
09665         // abd and abe should not be hull faces, check it.
09666         fnext(horiz, casing);
09667         symself(casing);
09668         assert(casing.tet != dummytet);
09669         fnext(symhoriz, casing);
09670         symself(casing);
09671         assert(casing.tet != dummytet);
09672       }
09673 #endif
09674       if (checksubfaces) {
09675         // The nonconvexbility may be casued by existing an subsegment.
09676         tsspivot(&horiz, &checkseg);
09677         if (checkseg.sh != dummysh) {
09678           return FORBIDDENEDGE;
09679         }
09680       }
09681       return N32;
09682     }
09683     ori2 = orient3d(pb, pc, pd, pe);
09684     if (checksubfaces && ori2 != 0.0) {
09685       // Check if bcd and cbe are both boundary faces.
09686       enextfnext(horiz, casing);
09687       tspivot(casing, cassh1);
09688       enext2fnext(symhoriz, casing);
09689       tspivot(casing, cassh2);
09690       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09691         // bcd and cbe are both boundary faces. Check if bc is a segment.
09692         findedge(&cassh1, pb, pc);
09693         sspivot(cassh1, checkseg);
09694         if (checkseg.sh == dummysh) {
09695           // bc is not a segment - bcd and cbe belong to the same facet.
09696           //   The four points are forced to be coplanar.
09697           ori2 = 0.0;
09698         } else {
09699           if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09700         }
09701       } else {
09702         //  bcd and cbe are not both boundary faces. Check if bcd and cbe
09703         //   are approximately coplanar with respect to the epsilon.
09704         if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon)) ori2 = 0.0;
09705       }
09706     }
09707     if (ori2 < 0.0) {
09708       // e lies above bcd, unflipable, tet bcde is not present.
09709 #ifdef SELF_CHECK
09710       if (!nonconvex) {
09711         // bcd and cbe should not be hull faces, check it.
09712         enextfnext(horiz, casing);
09713         symself(casing);
09714         assert(casing.tet != dummytet);
09715         enext2fnext(symhoriz, casing);
09716         symself(casing);
09717         assert(casing.tet != dummytet);
09718       }
09719 #endif
09720       enextself(horiz);
09721       if (checksubfaces) {
09722         // The nonconvexbility may be casued by existing an subsegment.
09723         tsspivot(&horiz, &checkseg);
09724         if (checkseg.sh != dummysh) {
09725           return FORBIDDENEDGE;
09726         }
09727       }
09728       return N32;
09729     }
09730     ori3 = orient3d(pc, pa, pd, pe);
09731     if (checksubfaces && ori3 != 0.0) {
09732       // Check if cad and ace are both boundary faces.
09733       enext2fnext(horiz, casing);
09734       tspivot(casing, cassh1);
09735       enextfnext(symhoriz, casing);
09736       tspivot(casing, cassh2);
09737       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09738         // cad and ace are both boundary faces. Check if ca is a segment.
09739         findedge(&cassh1, pc, pa);
09740         sspivot(cassh1, checkseg);
09741         if (checkseg.sh == dummysh) {
09742           // ca is not a segment - cad and ace belong to the same facet.
09743           //   The four points are forced to be coplanar.
09744           ori3 = 0.0;
09745         } else {
09746           // ca is a segment - cad and ace belong to two different facets.
09747           //   In principle, c, a, d and e can form a tetrahedron (since
09748           //   ori3 != 0.0). Use a larger eps to test if they're coplanar.
09749           if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon * 1e+2)) ori3 = 0.0;
09750         }
09751       } else {
09752         // cad and ace are not both boundary faces. Check if cad and ace
09753         //   are approximately coplanar with respect to the epsilon.
09754         if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon)) ori3 = 0.0;
09755       }
09756     }
09757     if (ori3 < 0.0) {
09758       // e lies above cad, unflipable, tet cade is not present.
09759 #ifdef SELF_CHECK
09760       if (!nonconvex) {
09761         // cad and ace should not be hull faces, check it.
09762         enext2fnext(horiz, casing);
09763         symself(casing);
09764         assert(casing.tet != dummytet);
09765         enextfnext(symhoriz, casing);
09766         symself(casing);
09767         assert(casing.tet != dummytet);
09768       }
09769 #endif
09770       enext2self(horiz);
09771       if (checksubfaces) {
09772         // The nonconvexbility may be casued by existing an subsegment.
09773         tsspivot(&horiz, &checkseg);
09774         if (checkseg.sh != dummysh) {
09775           return FORBIDDENEDGE;
09776         }
09777       }
09778       return N32;
09779     }
09780     if (ori1 == 0.0) {
09781       // e is coplanar with abd.
09782       if (ori2 * ori3 == 0.0) {
09783         // only one zero is possible.
09784         // assert(!(ori2 == 0.0 && ori3 == 0.0));
09785         // Three points (d, e, and a or b) are collinear, abc is unflipable
09786         //   and locally Delaunay.
09787         return N40;
09788       }
09789     } else if (ori2 == 0.0) {
09790       // e is coplanar with bcd.
09791       if (ori1 * ori3 == 0.0) {
09792         // only one zero is possible.
09793         // assert(!(ori1 == 0.0 && ori3 == 0.0));
09794         // Three points (d, e, and b or c) are collinear, abc is unflipable
09795         //   and locally Delaunay.
09796         return N40;
09797       }
09798       // Adjust 'horiz' and 'symhoriz' be the edge bc.
09799       enextself(horiz);
09800       enext2self(symhoriz);
09801     } else if (ori3 == 0.0) {
09802       // e is coplanar with cad.
09803       if (ori1 * ori2 == 0.0) {
09804         // only one zero is possible.
09805         // assert(!(ori1 == 0.0 && ori2 == 0.0));
09806         // Three points (d, e, and c or a) are collinear, abc is unflipable
09807         //   and locally Delaunay.
09808         return N40;
09809       }
09810       // Adjust 'horiz' and 'symhoriz' be the edge ca.
09811       enext2self(horiz);
09812       enextself(symhoriz);
09813     } else {
09814       // e lies below all three faces, flipable.
09815       if (checksubfaces) {
09816         tspivot(horiz, checksh);
09817         if (checksh.sh != dummysh) {
09818           // To flip a subface is forbidden.
09819           return FORBIDDENFACE;
09820         }
09821       }
09822       return T23;
09823     }
09824     // Four points are coplanar, T22 or T44 is possible.
09825     if (checksubfaces) {
09826       tsspivot(&horiz, &checkseg);
09827       if (checkseg.sh != dummysh) {
09828         // To flip a subsegment is forbidden.
09829         return FORBIDDENEDGE;
09830       }
09831       tspivot(horiz, checksh);
09832       if (checksh.sh != dummysh) {
09833         // To flip a subface is forbidden.
09834         return FORBIDDENFACE;
09835       }
09836     }
09837     // Assume the four coplanar points are a, b, d, e, abd and abe are two
09838     //   coplanar faces. If both abd and abe are hull faces, flipable(T22).
09839     //   If they are interior faces, get the opposite tetrahedra abdf and
09840     //   abeg, if f = g, flipable (T44). Otherwise, unflipable.
09841     pf = pg = (point) NULL;
09842     fnext(horiz, casing);
09843     symself(casing);
09844     if (casing.tet != dummytet) {
09845       pf = oppo(casing);
09846     }
09847     fnext(symhoriz, casing);
09848     symself(casing);
09849     if (casing.tet != dummytet) {
09850       pg = oppo(casing);
09851     }
09852     if (pf == pg) {
09853       // Either T22 (pf == pg == NULL) or T44 (pf and pg) is possible.
09854       if (checksubfaces) {
09855         // Retreat the corner points a, b, and c.
09856         pa = org(horiz);
09857         pb = dest(horiz);
09858         pc = apex(horiz);
09859         // Be careful not to create an inverted tetrahedron. Check the case.
09860         ori1 = orient3d(pc, pd, pe, pa);
09861         if (ori1 <= 0) return N40;
09862         ori1 = orient3d(pd, pc, pe, pb);
09863         if (ori1 <= 0) return N40;
09864         if (pf != (point) NULL) {
09865           ori1 = orient3d(pd, pf, pe, pa);
09866           if (ori1 <= 0) return N40;
09867           ori1 = orient3d(pf, pd, pe, pb);
09868           if (ori1 <= 0) return N40;
09869         }
09870       }
09871       if (pf == (point) NULL) {
09872         // abd and abe are hull faces, flipable.
09873         return T22;
09874       } else {
09875         // abd and abe are interior faces, flipable.
09876 #ifdef SELF_CHECK
09877         assert(pf != (point) NULL);
09878 #endif
09879         return T44;
09880       }
09881     } else {
09882       // ab has more than four faces around it, unflipable.
09883       return N32;
09884     }
09885   } else if (adjtet == 1) {
09886     // One of its three edges is locally non-convex. Type T32 is possible.
09887     // Adjust current configuration so that edge ab is non-convex.
09888     if (bcdoppo == pe) {
09889       // Edge bc is non-convex. Adjust 'horiz' and 'symhoriz' be edge bc.
09890       enextself(horiz);
09891       enext2self(symhoriz);
09892       pa = org(horiz);
09893       pb = dest(horiz);
09894       pc = apex(horiz);
09895     } else if (cadoppo == pe) {
09896       // Edge ca is non-convex. Adjust 'horiz' and 'symhoriz' be edge ca.
09897       enext2self(horiz);
09898       enextself(symhoriz);
09899       pa = org(horiz);
09900       pb = dest(horiz);
09901       pc = apex(horiz);
09902     } else {
09903       // Edge ab is non-convex.
09904 #ifdef SELF_CHECK
09905       assert(abdoppo == pe);
09906 #endif
09907     } // Now ab is the non-convex edge.
09908     // In order to be flipable, ab should cross face cde. Check it.
09909     ori1 = orient3d(pc, pd, pe, pa);
09910     if (checksubfaces && ori1 != 0.0) {
09911       // Check if cad and ace are both boundary faces.
09912       enext2fnext(horiz, casing);
09913       tspivot(casing, cassh1);
09914       enextfnext(symhoriz, casing);
09915       tspivot(casing, cassh2);
09916       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09917         // cad and ace are both boundary faces. Check if ca is a segment.
09918         findedge(&cassh1, pc, pa);
09919         sspivot(cassh1, checkseg);
09920         if (checkseg.sh == dummysh) {
09921           // ca is not a segment. cad and ace belong to the same facet.
09922           //   The four points are forced to be coplanar.
09923           ori1 = 0.0;
09924         } else {
09925           // ca is a segment. cad and ace belong to different facets.
09926           //   In principle, c, d, e, and a can form a tetrahedron (since
09927           //   ori1 != 0.0).  However, we should avoid to create a very
09928           //   flat tet. Use a larger epsilon to test if they're coplanar.
09929           if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09930         }
09931       } else {
09932         // Check if c, d, e, and a are approximately coplanar.
09933         if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon)) ori1 = 0.0;
09934       }
09935     }
09936     if (ori1 <= 0.0) {
09937       // a lies above or is coplanar cde, abc is locally Delaunay.
09938       return N40;
09939     }
09940     ori2 = orient3d(pd, pc, pe, pb);
09941     if (checksubfaces && ori2 != 0.0) {
09942       // Check if bcd and cbe are both boundary faces.
09943       enextfnext(horiz, casing);
09944       tspivot(casing, cassh1);
09945       enext2fnext(symhoriz, casing);
09946       tspivot(casing, cassh2);
09947       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09948         // bcd and cbe are both boundary faces. Check if bc is a segment.
09949         findedge(&cassh1, pb, pc);
09950         sspivot(cassh1, checkseg);
09951         if (checkseg.sh == dummysh) {
09952           // bc is not a segment. bcd and cbe belong to the same facet.
09953           //   The four points are forced to be coplanar.
09954           ori2 = 0.0;
09955         } else {
09956           // bc is a segment. bcd and cbe belong to different facets.
09957           //   In principle, d, c, e, and b can form a tetrahedron (since
09958           //   ori2 != 0.0).  However, we should avoid to create a very
09959           //   flat tet. Use a larger epsilon to test if they're coplanar.
09960           if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09961         }
09962       } else {
09963         // Check if d, c, e, and b are approximately coplanar.
09964         if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon)) ori2 = 0.0;
09965       }
09966     }
09967     if (ori2 <= 0.0) {
09968       // b lies above dce, unflipable, and abc is locally Delaunay.
09969       return N40;
09970     }
09971     // Edge ab crosses face cde properly.
09972     if (checksubfaces) {
09973       // If abc is subface, then ab must be a subsegment (because abde is
09974       //   a tetrahedron and ab crosses cde properly).
09975       tsspivot(&horiz, &checkseg);
09976       if (checkseg.sh != dummysh) {
09977         // To flip a subsegment is forbidden.
09978         return FORBIDDENEDGE;
09979       }
09980       // Both abd and bae should not be subfaces (because they're not
09981       //   coplanar and ab is not a subsegment). However, they may be
09982       //   subfaces and belong to a facet (created during facet recovery),
09983       //   that is, abde is an invalid tetrahedron. Find this case out.
09984       fnext(horiz, casing);
09985       tspivot(casing, cassh1);
09986       fnext(symhoriz, casing);
09987       tspivot(casing, cassh2);
09988       if (cassh1.sh != dummysh || cassh2.sh != dummysh) {
09989         if (!b->quiet) {
09990           // Unfortunately, they're subfaces. Corrections need be done here.
09991           printf("Warning:  A tetrahedron spans two subfaces of a facet.\n");
09992         }
09993         // Temporarily, let it be there.
09994         return N32;
09995       }
09996     }
09997     return T32;
09998   } else {
09999     // The convex hull of {a, b, c, d, e} has only four vertices, abc is
10000     //   unflipable, furthermore, it is locally Delaunay.
10001     return N40;
10002   }
10003 }
10004 
10006 //                                                                           //
10007 // enqueueflipface(), enqueueflipedge()    Queue a face (or an edge).        //
10008 //                                                                           //
10009 // The face (or edge) may be non-locally Delaunay. It is queued for process- //
10010 // ing in flip() (or flipsub()). The vertices of the face (edge) are stored  //
10011 // seperatly to ensure the face (or edge) is still the same one when we save //
10012 // it since other flips will cause this face (or edge) be changed or dead.   //
10013 //                                                                           //
10015 
10016 void tetgenmesh::enqueueflipface(triface& checkface, queue* flipqueue)
10017 {
10018   badface *queface;
10019   triface symface;
10020 
10021   sym(checkface, symface);
10022   if (symface.tet != dummytet) {
10023     queface = (badface *) flipqueue->push((void *) NULL);
10024     queface->tt = checkface;
10025     queface->foppo = oppo(symface);
10026   }
10027 }
10028 
10029 void tetgenmesh::enqueueflipedge(face& checkedge, queue* flipqueue)
10030 {
10031   badface *queface;
10032 
10033   queface = (badface *) flipqueue->push((void *) NULL);
10034   queface->ss = checkedge;
10035   queface->forg = sorg(checkedge);
10036   queface->fdest = sdest(checkedge);
10037 }
10038 
10040 //                                                                           //
10041 // flip23()    Perform a 2-to-3 flip.                                        //
10042 //                                                                           //
10043 // On input, 'flipface' represents the face will be flipped.  Let it is abc, //
10044 // the two tetrahedra sharing abc are abcd, bace. abc is not a subface.      //
10045 //                                                                           //
10046 // A 2-to-3 flip is to change two tetrahedra abcd, bace to three tetrahedra  //
10047 // edab, edbc, and edca.  As a result, face abc has been removed and three   //
10048 // new faces eda, edb and edc have been created.                             //
10049 //                                                                           //
10050 // On completion, 'flipface' returns edab.  If 'flipqueue' is not NULL, all  //
10051 // possibly non-Delaunay faces are added into it.                            //
10052 //                                                                           //
10054 
10055 void tetgenmesh::flip23(triface* flipface, queue* flipqueue)
10056 {
10057   triface abcd, bace;                                  // Old configuration.
10058   triface oldabd, oldbcd, oldcad;
10059   triface abdcasing, bcdcasing, cadcasing;
10060   triface oldbae, oldcbe, oldace;
10061   triface baecasing, cbecasing, acecasing;
10062   triface worktet;
10063   face abdsh, bcdsh, cadsh;                   // The six subfaces on the CH.
10064   face baesh, cbesh, acesh;
10065   face abseg, bcseg, caseg;                      // The nine segs on the CH.
10066   face adseg, bdseg, cdseg;
10067   face aeseg, beseg, ceseg;
10068   triface edab, edbc, edca;                            // New configuration.
10069   point pa, pb, pc, pd, pe;
10070   REAL attrib, volume;
10071   int i;
10072 
10073   abcd = *flipface;
10074   adjustedgering(abcd, CCW); // abcd represents edge ab.
10075   pa = org(abcd);
10076   pb = dest(abcd);
10077   pc = apex(abcd);
10078   pd = oppo(abcd);
10079   // sym(abcd, bace);
10080   // findedge(&bace, dest(abcd), org(abcd)); // bace represents edge ba.
10081   sym(abcd, bace);
10082   bace.ver = 0; // CCW.
10083   for (i = 0; (i < 3) && (org(bace) != pb); i++) {
10084     enextself(bace);
10085   }
10086   pe = oppo(bace);
10087 
10088   if (b->verbose > 2) {
10089     printf("    Do T23 on face (%d, %d, %d) %d, %d.\n", pointmark(pa),
10090            pointmark(pb), pointmark(pc), pointmark(pd), pointmark(pe));
10091   }
10092   flip23s++;
10093 
10094   // Storing the old configuration outside the convex hull.
10095   fnext(abcd, oldabd);
10096   enextfnext(abcd, oldbcd);
10097   enext2fnext(abcd, oldcad);
10098   fnext(bace, oldbae);
10099   enext2fnext(bace, oldcbe);
10100   enextfnext(bace, oldace);
10101   sym(oldabd, abdcasing);
10102   sym(oldbcd, bcdcasing);
10103   sym(oldcad, cadcasing);
10104   sym(oldbae, baecasing);
10105   sym(oldcbe, cbecasing);
10106   sym(oldace, acecasing);
10107   if (checksubfaces) {
10108     tspivot(oldabd, abdsh);
10109     tspivot(oldbcd, bcdsh);
10110     tspivot(oldcad, cadsh);
10111     tspivot(oldbae, baesh);
10112     tspivot(oldcbe, cbesh);
10113     tspivot(oldace, acesh);
10114   } else if (checksubsegs) {
10115     tsspivot1(abcd, abseg);
10116     enext(abcd, worktet);
10117     tsspivot1(worktet, bcseg);
10118     enext2(abcd, worktet);
10119     tsspivot1(worktet, caseg);
10120     enext2(oldabd, worktet);
10121     tsspivot1(worktet, adseg);
10122     enext2(oldbcd, worktet);
10123     tsspivot1(worktet, bdseg);
10124     enext2(oldcad, worktet);
10125     tsspivot1(worktet, cdseg);
10126     enext(oldbae, worktet);
10127     tsspivot1(worktet, aeseg);
10128     enext(oldcbe, worktet);
10129     tsspivot1(worktet, beseg);
10130     enext(oldace, worktet);
10131     tsspivot1(worktet, ceseg);
10132   }
10133 
10134   // Creating the new configuration inside the convex hull.
10135   edab.tet = abcd.tet; // Update abcd to be edab.
10136   setorg (edab, pe);
10137   setdest(edab, pd);
10138   setapex(edab, pa);
10139   setoppo(edab, pb);
10140   edbc.tet = bace.tet; // Update bace to be edbc.
10141   setorg (edbc, pe);
10142   setdest(edbc, pd);
10143   setapex(edbc, pb);
10144   setoppo(edbc, pc);
10145   maketetrahedron(&edca); // Create edca.
10146   setorg (edca, pe);
10147   setdest(edca, pd);
10148   setapex(edca, pc);
10149   setoppo(edca, pa);
10150   // Set the element attributes of the new tetrahedron 'edca'.
10151   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
10152     attrib = elemattribute(abcd.tet, i);
10153     setelemattribute(edca.tet, i, attrib);
10154   }
10155   // Set the volume constraint of the new tetrahedron 'edca' if the -ra
10156   //   switches are not used together. In -ra case, the various volume
10157   //   constraints can be spreaded very far.
10158   if (b->varvolume && !b->refine) {
10159     volume = volumebound(abcd.tet);
10160     setvolumebound(edca.tet, volume);
10161   }
10162 
10163   // Clear old bonds in edab(was abcd) and edbc(was bace).
10164   for (i = 0; i < 4; i ++) {
10165     edab.tet[i] = (tetrahedron) dummytet;
10166   }
10167   for (i = 0; i < 4; i ++) {
10168     edbc.tet[i] = (tetrahedron) dummytet;
10169   }
10170   // Bond the faces inside the convex hull.
10171   edab.loc = 0;
10172   edca.loc = 1;
10173   bond(edab, edca);
10174   edab.loc = 1;
10175   edbc.loc = 0;
10176   bond(edab, edbc);
10177   edbc.loc = 1;
10178   edca.loc = 0;
10179   bond(edbc, edca);
10180   // Bond the faces on the convex hull.
10181   edab.loc = 2;
10182   bond(edab, abdcasing);
10183   edab.loc = 3;
10184   bond(edab, baecasing);
10185   edbc.loc = 2;
10186   bond(edbc, bcdcasing);
10187   edbc.loc = 3;
10188   bond(edbc, cbecasing);
10189   edca.loc = 2;
10190   bond(edca, cadcasing);
10191   edca.loc = 3;
10192   bond(edca, acecasing);
10193   // There may exist subfaces that need to be bonded to new configuarton.
10194   if (checksubfaces) {
10195     // Clear old flags in edab(was abcd) and edbc(was bace).
10196     for (i = 0; i < 4; i ++) {
10197       edab.loc = i;
10198       tsdissolve(edab);
10199       edbc.loc = i;
10200       tsdissolve(edbc);
10201     }
10202     if (abdsh.sh != dummysh) {
10203       edab.loc = 2;
10204       tsbond(edab, abdsh);
10205     }
10206     if (baesh.sh != dummysh) {
10207       edab.loc = 3;
10208       tsbond(edab, baesh);
10209     }
10210     if (bcdsh.sh != dummysh) {
10211       edbc.loc = 2;
10212       tsbond(edbc, bcdsh);
10213     }
10214     if (cbesh.sh != dummysh) {
10215       edbc.loc = 3;
10216       tsbond(edbc, cbesh);
10217     }
10218     if (cadsh.sh != dummysh) {
10219       edca.loc = 2;
10220       tsbond(edca, cadsh);
10221     }
10222     if (acesh.sh != dummysh) {
10223       edca.loc = 3;
10224       tsbond(edca, acesh);
10225     }
10226   } else if (checksubsegs) {
10227     for (i = 0; i < 6; i++) {
10228       edab.tet[8 + i] = (tetrahedron) dummysh;
10229     }
10230     for (i = 0; i < 6; i++) {
10231       edbc.tet[8 + i] = (tetrahedron) dummysh;
10232     }
10233     edab.loc = edab.ver = 0;
10234     edbc.loc = edab.ver = 0;
10235     edca.loc = edab.ver = 0;
10236     // Operate in tet edab (5 edges).
10237     enext(edab, worktet);
10238     tssbond1(worktet, adseg);
10239     enext2(edab, worktet);
10240     tssbond1(worktet, aeseg);
10241     fnext(edab, worktet);
10242     enextself(worktet);
10243     tssbond1(worktet, bdseg);
10244     enextself(worktet);
10245     tssbond1(worktet, beseg);
10246     enextfnext(edab, worktet);
10247     enextself(worktet);
10248     tssbond1(worktet, abseg);
10249     // Operate in tet edbc (5 edges)
10250     enext(edbc, worktet);
10251     tssbond1(worktet, bdseg);
10252     enext2(edbc, worktet);
10253     tssbond1(worktet, beseg);
10254     fnext(edbc, worktet);
10255     enextself(worktet);
10256     tssbond1(worktet, cdseg);
10257     enextself(worktet);
10258     tssbond1(worktet, ceseg);
10259     enextfnext(edbc, worktet);
10260     enextself(worktet);
10261     tssbond1(worktet, bcseg);
10262     // Operate in tet edca (5 edges)
10263     enext(edca, worktet);
10264     tssbond1(worktet, cdseg);
10265     enext2(edca, worktet);
10266     tssbond1(worktet, ceseg);
10267     fnext(edca, worktet);
10268     enextself(worktet);
10269     tssbond1(worktet, adseg);
10270     enextself(worktet);
10271     tssbond1(worktet, aeseg);
10272     enextfnext(edca, worktet);
10273     enextself(worktet);
10274     tssbond1(worktet, caseg);
10275   }
10276 
10277   edab.loc = 0;
10278   edbc.loc = 0;
10279   edca.loc = 0;
10280   if (b->verbose > 3) {
10281     printf("    Updating edab ");
10282     printtet(&edab);
10283     printf("    Updating edbc ");
10284     printtet(&edbc);
10285     printf("    Creating edca ");
10286     printtet(&edca);
10287   }
10288 
10289   if (flipqueue != (queue *) NULL) {
10290     enextfnext(edab, abdcasing);
10291     enqueueflipface(abdcasing, flipqueue);
10292     enext2fnext(edab, baecasing);
10293     enqueueflipface(baecasing, flipqueue);
10294     enextfnext(edbc, bcdcasing);
10295     enqueueflipface(bcdcasing, flipqueue);
10296     enext2fnext(edbc, cbecasing);
10297     enqueueflipface(cbecasing, flipqueue);
10298     enextfnext(edca, cadcasing);
10299     enqueueflipface(cadcasing, flipqueue);
10300     enext2fnext(edca, acecasing);
10301     enqueueflipface(acecasing, flipqueue);
10302   }
10303 
10304   // Save a live handle in 'recenttet'.
10305   recenttet = edbc;
10306   // Set the return handle be edab.
10307   *flipface = edab;
10308 }
10309 
10311 //                                                                           //
10312 // flip32()    Perform a 3-to-2 flip.                                        //
10313 //                                                                           //
10314 // On input, 'flipface' represents the face will be flipped.  Let it is eda, //
10315 // where edge ed is locally non-convex. Three tetrahedra sharing ed are edab,//
10316 // edbc, and edca.  ed is not a subsegment.                                  //
10317 //                                                                           //
10318 // A 3-to-2 flip is to change the three tetrahedra edab, edbc, and edca into //
10319 // another two tetrahedra abcd and bace.  As a result, the edge ed has been  //
10320 // removed and the face abc has been created.                                //
10321 //                                                                           //
10322 // On completion, 'flipface' returns abcd.  If 'flipqueue' is not NULL, all  //
10323 // possibly non-Delaunay faces are added into it.                            //
10324 //                                                                           //
10326 
10327 void tetgenmesh::flip32(triface* flipface, queue* flipqueue)
10328 {
10329   triface edab, edbc, edca;                            // Old configuration.
10330   triface oldabd, oldbcd, oldcad;
10331   triface abdcasing, bcdcasing, cadcasing;
10332   triface oldbae, oldcbe, oldace;
10333   triface baecasing, cbecasing, acecasing;
10334   triface worktet;
10335   face abdsh, bcdsh, cadsh;
10336   face baesh, cbesh, acesh;
10337   face abseg, bcseg, caseg;                      // The nine segs on the CH.
10338   face adseg, bdseg, cdseg;
10339   face aeseg, beseg, ceseg;
10340   triface abcd, bace;                                  // New configuration.
10341   point pa, pb, pc, pd, pe;
10342   int i;
10343 
10344   edab = *flipface;
10345   adjustedgering(edab, CCW);
10346   pa = apex(edab);
10347   pb = oppo(edab);
10348   pd = dest(edab);
10349   pe = org(edab);
10350   fnext(edab, edbc);
10351   symself(edbc);
10352   edbc.ver = 0;
10353   for (i = 0; (i < 3) && (org(edbc) != pe); i++) {
10354     enextself(edbc);
10355   }
10356   pc = oppo(edbc);
10357   fnext(edbc, edca);
10358   symself(edca);
10359   edca.ver = 0;
10360   for (i = 0; (i < 3) && (org(edca) != pe); i++) {
10361     enextself(edca);
10362   }
10363 
10364   if (b->verbose > 2) {
10365     printf("    Do T32 on edge (%d, %d) %d, %d, %d.\n", pointmark(pe),
10366            pointmark(pd), pointmark(pa), pointmark(pb), pointmark(pc));
10367   }
10368   flip32s++;
10369 
10370   // Storing the old configuration outside the convex hull.
10371   enextfnext(edab, oldabd);
10372   enext2fnext(edab, oldbae);
10373   enextfnext(edbc, oldbcd);
10374   enext2fnext(edbc, oldcbe);
10375   enextfnext(edca, oldcad);
10376   enext2fnext(edca, oldace);
10377   sym(oldabd, abdcasing);
10378   sym(oldbcd, bcdcasing);
10379   sym(oldcad, cadcasing);
10380   sym(oldbae, baecasing);
10381   sym(oldcbe, cbecasing);
10382   sym(oldace, acecasing);
10383   if (checksubfaces) {
10384     tspivot(oldabd, abdsh);
10385     tspivot(oldbcd, bcdsh);
10386     tspivot(oldcad, cadsh);
10387     tspivot(oldbae, baesh);
10388     tspivot(oldcbe, cbesh);
10389     tspivot(oldace, acesh);
10390   } else if (checksubsegs) {
10391     enext(edab, worktet);
10392     tsspivot1(worktet, adseg);
10393     enext2(edab, worktet);
10394     tsspivot1(worktet, aeseg);
10395     enext(edbc, worktet);
10396     tsspivot1(worktet, bdseg);
10397     enext2(edbc, worktet);
10398     tsspivot1(worktet, beseg);
10399     enext(edca, worktet);
10400     tsspivot1(worktet, cdseg);
10401     enext2(edca, worktet);
10402     tsspivot1(worktet, ceseg);
10403     enextfnext(edab, worktet);
10404     enextself(worktet);
10405     tsspivot1(worktet, abseg);
10406     enextfnext(edbc, worktet);
10407     enextself(worktet);
10408     tsspivot1(worktet, bcseg);
10409     enextfnext(edca, worktet);
10410     enextself(worktet);
10411     tsspivot1(worktet, caseg);
10412   }
10413 
10414   // Creating the new configuration inside the convex hull.
10415   abcd.tet = edab.tet; // Update edab to be abcd.
10416   setorg (abcd, pa);
10417   setdest(abcd, pb);
10418   setapex(abcd, pc);
10419   setoppo(abcd, pd);
10420   bace.tet = edbc.tet; // Update edbc to be bace.
10421   setorg (bace, pb);
10422   setdest(bace, pa);
10423   setapex(bace, pc);
10424   setoppo(bace, pe);
10425   // Dealloc a redundant tetrahedron (edca).
10426   tetrahedrondealloc(edca.tet);
10427 
10428   // Clear the old bonds in abcd (was edab) and bace (was edbc).
10429   for (i = 0; i < 4; i ++) {
10430     abcd.tet[i] = (tetrahedron) dummytet;
10431   }
10432   for (i = 0; i < 4; i ++) {
10433     bace.tet[i] = (tetrahedron) dummytet;
10434   }
10435   // Bond the inside face of the convex hull.
10436   abcd.loc = 0;
10437   bace.loc = 0;
10438   bond(abcd, bace);
10439   // Bond the outside faces of the convex hull.
10440   abcd.loc = 1;
10441   bond(abcd, abdcasing);
10442   abcd.loc = 2;
10443   bond(abcd, bcdcasing);
10444   abcd.loc = 3;
10445   bond(abcd, cadcasing);
10446   bace.loc = 1;
10447   bond(bace, baecasing);
10448   bace.loc = 3;
10449   bond(bace, cbecasing);
10450   bace.loc = 2;
10451   bond(bace, acecasing);
10452   if (checksubfaces) {
10453     // Clear old bonds in abcd(was edab) and bace(was edbc).
10454     for (i = 0; i < 4; i ++) {
10455       abcd.tet[8 + i] = (tetrahedron) dummysh;
10456     }
10457     for (i = 0; i < 4; i ++) {
10458       bace.tet[8 + i] = (tetrahedron) dummysh;
10459     }
10460     if (abdsh.sh != dummysh) {
10461       abcd.loc = 1;
10462       tsbond(abcd, abdsh);
10463     }
10464     if (bcdsh.sh != dummysh) {
10465       abcd.loc = 2;
10466       tsbond(abcd, bcdsh);
10467     }
10468     if (cadsh.sh != dummysh) {
10469       abcd.loc = 3;
10470       tsbond(abcd, cadsh);
10471     }
10472     if (baesh.sh != dummysh) {
10473       bace.loc = 1;
10474       tsbond(bace, baesh);
10475     }
10476     if (cbesh.sh != dummysh) {
10477       bace.loc = 3;
10478       tsbond(bace, cbesh);
10479     }
10480     if (acesh.sh != dummysh) {
10481       bace.loc = 2;
10482       tsbond(bace, acesh);
10483     }
10484   } else if (checksubsegs) {
10485     for (i = 0; i < 6; i++) {
10486       abcd.tet[8 + i] = (tetrahedron) dummysh;
10487     }
10488     for (i = 0; i < 6; i++) {
10489       bace.tet[8 + i] = (tetrahedron) dummysh;
10490     }
10491     abcd.loc = abcd.ver = 0;
10492     bace.loc = bace.ver = 0;
10493     tssbond1(abcd, abseg);     // 1
10494     enext(abcd, worktet);
10495     tssbond1(worktet, bcseg);  // 2
10496     enext2(abcd, worktet);
10497     tssbond1(worktet, caseg);  // 3
10498     fnext(abcd, worktet);
10499     enext2self(worktet);
10500     tssbond1(worktet, adseg);  // 4
10501     enextfnext(abcd, worktet);
10502     enext2self(worktet);
10503     tssbond1(worktet, bdseg);  // 5
10504     enext2fnext(abcd, worktet);
10505     enext2self(worktet);
10506     tssbond1(worktet, cdseg);  // 6
10507     tssbond1(bace, abseg);
10508     enext2(bace, worktet);
10509     tssbond1(worktet, bcseg);
10510     enext(bace, worktet);
10511     tssbond1(worktet, caseg);
10512     fnext(bace, worktet);
10513     enextself(worktet);
10514     tssbond1(worktet, aeseg);  // 7
10515     enext2fnext(bace, worktet);
10516     enextself(worktet);
10517     tssbond1(worktet, beseg);  // 8
10518     enextfnext(bace, worktet);
10519     enextself(worktet);
10520     tssbond1(worktet, ceseg);  // 9
10521   }
10522 
10523   abcd.loc = 0;
10524   bace.loc = 0;
10525   if (b->verbose > 3) {
10526     printf("    Updating abcd ");
10527     printtet(&abcd);
10528     printf("    Updating bace ");
10529     printtet(&bace);
10530     printf("    Deleting edca ");
10531     // printtet(&edca);
10532   }
10533 
10534   if (flipqueue != (queue *) NULL) {
10535     fnext(abcd, abdcasing);
10536     enqueueflipface(abdcasing, flipqueue);
10537     fnext(bace, baecasing);
10538     enqueueflipface(baecasing, flipqueue);
10539     enextfnext(abcd, bcdcasing);
10540     enqueueflipface(bcdcasing, flipqueue);
10541     enextfnext(bace, cbecasing);
10542     enqueueflipface(cbecasing, flipqueue);
10543     enext2fnext(abcd, cadcasing);
10544     enqueueflipface(cadcasing, flipqueue);
10545     enext2fnext(bace, acecasing);
10546     enqueueflipface(acecasing, flipqueue);
10547   }
10548 
10549   // Save a live handle in 'recenttet'.
10550   recenttet = abcd;
10551   // Set the return handle be abcd.
10552   *flipface = abcd;
10553 }
10554 
10556 //                                                                           //
10557 // flip22()    Perform a 2-to-2 (or 4-to-4) flip.                            //
10558 //                                                                           //
10559 // On input, 'flipface' represents the face will be flipped.  Let it is abe, //
10560 // ab is the flipable edge, the two tetrahedra sharing abe are abce and bade,//
10561 // hence a, b, c and d are coplanar. If abc, bad are interior faces, the two //
10562 // tetrahedra opposite to e are bacf and abdf.  ab is not a subsegment.      //
10563 //                                                                           //
10564 // A 2-to-2 flip is to change two tetrahedra abce and bade into another two  //
10565 // tetrahedra dcae and cdbe. If bacf and abdf exist, they're changed to cdaf //
10566 // and dcbf, thus a 4-to-4 flip.  As a result, two or four tetrahedra have   //
10567 // rotated counterclockwise (using right-hand rule with thumb points to e):  //
10568 // abce->dcae, bade->cdbe, and bacf->cdaf, abdf->dcbf.                       //
10569 //                                                                           //
10570 // If abc and bad are subfaces, a 2-to-2 flip is performed simultaneously by //
10571 // calling routine flip22sub(), hence abc->dca, bad->cdb.  The edge rings of //
10572 // the flipped subfaces dca and cdb have the same orientation as abc and bad.//
10573 // Hence, they have the same orientation as other subfaces of the facet with //
10574 // respect to the lift point of this facet.                                  //
10575 //                                                                           //
10576 // On completion, 'flipface' holds edge dc of tetrahedron dcae. 'flipqueue'  //
10577 // contains all possibly non-Delaunay faces if it is not NULL.               //
10578 //                                                                           //
10580 
10581 void tetgenmesh::flip22(triface* flipface, queue* flipqueue)
10582 {
10583   triface abce, bade;
10584   triface oldbce, oldcae, oldade, olddbe;
10585   triface bcecasing, caecasing, adecasing, dbecasing;
10586   face bcesh, caesh, adesh, dbesh;
10587   triface bacf, abdf;
10588   triface oldacf, oldcbf, oldbdf, olddaf;
10589   triface acfcasing, cbfcasing, bdfcasing, dafcasing;
10590   triface worktet;
10591   face acfsh, cbfsh, bdfsh, dafsh;
10592   face abc, bad;
10593   face adseg, dbseg, bcseg, caseg;  // Coplanar segs.
10594   face aeseg, deseg, beseg, ceseg;  // Above segs.
10595   face afseg, dfseg, bfseg, cfseg;  // Below segs.
10596   point pa, pb, pc, pd;
10597 #ifdef SELF_CHECK
10598   point pe, pf;
10599 #endif
10600   int mirrorflag, i;
10601 
10602   adjustedgering(*flipface, CCW); // 'flipface' is bae.
10603   fnext(*flipface, abce);
10604   esymself(abce);
10605   adjustedgering(*flipface, CW); // 'flipface' is abe.
10606   fnext(*flipface, bade);
10607 #ifdef SELF_CHECK
10608   assert(bade.tet != dummytet);
10609 #endif
10610   esymself(bade);
10611   pa = org(abce);
10612   pb = dest(abce);
10613   pc = apex(abce);
10614   pd = apex(bade);
10615 #ifdef SELF_CHECK
10616   pe = oppo(bade);
10617   assert(oppo(abce) == pe);
10618 #endif
10619   sym(abce, bacf);
10620   mirrorflag = bacf.tet != dummytet;
10621   if (mirrorflag) {
10622     // findedge(&bacf, pb, pa);
10623     bacf.ver = 0;
10624     for (i = 0; (i < 3) && (org(bacf) != pb); i++) {
10625       enextself(bacf);
10626     }
10627     sym(bade, abdf);
10628 #ifdef SELF_CHECK
10629     assert(abdf.tet != dummytet);
10630 #endif
10631     // findedge(&abdf, pa, pb);
10632     abdf.ver = 0;
10633     for (i = 0; (i < 3) && (org(abdf) != pa); i++) {
10634       enextself(abdf);
10635     }
10636 
10637 #ifdef SELF_CHECK
10638     pf = oppo(bacf);
10639     assert(oppo(abdf) == pf);
10640 #endif
10641   }
10642 
10643   if (b->verbose > 2) {
10644     printf("    Do %s on edge (%d, %d).\n", mirrorflag ? "T44" : "T22",
10645            pointmark(pa), pointmark(pb));
10646   }
10647   mirrorflag ? flip44s++ : flip22s++;
10648 
10649   // Save the old configuration at the convex hull.
10650   enextfnext(abce, oldbce);
10651   enext2fnext(abce, oldcae);
10652   enextfnext(bade, oldade);
10653   enext2fnext(bade, olddbe);
10654   sym(oldbce, bcecasing);
10655   sym(oldcae, caecasing);
10656   sym(oldade, adecasing);
10657   sym(olddbe, dbecasing);
10658   if (checksubfaces) {
10659     tspivot(oldbce, bcesh);
10660     tspivot(oldcae, caesh);
10661     tspivot(oldade, adesh);
10662     tspivot(olddbe, dbesh);
10663     tspivot(abce, abc);
10664     tspivot(bade, bad);
10665   } else if (checksubsegs) {
10666     // Coplanar segs: a->d->b->c.
10667     enext(bade, worktet);
10668     tsspivot1(worktet, adseg);
10669     enext2(bade, worktet);
10670     tsspivot1(worktet, dbseg);
10671     enext(abce, worktet);
10672     tsspivot1(worktet, bcseg);
10673     enext2(abce, worktet);
10674     tsspivot1(worktet, caseg);
10675     // Above segs: a->e, d->e, b->e, c->e.
10676     fnext(bade, worktet);
10677     enextself(worktet);
10678     tsspivot1(worktet, aeseg);
10679     enextfnext(bade, worktet);
10680     enextself(worktet);
10681     tsspivot1(worktet, deseg);
10682     enext2fnext(bade, worktet);
10683     enextself(worktet);
10684     tsspivot1(worktet, beseg);
10685     enextfnext(abce, worktet);
10686     enextself(worktet);
10687     tsspivot1(worktet, ceseg);
10688   }
10689   if (mirrorflag) {
10690     enextfnext(bacf, oldacf);
10691     enext2fnext(bacf, oldcbf);
10692     enextfnext(abdf, oldbdf);
10693     enext2fnext(abdf, olddaf);
10694     sym(oldacf, acfcasing);
10695     sym(oldcbf, cbfcasing);
10696     sym(oldbdf, bdfcasing);
10697     sym(olddaf, dafcasing);
10698     if (checksubfaces) {
10699       tspivot(oldacf, acfsh);
10700       tspivot(oldcbf, cbfsh);
10701       tspivot(oldbdf, bdfsh);
10702       tspivot(olddaf, dafsh);
10703     } else if (checksubsegs) {
10704       // Below segs: a->f, d->f, b->f, c->f.
10705       fnext(abdf, worktet);
10706       enext2self(worktet);
10707       tsspivot1(worktet, afseg);
10708       enext2fnext(abdf, worktet);
10709       enext2self(worktet);
10710       tsspivot1(worktet, dfseg);
10711       enextfnext(abdf, worktet);
10712       enext2self(worktet);
10713       tsspivot1(worktet, bfseg);
10714       enextfnext(bacf, worktet);
10715       enextself(worktet);
10716       tsspivot1(worktet, cfseg);
10717     }
10718   }
10719 
10720   // Rotate abce, bade one-quarter turn counterclockwise.
10721   bond(oldbce, caecasing);
10722   bond(oldcae, adecasing);
10723   bond(oldade, dbecasing);
10724   bond(olddbe, bcecasing);
10725   if (checksubfaces) {
10726     // Check for subfaces and rebond them to the rotated tets.
10727     if (caesh.sh == dummysh) {
10728       tsdissolve(oldbce);
10729     } else {
10730       tsbond(oldbce, caesh);
10731     }
10732     if (adesh.sh == dummysh) {
10733       tsdissolve(oldcae);
10734     } else {
10735       tsbond(oldcae, adesh);
10736     }
10737     if (dbesh.sh == dummysh) {
10738       tsdissolve(oldade);
10739     } else {
10740       tsbond(oldade, dbesh);
10741     }
10742     if (bcesh.sh == dummysh) {
10743       tsdissolve(olddbe);
10744     } else {
10745       tsbond(olddbe, bcesh);
10746     }
10747   } else if (checksubsegs) {
10748     // 5 edges in abce are changed.
10749     enext(abce, worktet);  // fit b->c into c->a.
10750     if (caseg.sh == dummysh) {
10751       tssdissolve1(worktet);
10752     } else {
10753       tssbond1(worktet, caseg);
10754     }
10755     enext2(abce, worktet); // fit c->a into a->d.
10756     if (adseg.sh == dummysh) {
10757       tssdissolve1(worktet);
10758     } else {
10759       tssbond1(worktet, adseg);
10760     }
10761     fnext(abce, worktet); // fit b->e into c->e.
10762     enextself(worktet);
10763     if (ceseg.sh == dummysh) {
10764       tssdissolve1(worktet);
10765     } else {
10766       tssbond1(worktet, ceseg);
10767     }
10768     enextfnext(abce, worktet); // fit c->e into a->e.
10769     enextself(worktet);
10770     if (aeseg.sh == dummysh) {
10771       tssdissolve1(worktet);
10772     } else {
10773       tssbond1(worktet, aeseg);
10774     }
10775     enext2fnext(abce, worktet); // fit a->e into d->e.
10776     enextself(worktet);
10777     if (deseg.sh == dummysh) {
10778       tssdissolve1(worktet);
10779     } else {
10780       tssbond1(worktet, deseg);
10781     }
10782     // 5 edges in bade are changed.
10783     enext(bade, worktet); // fit a->d into d->b.
10784     if (dbseg.sh == dummysh) {
10785       tssdissolve1(worktet);
10786     } else {
10787       tssbond1(worktet, dbseg);
10788     }
10789     enext2(bade, worktet); // fit d->b into b->c.
10790     if (bcseg.sh == dummysh) {
10791       tssdissolve1(worktet);
10792     } else {
10793       tssbond1(worktet, bcseg);
10794     }
10795     fnext(bade, worktet); // fit a->e into d->e.
10796     enextself(worktet);
10797     if (deseg.sh == dummysh) {
10798       tssdissolve1(worktet);
10799     } else {
10800       tssbond1(worktet, deseg);
10801     }
10802     enextfnext(bade, worktet); // fit d->e into b->e.
10803     enextself(worktet);
10804     if (beseg.sh == dummysh) {
10805       tssdissolve1(worktet);
10806     } else {
10807       tssbond1(worktet, beseg);
10808     }
10809     enext2fnext(bade, worktet); // fit b->e into c->e.
10810     enextself(worktet);
10811     if (ceseg.sh == dummysh) {
10812       tssdissolve1(worktet);
10813     } else {
10814       tssbond1(worktet, ceseg);
10815     }
10816   }
10817   if (mirrorflag) {
10818     // Rotate bacf, abdf one-quarter turn counterclockwise.
10819     bond(oldcbf, acfcasing);
10820     bond(oldacf, dafcasing);
10821     bond(olddaf, bdfcasing);
10822     bond(oldbdf, cbfcasing);
10823     if (checksubfaces) {
10824       // Check for subfaces and rebond them to the rotated tets.
10825       if (acfsh.sh == dummysh) {
10826         tsdissolve(oldcbf);
10827       } else {
10828         tsbond(oldcbf, acfsh);
10829       }
10830       if (dafsh.sh == dummysh) {
10831         tsdissolve(oldacf);
10832       } else {
10833         tsbond(oldacf, dafsh);
10834       }
10835       if (bdfsh.sh == dummysh) {
10836         tsdissolve(olddaf);
10837       } else {
10838         tsbond(olddaf, bdfsh);
10839       }
10840       if (cbfsh.sh == dummysh) {
10841         tsdissolve(oldbdf);
10842       } else {
10843         tsbond(oldbdf, cbfsh);
10844       }
10845     } else if (checksubsegs) {
10846       // 5 edges in bacf are changed.
10847       enext2(bacf, worktet); // fit b->c into c->a.
10848       if (caseg.sh == dummysh) {
10849         tssdissolve1(worktet);
10850       } else {
10851         tssbond1(worktet, caseg);
10852       }
10853       enext(bacf, worktet); // fit c->a into a->d.
10854       if (adseg.sh == dummysh) {
10855         tssdissolve1(worktet);
10856       } else {
10857         tssbond1(worktet, adseg);
10858       }
10859       fnext(bacf, worktet); // fit b->f into c->f.
10860       enext2self(worktet);
10861       if (cfseg.sh == dummysh) {
10862         tssdissolve1(worktet);
10863       } else {
10864         tssbond1(worktet, cfseg);
10865       }
10866       enext2fnext(bacf, worktet); // fit c->f into a->f.
10867       enext2self(worktet);
10868       if (afseg.sh == dummysh) {
10869         tssdissolve1(worktet);
10870       } else {
10871         tssbond1(worktet, afseg);
10872       }
10873       enextfnext(bacf, worktet); // fit a->f into d->f.
10874       enext2self(worktet);
10875       if (dfseg.sh == dummysh) {
10876         tssdissolve1(worktet);
10877       } else {
10878         tssbond1(worktet, dfseg);
10879       }
10880       // 5 edges in abdf are changed.
10881       enext2(abdf, worktet); // fit a->d into d->b.
10882       if (dbseg.sh == dummysh) {
10883         tssdissolve1(worktet);
10884       } else {
10885         tssbond1(worktet, dbseg);
10886       }
10887       enext(abdf, worktet); // fit d->b into b->c.
10888       if (bcseg.sh == dummysh) {
10889         tssdissolve1(worktet);
10890       } else {
10891         tssbond1(worktet, bcseg);
10892       }
10893       fnext(abdf, worktet); // fit a->f into d->f.
10894       enext2self(worktet);
10895       if (dfseg.sh == dummysh) {
10896         tssdissolve1(worktet);
10897       } else {
10898         tssbond1(worktet, dfseg);
10899       }
10900       enext2fnext(abdf, worktet); // fit d->f into b->f.
10901       enext2self(worktet);
10902       if (bfseg.sh == dummysh) {
10903         tssdissolve1(worktet);
10904       } else {
10905         tssbond1(worktet, bfseg);
10906       }
10907       enextfnext(abdf, worktet); // fit b->f into c->f.
10908       enext2self(worktet);
10909       if (cfseg.sh == dummysh) {
10910         tssdissolve1(worktet);
10911       } else {
10912         tssbond1(worktet, cfseg);
10913       }
10914     }
10915   }
10916 
10917   // New vertex assignments for the rotated tetrahedra.
10918   setorg(abce, pd); // Update abce to dcae
10919   setdest(abce, pc);
10920   setapex(abce, pa);
10921   setorg(bade, pc); // Update bade to cdbe
10922   setdest(bade, pd);
10923   setapex(bade, pb);
10924   if (mirrorflag) {
10925     setorg(bacf, pc); // Update bacf to cdaf
10926     setdest(bacf, pd);
10927     setapex(bacf, pa);
10928     setorg(abdf, pd); // Update abdf to dcbf
10929     setdest(abdf, pc);
10930     setapex(abdf, pb);
10931   }
10932 
10933   // Are there subfaces need to be flipped?
10934   if (checksubfaces && abc.sh != dummysh) {
10935 #ifdef SELF_CHECK
10936     assert(bad.sh != dummysh);
10937 #endif
10938     // Adjust the edge be ab, so the rotation of subfaces is according with
10939     //   the rotation of tetrahedra.
10940     findedge(&abc, pa, pb);
10941     // Flip an edge of two subfaces, ignore non-Delaunay edges.
10942     flip22sub(&abc, NULL);
10943   }
10944 
10945   if (b->verbose > 3) {
10946     printf("    Updating abce ");
10947     printtet(&abce);
10948     printf("    Updating bade ");
10949     printtet(&bade);
10950     if (mirrorflag) {
10951       printf("    Updating bacf ");
10952       printtet(&bacf);
10953       printf("    Updating abdf ");
10954       printtet(&abdf);
10955     }
10956   }
10957 
10958   if (flipqueue != (queue *) NULL) {
10959     enextfnext(abce, bcecasing);
10960     enqueueflipface(bcecasing, flipqueue);
10961     enext2fnext(abce, caecasing);
10962     enqueueflipface(caecasing, flipqueue);
10963     enextfnext(bade, adecasing);
10964     enqueueflipface(adecasing, flipqueue);
10965     enext2fnext(bade, dbecasing);
10966     enqueueflipface(dbecasing, flipqueue);
10967     if (mirrorflag) {
10968       enextfnext(bacf, acfcasing);
10969       enqueueflipface(acfcasing, flipqueue);
10970       enext2fnext(bacf, cbfcasing);
10971       enqueueflipface(cbfcasing, flipqueue);
10972       enextfnext(abdf, bdfcasing);
10973       enqueueflipface(bdfcasing, flipqueue);
10974       enext2fnext(abdf, dafcasing);
10975       enqueueflipface(dafcasing, flipqueue);
10976     }
10977     // The two new faces dcae (abce), cdbe (bade) may still not be locally
10978     //   Delaunay, and may need be flipped (flip23).  On the other hand, in
10979     //   conforming Delaunay algorithm, two new subfaces dca (abc), and cdb
10980     //   (bad) may be non-conforming Delaunay, they need be queued if they
10981     //   are locally Delaunay but non-conforming Delaunay.
10982     enqueueflipface(abce, flipqueue);
10983     enqueueflipface(bade, flipqueue);
10984   }
10985 
10986   // Save a live handle in 'recenttet'.
10987   recenttet = abce;
10988 }
10989 
10991 //                                                                           //
10992 // flip22sub()    Perform a 2-to-2 flip on a subface edge.                   //
10993 //                                                                           //
10994 // The flip edge is given by subface 'flipedge'.  Let it is abc, where ab is //
10995 // the flipping edge.  The other subface is bad,  where a, b, c, d form a    //
10996 // convex quadrilateral.  ab is not a subsegment.                            //
10997 //                                                                           //
10998 // A 2-to-2 subface flip is to change two subfaces abc and bad to another    //
10999 // two subfaces dca and cdb.  Hence, edge ab has been removed and dc becomes //
11000 // an edge. If a point e is above abc, this flip is equal to rotate abc and  //
11001 // bad counterclockwise using right-hand rule with thumb points to e. It is  //
11002 // important to know that the edge rings of the flipped subfaces dca and cdb //
11003 // are keeping the same orientation as their original subfaces. So they have //
11004 // the same orientation with respect to the lift point of this facet.        //
11005 //                                                                           //
11006 // During rotating, the face rings of the four edges bc, ca, ad, and de need //
11007 // be re-connected. If the edge is not a subsegment, then its face ring has  //
11008 // only two faces, a sbond() will bond them together. If it is a subsegment, //
11009 // one should use sbond1() twice to bond two different handles to the rotat- //
11010 // ing subface, one is predecssor (-casin), another is successor (-casout).  //
11011 //                                                                           //
11012 // If 'flipqueue' is not NULL, it returns four edges bc, ca, ad, de, which   //
11013 // may be non-Delaunay.                                                      //
11014 //                                                                           //
11016 
11017 void tetgenmesh::flip22sub(face* flipedge, queue* flipqueue)
11018 {
11019   face abc, bad;
11020   face oldbc, oldca, oldad, olddb;
11021   face bccasin, bccasout, cacasin, cacasout;
11022   face adcasin, adcasout, dbcasin, dbcasout;
11023   face bc, ca, ad, db;
11024   face spinsh;
11025   point pa, pb, pc, pd;
11026 
11027   abc = *flipedge;
11028   spivot(abc, bad);
11029   if (sorg(bad) != sdest(abc)) {
11030     sesymself(bad);
11031   }
11032   pa = sorg(abc);
11033   pb = sdest(abc);
11034   pc = sapex(abc);
11035   pd = sapex(bad);
11036 
11037   if (b->verbose > 2) {
11038     printf("    Flip sub edge (%d, %d).\n", pointmark(pa), pointmark(pb));
11039   }
11040 
11041   // Save the old configuration outside the quadrilateral.
11042   senext(abc, oldbc);
11043   senext2(abc, oldca);
11044   senext(bad, oldad);
11045   senext2(bad, olddb);
11046   // Get the outside connection. Becareful if there is a subsegment on the
11047   //   quadrilateral, two casings (casin and casout) are needed to save for
11048   //   keeping the face link.
11049   spivot(oldbc, bccasout);
11050   sspivot(oldbc, bc);
11051   if (bc.sh != dummysh) {
11052     // 'bc' is a subsegment.
11053     if (bccasout.sh != dummysh) {
11054       if (oldbc.sh != bccasout.sh) {
11055         // 'oldbc' is not self-bonded.
11056         spinsh = bccasout;
11057         do {
11058           bccasin = spinsh;
11059           spivotself(spinsh);
11060         } while (spinsh.sh != oldbc.sh);
11061       } else {
11062         bccasout.sh = dummysh;
11063       }
11064     }
11065     ssdissolve(oldbc);
11066   }
11067   spivot(oldca, cacasout);
11068   sspivot(oldca, ca);
11069   if (ca.sh != dummysh) {
11070     // 'ca' is a subsegment.
11071     if (cacasout.sh != dummysh) {
11072       if (oldca.sh != cacasout.sh) {
11073         // 'oldca' is not self-bonded.
11074         spinsh = cacasout;
11075         do {
11076           cacasin = spinsh;
11077           spivotself(spinsh);
11078         } while (spinsh.sh != oldca.sh);
11079       } else {
11080         cacasout.sh = dummysh;
11081       }
11082     }
11083     ssdissolve(oldca);
11084   }
11085   spivot(oldad, adcasout);
11086   sspivot(oldad, ad);
11087   if (ad.sh != dummysh) {
11088     // 'ad' is a subsegment.
11089     if (adcasout.sh != dummysh) {
11090       if (oldad.sh != adcasout.sh) {
11091         // 'adcasout' is not self-bonded.
11092         spinsh = adcasout;
11093         do {
11094           adcasin = spinsh;
11095           spivotself(spinsh);
11096         } while (spinsh.sh != oldad.sh);
11097       } else {
11098         adcasout.sh = dummysh;
11099       }
11100     }
11101     ssdissolve(oldad);
11102   }
11103   spivot(olddb, dbcasout);
11104   sspivot(olddb, db);
11105   if (db.sh != dummysh) {
11106     // 'db' is a subsegment.
11107     if (dbcasout.sh != dummysh) {
11108       if (olddb.sh != dbcasout.sh) {
11109         // 'dbcasout' is not self-bonded.
11110         spinsh = dbcasout;
11111         do {
11112           dbcasin = spinsh;
11113           spivotself(spinsh);
11114         } while (spinsh.sh != olddb.sh);
11115       } else {
11116         dbcasout.sh = dummysh;
11117       }
11118     }
11119     ssdissolve(olddb);
11120   }
11121 
11122   // Rotate abc and bad one-quarter turn counterclockwise.
11123   if (ca.sh != dummysh) {
11124     if (cacasout.sh != dummysh) {
11125       sbond1(cacasin, oldbc);
11126       sbond1(oldbc, cacasout);
11127     } else {
11128       // Bond 'oldbc' to itself.
11129       sbond(oldbc, oldbc);
11130       // Make sure that dummysh always correctly bonded.
11131       dummysh[0] = sencode(oldbc);
11132     }
11133     ssbond(oldbc, ca);
11134   } else {
11135     sbond(oldbc, cacasout);
11136   }
11137   if (ad.sh != dummysh) {
11138     if (adcasout.sh != dummysh) {
11139       sbond1(adcasin, oldca);
11140       sbond1(oldca, adcasout);
11141     } else {
11142       // Bond 'oldca' to itself.
11143       sbond(oldca, oldca);
11144       // Make sure that dummysh always correctly bonded.
11145       dummysh[0] = sencode(oldca);
11146     }
11147     ssbond(oldca, ad);
11148   } else {
11149     sbond(oldca, adcasout);
11150   }
11151   if (db.sh != dummysh) {
11152     if (dbcasout.sh != dummysh) {
11153       sbond1(dbcasin, oldad);
11154       sbond1(oldad, dbcasout);
11155     } else {
11156       // Bond 'oldad' to itself.
11157       sbond(oldad, oldad);
11158       // Make sure that dummysh always correctly bonded.
11159       dummysh[0] = sencode(oldad);
11160     }
11161     ssbond(oldad, db);
11162   } else {
11163     sbond(oldad, dbcasout);
11164   }
11165   if (bc.sh != dummysh) {
11166     if (bccasout.sh != dummysh) {
11167       sbond1(bccasin, olddb);
11168       sbond1(olddb, bccasout);
11169     } else {
11170       // Bond 'olddb' to itself.
11171       sbond(olddb, olddb);
11172       // Make sure that dummysh always correctly bonded.
11173       dummysh[0] = sencode(olddb);
11174     }
11175     ssbond(olddb, bc);
11176   } else {
11177     sbond(olddb, bccasout);
11178   }
11179 
11180   // New vertex assignments for the rotated subfaces.
11181   setsorg(abc, pd);  // Update abc to dca.
11182   setsdest(abc, pc);
11183   setsapex(abc, pa);
11184   setsorg(bad, pc);  // Update bad to cdb.
11185   setsdest(bad, pd);
11186   setsapex(bad, pb);
11187 
11188   if (flipqueue != (queue *) NULL) {
11189     enqueueflipedge(bccasout, flipqueue);
11190     enqueueflipedge(cacasout, flipqueue);
11191     enqueueflipedge(adcasout, flipqueue);
11192     enqueueflipedge(dbcasout, flipqueue);
11193   }
11194 }
11195 
11197 //                                                                           //
11198 // flip()    Flips non-locally Delaunay faces in flipqueue until it is empty.//
11199 //                                                                           //
11200 // Assumpation:  Current tetrahedralization is non-Delaunay after inserting  //
11201 // a point or performing a flip operation, all possibly non-Delaunay faces   //
11202 // are in 'flipqueue'.                                                       //
11203 //                                                                           //
11204 // If 'plastflip' is not NULL,  it is used to return a stack of recently     //
11205 // flipped faces.  This stack will be used to reverse the flips done in this //
11206 // routine later for removing a newly inserted point because it encroaches   //
11207 // any subfaces or subsegments.                                              //
11208 //                                                                           //
11209 // The return value is the total number of flips done during this invocation.//
11210 //                                                                           //
11212 
11213 long tetgenmesh::flip(queue* flipqueue, badface **plastflip)
11214 {
11215   badface *qface, *newflip;
11216   triface flipface, symface;
11217   point pa, pb, pc, pd, pe;
11218   enum fliptype fc;
11219   REAL sign, bakepsilon;
11220   long flipcount; //, maxfaces; - commented out to get gcc4.6 working
11221   int epscount, fcount;
11222   int ia, ib, ic, id, ie;
11223 
11224   if (b->verbose > 1) {
11225     printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
11226   }
11227 
11228   flipcount = flip23s + flip32s + flip22s + flip44s;
11229   if (checksubfaces) {
11230     //maxfaces = (4l * tetrahedrons->items + hullsize) / 2l; // commented out to get gcc 4.6 working
11231     fcount = 0;
11232   }
11233 
11234   if (plastflip != (badface **) NULL) {
11235     // Initialize the stack of the flip sequence.
11236     flipstackers->restart();
11237     *plastflip = (badface *) NULL;
11238   }
11239 
11240   // Loop until the queue is empty.
11241   while (!flipqueue->empty()) {
11242     qface = (badface *) flipqueue->pop();
11243     flipface = qface->tt;
11244     if (isdead(&flipface)) continue;
11245     sym(flipface, symface);
11246     // Only do check when the adjacent tet exists and it's not a "fake" tet.
11247     if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11248       // For positive orientation that insphere() test requires.
11249       adjustedgering(flipface, CW);
11250       pa = org(flipface);
11251       pb = dest(flipface);
11252       pc = apex(flipface);
11253       pd = oppo(flipface);
11254       pe = oppo(symface);
11255       if (symbolic) {
11256         ia = pointmark(pa);
11257         ib = pointmark(pb);
11258         ic = pointmark(pc);
11259         id = pointmark(pd);
11260         ie = pointmark(pe);
11261         sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
11262         assert(sign != 0.0);
11263       } else {
11264         sign = insphere(pa, pb, pc, pd, pe);
11265       }
11266     } else {
11267       sign = -1.0; // A hull face is locally Delaunay.
11268     }
11269     if (sign > 0.0) {
11270       // 'flipface' is non-locally Delaunay, try to flip it.
11271       if (checksubfaces) {
11272         fcount++;
11273         bakepsilon = b->epsilon;
11274         epscount = 0;
11275         while (epscount < 32) {
11276           fc = categorizeface(flipface);
11277           if (fc == N40) {
11278             b->epsilon *= 1e-1;
11279             epscount++;
11280             continue;
11281           }
11282           break;
11283         }
11284         b->epsilon = bakepsilon;
11285         if (epscount >= 32) {
11286           if (b->verbose > 0) {
11287             printf("Warning:  Can't flip a degenerate tetrahedron.\n");
11288           }
11289           fc = N40;
11290         }
11291       } else {
11292         fc = categorizeface(flipface);
11293 #ifdef SELF_CHECK
11294         assert(fc != N40);
11295 #endif
11296       }
11297       switch (fc) {
11298       // The following face types are flipable.
11299       case T44:
11300       case T22:
11301         flip22(&flipface, flipqueue);
11302         break;
11303       case T23:
11304         flip23(&flipface, flipqueue);
11305         break;
11306       case T32:
11307         flip32(&flipface, flipqueue);
11308         break;
11309       // The following face types are unflipable.
11310       case N32:
11311         break;
11312       case FORBIDDENFACE:
11313         break;
11314       case FORBIDDENEDGE:
11315         break;
11316       // This case is only possible when the domain is nonconvex.
11317       case N40:
11318         // assert(nonconvex);
11319         break;
11320       }
11321       if (plastflip != (badface **) NULL) {
11322         if ((fc == T44) || (fc == T22) || (fc == T23) || (fc == T32)) {
11323           // Push the flipped face into stack.
11324           newflip = (badface *) flipstackers->alloc();
11325           newflip->tt = flipface;
11326           newflip->key = (REAL) fc;
11327           newflip->forg = org(flipface);
11328           newflip->fdest = dest(flipface);
11329           newflip->fapex = apex(flipface);
11330           newflip->previtem = *plastflip;
11331           *plastflip = newflip;
11332         }
11333       }
11334     }
11335   }
11336 
11337   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11338   if (b->verbose > 1) {
11339     printf("    %ld flips.\n", flipcount);
11340   }
11341 
11342   return flipcount;
11343 }
11344 
11346 //                                                                           //
11347 // lawson()    Flip locally non-Delaunay faces by Lawson's algorithm.        //
11348 //                                                                           //
11350 
11351 long tetgenmesh::lawson(list *misseglist, queue* flipqueue)
11352 {
11353   badface *qface, *misseg;
11354   triface flipface, symface;
11355   triface starttet, spintet;
11356   face checksh, checkseg;
11357   point pa, pb, pc, pd, pe;
11358   point swappt;
11359   REAL sign, ori;
11360   long flipcount;
11361   int ia, ib, ic, id, ie;
11362   int hitbdry, i;
11363 
11364   if (b->verbose > 1) {
11365     printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
11366   }
11367   flipcount = flip23s + flip32s + flip22s + flip44s;
11368 
11369   // Go through the stack of possible flips and decide whether to do them.
11370   //   Note that during the loop new possible flips will be pushed onto
11371   //   this stack, while they popped in this loop.
11372   while (!flipqueue->empty()) {
11373     qface = (badface *) flipqueue->pop();
11374     flipface = qface->tt;
11375     // Check if tet has already been flipped out of existence.
11376     if (!isdead(&flipface)) {
11377       sym(flipface, symface);
11378       // Check if this tet is the same as the one which was stacked.
11379       if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11380         flipface.ver = 0; // Select the CCW ring.
11381         pa = org(flipface);
11382         pb = dest(flipface);
11383         pc = apex(flipface);
11384         pd = oppo(flipface);
11385         pe = oppo(symface);
11386         if (symbolic) {
11387           ia = pointmark(pa);
11388           ib = pointmark(pb);
11389           ic = pointmark(pc);
11390           id = pointmark(pd);
11391           ie = pointmark(pe);
11392           sign = insphere_sos(pb, pa, pc, pd, pe, ib, ia, ic, id, ie);
11393         } else {
11394           sign = insphere(pb, pa, pc, pd, pe);
11395         }
11396         if (sign > 0.0) {
11397           for (i = 0; i < 3; i++) {
11398             ori = orient3d(pa, pb, pd, pe);
11399             if (ori > 0.0) {
11400               // Goto and check the next edge.
11401               swappt = pa;
11402               pa = pb;
11403               pb = pc;
11404               pc = swappt;
11405               enextself(flipface);
11406             } else {
11407               break; // either (ori < 0.0) or (ori == 0.0)
11408             }
11409           } // for (i = 0; ....)
11410           if (ori > 0.0) {
11411             // All three edges are convex, a 2-3 flip is possible.
11412             if (checksubfaces) {
11413               tspivot(flipface, checksh);
11414               if (checksh.sh != dummysh) {
11415                 // A subface is not flipable.
11416                 continue;
11417               }
11418             }
11419             flip23(&flipface, flipqueue);
11420           } else if (ori < 0.0) {
11421             // The edge (a, b) is non-convex, check for a 3-2 flip.
11422             fnext(flipface, symface);
11423             symself(symface);
11424             if (oppo(symface) == pe) {
11425               // Only three tets adjoining this edge.
11426               if (checksubfaces) {
11427                 tsspivot(&flipface, &checkseg);
11428                 if (checkseg.sh != dummysh) {
11429                   // A subsegment is not flipable.
11430                   continue;
11431                 }
11432               } else if (checksubsegs) {
11433                 tsspivot1(flipface, checkseg);
11434                 if (checkseg.sh != dummysh) {
11435                   if (b->verbose > 2) {
11436                     printf("    Queuing missing segment (%d, %d).\n",
11437                       pointmark(org(flipface)), pointmark(dest(flipface)));
11438                   }
11439                   misseg = (badface *) misseglist->append(NULL);
11440                   misseg->ss = checkseg;
11441                   misseg->forg = sorg(checkseg);
11442                   misseg->fdest = sdest(checkseg);
11443                   // Detach all tets having this seg.
11444                   starttet = flipface;
11445                   adjustedgering(starttet, CCW);
11446                   fnextself(starttet);
11447                   spintet = starttet;
11448                   hitbdry = 0;
11449                   do {
11450                     tssdissolve1(spintet);
11451                     if (!fnextself(spintet)) {
11452                       hitbdry++;
11453                       if (hitbdry < 2) {
11454                         esym(starttet, spintet);
11455                         if (!fnextself(spintet)) {
11456                           hitbdry++;
11457                         }
11458                       }
11459                     }
11460                   } while ((apex(spintet) != apex(starttet)) && (hitbdry < 2));
11461                 }
11462               } // if (checksubfaces)
11463               flip32(&flipface, flipqueue);
11464             }
11465           } else {
11466             // Four points (a, b, d, e) are coplanar.
11467             fnext(flipface, symface);
11468             if (fnextself(symface)) {
11469               // Check for a 4-4 flip.
11470               fnextself(symface);
11471               if (apex(symface) == pe) {
11472                 if (checksubfaces) {
11473                   tsspivot(&flipface, &checkseg);
11474                   if (checkseg.sh != dummysh) {
11475                     // A subsegment is not flippable.
11476                     continue;
11477                   }
11478                 } else if (checksubsegs) {
11479                   tsspivot1(flipface, checkseg);
11480                   if (checkseg.sh != dummysh) {
11481                     if (b->verbose > 2) {
11482                       printf("    Queuing missing segment (%d, %d).\n",
11483                         pointmark(org(flipface)), pointmark(dest(flipface)));
11484                     }
11485                     misseg = (badface *) misseglist->append(NULL);
11486                     misseg->ss = checkseg;
11487                     misseg->forg = sorg(checkseg);
11488                     misseg->fdest = sdest(checkseg);
11489                     // Detach all tets having this seg.
11490                     starttet = flipface;
11491                     adjustedgering(starttet, CCW);
11492                     fnextself(starttet);
11493                     spintet = starttet;
11494                     hitbdry = 0;
11495                     do {
11496                       tssdissolve1(spintet);
11497                       if (!fnextself(spintet)) {
11498                         hitbdry++;
11499                         if (hitbdry < 2) {
11500                           esym(starttet, spintet);
11501                           if (!fnextself(spintet)) {
11502                             hitbdry++;
11503                           }
11504                         }
11505                       }
11506                     } while ((apex(spintet) != apex(starttet)) &&
11507                              (hitbdry < 2));
11508                   }
11509                 } // if (checksubfaces)
11510                 flip22(&flipface, flipqueue);
11511               }
11512             } else {
11513               // Check for a 2-2 flip.
11514               esym(flipface, symface);
11515               fnextself(symface);
11516               symself(symface);
11517               if (symface.tet == dummytet) {
11518                 if (checksubfaces) {
11519                   tsspivot(&flipface, &checkseg);
11520                   if (checkseg.sh != dummysh) {
11521                     // A subsegment is not flipable.
11522                     continue;
11523                   }
11524                 } else if (checksubsegs) {
11525                   tsspivot1(flipface, checkseg);
11526                   if (checkseg.sh != dummysh) {
11527                     if (b->verbose > 2) {
11528                       printf("    Queuing missing segment (%d, %d).\n",
11529                         pointmark(org(flipface)), pointmark(dest(flipface)));
11530                     }
11531                     misseg = (badface *) misseglist->append(NULL);
11532                     misseg->ss = checkseg;
11533                     misseg->forg = sorg(checkseg);
11534                     misseg->fdest = sdest(checkseg);
11535                     // Detach all tets having this seg.
11536                     starttet = flipface;
11537                     adjustedgering(starttet, CCW);
11538                     fnextself(starttet);
11539                     spintet = starttet;
11540                     hitbdry = 0;
11541                     do {
11542                       tssdissolve1(spintet);
11543                       if (!fnextself(spintet)) {
11544                         hitbdry++;
11545                         if (hitbdry < 2) {
11546                           esym(starttet, spintet);
11547                           if (!fnextself(spintet)) {
11548                             hitbdry++;
11549                           }
11550                         }
11551                       }
11552                     } while ((apex(spintet) != apex(starttet)) &&
11553                              (hitbdry < 2));
11554                   }
11555                 } // if (checksubfaces)
11556                 flip22(&flipface, flipqueue);
11557               }
11558             }
11559           } // if (ori > 0.0)
11560         } // if (sign > 0.0)
11561       }
11562     } // !isdead(&qface->tt)
11563   } // while (!flipqueue->empty())
11564 
11565   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11566   if (b->verbose > 1) {
11567     printf("    %ld flips.\n", flipcount);
11568   }
11569   return flipcount;
11570 }
11571 
11573 //                                                                           //
11574 // undoflip()    Undo the most recent flip sequence induced by flip().       //
11575 //                                                                           //
11576 // 'lastflip' is the stack of recently flipped faces. Walks through the list //
11577 // of flips, in the reverse of the order in which they were done, and undoes //
11578 // them.                                                                     //
11579 //                                                                           //
11581 
11582 void tetgenmesh::undoflip(badface *lastflip)
11583 {
11584   enum fliptype fc;
11585 
11586   while (lastflip != (badface *) NULL) {
11587     // Get the right flipped face.
11588     findface(&lastflip->tt, lastflip->forg, lastflip->fdest, lastflip->fapex);
11589     fc = (enum fliptype) (int) lastflip->key;
11590     switch (fc) {
11591     case T23:
11592       // The reverse operation of T23 is T32.
11593       flip32(&lastflip->tt, NULL);
11594       break;
11595     case T32:
11596       // The reverse operation of T32 is T23.
11597       flip23(&lastflip->tt, NULL);
11598       break;
11599     case T22:
11600     case T44:
11601       // The reverse operation of T22 or T44 is again T22 or T44.
11602       flip22(&lastflip->tt, NULL);
11603       break;
11604     default: // To omit compile warnings.
11605       break;
11606     }
11607     // Go on and process the next transformation.
11608     lastflip = lastflip->previtem;
11609   }
11610 }
11611 
11613 //                                                                           //
11614 // flipsub()    Flip non-Delaunay edges in a queue of (coplanar) subfaces.   //
11615 //                                                                           //
11616 // Assumpation:  Current triangulation T contains non-Delaunay edges (after  //
11617 // inserting a point or performing a flip). Non-Delaunay edges are queued in //
11618 // 'facequeue'. Returns the total number of flips done during this call.     //
11619 //                                                                           //
11621 
11622 long tetgenmesh::flipsub(queue* flipqueue)
11623 {
11624   badface *qedge;
11625   face flipedge, symedge;
11626   face checkseg;
11627   point pa, pb, pc, pd;
11628   REAL vab[3], vac[3], vad[3];
11629   REAL dot1, dot2, lac, lad;
11630   REAL sign, ori;
11631   int edgeflips;
11632   int i;
11633 
11634   if (b->verbose > 1) {
11635     printf("  Start do edge queue: %ld edges.\n", flipqueue->len());
11636   }
11637 
11638   edgeflips = 0;
11639 
11640   while (!flipqueue->empty()) {
11641     qedge = (badface *) flipqueue->pop();
11642     flipedge = qedge->ss;
11643     if (flipedge.sh == dummysh) continue;
11644     if ((sorg(flipedge) != qedge->forg) ||
11645         (sdest(flipedge) != qedge->fdest)) continue;
11646     sspivot(flipedge, checkseg);
11647     if (checkseg.sh != dummysh) continue;  // Can't flip a subsegment.
11648     spivot(flipedge, symedge);
11649     if (symedge.sh == dummysh) continue; // Can't flip a hull edge.
11650     pa = sorg(flipedge);
11651     pb = sdest(flipedge);
11652     pc = sapex(flipedge);
11653     pd = sapex(symedge);
11654     // Choose the triangle abc or abd as the base depending on the angle1
11655     //   (Vac, Vab) and angle2 (Vad, Vab).
11656     for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
11657     for (i = 0; i < 3; i++) vac[i] = pc[i] - pa[i];
11658     for (i = 0; i < 3; i++) vad[i] = pd[i] - pa[i];
11659     dot1 = dot(vac, vab);
11660     dot2 = dot(vad, vab);
11661     dot1 *= dot1;
11662     dot2 *= dot2;
11663     lac = dot(vac, vac);
11664     lad = dot(vad, vad);
11665     if (lad * dot1 <= lac * dot2) {
11666       // angle1 is closer to 90 than angle2, choose abc (flipedge).
11667       abovepoint = facetabovepointarray[shellmark(flipedge)];
11668       if (abovepoint == (point) NULL) {
11669         getfacetabovepoint(&flipedge);
11670       }
11671       sign = insphere(pa, pb, pc, abovepoint, pd);
11672       ori = orient3d(pa, pb, pc, abovepoint);
11673     } else {
11674       // angle2 is closer to 90 than angle1, choose abd (symedge).
11675       abovepoint = facetabovepointarray[shellmark(symedge)];
11676       if (abovepoint == (point) NULL) {
11677         getfacetabovepoint(&symedge);
11678       }
11679       sign = insphere(pa, pb, pd, abovepoint, pc);
11680       ori = orient3d(pa, pb, pd, abovepoint);
11681     }
11682     // Correct the sign.
11683     sign = ori > 0.0 ? sign : -sign;
11684     if (sign > 0.0) {
11685       // Flip the non-Delaunay edge.
11686       flip22sub(&flipedge, flipqueue);
11687       edgeflips++;
11688     }
11689   }
11690 
11691   if (b->verbose > 1) {
11692     printf("  Total %d flips.\n", edgeflips);
11693   }
11694 
11695   return edgeflips;
11696 }
11697 
11699 //                                                                           //
11700 // removetetbypeeloff()    Remove a boundary tet by peeling it off.          //
11701 //                                                                           //
11702 // 'striptet' (abcd) is on boundary and can be removed by stripping it off.  //
11703 // Let abc and bad are the external boundary faces.                          //
11704 //                                                                           //
11705 // To strip 'abcd' from the mesh is to detach its two interal faces (dca and //
11706 // cdb) from their adjoining tets together with a 2-to-2 flip to transform   //
11707 // two subfaces (abc and bad) into another two (dca and cdb).                //
11708 //                                                                           //
11709 // In mesh optimization. It is possible that ab is a segment and abcd is a   //
11710 // sliver on the hull. Strip abcd will also delete the segment ab.           //
11711 //                                                                           //
11713 
11714 bool tetgenmesh::removetetbypeeloff(triface *striptet)
11715 {
11716   triface abcd, badc;
11717   triface dcacasing, cdbcasing;
11718   face abc, bad;
11719   face abseg;
11720   REAL ang;
11721 
11722   abcd = *striptet;
11723   adjustedgering(abcd, CCW);
11724   // Get the casing tets at the internal sides.
11725   enextfnext(abcd, cdbcasing);
11726   enext2fnext(abcd, dcacasing);
11727   symself(cdbcasing);
11728   symself(dcacasing);
11729   // Do the neighboring tets exist?  During optimization. It is possible
11730   //   that the neighboring tets are already dead.
11731   if ((cdbcasing.tet == dummytet) || (dcacasing.tet == dummytet)) {
11732     // Do not strip this tet.
11733     return false;
11734   }
11735 
11736   // Are there subfaces?
11737   if (checksubfaces) {
11738     // Get the external subfaces abc, bad.
11739     fnext(abcd, badc);
11740     esymself(badc);
11741     tspivot(abcd, abc);
11742     tspivot(badc, bad);
11743     if (abc.sh != dummysh) {
11744       assert(bad.sh != dummysh);
11745       findedge(&abc, org(abcd), dest(abcd));
11746       findedge(&bad, org(badc), dest(badc));
11747       // Is ab a segment?
11748       sspivot(abc, abseg);
11749       if (abseg.sh != dummysh) {
11750         // Does a segment allow to be removed?
11751         if ((b->optlevel > 3) && (b->nobisect == 0)) {
11752           // Only remove this segment if the dihedal angle at ab is between
11753           //   [b->maxdihedral-9, 180] (deg).  This avoids mistakely fliping
11754           //   ab when it has actually no big dihedral angle while cd has.
11755           ang = facedihedral(org(abcd), dest(abcd), apex(abcd), oppo(abcd));
11756           ang = ang * 180.0 / PI;
11757           if ((ang + 9.0) > b->maxdihedral) {
11758             if (b->verbose > 1) {
11759               printf("    Remove a segment during peeling.\n");
11760             }
11761             face prevseg, nextseg;
11762             // It is only shared by abc and bad (abcd is a tet).
11763             ssdissolve(abc);
11764             ssdissolve(bad);
11765             abseg.shver = 0;
11766             senext(abseg, nextseg);
11767             spivotself(nextseg);
11768             if (nextseg.sh != dummysh) {
11769               ssdissolve(nextseg);
11770             }
11771             senext2(abseg, prevseg);
11772             spivotself(prevseg);
11773             if (prevseg.sh != dummysh) {
11774               ssdissolve(prevseg);
11775             }
11776             shellfacedealloc(subsegs, abseg.sh);
11777             optcount[1]++;
11778           } else {
11779             return false;
11780           }
11781         } else {
11782           return false;
11783         }
11784       }
11785       // Do a 2-to-2 flip on abc and bad, transform abc->dca, bad->cdb.
11786       flip22sub(&abc, NULL);
11787       // The two internal faces become boundary faces.
11788       tsbond(cdbcasing, bad);
11789       tsbond(dcacasing, abc);
11790     }
11791   }
11792 
11793   // Detach abcd from the two internal faces.
11794   dissolve(cdbcasing);
11795   dissolve(dcacasing);
11796   // Delete abcd.
11797   tetrahedrondealloc(abcd.tet);
11798   return true;
11799 }
11800 
11802 //                                                                           //
11803 // removeedgebyflip22()    Remove an edge by a 2-to-2 (or 4-to-4) flip.      //
11804 //                                                                           //
11805 // 'abtetlist' contains n tets (n is 2 or 4) sharing edge ab,  abtetlist[0]  //
11806 // and abtetlist[1] are tets abec and abde, respectively (NOTE, both are in  //
11807 // CW edge ring), where a, b, c, and d are coplanar.  If n = 4, abtetlist[2] //
11808 // and abtetlist[3] are tets abfd and abcf, respectively.  This routine uses //
11809 // flip22() to replace edge ab with cd, the surrounding tets are rotated.    //
11810 //                                                                           //
11811 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
11812 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
11813 // is the maximum dihedral angle in the old tets.                            //
11814 //                                                                           //
11816 
11817 bool tetgenmesh::removeedgebyflip22(REAL *key, int n, triface *abtetlist,
11818   queue *flipque)
11819 {
11820   point pa, pb, pc, pd, pe, pf;
11821   REAL cosmaxd, d1, d2, d3;
11822   bool doflip;
11823 
11824   cosmaxd = 0.0;
11825   pf = apex(abtetlist[2]);
11826   doflip = true;
11827   adjustedgering(abtetlist[0], CW);
11828   pa = org(abtetlist[0]);
11829   pb = dest(abtetlist[0]);
11830   pe = apex(abtetlist[0]);
11831   pc = oppo(abtetlist[0]);
11832   pd = apex(abtetlist[1]);
11833   if (n == 4) {
11834     pf = apex(abtetlist[2]);
11835   }
11836   if (key && (*key > -1.0)) {
11837     tetalldihedral(pc, pd, pe, pa, NULL, &d1, NULL);
11838     tetalldihedral(pd, pc, pe, pb, NULL, &d2, NULL);
11839     cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11840     if (n == 4) {
11841       tetalldihedral(pd, pc, pf, pa, NULL, &d1, NULL);
11842       tetalldihedral(pc, pd, pf, pb, NULL, &d2, NULL);
11843       d3 = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11844       cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
11845     }
11846     doflip = (*key < cosmaxd); // Can local quality be improved?
11847   }
11848 
11849   if (doflip) {
11850     flip22(&abtetlist[0], NULL);
11851     // Return the improved quality value.
11852     if (key) *key = cosmaxd;
11853   }
11854 
11855   return doflip;
11856 }
11857 
11859 //                                                                           //
11860 // removefacebyflip23()    Remove a face by a 2-to-3 flip.                   //
11861 //                                                                           //
11862 // 'abctetlist' contains 2 tets sharing abc, which are [0]abcd and [1]bace.  //
11863 // This routine forms three new tets that abc is not a face anymore. Save    //
11864 // them in 'newtetlist': [0]edab, [1]edbc, and [2]edca.  Note that the new   //
11865 // tets may not valid if one of them get inverted. return false if so.       //
11866 //                                                                           //
11867 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
11868 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
11869 // is the maximum dihedral angle in the old tets.                            //
11870 //                                                                           //
11871 // If the face is flipped, 'newtetlist' returns the three new tets. The two  //
11872 // tets in 'abctetlist' are NOT deleted.  The caller has the right to either //
11873 // delete them or reverse the operation.                                     //
11874 //                                                                           //
11876 
11877 bool tetgenmesh::removefacebyflip23(REAL *key, triface *abctetlist,
11878   triface *newtetlist, queue *flipque)
11879 {
11880   triface edab, edbc, edca; // new configuration.
11881   triface newfront, oldfront, adjfront;
11882   face checksh;
11883   point pa, pb, pc, pd, pe;
11884   REAL ori, cosmaxd, d1, d2, d3;
11885   REAL attrib, volume;
11886   bool doflip;
11887   int i;
11888 
11889   cosmaxd = 0.0;
11890 
11891   adjustedgering(abctetlist[0], CCW);
11892   pa = org(abctetlist[0]);
11893   pb = dest(abctetlist[0]);
11894   pc = apex(abctetlist[0]);
11895   pd = oppo(abctetlist[0]);
11896   pe = oppo(abctetlist[1]);
11897 
11898   // Check if the flip creates valid new tets.
11899   ori = orient3d(pe, pd, pa, pb);
11900   if (ori < 0.0) {
11901     ori = orient3d(pe, pd, pb, pc);
11902     if (ori < 0.0) {
11903       ori = orient3d(pe, pd, pc, pa);
11904     }
11905   }
11906   doflip = (ori < 0.0); // Can abc be flipped away?
11907   if (doflip && (key != (REAL *) NULL)) {
11908     if (*key > -1.0) {
11909       // Test if the new tets reduce the maximal dihedral angle.
11910       tetalldihedral(pe, pd, pa, pb, NULL, &d1, NULL);
11911       tetalldihedral(pe, pd, pb, pc, NULL, &d2, NULL);
11912       tetalldihedral(pe, pd, pc, pa, NULL, &d3, NULL);
11913       cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11914       cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
11915       doflip = (*key < cosmaxd); // Can local quality be improved?
11916     }
11917   }
11918 
11919   if (doflip) {
11920     // A valid (2-to-3) flip is found.
11921     flip23s++;
11922     // Create the new tets.
11923     maketetrahedron(&edab);
11924     setorg(edab, pe);
11925     setdest(edab, pd);
11926     setapex(edab, pa);
11927     setoppo(edab, pb);
11928     maketetrahedron(&edbc);
11929     setorg(edbc, pe);
11930     setdest(edbc, pd);
11931     setapex(edbc, pb);
11932     setoppo(edbc, pc);
11933     maketetrahedron(&edca);
11934     setorg(edca, pe);
11935     setdest(edca, pd);
11936     setapex(edca, pc);
11937     setoppo(edca, pa);
11938     // Transfer the element attributes.
11939     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
11940       attrib = elemattribute(abctetlist[0].tet, i);
11941       setelemattribute(edab.tet, i, attrib);
11942       setelemattribute(edbc.tet, i, attrib);
11943       setelemattribute(edca.tet, i, attrib);
11944     }
11945     // Transfer the volume constraints.
11946     if (b->varvolume && !b->refine) {
11947       volume = volumebound(abctetlist[0].tet);
11948       setvolumebound(edab.tet, volume);
11949       setvolumebound(edbc.tet, volume);
11950       setvolumebound(edca.tet, volume);
11951     }
11952     // Return two new tets.
11953     newtetlist[0] = edab;
11954     newtetlist[1] = edbc;
11955     newtetlist[2] = edca;
11956     // Glue the three new tets.
11957     for (i = 0; i < 3; i++) {
11958       fnext(newtetlist[i], newfront);
11959       bond(newfront, newtetlist[(i + 1) % 3]);
11960     }
11961     // Substitute the three new tets into the old cavity.
11962     for (i = 0; i < 3; i++) {
11963       fnext(abctetlist[0], oldfront);
11964       sym(oldfront, adjfront); // may be outside.
11965       enextfnext(newtetlist[i], newfront);
11966       bond(newfront, adjfront);
11967       if (checksubfaces) {
11968         tspivot(oldfront, checksh);
11969         if (checksh.sh != dummysh) {
11970           tsbond(newfront, checksh);
11971         }
11972       }
11973       if (flipque != (queue *) NULL) {
11974         enqueueflipface(newfront, flipque);
11975       }
11976       enextself(abctetlist[0]);
11977     }
11978     findedge(&(abctetlist[1]), pb, pa);
11979     for (i = 0; i < 3; i++) {
11980       fnext(abctetlist[1], oldfront);
11981       sym(oldfront, adjfront); // may be outside.
11982       enext2fnext(newtetlist[i], newfront);
11983       bond(newfront, adjfront);
11984       if (checksubfaces) {
11985         tspivot(oldfront, checksh);
11986         if (checksh.sh != dummysh) {
11987           tsbond(newfront, checksh);
11988         }
11989       }
11990       if (flipque != (queue *) NULL) {
11991         enqueueflipface(newfront, flipque);
11992       }
11993       enext2self(abctetlist[1]);
11994     }
11995     // Do not delete the old tets.
11996     // for (i = 0; i < 2; i++) {
11997     //   tetrahedrondealloc(abctetlist[i].tet);
11998     // }
11999     // Return the improved quality value.
12000     if (key != (REAL *) NULL) *key = cosmaxd;
12001     return true;
12002   }
12003 
12004   return false;
12005 }
12006 
12008 //                                                                           //
12009 // removeedgebyflip32()    Remove an edge by a 3-to-2 flip.                  //
12010 //                                                                           //
12011 // 'abtetlist' contains 3 tets sharing ab. Imaging that ab is perpendicular  //
12012 // to the screen, where a lies in front of and b lies behind it. The 3 tets  //
12013 // of the list are: [0]abce, [1]abdc, and [2]abed, respectively.             //
12014 //                                                                           //
12015 // This routine forms two new tets that ab is not an edge of them. Save them //
12016 // in 'newtetlist', [0]dcea, [1]cdeb. Note that the new tets may not valid   //
12017 // if one of them get inverted. return false if so.                          //
12018 //                                                                           //
12019 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
12020 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
12021 // is the maximum dihedral angle in the old tets.                            //
12022 //                                                                           //
12023 // If the edge is flipped, 'newtetlist' returns the two new tets. The three  //
12024 // tets in 'abtetlist' are NOT deleted.  The caller has the right to either  //
12025 // delete them or reverse the operation.                                     //
12026 //                                                                           //
12028 
12029 bool tetgenmesh::removeedgebyflip32(REAL *key, triface *abtetlist,
12030   triface *newtetlist, queue *flipque)
12031 {
12032   triface dcea, cdeb; // new configuration.
12033   triface newfront, oldfront, adjfront;
12034   face checksh;
12035   point pa, pb, pc, pd, pe;
12036   REAL ori, cosmaxd, d1, d2;
12037   REAL attrib, volume;
12038   bool doflip;
12039   int i;
12040 
12041   pa = org(abtetlist[0]);
12042   pb = dest(abtetlist[0]);
12043   pc = apex(abtetlist[0]);
12044   pd = apex(abtetlist[1]);
12045   pe = apex(abtetlist[2]);
12046 
12047   ori = orient3d(pd, pc, pe, pa);
12048   if (ori < 0.0) {
12049     ori = orient3d(pc, pd, pe, pb);
12050   }
12051   doflip = (ori < 0.0); // Can ab be flipped away?
12052 
12053   // Does the caller ensure a valid configuration?
12054   if (doflip && (key != (REAL *) NULL)) {
12055     if (*key > -1.0) {
12056       // Test if the new tets reduce the maximal dihedral angle.
12057       tetalldihedral(pd, pc, pe, pa, NULL, &d1, NULL);
12058       tetalldihedral(pc, pd, pe, pb, NULL, &d2, NULL);
12059       cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
12060       doflip = (*key < cosmaxd); // Can local quality be improved?
12061       // Return the key
12062       *key = cosmaxd;
12063     }
12064   }
12065 
12066   if (doflip) {
12067     // Create the new tets.
12068     maketetrahedron(&dcea);
12069     setorg(dcea, pd);
12070     setdest(dcea, pc);
12071     setapex(dcea, pe);
12072     setoppo(dcea, pa);
12073     maketetrahedron(&cdeb);
12074     setorg(cdeb, pc);
12075     setdest(cdeb, pd);
12076     setapex(cdeb, pe);
12077     setoppo(cdeb, pb);
12078     // Transfer the element attributes.
12079     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12080       attrib = elemattribute(abtetlist[0].tet, i);
12081       setelemattribute(dcea.tet, i, attrib);
12082       setelemattribute(cdeb.tet, i, attrib);
12083     }
12084     // Transfer the volume constraints.
12085     if (b->varvolume && !b->refine) {
12086       volume = volumebound(abtetlist[0].tet);
12087       setvolumebound(dcea.tet, volume);
12088       setvolumebound(cdeb.tet, volume);
12089     }
12090     // Return two new tets.
12091     newtetlist[0] = dcea;
12092     newtetlist[1] = cdeb;
12093     // Glue the two new tets.
12094     bond(dcea, cdeb);
12095     // Substitute the two new tets into the old three-tets cavity.
12096     for (i = 0; i < 3; i++) {
12097       fnext(dcea, newfront); // face dca, cea, eda.
12098       esym(abtetlist[(i + 1) % 3], oldfront);
12099       enextfnextself(oldfront);
12100       // Get the adjacent tet at the face (may be a dummytet).
12101       sym(oldfront, adjfront);
12102       bond(newfront, adjfront);
12103       if (checksubfaces) {
12104         tspivot(oldfront, checksh);
12105         if (checksh.sh != dummysh) {
12106           tsbond(newfront, checksh);
12107         }
12108       }
12109       if (flipque != (queue *) NULL) {
12110         enqueueflipface(newfront, flipque);
12111       }
12112       enext2self(dcea);
12113     }
12114     for (i = 0; i < 3; i++) {
12115       fnext(cdeb, newfront); // face cdb, deb, ecb.
12116       esym(abtetlist[(i + 1) % 3], oldfront);
12117       enext2fnextself(oldfront);
12118       // Get the adjacent tet at the face (may be a dummytet).
12119       sym(oldfront, adjfront);
12120       bond(newfront, adjfront);
12121       if (checksubfaces) {
12122         tspivot(oldfront, checksh);
12123         if (checksh.sh != dummysh) {
12124           tsbond(newfront, checksh);
12125         }
12126       }
12127       if (flipque != (queue *) NULL) {
12128         enqueueflipface(newfront, flipque);
12129       }
12130       enextself(cdeb);
12131     }
12132     // Do not delete the old tets.
12133     // for (i = 0; i < 3; i++) {
12134     //   tetrahedrondealloc(abtetlist[i].tet);
12135     // }
12136     return true;
12137   } // if (doflip)
12138 
12139   return false;
12140 }
12141 
12143 //                                                                           //
12144 // removeedgebytranNM()    Remove an edge by transforming n-to-m tets.       //
12145 //                                                                           //
12146 // This routine attempts to remove a given edge (ab) by transforming the set //
12147 // T of tets surrounding ab into another set T' of tets.  T and T' have the  //
12148 // same outer faces and ab is not an edge of T' anymore. Let |T|=n, and |T'| //
12149 // =m, it is actually a n-to-m flip for n > 3.  The relation between n and m //
12150 // depends on the method, ours is found below.                               //
12151 //                                                                           //
12152 // 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
12153 // to the screen, where a lies in front of and b lies behind it.  Let the    //
12154 // projections of the n apexes onto screen in clockwise order are: p_0, ...  //
12155 // p_n-1, respectively. The tets in the list are: [0]abp_0p_n-1,[1]abp_1p_0, //
12156 // ..., [n-1]abp_n-1p_n-2, respectively.                                     //
12157 //                                                                           //
12158 // The principle of the approach is: Recursively reduce the link of ab by    //
12159 // using flip23 until only three faces remain, hence a flip32 can be applied //
12160 // to remove ab. For a given face a.b.p_0, check a flip23 can be applied on  //
12161 // it, i.e, edge p_1.p_n-1 crosses it. NOTE*** We do the flip even p_1.p_n-1 //
12162 // intersects with a.b (they are coplanar). If so, a degenerate tet (a.b.p_1.//
12163 // p_n-1) is temporarily created, but it will be eventually removed by the   //
12164 // final flip32. This relaxation splits a flip44 into flip23 + flip32. *NOTE //
12165 // Now suppose a.b.p_0 gets flipped, p_0 is not on the link of ab anymore.   //
12166 // The link is then reduced (by 1). 2 of the 3 new tets, p_n-1.p_1.p_0.a and //
12167 // p_1.p_n-1.p_0.b, will be part of the new configuration.  The left new tet,//
12168 // a.b.p_1.p_n-1, goes into the new link of ab. A recurrence can be applied. //
12169 //                                                                           //
12170 // If 'e1' and 'e2' are not NULLs, they specify an wanted edge to appear in  //
12171 // the new tet configuration. In such case, only do flip23 if edge e1<->e2   //
12172 // can be recovered. It is used in removeedgebycombNM().                     //
12173 //                                                                           //
12174 // If ab gets removed. 'newtetlist' contains m new tets.  By using the above //
12175 // approach, the pairs (n, m) can be easily enumerated.  For example, (3, 2),//
12176 // (4, 4), (5, 6), (6, 8), (7, 10), (8, 12), (9, 14), (10, 16),  and so on.  //
12177 // It is easy to deduce, that m = (n - 2) * 2, when n >= 3.  The n tets in   //
12178 // 'abtetlist' are NOT deleted in this routine. The caller has the right to  //
12179 // either delete them or reverse this operation.                             //
12180 //                                                                           //
12182 
12183 bool tetgenmesh::removeedgebytranNM(REAL *key, int n, triface *abtetlist,
12184   triface *newtetlist, point e1, point e2, queue *flipque)
12185 {
12186   triface tmpabtetlist[9]; // Temporary max 9 tets configuration.
12187   triface newfront, oldfront, adjfront;
12188   face checksh;
12189   point pa, pb, p[10];
12190   REAL ori, cosmaxd, d1, d2;
12191   REAL tmpkey;
12192   REAL attrib, volume;
12193   bool doflip, copflag, success;
12194   int i, j, k;
12195 
12196   cosmaxd = 0.0;
12197   // Maximum 10 tets.
12198   assert(n <= 10);
12199   // Two points a and b are fixed.
12200   pa = org(abtetlist[0]);
12201   pb = dest(abtetlist[0]);
12202   // The points p_0, p_1, ..., p_n-1 are permuted in each new configuration.
12203   //   These permutations can be easily done in the following loop.
12204   // Loop through all the possible new tets configurations. Stop on finding
12205   //   a valid new tet configuration which also immproves the quality value.
12206   for (i = 0; i < n; i++) {
12207     // Get other n points for the current configuration.
12208     for (j = 0; j < n; j++) {
12209       p[j] = apex(abtetlist[(i + j) % n]);
12210     }
12211     // Is there a wanted edge?
12212     if ((e1 != (point) NULL) && (e2 != (point) NULL)) {
12213       // Yes. Skip this face if p[1]<->p[n-1] is not the edge.
12214       if (!(((p[1] == e1) && (p[n - 1] == e2)) ||
12215         ((p[1] == e2) && (p[n - 1] == e1)))) continue;
12216     }
12217     // Test if face a.b.p_0 can be flipped (by flip23), ie, to check if the
12218     //   edge p_n-1.p_1 crosses face a.b.p_0 properly.
12219     // Note. It is possible that face a.b.p_0 has type flip44, ie, a,b,p_1,
12220     //   and p_n-1 are coplanar. A trick is to split the flip44 into two
12221     //   steps: frist a flip23, then a flip32. The first step creates a
12222     //   degenerate tet (vol=0) which will be removed by the second flip.
12223     ori = orient3d(pa, pb, p[1], p[n - 1]);
12224     copflag = (ori == 0.0); // Are they coplanar?
12225     if (ori >= 0.0) {
12226       // Accept the coplanar case which supports flip44.
12227       ori = orient3d(pb, p[0], p[1], p[n - 1]);
12228       if (ori > 0.0) {
12229         ori = orient3d(p[0], pa, p[1], p[n - 1]);
12230       }
12231     }
12232     // Is face abc flipable?
12233     if (ori > 0.0) {
12234       // A valid (2-to-3) flip (or 4-to-4 flip) is found.
12235       copflag ? flip44s++ : flip23s++;
12236       doflip = true;
12237       if (key != (REAL *) NULL) {
12238         if (*key > -1.0) {
12239           // Test if the new tets reduce the maximal dihedral angle. Only 2
12240           //   tets, p_n-1.p_1.p_0.a and p_1.p_n-1.p_0.b, need to be tested
12241           //   The left one a.b.p_n-1.p_1 goes into the new link of ab.
12242           tetalldihedral(p[n - 1], p[1], p[0], pa, NULL, &d1, NULL);
12243           tetalldihedral(p[1], p[n - 1], p[0], pb, NULL, &d2, NULL);
12244           cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
12245           doflip = *key < cosmaxd; // Can the local quality be improved?
12246         }
12247       }
12248       if (doflip) {
12249         tmpkey = key != NULL ? *key : -1.0;
12250         // Create the two new tets.
12251         maketetrahedron(&(newtetlist[0]));
12252         setorg(newtetlist[0], p[n - 1]);
12253         setdest(newtetlist[0], p[1]);
12254         setapex(newtetlist[0], p[0]);
12255         setoppo(newtetlist[0], pa);
12256         maketetrahedron(&(newtetlist[1]));
12257         setorg(newtetlist[1], p[1]);
12258         setdest(newtetlist[1], p[n - 1]);
12259         setapex(newtetlist[1], p[0]);
12260         setoppo(newtetlist[1], pb);
12261         // Create the n - 1 temporary new tets (the new Star(ab)).
12262         maketetrahedron(&(tmpabtetlist[0]));
12263         setorg(tmpabtetlist[0], pa);
12264         setdest(tmpabtetlist[0], pb);
12265         setapex(tmpabtetlist[0], p[n - 1]);
12266         setoppo(tmpabtetlist[0], p[1]);
12267         for (j = 1; j < n - 1; j++) {
12268           maketetrahedron(&(tmpabtetlist[j]));
12269           setorg(tmpabtetlist[j], pa);
12270           setdest(tmpabtetlist[j], pb);
12271           setapex(tmpabtetlist[j], p[j]);
12272           setoppo(tmpabtetlist[j], p[j + 1]);
12273         }
12274         // Transfer the element attributes.
12275         for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12276           attrib = elemattribute(abtetlist[0].tet, j);
12277           setelemattribute(newtetlist[0].tet, j, attrib);
12278           setelemattribute(newtetlist[1].tet, j, attrib);
12279           for (k = 0; k < n - 1; k++) {
12280             setelemattribute(tmpabtetlist[k].tet, j, attrib);
12281           }
12282         }
12283         // Transfer the volume constraints.
12284         if (b->varvolume && !b->refine) {
12285           volume = volumebound(abtetlist[0].tet);
12286           setvolumebound(newtetlist[0].tet, volume);
12287           setvolumebound(newtetlist[1].tet, volume);
12288           for (k = 0; k < n - 1; k++) {
12289             setvolumebound(tmpabtetlist[k].tet, volume);
12290           }
12291         }
12292         // Glue the new tets at their internal faces: 2 + (n - 1).
12293         bond(newtetlist[0], newtetlist[1]); // p_n-1.p_1.p_0.
12294         fnext(newtetlist[0], newfront);
12295         enext2fnext(tmpabtetlist[0], adjfront);
12296         bond(newfront, adjfront); // p_n-1.p_1.a.
12297         fnext(newtetlist[1], newfront);
12298         enextfnext(tmpabtetlist[0], adjfront);
12299         bond(newfront, adjfront); // p_n-1.p_1.b.
12300         // Glue n - 1 internal faces around ab.
12301         for (j = 0; j < n - 1; j++) {
12302           fnext(tmpabtetlist[j], newfront);
12303           bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
12304         }
12305         // Substitute the old tets with the new tets by connecting the new
12306         //   tets to the adjacent tets in the mesh. There are n * 2 (outer)
12307         //   faces of the new tets need to be operated.
12308         // Note, after the substitution, the old tets still have pointers to
12309         //   their adjacent tets in the mesh.  These pointers can be re-used
12310         //   to inverse the substitution.
12311         for (j = 0; j < n; j++) {
12312           // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
12313           oldfront = abtetlist[(i + j) % n];
12314           esymself(oldfront);
12315           enextfnextself(oldfront);
12316           // Get an adjacent tet at face: [0]a.p_0.p_n-1 or [j]a.p_j.p_j-1.
12317           sym(oldfront, adjfront); // adjfront may be dummy.
12318           // Get the corresponding face from the new tets.
12319           if (j == 0) {
12320             enext2fnext(newtetlist[0], newfront); // a.p_0.n_n-1
12321           } else if (j == 1) {
12322             enextfnext(newtetlist[0], newfront); // a.p_1.p_0
12323           } else { // j >= 2.
12324             enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
12325           }
12326           bond(newfront, adjfront);
12327           if (checksubfaces) {
12328             tspivot(oldfront, checksh);
12329             if (checksh.sh != dummysh) {
12330               tsbond(newfront, checksh);
12331             }
12332           }
12333           if (flipque != (queue *) NULL) {
12334             // Only queue the faces of the two new tets.
12335             if (j < 2) enqueueflipface(newfront, flipque);
12336           }
12337         }
12338         for (j = 0; j < n; j++) {
12339           // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
12340           oldfront = abtetlist[(i + j) % n];
12341           esymself(oldfront);
12342           enext2fnextself(oldfront);
12343           // Get an adjacent tet at face: [0]b.p_0.p_n-1 or [j]b.p_j.p_j-1.
12344           sym(oldfront, adjfront); // adjfront may be dummy.
12345           // Get the corresponding face from the new tets.
12346           if (j == 0) {
12347             enextfnext(newtetlist[1], newfront); // b.p_0.n_n-1
12348           } else if (j == 1) {
12349             enext2fnext(newtetlist[1], newfront); // b.p_1.p_0
12350           } else { // j >= 2.
12351             enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
12352           }
12353           bond(newfront, adjfront);
12354           if (checksubfaces) {
12355             tspivot(oldfront, checksh);
12356             if (checksh.sh != dummysh) {
12357               tsbond(newfront, checksh);
12358             }
12359           }
12360           if (flipque != (queue *) NULL) {
12361             // Only queue the faces of the two new tets.
12362             if (j < 2) enqueueflipface(newfront, flipque);
12363           }
12364         }
12365         // Adjust the faces in the temporary new tets at ab for recursively
12366         //   processing on the n-1 tets.(See the description at beginning)
12367         for (j = 0; j < n - 1; j++) {
12368           fnextself(tmpabtetlist[j]);
12369         }
12370         if (n > 4) {
12371           success = removeedgebytranNM(&tmpkey, n-1, tmpabtetlist,
12372             &(newtetlist[2]), NULL, NULL, flipque);
12373         } else { // assert(n == 4);
12374           success = removeedgebyflip32(&tmpkey, tmpabtetlist,
12375             &(newtetlist[2]), flipque);
12376         }
12377         // No matter it was success or not, delete the temporary tets.
12378         for (j = 0; j < n - 1; j++) {
12379           tetrahedrondealloc(tmpabtetlist[j].tet);
12380         }
12381         if (success) {
12382           // The new configuration is good.
12383           // Do not delete the old tets.
12384           // for (j = 0; j < n; j++) {
12385           //   tetrahedrondealloc(abtetlist[j].tet);
12386           // }
12387           // Save the minimal improved quality value.
12388           if (key != (REAL *) NULL) {
12389             *key = (tmpkey < cosmaxd ? tmpkey : cosmaxd);
12390           }
12391           return true;
12392         } else {
12393           // The new configuration is bad, substitue back the old tets.
12394           for (j = 0; j < n; j++) {
12395             oldfront = abtetlist[(i + j) % n];
12396             esymself(oldfront);
12397             enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
12398             sym(oldfront, adjfront); // adjfront may be dummy.
12399             bond(oldfront, adjfront);
12400             if (checksubfaces) {
12401               tspivot(oldfront, checksh);
12402               if (checksh.sh != dummysh) {
12403                 tsbond(oldfront, checksh);
12404               }
12405             }
12406           }
12407           for (j = 0; j < n; j++) {
12408             oldfront = abtetlist[(i + j) % n];
12409             esymself(oldfront);
12410             enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12411             sym(oldfront, adjfront); // adjfront may be dummy
12412             bond(oldfront, adjfront);
12413             if (checksubfaces) {
12414               tspivot(oldfront, checksh);
12415               if (checksh.sh != dummysh) {
12416                 tsbond(oldfront, checksh);
12417               }
12418             }
12419           }
12420           // Delete the new tets.
12421           tetrahedrondealloc(newtetlist[0].tet);
12422           tetrahedrondealloc(newtetlist[1].tet);
12423           // If tmpkey has been modified, then the failure was not due to
12424           //   unflipable configuration, but the non-improvement.
12425           if (key && (tmpkey < *key)) {
12426             *key = tmpkey;
12427             return false;
12428           }
12429         } // if (success)
12430       } // if (doflip)
12431     } // if (ori > 0.0)
12432   } // for (i = 0; i < n; i++)
12433 
12434   return false;
12435 }
12436 
12438 //                                                                           //
12439 // removeedgebycombNM()    Remove an edge by combining two flipNMs.          //
12440 //                                                                           //
12441 // Given a set T of tets surrounding edge ab. The premise is that ab can not //
12442 // be removed by a flipNM. This routine attempts to remove ab by two flipNMs,//
12443 // i.e., first find and flip an edge af (or bf) by flipNM, then flip ab by   //
12444 // flipNM. If it succeeds, two sets T(ab) and T(af) of tets are replaced by  //
12445 // a new set T' and both ab and af are not edges in T' anymore.              //
12446 //                                                                           //
12447 // 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
12448 // to the screen, such that a lies in front of and b lies behind it. Let the //
12449 // projections of the n apexes on the screen in clockwise order are: p_0,...,//
12450 // p_n-1, respectively. So the list of tets are: [0]abp_0p_n-1, [1]abp_1p_0, //
12451 // ..., [n-1]abp_n-1p_n-2, respectively.                                     //
12452 //                                                                           //
12453 // The principle of the approach is: for a face a.b.p_0, check if edge b.p_0 //
12454 // is of type N32 (or N44). If it is, then try to do a flipNM on it. If the  //
12455 // flip is successful, then try to do another flipNM on a.b.  If one of the  //
12456 // two flipNMs fails, restore the old tets as they have never been flipped.  //
12457 // Then try the next face a.b.p_1.  The process can be looped for all faces  //
12458 // having ab. Stop if ab is removed or all faces have been visited. Note in  //
12459 // the above description only b.p_0 is considered, a.p_0 is done by swapping //
12460 // the position of a and b.                                                  //
12461 //                                                                           //
12462 // Similar operations have been described in [Joe,1995].  My approach checks //
12463 // more cases for finding flips than Joe's.  For instance, the cases (1)-(7) //
12464 // of Joe only consider abf for finding a flip (T23/T32).  My approach looks //
12465 // all faces at ab for finding flips. Moreover, the flipNM can flip an edge  //
12466 // whose star may have more than 3 tets while Joe's only works on 3-tet case.//
12467 //                                                                           //
12468 // If ab is removed, 'newtetlist' contains the new tets. Two sets 'abtetlist'//
12469 // (n tets) and 'bftetlist' (n1 tets) have been replaced.  The number of new //
12470 // tets can be calculated by follows: the 1st flip transforms n1 tets into   //
12471 // (n1 - 2) * 2 new tets, however,one of the new tets goes into the new link //
12472 // of ab, i.e., the reduced tet number in Star(ab) is n - 1;  the 2nd flip   //
12473 // transforms n - 1 tets into (n - 3) * 2 new tets. Hence the number of new  //
12474 // tets are: m = ((n1 - 2) * 2 - 1) + (n - 3) * 2.  The old tets are NOT del-//
12475 // eted. The caller has the right to delete them or reverse the operation.   //
12476 //                                                                           //
12478 
12479 bool tetgenmesh::removeedgebycombNM(REAL *key, int n, triface *abtetlist,
12480   int *n1, triface *bftetlist, triface *newtetlist, queue *flipque)
12481 {
12482   triface tmpabtetlist[11];
12483   triface newfront, oldfront, adjfront;
12484   face checksh;
12485   point pa, pb, p[10];
12486   REAL ori, tmpkey, tmpkey2;
12487   REAL attrib, volume;
12488   bool doflip, success;
12489   int twice, count;
12490   int i, j, k, m;
12491 
12492   // Maximal 10 tets in Star(ab).
12493   assert(n <= 10);
12494 
12495   // Do the following procedure twice, one for flipping edge b.p_0 and the
12496   //   other for p_0.a which is symmetric to the first.
12497   twice = 0;
12498   do {
12499     // Two points a and b are fixed.
12500     pa = org(abtetlist[0]);
12501     pb = dest(abtetlist[0]);
12502     // The points p_0, ..., p_n-1 are permuted in the following loop.
12503     for (i = 0; i < n; i++) {
12504       // Get the n points for the current configuration.
12505       for (j = 0; j < n; j++) {
12506         p[j] = apex(abtetlist[(i + j) % n]);
12507       }
12508       // Check if b.p_0 is of type N32 or N44.
12509       ori = orient3d(pb, p[0], p[1], p[n - 1]);
12510       if ((ori > 0) && (key != (REAL *) NULL)) {
12511         // b.p_0 is not N32. However, it is possible that the tet b.p_0.p_1.
12512         //   p_n-1 has worse quality value than the key. In such case, also
12513         //   try to flip b.p_0.
12514         tetalldihedral(pb, p[0], p[n - 1], p[1], NULL, &tmpkey, NULL);
12515         if (tmpkey < *key) ori = 0.0;
12516       }
12517       if (ori <= 0.0) {
12518         // b.p_0 is either N32 or N44. Try the 1st flipNM.
12519         bftetlist[0] = abtetlist[i];
12520         enextself(bftetlist[0]);// go to edge b.p_0.
12521         adjustedgering(bftetlist[0], CW); // edge p_0.b.
12522         assert(apex(bftetlist[0]) == pa);
12523         // Form Star(b.p_0).
12524         doflip = true;
12525         *n1 = 0;
12526         do {
12527           // Is the list full?
12528           if (*n1 == 10) break;
12529           if (checksubfaces) {
12530             // Stop if a subface appears.
12531             tspivot(bftetlist[*n1], checksh);
12532             if (checksh.sh != dummysh) {
12533               doflip = false; break;
12534             }
12535           }
12536           // Get the next tet at p_0.b.
12537           fnext(bftetlist[*n1], bftetlist[(*n1) + 1]);
12538           (*n1)++;
12539         } while (apex(bftetlist[*n1]) != pa);
12540         // 2 <= n1 <= 10.
12541         if (doflip) {
12542           success = false;
12543           tmpkey = -1.0;  // = acos(pi).
12544           if (key != (REAL *) NULL) tmpkey = *key;
12545           m = 0;
12546           if (*n1 == 3) {
12547             // Three tets case. Try flip32.
12548             success = removeedgebyflip32(&tmpkey,bftetlist,newtetlist,flipque);
12549             m = 2;
12550           } else if ((*n1 > 3) && (*n1 < 7)) {
12551             // Four or more tets case. Try flipNM.
12552             success = removeedgebytranNM(&tmpkey, *n1, bftetlist, newtetlist,
12553                                          p[1], p[n - 1], flipque);
12554             // If success, the number of new tets.
12555             m = ((*n1) - 2) * 2;
12556           } else {
12557             if (b->verbose > 1) {
12558               printf("  !! Unhandled case: n1 = %d.\n", *n1);
12559             }
12560           }
12561           if (success) {
12562             // b.p_0 is flipped. The link of ab is reduced (by 1), i.e., p_0
12563             //   is not on the link of ab. Two old tets a.b.p_0.p_n-1 and
12564             //   a.b.p_1.p_0 have been removed from the Star(ab) and one new
12565             //   tet t = a.b.p_1.p_n-1 belongs to Star(ab).
12566             // Find t in the 'newtetlist' and remove it from the list.
12567             setpointmark(pa, -pointmark(pa) - 1);
12568             setpointmark(pb, -pointmark(pb) - 1);
12569             assert(m > 0);
12570             for (j = 0; j < m; j++) {
12571               tmpabtetlist[0] = newtetlist[j];
12572               // Does it has ab?
12573               count = 0;
12574               for (k = 0; k < 4; k++) {
12575                 if (pointmark((point)(tmpabtetlist[0].tet[4+k])) < 0) count++;
12576               }
12577               if (count == 2) {
12578                 // It is. Adjust t to be the edge ab.
12579                 for (tmpabtetlist[0].loc = 0; tmpabtetlist[0].loc < 4;
12580                      tmpabtetlist[0].loc++) {
12581                   if ((oppo(tmpabtetlist[0]) != pa) &&
12582                       (oppo(tmpabtetlist[0]) != pb)) break;
12583                 }
12584                 // The face of t must contain ab.
12585                 assert(tmpabtetlist[0].loc < 4);
12586                 findedge(&(tmpabtetlist[0]), pa, pb);
12587                 break;
12588               }
12589             }
12590             assert(j < m); // The tet must exist.
12591             // Remove t from list. Fill t's position by the last tet.
12592             newtetlist[j] = newtetlist[m - 1];
12593             setpointmark(pa, -(pointmark(pa) + 1));
12594             setpointmark(pb, -(pointmark(pb) + 1));
12595             // Create the temporary Star(ab) for the next flipNM.
12596             adjustedgering(tmpabtetlist[0], CCW);
12597             if (org(tmpabtetlist[0]) != pa) {
12598               fnextself(tmpabtetlist[0]);
12599               esymself(tmpabtetlist[0]);
12600             }
12601 #ifdef SELF_CHECK
12602             // Make sure current edge is a->b.
12603             assert(org(tmpabtetlist[0]) == pa);
12604             assert(dest(tmpabtetlist[0]) == pb);
12605             assert(apex(tmpabtetlist[0]) == p[n - 1]);
12606             assert(oppo(tmpabtetlist[0]) == p[1]);
12607 #endif // SELF_CHECK
12608             // There are n - 2 left temporary tets.
12609             for (j = 1; j < n - 1; j++) {
12610               maketetrahedron(&(tmpabtetlist[j]));
12611               setorg(tmpabtetlist[j], pa);
12612               setdest(tmpabtetlist[j], pb);
12613               setapex(tmpabtetlist[j], p[j]);
12614               setoppo(tmpabtetlist[j], p[j + 1]);
12615             }
12616             // Transfer the element attributes.
12617             for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12618               attrib = elemattribute(abtetlist[0].tet, j);
12619               for (k = 0; k < n - 1; k++) {
12620                 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12621               }
12622             }
12623             // Transfer the volume constraints.
12624             if (b->varvolume && !b->refine) {
12625               volume = volumebound(abtetlist[0].tet);
12626               for (k = 0; k < n - 1; k++) {
12627                 setvolumebound(tmpabtetlist[k].tet, volume);
12628               }
12629             }
12630             // Glue n - 1 internal faces of Star(ab).
12631             for (j = 0; j < n - 1; j++) {
12632               fnext(tmpabtetlist[j], newfront);
12633               bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
12634             }
12635             // Substitute the old tets with the new tets by connecting the
12636             //   new tets to the adjacent tets in the mesh. There are (n-2)
12637             //   * 2 (outer) faces of the new tets need to be operated.
12638             // Note that the old tets still have the pointers to their
12639             //   adjacent tets in the mesh.  These pointers can be re-used
12640             //   to inverse the substitution.
12641             for (j = 2; j < n; j++) {
12642               // Get an old tet: [j]a.b.p_j.p_j-1, (j > 1).
12643               oldfront = abtetlist[(i + j) % n];
12644               esymself(oldfront);
12645               enextfnextself(oldfront);
12646               // Get an adjacent tet at face: [j]a.p_j.p_j-1.
12647               sym(oldfront, adjfront); // adjfront may be dummy.
12648               // Get the corresponding face from the new tets.
12649               // j >= 2.
12650               enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
12651               bond(newfront, adjfront);
12652               if (checksubfaces) {
12653                 tspivot(oldfront, checksh);
12654                 if (checksh.sh != dummysh) {
12655                   tsbond(newfront, checksh);
12656                 }
12657               }
12658             }
12659             for (j = 2; j < n; j++) {
12660               // Get an old tet: [j]a.b.p_j.p_j-1, (j > 2).
12661               oldfront = abtetlist[(i + j) % n];
12662               esymself(oldfront);
12663               enext2fnextself(oldfront);
12664               // Get an adjacent tet at face: [j]b.p_j.p_j-1.
12665               sym(oldfront, adjfront); // adjfront may be dummy.
12666               // Get the corresponding face from the new tets.
12667               // j >= 2.
12668               enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
12669               bond(newfront, adjfront);
12670               if (checksubfaces) {
12671                 tspivot(oldfront, checksh);
12672                 if (checksh.sh != dummysh) {
12673                   tsbond(newfront, checksh);
12674                 }
12675               }
12676             }
12677             // Adjust the faces in the temporary new tets at ab for
12678             //   recursively processing on the n-1 tets.
12679             for (j = 0; j < n - 1; j++) {
12680               fnextself(tmpabtetlist[j]);
12681             }
12682             tmpkey2 = -1;
12683             if (key) tmpkey2 = *key;
12684             if ((n - 1) == 3) {
12685               success = removeedgebyflip32(&tmpkey2, tmpabtetlist,
12686                 &(newtetlist[m - 1]), flipque);
12687             } else { // assert((n - 1) >= 4);
12688               success = removeedgebytranNM(&tmpkey2, n - 1, tmpabtetlist,
12689                 &(newtetlist[m - 1]), NULL, NULL, flipque);
12690             }
12691             // No matter it was success or not, delete the temporary tets.
12692             for (j = 0; j < n - 1; j++) {
12693               tetrahedrondealloc(tmpabtetlist[j].tet);
12694             }
12695             if (success) {
12696               // The new configuration is good.
12697               // Do not delete the old tets.
12698               // for (j = 0; j < n; j++) {
12699               //   tetrahedrondealloc(abtetlist[j].tet);
12700               // }
12701               // Return the bigger dihedral in the two sets of new tets.
12702               if (key != (REAL *) NULL) {
12703                 *key = tmpkey2 < tmpkey ? tmpkey2 : tmpkey;
12704               }
12705               return true;
12706             } else {
12707               // The new configuration is bad, substitue back the old tets.
12708               for (j = 0; j < n; j++) {
12709                 oldfront = abtetlist[(i + j) % n];
12710                 esymself(oldfront);
12711                 enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
12712                 sym(oldfront, adjfront); // adjfront may be dummy.
12713                 bond(oldfront, adjfront);
12714                 if (checksubfaces) {
12715                   tspivot(oldfront, checksh);
12716                   if (checksh.sh != dummysh) {
12717                     tsbond(oldfront, checksh);
12718                   }
12719                 }
12720               }
12721               for (j = 0; j < n; j++) {
12722                 oldfront = abtetlist[(i + j) % n];
12723                 esymself(oldfront);
12724                 enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12725                 sym(oldfront, adjfront); // adjfront may be dummy
12726                 bond(oldfront, adjfront);
12727                 if (checksubfaces) {
12728                   tspivot(oldfront, checksh);
12729                   if (checksh.sh != dummysh) {
12730                     tsbond(oldfront, checksh);
12731                   }
12732                 }
12733               }
12734               // Substitute back the old tets of the first flip.
12735               for (j = 0; j < *n1; j++) {
12736                 oldfront = bftetlist[j];
12737                 esymself(oldfront);
12738                 enextfnextself(oldfront);
12739                 sym(oldfront, adjfront); // adjfront may be dummy.
12740                 bond(oldfront, adjfront);
12741                 if (checksubfaces) {
12742                   tspivot(oldfront, checksh);
12743                   if (checksh.sh != dummysh) {
12744                     tsbond(oldfront, checksh);
12745                   }
12746                 }
12747               }
12748               for (j = 0; j < *n1; j++) {
12749                 oldfront = bftetlist[j];
12750                 esymself(oldfront);
12751                 enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12752                 sym(oldfront, adjfront); // adjfront may be dummy
12753                 bond(oldfront, adjfront);
12754                 if (checksubfaces) {
12755                   tspivot(oldfront, checksh);
12756                   if (checksh.sh != dummysh) {
12757                     tsbond(oldfront, checksh);
12758                   }
12759                 }
12760               }
12761               // Delete the new tets of the first flip. Note that one new
12762               //   tet has already been removed from the list.
12763               for (j = 0; j < m - 1; j++) {
12764                 tetrahedrondealloc(newtetlist[j].tet);
12765               }
12766             } // if (success)
12767           } // if (success)
12768         } // if (doflip)
12769       } // if (ori <= 0.0)
12770     } // for (i = 0; i < n; i++)
12771     // Inverse a and b and the tets configuration.
12772     for (i = 0; i < n; i++) newtetlist[i] = abtetlist[i];
12773     for (i = 0; i < n; i++) {
12774       oldfront = newtetlist[n - i - 1];
12775       esymself(oldfront);
12776       fnextself(oldfront);
12777       abtetlist[i] = oldfront;
12778     }
12779     twice++;
12780   } while (twice < 2);
12781 
12782   return false;
12783 }
12784 
12786 //                                                                           //
12787 // splittetrahedron()    Insert a point into a tetrahedron, split it into    //
12788 //                       four tetrahedra.                                    //
12789 //                                                                           //
12790 // The tetrahedron is given by 'splittet'.  Let it is abcd.  The inserting   //
12791 // point 'newpoint' v should lie strictly inside abcd.                       //
12792 //                                                                           //
12793 // Splitting a tetrahedron is to shrink abcd to abcv,  and create three new  //
12794 // tetrahedra badv, cbdv, and acdv.                                          //
12795 //                                                                           //
12796 // On completion, 'splittet' returns abcv.  If 'flipqueue' is not NULL, it   //
12797 // contains all possibly non-locally Delaunay faces.                         //
12798 //                                                                           //
12800 
12801 void tetgenmesh::splittetrahedron(point newpoint, triface* splittet,
12802   queue* flipqueue)
12803 {
12804   triface oldabd, oldbcd, oldcad;                      // Old configuration.
12805   triface abdcasing, bcdcasing, cadcasing;
12806   face abdsh, bcdsh, cadsh;
12807   triface abcv, badv, cbdv, acdv;                      // New configuration.
12808   triface worktet;
12809   face abseg, bcseg, caseg;
12810   face adseg, bdseg, cdseg;
12811   point pa, pb, pc, pd;
12812   REAL attrib, volume;
12813   int i;
12814 
12815   abcv = *splittet;
12816   abcv.ver = 0;
12817   // Set the changed vertices and new tetrahedron.
12818   pa = org(abcv);
12819   pb = dest(abcv);
12820   pc = apex(abcv);
12821   pd = oppo(abcv);
12822 
12823   if (b->verbose > 1) {
12824     printf("  Inserting point %d in tetrahedron (%d, %d, %d, %d).\n",
12825            pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc),
12826            pointmark(pd));
12827   }
12828 
12829   fnext(abcv, oldabd);
12830   enextfnext(abcv, oldbcd);
12831   enext2fnext(abcv, oldcad);
12832   sym(oldabd, abdcasing);
12833   sym(oldbcd, bcdcasing);
12834   sym(oldcad, cadcasing);
12835   maketetrahedron(&badv);
12836   maketetrahedron(&cbdv);
12837   maketetrahedron(&acdv);
12838 
12839   // Set 'badv' vertices.
12840   setorg (badv, pb);
12841   setdest(badv, pa);
12842   setapex(badv, pd);
12843   setoppo(badv, newpoint);
12844   // Set 'cbdv' vertices.
12845   setorg (cbdv, pc);
12846   setdest(cbdv, pb);
12847   setapex(cbdv, pd);
12848   setoppo(cbdv, newpoint);
12849   // Set 'acdv' vertices.
12850   setorg (acdv, pa);
12851   setdest(acdv, pc);
12852   setapex(acdv, pd);
12853   setoppo(acdv, newpoint);
12854   // Set 'abcv' vertices
12855   setoppo(abcv, newpoint);
12856 
12857   // Set the element attributes of the new tetrahedra.
12858   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12859     attrib = elemattribute(abcv.tet, i);
12860     setelemattribute(badv.tet, i, attrib);
12861     setelemattribute(cbdv.tet, i, attrib);
12862     setelemattribute(acdv.tet, i, attrib);
12863   }
12864   // Set the volume constraint of the new tetrahedra.
12865   if (b->varvolume) {
12866     volume = volumebound(abcv.tet);
12867     setvolumebound(badv.tet, volume);
12868     setvolumebound(cbdv.tet, volume);
12869     setvolumebound(acdv.tet, volume);
12870   }
12871 
12872   // Bond the new triangles to the surrounding tetrahedron.
12873   bond(badv, abdcasing);
12874   bond(cbdv, bcdcasing);
12875   bond(acdv, cadcasing);
12876   // There may exist subfaces need to be bonded to the new tetrahedra.
12877   if (checksubfaces) {
12878     tspivot(oldabd, abdsh);
12879     if (abdsh.sh != dummysh) {
12880       tsdissolve(oldabd);
12881       tsbond(badv, abdsh);
12882     }
12883     tspivot(oldbcd, bcdsh);
12884     if (bcdsh.sh != dummysh) {
12885       tsdissolve(oldbcd);
12886       tsbond(cbdv, bcdsh);
12887     }
12888     tspivot(oldcad, cadsh);
12889     if (cadsh.sh != dummysh) {
12890       tsdissolve(oldcad);
12891       tsbond(acdv, cadsh);
12892     }
12893   } else if (checksubsegs) {
12894     tsspivot1(abcv, abseg);
12895     if (abseg.sh != dummysh) {
12896       tssbond1(badv, abseg);
12897     }
12898     enext(abcv, worktet);
12899     tsspivot1(worktet, bcseg);
12900     if (bcseg.sh != dummysh) {
12901       tssbond1(cbdv, bcseg);
12902     }
12903     enext2(abcv, worktet);
12904     tsspivot1(worktet, caseg);
12905     if (caseg.sh != dummysh) {
12906       tssbond1(acdv, caseg);
12907     }
12908     fnext(abcv, worktet);
12909     enext2self(worktet);
12910     tsspivot1(worktet, adseg);
12911     if (adseg.sh != dummysh) {
12912       tssdissolve1(worktet);
12913       enext(badv, worktet);
12914       tssbond1(worktet, adseg);
12915       enext2(acdv, worktet);
12916       tssbond1(worktet, adseg);
12917     }
12918     enextfnext(abcv, worktet);
12919     enext2self(worktet);
12920     tsspivot1(worktet, bdseg);
12921     if (bdseg.sh != dummysh) {
12922       tssdissolve1(worktet);
12923       enext(cbdv, worktet);
12924       tssbond1(worktet, bdseg);
12925       enext2(badv, worktet);
12926       tssbond1(worktet, bdseg);
12927     }
12928     enext2fnext(abcv, worktet);
12929     enext2self(worktet);
12930     tsspivot1(worktet, cdseg);
12931     if (cdseg.sh != dummysh) {
12932       tssdissolve1(worktet);
12933       enext(acdv, worktet);
12934       tssbond1(worktet, cdseg);
12935       enext2(cbdv, worktet);
12936       tssbond1(worktet, cdseg);
12937     }
12938   }
12939   badv.loc = 3;
12940   cbdv.loc = 2;
12941   bond(badv, cbdv);
12942   cbdv.loc = 3;
12943   acdv.loc = 2;
12944   bond(cbdv, acdv);
12945   acdv.loc = 3;
12946   badv.loc = 2;
12947   bond(acdv, badv);
12948   badv.loc = 1;
12949   bond(badv, oldabd);
12950   cbdv.loc = 1;
12951   bond(cbdv, oldbcd);
12952   acdv.loc = 1;
12953   bond(acdv, oldcad);
12954 
12955   badv.loc = 0;
12956   cbdv.loc = 0;
12957   acdv.loc = 0;
12958   if (b->verbose > 3) {
12959     printf("    Updating abcv ");
12960     printtet(&abcv);
12961     printf("    Creating badv ");
12962     printtet(&badv);
12963     printf("    Creating cbdv ");
12964     printtet(&cbdv);
12965     printf("    Creating acdv ");
12966     printtet(&acdv);
12967   }
12968 
12969   if (flipqueue != (queue *) NULL) {
12970     enqueueflipface(abcv, flipqueue);
12971     enqueueflipface(badv, flipqueue);
12972     enqueueflipface(cbdv, flipqueue);
12973     enqueueflipface(acdv, flipqueue);
12974   }
12975 
12976   // Save a handle for quick point location.
12977   recenttet = abcv;
12978   // Set the return handle be abcv.
12979   *splittet = abcv;
12980 }
12981 
12983 //                                                                           //
12984 // unsplittetrahedron()    Reverse the operation of inserting a point into a //
12985 //                         tetrahedron, so as to remove the newly inserted   //
12986 //                         point from the mesh.                              //
12987 //                                                                           //
12988 // Assume the origional tetrahedron is abcd, it was split by v into four     //
12989 // tetrahedra abcv, badv, cbdv, and acdv. 'splittet' represents face abc of  //
12990 // abcv (i.e., its opposite is v).                                           //
12991 //                                                                           //
12992 // Point v is removed by expanding abcv to abcd, deleting three tetrahedra   //
12993 // badv, cbdv and acdv.  On return, point v is not deleted in this routine.  //
12994 //                                                                           //
12996 
12997 void tetgenmesh::unsplittetrahedron(triface* splittet)
12998 {
12999   triface abcv, badv, cbdv, acdv;
13000   triface oldabv, oldbcv, oldcav;
13001   triface badcasing, cbdcasing, acdcasing;
13002   face badsh, cbdsh, acdsh;
13003 
13004   abcv = *splittet;
13005   adjustedgering(abcv, CCW);  // for sure.
13006   fnext(abcv, oldabv);
13007   fnext(oldabv, badv);
13008   esymself(badv);
13009   enextfnext(abcv, oldbcv);
13010   fnext(oldbcv, cbdv);
13011   esymself(cbdv);
13012   enext2fnext(abcv, oldcav);
13013   fnext(oldcav, acdv);
13014   esymself(acdv);
13015 
13016   if (b->verbose > 1) {
13017     printf("  Removing point %d in tetrahedron (%d, %d, %d, %d).\n",
13018            pointmark(oppo(abcv)), pointmark(org(abcv)), pointmark(dest(abcv)),
13019            pointmark(apex(abcv)), pointmark(apex(badv)));
13020   }
13021 
13022   sym(badv, badcasing);
13023   tspivot(badv, badsh);
13024   sym(cbdv, cbdcasing);
13025   tspivot(cbdv, cbdsh);
13026   sym(acdv, acdcasing);
13027   tspivot(acdv, acdsh);
13028 
13029   // Expanding abcv to abcd.
13030   setoppo(abcv, apex(badv));
13031   bond(oldabv, badcasing);
13032   if (badsh.sh != dummysh) {
13033     tsbond(oldabv, badsh);
13034   }
13035   bond(oldbcv, cbdcasing);
13036   if (cbdsh.sh != dummysh) {
13037     tsbond(oldbcv, cbdsh);
13038   }
13039   bond(oldcav, acdcasing);
13040   if (acdsh.sh != dummysh) {
13041     tsbond(oldcav, acdsh);
13042   }
13043 
13044   // Delete the three split-out tetrahedra.
13045   tetrahedrondealloc(badv.tet);
13046   tetrahedrondealloc(cbdv.tet);
13047   tetrahedrondealloc(acdv.tet);
13048 }
13049 
13051 //                                                                           //
13052 // splittetface()    Insert a point on a face of a mesh.                     //
13053 //                                                                           //
13054 // 'splittet' is the splitting face.  Let it is abcd, where abc is the face  //
13055 // will be split. If abc is not a hull face, abce is the tetrahedron at the  //
13056 // opposite of d.                                                            //
13057 //                                                                           //
13058 // To split face abc by a point v is to shrink the tetrahedra abcd to abvd,  //
13059 // create two new tetrahedra bcvd, cavd.  If abc is not a hull face, shrink  //
13060 // the tetrahedra bace to bave, create two new tetrahedra cbve, acve.        //
13061 //                                                                           //
13062 // If abc is a subface, it is split into three subfaces simultaneously by    //
13063 // calling routine splitsubface(), hence, abv, bcv, cav.  The edge rings of  //
13064 // the split subfaces have the same orientation as abc's.                    //
13065 //                                                                           //
13066 // On completion, 'splittet' returns abvd.  If 'flipqueue' is not NULL, it   //
13067 // contains all possibly non-locally Delaunay faces.                         //
13068 //                                                                           //
13070 
13071 void tetgenmesh::splittetface(point newpoint, triface* splittet,
13072   queue* flipqueue)
13073 {
13074   triface abcd, bace;                                  // Old configuration.
13075   triface oldbcd, oldcad, oldace, oldcbe;
13076   triface bcdcasing, cadcasing, acecasing, cbecasing;
13077   face abcsh, bcdsh, cadsh, acesh, cbesh;
13078   triface abvd, bcvd, cavd, bave, cbve, acve;          // New configuration.
13079   triface worktet;
13080   face bcseg, caseg;
13081   face adseg, bdseg, cdseg;
13082   face aeseg, beseg, ceseg;
13083   point pa, pb, pc, pd, pe;
13084   REAL attrib, volume;
13085   bool mirrorflag;
13086   int i;
13087 
13088   abcd = *splittet;
13089   // abcd.ver = 0; // Adjust to be CCW edge ring.
13090   adjustedgering(abcd, CCW);
13091   pa = org(abcd);
13092   pb = dest(abcd);
13093   pc = apex(abcd);
13094   pd = oppo(abcd);
13095   pe = (point) NULL; // avoid a compile warning.
13096   // Is there a second tetrahderon?
13097   mirrorflag = issymexist(&abcd);
13098   if (mirrorflag) {
13099     // This is an interior face.
13100     sym(abcd, bace);
13101     findedge(&bace, dest(abcd), org(abcd));
13102     pe = oppo(bace);
13103   }
13104   if (checksubfaces) {
13105     // Is there a subface need to be split together?
13106     tspivot(abcd, abcsh);
13107     if (abcsh.sh != dummysh) {
13108       // Exists! Keep the edge ab of both handles be the same.
13109       findedge(&abcsh, org(abcd), dest(abcd));
13110     }
13111   }
13112 
13113   if (b->verbose > 1) {
13114     printf("  Inserting point %d on face (%d, %d, %d).\n", pointmark(newpoint),
13115            pointmark(pa), pointmark(pb), pointmark(pc));
13116   }
13117 
13118   // Save the old configuration at faces bcd and cad.
13119   enextfnext(abcd, oldbcd);
13120   enext2fnext(abcd, oldcad);
13121   sym(oldbcd, bcdcasing);
13122   sym(oldcad, cadcasing);
13123   // Create two new tetrahedra.
13124   maketetrahedron(&bcvd);
13125   maketetrahedron(&cavd);
13126   if (mirrorflag) {
13127     // Save the old configuration at faces bce and cae.
13128     enextfnext(bace, oldace);
13129     enext2fnext(bace, oldcbe);
13130     sym(oldace, acecasing);
13131     sym(oldcbe, cbecasing);
13132     // Create two new tetrahedra.
13133     maketetrahedron(&acve);
13134     maketetrahedron(&cbve);
13135   } else {
13136     // Splitting a boundary face increases the number of boundary faces.
13137     hullsize += 2;
13138   }
13139 
13140   // Set vertices to the changed tetrahedron and new tetrahedra.
13141   abvd = abcd;  // Update 'abcd' to 'abvd'.
13142   setapex(abvd, newpoint);
13143   setorg (bcvd, pb);  // Set 'bcvd'.
13144   setdest(bcvd, pc);
13145   setapex(bcvd, newpoint);
13146   setoppo(bcvd, pd);
13147   setorg (cavd, pc);  // Set 'cavd'.
13148   setdest(cavd, pa);
13149   setapex(cavd, newpoint);
13150   setoppo(cavd, pd);
13151   // Set the element attributes of the new tetrahedra.
13152   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13153     attrib = elemattribute(abvd.tet, i);
13154     setelemattribute(bcvd.tet, i, attrib);
13155     setelemattribute(cavd.tet, i, attrib);
13156   }
13157   if (b->varvolume) {
13158     // Set the area constraint of the new tetrahedra.
13159     volume = volumebound(abvd.tet);
13160     setvolumebound(bcvd.tet, volume);
13161     setvolumebound(cavd.tet, volume);
13162   }
13163   if (mirrorflag) {
13164     bave = bace;  // Update 'bace' to 'bave'.
13165     setapex(bave, newpoint);
13166     setorg (acve, pa);  // Set 'acve'.
13167     setdest(acve, pc);
13168     setapex(acve, newpoint);
13169     setoppo(acve, pe);
13170     setorg (cbve, pc);  // Set 'cbve'.
13171     setdest(cbve, pb);
13172     setapex(cbve, newpoint);
13173     setoppo(cbve, pe);
13174     // Set the element attributes of the new tetrahedra.
13175     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13176       attrib = elemattribute(bave.tet, i);
13177       setelemattribute(acve.tet, i, attrib);
13178       setelemattribute(cbve.tet, i, attrib);
13179     }
13180     if (b->varvolume) {
13181       // Set the area constraint of the new tetrahedra.
13182       volume = volumebound(bave.tet);
13183       setvolumebound(acve.tet, volume);
13184       setvolumebound(cbve.tet, volume);
13185     }
13186   }
13187 
13188   // Bond the new tetrahedra to the surrounding tetrahedra.
13189   bcvd.loc = 1;
13190   bond(bcvd, bcdcasing);
13191   cavd.loc = 1;
13192   bond(cavd, cadcasing);
13193   bcvd.loc = 3;
13194   bond(bcvd, oldbcd);
13195   cavd.loc = 2;
13196   bond(cavd, oldcad);
13197   bcvd.loc = 2;
13198   cavd.loc = 3;
13199   bond(bcvd, cavd);
13200   if (mirrorflag) {
13201     acve.loc = 1;
13202     bond(acve, acecasing);
13203     cbve.loc = 1;
13204     bond(cbve, cbecasing);
13205     acve.loc = 3;
13206     bond(acve, oldace);
13207     cbve.loc = 2;
13208     bond(cbve, oldcbe);
13209     acve.loc = 2;
13210     cbve.loc = 3;
13211     bond(acve, cbve);
13212     // Bond two new coplanar facets.
13213     bcvd.loc = 0;
13214     cbve.loc = 0;
13215     bond(bcvd, cbve);
13216     cavd.loc = 0;
13217     acve.loc = 0;
13218     bond(cavd, acve);
13219   }
13220 
13221   // There may exist subface needed to be bonded to the new tetrahedra.
13222   if (checksubfaces) {
13223     tspivot(oldbcd, bcdsh);
13224     if (bcdsh.sh != dummysh) {
13225       tsdissolve(oldbcd);
13226       bcvd.loc = 1;
13227       tsbond(bcvd, bcdsh);
13228     }
13229     tspivot(oldcad, cadsh);
13230     if (cadsh.sh != dummysh) {
13231       tsdissolve(oldcad);
13232       cavd.loc = 1;
13233       tsbond(cavd, cadsh);
13234     }
13235     if (mirrorflag) {
13236       tspivot(oldace, acesh);
13237       if (acesh.sh != dummysh) {
13238         tsdissolve(oldace);
13239         acve.loc = 1;
13240         tsbond(acve, acesh);
13241       }
13242       tspivot(oldcbe, cbesh);
13243       if (cbesh.sh != dummysh) {
13244         tsdissolve(oldcbe);
13245         cbve.loc = 1;
13246         tsbond(cbve, cbesh);
13247       }
13248     }
13249     // Is there a subface needs to be split together?
13250     if (abcsh.sh != dummysh) {
13251       // Split this subface 'abc' into three i.e, abv, bcv, cav.
13252       splitsubface(newpoint, &abcsh, (queue *) NULL);
13253     }
13254   } else if (checksubsegs) {
13255     // abvd.loc = abvd.ver = 0;
13256     bcvd.loc = bcvd.ver = 0;
13257     cavd.loc = cavd.ver = 0;
13258     if (mirrorflag) {
13259       // bave.loc = bave.ver = 0;
13260       cbve.loc = cbve.ver = 0;
13261       acve.loc = acve.ver = 0;
13262     }
13263     enext(abvd, worktet);
13264     tsspivot1(worktet, bcseg);
13265     if (bcseg.sh != dummysh) {
13266       tssdissolve1(worktet);
13267       tssbond1(bcvd, bcseg);
13268       if (mirrorflag) {
13269         enext2(bave, worktet);
13270         tssdissolve1(worktet);
13271         tssbond1(cbve, bcseg);
13272       }
13273     }
13274     enext2(abvd, worktet);
13275     tsspivot1(worktet, caseg);
13276     if (caseg.sh != dummysh) {
13277       tssdissolve1(worktet);
13278       tssbond1(cavd, caseg);
13279       if (mirrorflag) {
13280         enext(bave, worktet);
13281         tssdissolve1(worktet);
13282         tssbond1(acve, caseg);
13283       }
13284     }
13285     fnext(abvd, worktet);
13286     enext2self(worktet);
13287     tsspivot1(worktet, adseg);
13288     if (adseg.sh != dummysh) {
13289       fnext(cavd, worktet);
13290       enextself(worktet);
13291       tssbond1(worktet, adseg);
13292     }
13293     fnext(abvd, worktet);
13294     enextself(worktet);
13295     tsspivot1(worktet, bdseg);
13296     if (bdseg.sh != dummysh) {
13297       fnext(bcvd, worktet);
13298       enext2self(worktet);
13299       tssbond1(worktet, bdseg);
13300     }
13301     enextfnext(abvd, worktet);
13302     enextself(worktet);
13303     tsspivot1(worktet, cdseg);
13304     if (cdseg.sh != dummysh) {
13305       tssdissolve1(worktet);
13306       fnext(bcvd, worktet);
13307       enextself(worktet);
13308       tssbond1(worktet, cdseg);
13309       fnext(cavd, worktet);
13310       enext2self(worktet);
13311       tssbond1(worktet, cdseg);
13312     }
13313     if (mirrorflag) {
13314       fnext(bave, worktet);
13315       enextself(worktet);
13316       tsspivot1(worktet, aeseg);
13317       if (aeseg.sh != dummysh) {
13318         fnext(acve, worktet);
13319         enext2self(worktet);
13320         tssbond1(worktet, aeseg);
13321       }
13322       fnext(bave, worktet);
13323       enext2self(worktet);
13324       tsspivot1(worktet, beseg);
13325       if (beseg.sh != dummysh) {
13326         fnext(cbve, worktet);
13327         enextself(worktet);
13328         tssbond1(worktet, beseg);
13329       }
13330       enextfnext(bave, worktet);
13331       enextself(worktet);
13332       tsspivot1(worktet, ceseg);
13333       if (ceseg.sh != dummysh) {
13334         tssdissolve1(worktet);
13335         fnext(cbve, worktet);
13336         enext2self(worktet);
13337         tssbond1(worktet, ceseg);
13338         fnext(acve, worktet);
13339         enextself(worktet);
13340         tssbond1(worktet, ceseg);
13341       }
13342     }
13343   }
13344 
13345   // Save a handle for quick point location.
13346   recenttet = abvd;
13347   // Set the return handle be abvd.
13348   *splittet = abvd;
13349 
13350   bcvd.loc = 0;
13351   cavd.loc = 0;
13352   if (mirrorflag) {
13353     cbve.loc = 0;
13354     acve.loc = 0;
13355   }
13356   if (b->verbose > 3) {
13357     printf("    Updating abvd ");
13358     printtet(&abvd);
13359     printf("    Creating bcvd ");
13360     printtet(&bcvd);
13361     printf("    Creating cavd ");
13362     printtet(&cavd);
13363     if (mirrorflag) {
13364       printf("    Updating bave ");
13365       printtet(&bave);
13366       printf("    Creating cbve ");
13367       printtet(&cbve);
13368       printf("    Creating acve ");
13369       printtet(&acve);
13370     }
13371   }
13372 
13373   if (flipqueue != (queue *) NULL) {
13374     fnextself(abvd);
13375     enqueueflipface(abvd, flipqueue);
13376     fnextself(bcvd);
13377     enqueueflipface(bcvd, flipqueue);
13378     fnextself(cavd);
13379     enqueueflipface(cavd, flipqueue);
13380     if (mirrorflag) {
13381       fnextself(bave);
13382       enqueueflipface(bave, flipqueue);
13383       fnextself(cbve);
13384       enqueueflipface(cbve, flipqueue);
13385       fnextself(acve);
13386       enqueueflipface(acve, flipqueue);
13387     }
13388   }
13389 }
13390 
13392 //                                                                           //
13393 // unsplittetface()    Reverse the operation of inserting a point on a face, //
13394 //                     so as to remove the newly inserted point.             //
13395 //                                                                           //
13396 // Assume the original face is abc, the tetrahedron containing abc is abcd.  //
13397 // If abc is not a hull face, bace is the tetrahedron at the opposite of d.  //
13398 // After face abc was split by a point v, tetrahedron abcd had been split    //
13399 // into three tetrahedra, abvd, bcvd, cavd, and bace (if it exists) had been //
13400 // split into bave, cbve, acve. 'splittet' represents abvd (its apex is v).  //
13401 //                                                                           //
13402 // Point v is removed by expanding abvd to abcd, deleting two tetrahedra     //
13403 // bcvd, cavd. Expanding bave(if it exists) to bace, deleting two tetrahedra //
13404 // cbve, acve.  If abv is a subface, routine unsplitsubface() will be called //
13405 // to reverse the operation of splitting a subface. On completion, point v   //
13406 // is not deleted in this routine.                                           //
13407 //                                                                           //
13409 
13410 void tetgenmesh::unsplittetface(triface* splittet)
13411 {
13412   triface abvd, bcvd, cavd, bave, cbve, acve;
13413   triface oldbvd, oldvad, oldvbe, oldave;
13414   triface bcdcasing, cadcasing, cbecasing, acecasing;
13415   face bcdsh, cadsh, cbesh, acesh;
13416   face abvsh;
13417   bool mirrorflag;
13418 
13419   abvd = *splittet;
13420   adjustedgering(abvd, CCW); // for sure.
13421   enextfnext(abvd, oldbvd);
13422   fnext(oldbvd, bcvd);
13423   esymself(bcvd);
13424   enextself(bcvd);
13425   enext2fnext(abvd, oldvad);
13426   fnext(oldvad, cavd);
13427   esymself(cavd);
13428   enext2self(cavd);
13429   // Is there a second tetrahedron?
13430   sym(abvd, bave);
13431   mirrorflag = bave.tet != dummytet;
13432   if (mirrorflag) {
13433     findedge(&bave, dest(abvd), org(abvd));
13434     enextfnext(bave, oldave);
13435     fnext(oldave, acve);
13436     esymself(acve);
13437     enextself(acve);
13438     enext2fnext(bave, oldvbe);
13439     fnext(oldvbe, cbve);
13440     esymself(cbve);
13441     enext2self(cbve);
13442   } else {
13443     // Unsplit a hull face decrease the number of boundary faces.
13444     hullsize -= 2;
13445   }
13446   // Is there a subface at abv.
13447   tspivot(abvd, abvsh);
13448   if (abvsh.sh != dummysh) {
13449     // Exists! Keep the edge ab of both handles be the same.
13450     findedge(&abvsh, org(abvd), dest(abvd));
13451   }
13452 
13453   if (b->verbose > 1) {
13454     printf("  Removing point %d on face (%d, %d, %d).\n",
13455            pointmark(apex(abvd)), pointmark(org(abvd)), pointmark(dest(abvd)),
13456            pointmark(dest(bcvd)));
13457   }
13458 
13459   fnextself(bcvd); // bcvd has changed to bcdv.
13460   sym(bcvd, bcdcasing);
13461   tspivot(bcvd, bcdsh);
13462   fnextself(cavd); // cavd has changed to cadv.
13463   sym(cavd, cadcasing);
13464   tspivot(cavd, cadsh);
13465   if (mirrorflag) {
13466     fnextself(acve); // acve has changed to acev.
13467     sym(acve, acecasing);
13468     tspivot(acve, acesh);
13469     fnextself(cbve); // cbve has changed to cbev.
13470     sym(cbve, cbecasing);
13471     tspivot(cbve, cbesh);
13472   }
13473 
13474   // Expand abvd to abcd.
13475   setapex(abvd, dest(bcvd));
13476   bond(oldbvd, bcdcasing);
13477   if (bcdsh.sh != dummysh) {
13478     tsbond(oldbvd, bcdsh);
13479   }
13480   bond(oldvad, cadcasing);
13481   if (cadsh.sh != dummysh) {
13482     tsbond(oldvad, cadsh);
13483   }
13484   if (mirrorflag) {
13485     // Expanding bave to bace.
13486     setapex(bave, dest(acve));
13487     bond(oldave, acecasing);
13488     if (acesh.sh != dummysh) {
13489       tsbond(oldave, acesh);
13490     }
13491     bond(oldvbe, cbecasing);
13492     if (cbesh.sh != dummysh) {
13493       tsbond(oldvbe, cbesh);
13494     }
13495   }
13496 
13497   // Unsplit a subface if there exists.
13498   if (abvsh.sh != dummysh) {
13499     unsplitsubface(&abvsh);
13500   }
13501 
13502   // Delete the split-out tetrahedra.
13503   tetrahedrondealloc(bcvd.tet);
13504   tetrahedrondealloc(cavd.tet);
13505   if (mirrorflag) {
13506     tetrahedrondealloc(acve.tet);
13507     tetrahedrondealloc(cbve.tet);
13508   }
13509 }
13510 
13512 //                                                                           //
13513 // splitsubface()    Insert a point on a subface, split it into three.       //
13514 //                                                                           //
13515 // The subface is 'splitface'.  Let it is abc. The inserting point 'newpoint'//
13516 // v should lie inside abc.  If the neighbor tetrahedra of abc exist, i.e.,  //
13517 // abcd and bace, they should have been split by routine splittetface()      //
13518 // before calling this routine, so the connection between the new tetrahedra //
13519 // and new subfaces can be correctly set.                                    //
13520 //                                                                           //
13521 // To split subface abc by point v is to shrink abc to abv, create two new   //
13522 // subfaces bcv and cav.  Set the connection between updated and new created //
13523 // subfaces. If there is a subsegment at edge bc or ca, connection of new    //
13524 // subface (bcv or cav) to its casing subfaces is a face link, 'casingin' is //
13525 // the predecessor and 'casingout' is the successor. It is important to keep //
13526 // the orientations of the edge rings of the updated and created subfaces be //
13527 // the same as abc's. So they have the same orientation as other subfaces of //
13528 // this facet with respect to the lift point of this facet.                  //
13529 //                                                                           //
13530 // On completion, 'splitface' returns abv.  If 'flipqueue' is not NULL, it   //
13531 // returns all possibly non-Delaunay edges.                                  //
13532 //                                                                           //
13534 
13535 void tetgenmesh::splitsubface(point newpoint, face* splitface,
13536   queue* flipqueue)
13537 {
13538   triface abvd, bcvd, cavd, bave, cbve, acve;
13539   face abc, oldbc, oldca, bc, ca, spinsh;
13540   face bccasin, bccasout, cacasin, cacasout;
13541   face abv, bcv, cav;
13542   point pa, pb, pc;
13543 
13544   abc = *splitface;
13545   // The newly created subfaces will have the same edge ring as abc.
13546   adjustedgering(abc, CCW);
13547   pa = sorg(abc);
13548   pb = sdest(abc);
13549   pc = sapex(abc);
13550 
13551   if (b->verbose > 1) {
13552     printf("  Inserting point %d on subface (%d, %d, %d).\n",
13553            pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc));
13554   }
13555 
13556   // Save the old configuration at edge bc and ca.  Subsegments may appear
13557   //   at both sides, save the face links and dissolve them.
13558   senext(abc, oldbc);
13559   senext2(abc, oldca);
13560   spivot(oldbc, bccasout);
13561   sspivot(oldbc, bc);
13562   if (bc.sh != dummysh) {
13563     if (oldbc.sh != bccasout.sh) {
13564       // 'oldbc' is not self-bonded.
13565       spinsh = bccasout;
13566       do {
13567         bccasin = spinsh;
13568         spivotself(spinsh);
13569       } while (spinsh.sh != oldbc.sh);
13570     } else {
13571       bccasout.sh = dummysh;
13572     }
13573     ssdissolve(oldbc);
13574   }
13575   spivot(oldca, cacasout);
13576   sspivot(oldca, ca);
13577   if (ca.sh != dummysh) {
13578     if (oldca.sh != cacasout.sh) {
13579       // 'oldca' is not self-bonded.
13580       spinsh = cacasout;
13581       do {
13582         cacasin = spinsh;
13583         spivotself(spinsh);
13584       } while (spinsh.sh != oldca.sh);
13585     } else {
13586       cacasout.sh = dummysh;
13587     }
13588     ssdissolve(oldca);
13589   }
13590   // Create two new subfaces.
13591   makeshellface(subfaces, &bcv);
13592   makeshellface(subfaces, &cav);
13593 
13594   // Set the vertices of changed and new subfaces.
13595   abv = abc;  // Update 'abc' to 'abv'.
13596   setsapex(abv, newpoint);
13597   setsorg(bcv, pb);  // Set 'bcv'.
13598   setsdest(bcv, pc);
13599   setsapex(bcv, newpoint);
13600   setsorg(cav, pc);  // Set 'cav'.
13601   setsdest(cav, pa);
13602   setsapex(cav, newpoint);
13603   if (b->quality && varconstraint) {
13604     // Copy yhr area bound into the new subfaces.
13605     setareabound(bcv, areabound(abv));
13606     setareabound(cav, areabound(abv));
13607   }
13608   // Copy the boundary mark into the new subfaces.
13609   setshellmark(bcv, shellmark(abv));
13610   setshellmark(cav, shellmark(abv));
13611   // Copy the subface type into the new subfaces.
13612   setshelltype(bcv, shelltype(abv));
13613   setshelltype(cav, shelltype(abv));
13614   if (checkpbcs) {
13615     // Copy the pbcgroup into the new subfaces.
13616     setshellpbcgroup(bcv, shellpbcgroup(abv));
13617     setshellpbcgroup(cav, shellpbcgroup(abv));
13618   }
13619   // Bond the new subfaces to the surrounding subfaces.
13620   if (bc.sh != dummysh) {
13621     if (bccasout.sh != dummysh) {
13622       sbond1(bccasin, bcv);
13623       sbond1(bcv, bccasout);
13624     } else {
13625       // Bond 'bcv' to itsself.
13626       sbond(bcv, bcv);
13627     }
13628     ssbond(bcv, bc);
13629   } else {
13630     sbond(bcv, bccasout);
13631   }
13632   if (ca.sh != dummysh) {
13633     if (cacasout.sh != dummysh) {
13634       sbond1(cacasin, cav);
13635       sbond1(cav, cacasout);
13636     } else {
13637       // Bond 'cav' to itself.
13638       sbond(cav, cav);
13639     }
13640     ssbond(cav, ca);
13641   } else {
13642     sbond(cav, cacasout);
13643   }
13644   senext2self(bcv);
13645   sbond(bcv, oldbc);
13646   senextself(cav);
13647   sbond(cav, oldca);
13648   senext2self(bcv);
13649   senextself(cav);
13650   sbond(bcv, cav);
13651 
13652   // Bond the new subfaces to the new tetrahedra if they exist.
13653   stpivot(abv, abvd);
13654   if (abvd.tet != dummytet) {
13655     // Get two new tetrahedra and their syms.
13656     findedge(&abvd, sorg(abv), sdest(abv));
13657     enextfnext(abvd, bcvd);
13658 #ifdef SELF_CHECK
13659     assert(bcvd.tet != dummytet);
13660 #endif
13661     fnextself(bcvd);
13662     enext2fnext(abvd, cavd);
13663 #ifdef SELF_CHECK
13664     assert(cavd.tet != dummytet);
13665 #endif
13666     fnextself(cavd);
13667     // Bond two new subfaces to the two new tetrahedra.
13668     tsbond(bcvd, bcv);
13669     tsbond(cavd, cav);
13670   }
13671   // Set the connection at the other sides if the tetrahedra exist.
13672   sesymself(abv);  // bav
13673   stpivot(abv, bave);
13674   if (bave.tet != dummytet) {
13675     sesymself(bcv);  // cbv
13676     sesymself(cav);  // acv
13677     // Get two new tetrahedra and their syms.
13678     findedge(&bave, sorg(abv), sdest(abv));
13679     enextfnext(bave, acve);
13680 #ifdef SELF_CHECK
13681     assert(acve.tet != dummytet);
13682 #endif
13683     fnextself(acve);
13684     enext2fnext(bave, cbve);
13685 #ifdef SELF_CHECK
13686     assert(cbve.tet != dummytet);
13687 #endif
13688     fnextself(cbve);
13689     // Bond two new subfaces to the two new tetrahedra.
13690     tsbond(acve, cav);
13691     tsbond(cbve, bcv);
13692   }
13693 
13694   bcv.shver = 0;
13695   cav.shver = 0;
13696   if (b->verbose > 3) {
13697     printf("    Updating abv ");
13698     printsh(&abv);
13699     printf("    Creating bcv ");
13700     printsh(&bcv);
13701     printf("    Creating cav ");
13702     printsh(&cav);
13703   }
13704 
13705   if (flipqueue != (queue *) NULL) {
13706     enqueueflipedge(abv, flipqueue);
13707     enqueueflipedge(bcv, flipqueue);
13708     enqueueflipedge(cav, flipqueue);
13709   }
13710 
13711   // Set the return handle be abv.
13712   *splitface = abv;
13713 }
13714 
13716 //                                                                           //
13717 // unsplitsubface()    Reverse the operation of inserting a point on a       //
13718 //                     subface, so as to remove the newly inserted point.    //
13719 //                                                                           //
13720 // Assume the original subface is abc, it was split by a point v into three  //
13721 // subfaces abv, bcv and cav.  'splitsh' represents abv.                     //
13722 //                                                                           //
13723 // To remove point v is to expand abv to abc, delete bcv and cav. If edge bc //
13724 // or ca is a subsegment,  the connection at a subsegment is a subface link, //
13725 // '-casin' and '-casout' are used to save the predecessor and successor of  //
13726 // bcv or cav.  On completion, point v is not deleted in this routine.       //
13727 //                                                                           //
13729 
13730 void tetgenmesh::unsplitsubface(face* splitsh)
13731 {
13732   face abv, bcv, cav;
13733   face oldbv, oldva, bc, ca, spinsh;
13734   face bccasin, bccasout, cacasin, cacasout;
13735 
13736   abv = *splitsh;
13737   senext(abv, oldbv);
13738   spivot(oldbv, bcv);
13739   if (sorg(bcv) != sdest(oldbv)) {
13740     sesymself(bcv);
13741   }
13742   senextself(bcv);
13743   senext2(abv, oldva);
13744   spivot(oldva, cav);
13745   if (sorg(cav) != sdest(oldva)) {
13746     sesymself(cav);
13747   }
13748   senext2self(cav);
13749 
13750   if (b->verbose > 1) {
13751     printf("  Removing point %d on subface (%d, %d, %d).\n",
13752            pointmark(sapex(abv)), pointmark(sorg(abv)), pointmark(sdest(abv)),
13753            pointmark(sdest(bcv)));
13754   }
13755 
13756   spivot(bcv, bccasout);
13757   sspivot(bcv, bc);
13758   if (bc.sh != dummysh) {
13759     if (bcv.sh != bccasout.sh) {
13760       // 'bcv' is not self-bonded.
13761       spinsh = bccasout;
13762       do {
13763         bccasin = spinsh;
13764         spivotself(spinsh);
13765       } while (spinsh.sh != bcv.sh);
13766     } else {
13767       bccasout.sh = dummysh;
13768     }
13769   }
13770   spivot(cav, cacasout);
13771   sspivot(cav, ca);
13772   if (ca.sh != dummysh) {
13773     if (cav.sh != cacasout.sh) {
13774       // 'cav' is not self-bonded.
13775       spinsh = cacasout;
13776       do {
13777        cacasin = spinsh;
13778        spivotself(spinsh);
13779       } while (spinsh.sh != cav.sh);
13780     } else {
13781       cacasout.sh = dummysh;
13782     }
13783   }
13784 
13785   // Expand abv to abc.
13786   setsapex(abv, sdest(bcv));
13787   if (bc.sh != dummysh) {
13788     if (bccasout.sh != dummysh) {
13789       sbond1(bccasin, oldbv);
13790       sbond1(oldbv, bccasout);
13791     } else {
13792       // Bond 'oldbv' to itself.
13793       sbond(oldbv, oldbv);
13794     }
13795     ssbond(oldbv, bc);
13796   } else {
13797     sbond(oldbv, bccasout);
13798   }
13799   if (ca.sh != dummysh) {
13800     if (cacasout.sh != dummysh) {
13801       sbond1(cacasin, oldva);
13802       sbond1(oldva, cacasout);
13803     } else {
13804       // Bond 'oldva' to itself.
13805       sbond(oldva, oldva);
13806     }
13807     ssbond(oldva, ca);
13808   } else {
13809     sbond(oldva, cacasout);
13810   }
13811 
13812   // Delete two split-out subfaces.
13813   shellfacedealloc(subfaces, bcv.sh);
13814   shellfacedealloc(subfaces, cav.sh);
13815 }
13816 
13818 //                                                                           //
13819 // splittetedge()    Insert a point on an edge of the mesh.                  //
13820 //                                                                           //
13821 // The edge is given by 'splittet'. Assume its four corners are a, b, n1 and //
13822 // n2, where ab is the edge will be split. Around ab may exist any number of //
13823 // tetrahedra. For convenience, they're ordered in a sequence following the  //
13824 // right-hand rule with your thumb points from a to b. Let the vertex set of //
13825 // these tetrahedra be {a, b, n1, n2, ..., n(i)}. NOTE the tetrahedra around //
13826 // ab may not connect to each other (can only happen when ab is a subsegment,//
13827 // hence some faces abn(i) are subfaces).  If ab is a subsegment, abn1 must  //
13828 // be a subface.                                                             //
13829 //                                                                           //
13830 // To split edge ab by a point v is to split all tetrahedra containing ab by //
13831 // v.  More specifically, for each such tetrahedron, an1n2b, it is shrunk to //
13832 // an1n2v, and a new tetrahedra bn2n1v is created. If ab is a subsegment, or //
13833 // some faces of the splitting tetrahedra are subfaces, they must be split   //
13834 // either by calling routine 'splitsubedge()'.                               //
13835 //                                                                           //
13836 // On completion, 'splittet' returns avn1n2.  If 'flipqueue' is not NULL, it //
13837 // returns all faces which may become non-Delaunay after this operation.     //
13838 //                                                                           //
13840 
13841 void tetgenmesh::splittetedge(point newpoint, triface* splittet,
13842   queue* flipqueue)
13843 {
13844   triface *bots, *newtops;
13845   triface oldtop, topcasing;
13846   triface spintet, tmpbond0, tmpbond1;
13847   face abseg, splitsh, topsh, spinsh;
13848   triface worktet;
13849   face n1n2seg, n2vseg, n1vseg;
13850   point pa, pb, n1, n2;
13851   REAL attrib, volume;
13852   int wrapcount, hitbdry;
13853   int i, j;
13854 
13855   if (checksubfaces) {
13856     // Is there a subsegment need to be split together?
13857     tsspivot(splittet, &abseg);
13858     if (abseg.sh != dummysh) {
13859       abseg.shver = 0;
13860       // Orient the edge direction of 'splittet' be abseg.
13861       if (org(*splittet) != sorg(abseg)) {
13862         esymself(*splittet);
13863       }
13864     }
13865   }
13866   spintet = *splittet;
13867   pa = org(spintet);
13868   pb = dest(spintet);
13869 
13870   if (b->verbose > 1) {
13871     printf("  Inserting point %d on edge (%d, %d).\n",
13872            pointmark(newpoint), pointmark(pa), pointmark(pb));
13873   }
13874 
13875   // Collect the tetrahedra containing the splitting edge (ab).
13876   n1 = apex(spintet);
13877   hitbdry = 0;
13878   wrapcount = 1;
13879   if (checksubfaces && abseg.sh != dummysh) {
13880     // It may happen that some tetrahedra containing ab (a subsegment) are
13881     //   completely disconnected with others. If it happens, use the face
13882     //   link of ab to cross the boundary.
13883     while (true) {
13884       if (!fnextself(spintet)) {
13885         // Meet a boundary, walk through it.
13886         hitbdry ++;
13887         tspivot(spintet, spinsh);
13888 #ifdef SELF_CHECK
13889         assert(spinsh.sh != dummysh);
13890 #endif
13891         findedge(&spinsh, pa, pb);
13892         sfnextself(spinsh);
13893         stpivot(spinsh, spintet);
13894 #ifdef SELF_CHECK
13895         assert(spintet.tet != dummytet);
13896 #endif
13897         findedge(&spintet, pa, pb);
13898         // Remember this position (hull face) in 'splittet'.
13899         *splittet = spintet;
13900         // Split two hull faces increase the hull size;
13901         hullsize += 2;
13902       }
13903       if (apex(spintet) == n1) break;
13904       wrapcount ++;
13905     }
13906     if (hitbdry > 0) {
13907       wrapcount -= hitbdry;
13908     }
13909   } else {
13910     // All the tetrahedra containing ab are connected together. If there
13911     //   are subfaces, 'splitsh' keeps one of them.
13912     splitsh.sh = dummysh;
13913     while (hitbdry < 2) {
13914       if (checksubfaces && splitsh.sh == dummysh) {
13915         tspivot(spintet, splitsh);
13916       }
13917       if (fnextself(spintet)) {
13918         if (apex(spintet) == n1) break;
13919         wrapcount++;
13920       } else {
13921         hitbdry ++;
13922         if (hitbdry < 2) {
13923           esym(*splittet, spintet);
13924         }
13925       }
13926     }
13927     if (hitbdry > 0) {
13928       // ab is on the hull.
13929       wrapcount -= 1;
13930       // 'spintet' now is a hull face, inverse its edge direction.
13931       esym(spintet, *splittet);
13932       // Split two hull faces increases the number of hull faces.
13933       hullsize += 2;
13934     }
13935   }
13936 
13937   // Make arrays of updating (bot, oldtop) and new (newtop) tetrahedra.
13938   bots = new triface[wrapcount];
13939   newtops = new triface[wrapcount];
13940   // Spin around ab, gather tetrahedra and set up new tetrahedra.
13941   spintet = *splittet;
13942   for (i = 0; i < wrapcount; i++) {
13943     // Get 'bots[i] = an1n2b'.
13944     enext2fnext(spintet, bots[i]);
13945     esymself(bots[i]);
13946     // Create 'newtops[i]'.
13947     maketetrahedron(&(newtops[i]));
13948     // Go to the next.
13949     fnextself(spintet);
13950     if (checksubfaces && abseg.sh != dummysh) {
13951       if (!issymexist(&spintet)) {
13952         // We meet a hull face, walk through it.
13953         tspivot(spintet, spinsh);
13954 #ifdef SELF_CHECK
13955         assert(spinsh.sh != dummysh);
13956 #endif
13957         findedge(&spinsh, pa, pb);
13958         sfnextself(spinsh);
13959         stpivot(spinsh, spintet);
13960 #ifdef SELF_CHECK
13961         assert(spintet.tet != dummytet);
13962 #endif
13963         findedge(&spintet, pa, pb);
13964       }
13965     }
13966   }
13967 
13968   // Set the vertices of updated and new tetrahedra.
13969   for (i = 0; i < wrapcount; i++) {
13970     // Update 'bots[i] = an1n2v'.
13971     setoppo(bots[i], newpoint);
13972     // Set 'newtops[i] = bn2n1v'.
13973     n1 = dest(bots[i]);
13974     n2 = apex(bots[i]);
13975     // Set 'newtops[i]'.
13976     setorg(newtops[i], pb);
13977     setdest(newtops[i], n2);
13978     setapex(newtops[i], n1);
13979     setoppo(newtops[i], newpoint);
13980     // Set the element attributes of a new tetrahedron.
13981     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
13982       attrib = elemattribute(bots[i].tet, j);
13983       setelemattribute(newtops[i].tet, j, attrib);
13984     }
13985     if (b->varvolume) {
13986       // Set the area constraint of a new tetrahedron.
13987       volume = volumebound(bots[i].tet);
13988       setvolumebound(newtops[i].tet, volume);
13989     }
13990 #ifdef SELF_CHECK
13991     // Make sure no inversed tetrahedron has been created.
13992     // volume = orient3d(pa, n1, n2, newpoint);
13993     // if (volume >= 0.0) {
13994     //   printf("Internal error in splittetedge(): volume = %.12g.\n", volume);
13995     // }
13996     // volume = orient3d(pb, n2, n1, newpoint);
13997     // if (volume >= 0.0) {
13998     //   printf("Internal error in splittetedge(): volume = %.12g.\n", volume);
13999     // }
14000 #endif
14001   }
14002 
14003   // Bond newtops to topcasings and bots.
14004   for (i = 0; i < wrapcount; i++) {
14005     // Get 'oldtop = n1n2va' from 'bots[i]'.
14006     enextfnext(bots[i], oldtop);
14007     sym(oldtop, topcasing);
14008     bond(newtops[i], topcasing);
14009     if (checksubfaces) {
14010       tspivot(oldtop, topsh);
14011       if (topsh.sh != dummysh) {
14012         tsdissolve(oldtop);
14013         tsbond(newtops[i], topsh);
14014       }
14015     }
14016     enextfnext(newtops[i], tmpbond0);
14017     bond(oldtop, tmpbond0);
14018   }
14019   // Bond between newtops.
14020   fnext(newtops[0], tmpbond0);
14021   enext2fnext(bots[0], spintet);
14022   for (i = 1; i < wrapcount; i ++) {
14023     if (issymexist(&spintet)) {
14024       enext2fnext(newtops[i], tmpbond1);
14025       bond(tmpbond0, tmpbond1);
14026     }
14027     fnext(newtops[i], tmpbond0);
14028     enext2fnext(bots[i], spintet);
14029   }
14030   // Bond the last to the first if no boundary.
14031   if (issymexist(&spintet)) {
14032     enext2fnext(newtops[0], tmpbond1);
14033     bond(tmpbond0, tmpbond1);
14034   }
14035   if (checksubsegs) {
14036     for (i = 0; i < wrapcount; i++) {
14037       enextfnext(bots[i], worktet); // edge n1->n2.
14038       tsspivot1(worktet, n1n2seg);
14039       if (n1n2seg.sh != dummysh) {
14040         enext(newtops[i], tmpbond0);
14041         tssbond1(tmpbond0, n1n2seg);
14042       }
14043       enextself(worktet); // edge n2->v ==> n2->b
14044       tsspivot1(worktet, n2vseg);
14045       if (n2vseg.sh != dummysh) {
14046         tssdissolve1(worktet);
14047         tssbond1(newtops[i], n2vseg);
14048       }
14049       enextself(worktet); // edge v->n1 ==> b->n1
14050       tsspivot1(worktet, n1vseg);
14051       if (n1vseg.sh != dummysh) {
14052         tssdissolve1(worktet);
14053         enext2(newtops[i], tmpbond0);
14054         tssbond1(tmpbond0, n1vseg);
14055       }
14056     }
14057   }
14058 
14059   // Is there exist subfaces and subsegment need to be split?
14060   if (checksubfaces) {
14061     if (abseg.sh != dummysh) {
14062       // A subsegment needs be split.
14063       spivot(abseg, splitsh);
14064 #ifdef SELF_CHECK
14065       assert(splitsh.sh != dummysh);
14066 #endif
14067     }
14068     if (splitsh.sh != dummysh) {
14069       // Split subfaces (and subsegment).
14070       findedge(&splitsh, pa, pb);
14071       splitsubedge(newpoint, &splitsh, (queue *) NULL);
14072     }
14073   }
14074 
14075   if (b->verbose > 3) {
14076     for (i = 0; i < wrapcount; i++) {
14077       printf("    Updating bots[%i] ", i);
14078       printtet(&(bots[i]));
14079       printf("    Creating newtops[%i] ", i);
14080       printtet(&(newtops[i]));
14081     }
14082   }
14083 
14084   if (flipqueue != (queue *) NULL) {
14085     for (i = 0; i < wrapcount; i++) {
14086       enqueueflipface(bots[i], flipqueue);
14087       enqueueflipface(newtops[i], flipqueue);
14088     }
14089   }
14090 
14091   // Set the return handle be avn1n2.  It is got by transforming from
14092   //   'bots[0]' (which is an1n2v).
14093   fnext(bots[0], spintet); // spintet is an1vn2.
14094   esymself(spintet); // spintet is n1avn2.
14095   enextself(spintet); // spintet is avn1n2.
14096   *splittet = spintet;
14097 
14098   delete [] bots;
14099   delete [] newtops;
14100 }
14101 
14103 //                                                                           //
14104 // unsplittetedge()    Reverse the operation of splitting an edge, so as to  //
14105 //                     remove the newly inserted point.                      //
14106 //                                                                           //
14107 // Assume the original edge is ab, the tetrahedron containing ab is abn1n2.  //
14108 // After ab was split by a point v, every tetrahedron containing ab (e.g.,   //
14109 // abn1n2) has been split into two (e.g., an1n2v and bn2n1v). 'splittet'     //
14110 // represents avn1n2 (i.e., its destination is v).                           //
14111 //                                                                           //
14112 // To remove point v is to expand each split tetrahedron containing ab (e.g.,//
14113 // (avn1n2 to abn1n2), then delete the redundant one(e.g., vbn1n2). If there //
14114 // exists any subface around ab, routine unsplitsubedge() will be called to  //
14115 // reverse the operation of splitting a edge (or a subsegment) of subfaces.  //
14116 // On completion, point v is not deleted in this routine.                    //
14117 //                                                                           //
14119 
14120 void tetgenmesh::unsplittetedge(triface* splittet)
14121 {
14122   triface *bots, *newtops;
14123   triface oldtop, topcasing;
14124   triface spintet;
14125   face avseg, splitsh, topsh, spinsh;
14126   point pa, pv, n1;
14127   int wrapcount, hitbdry;
14128   int i;
14129 
14130   spintet = *splittet;
14131   pa = org(spintet);
14132   pv = dest(spintet);
14133   if (checksubfaces) {
14134     // Is there a subsegment need to be unsplit together?
14135     tsspivot(splittet, &avseg);
14136     if (avseg.sh != dummysh) {
14137       // The subsegment's direction should conform to 'splittet'.
14138       if (sorg(avseg) != pa) {
14139         sesymself(avseg);
14140       }
14141     }
14142   }
14143 
14144   n1 = apex(spintet);
14145   hitbdry = 0;
14146   wrapcount = 1;
14147   if (checksubfaces && avseg.sh != dummysh) {
14148     // It may happen that some tetrahedra containing ab (a subsegment) are
14149     //   completely disconnected with others. If it happens, use the face
14150     //   link of ab to cross the boundary.
14151     while (true) {
14152       if (!fnextself(spintet)) {
14153         // Meet a boundary, walk through it.
14154         hitbdry ++;
14155         tspivot(spintet, spinsh);
14156 #ifdef SELF_CHECK
14157         assert(spinsh.sh != dummysh);
14158 #endif
14159         findedge(&spinsh, pa, pv);
14160         sfnextself(spinsh);
14161         stpivot(spinsh, spintet);
14162 #ifdef SELF_CHECK
14163         assert(spintet.tet != dummytet);
14164 #endif
14165         findedge(&spintet, pa, pv);
14166         // Remember this position (hull face) in 'splittet'.
14167         *splittet = spintet;
14168         // Split two hull faces increase the hull size;
14169         hullsize += 2;
14170       }
14171       if (apex(spintet) == n1) break;
14172       wrapcount ++;
14173     }
14174     if (hitbdry > 0) {
14175       wrapcount -= hitbdry;
14176     }
14177   } else {
14178     // All the tetrahedra containing ab are connected together. If there
14179     //   are subfaces, 'splitsh' keeps one of them.
14180     splitsh.sh = dummysh;
14181     while (hitbdry < 2) {
14182       if (checksubfaces && splitsh.sh == dummysh) {
14183         tspivot(spintet, splitsh);
14184       }
14185       if (fnextself(spintet)) {
14186         if (apex(spintet) == n1) break;
14187         wrapcount++;
14188       } else {
14189         hitbdry ++;
14190         if (hitbdry < 2) {
14191           esym(*splittet, spintet);
14192         }
14193       }
14194     }
14195     if (hitbdry > 0) {
14196       // ab is on the hull.
14197       wrapcount -= 1;
14198       // 'spintet' now is a hull face, inverse its edge direction.
14199       esym(spintet, *splittet);
14200       // Split two hull faces increases the number of hull faces.
14201       hullsize += 2;
14202     }
14203   }
14204 
14205   // Make arrays of updating (bot, oldtop) and new (newtop) tetrahedra.
14206   bots = new triface[wrapcount];
14207   newtops = new triface[wrapcount];
14208   // Spin around av, gather tetrahedra and set up new tetrahedra.
14209   spintet = *splittet;
14210   for (i = 0; i < wrapcount; i++) {
14211     // Get 'bots[i] = an1n2v'.
14212     enext2fnext(spintet, bots[i]);
14213     esymself(bots[i]);
14214     // Get 'oldtop = n1n2va'.
14215     enextfnext(bots[i], oldtop);
14216     // Get 'newtops[i] = 'bn1n2v'
14217     fnext(oldtop, newtops[i]); // newtop = n1n2bv
14218     esymself(newtops[i]); // newtop = n2n1bv
14219     enext2self(newtops[i]); // newtop = bn2n1v
14220     // Go to the next.
14221     fnextself(spintet);
14222     if (checksubfaces && avseg.sh != dummysh) {
14223       if (!issymexist(&spintet)) {
14224         // We meet a hull face, walk through it.
14225         tspivot(spintet, spinsh);
14226 #ifdef SELF_CHECK
14227         assert(spinsh.sh != dummysh);
14228 #endif
14229         findedge(&spinsh, pa, pv);
14230         sfnextself(spinsh);
14231         stpivot(spinsh, spintet);
14232 #ifdef SELF_CHECK
14233         assert(spintet.tet != dummytet);
14234 #endif
14235         findedge(&spintet, pa, pv);
14236       }
14237     }
14238   }
14239 
14240   if (b->verbose > 1) {
14241     printf("  Removing point %d from edge (%d, %d).\n",
14242            pointmark(oppo(bots[0])), pointmark(org(bots[0])),
14243            pointmark(org(newtops[0])));
14244   }
14245 
14246   for (i = 0; i < wrapcount; i++) {
14247     // Expand an1n2v to an1n2b.
14248     setoppo(bots[i], org(newtops[i]));
14249     // Get 'oldtop = n1n2va' from 'bot[i]'.
14250     enextfnext(bots[i], oldtop);
14251     // Get 'topcasing' from 'newtop[i]'
14252     sym(newtops[i], topcasing);
14253     // Bond them.
14254     bond(oldtop, topcasing);
14255     if (checksubfaces) {
14256       tspivot(newtops[i], topsh);
14257       if (topsh.sh != dummysh) {
14258         tsbond(oldtop, topsh);
14259       }
14260     }
14261     // Delete the tetrahedron above an1n2v.
14262     tetrahedrondealloc(newtops[i].tet);
14263   }
14264 
14265   // If there exists any subface, unsplit them.
14266   if (checksubfaces) {
14267     if (avseg.sh != dummysh) {
14268       spivot(avseg, splitsh);
14269 #ifdef SELF_CHECK
14270       assert(splitsh.sh != dummysh);
14271 #endif
14272     }
14273     if (splitsh.sh != dummysh) {
14274       findedge(&splitsh, pa, pv);
14275       unsplitsubedge(&splitsh);
14276     }
14277   }
14278 
14279   delete [] bots;
14280   delete [] newtops;
14281 }
14282 
14284 //                                                                           //
14285 // splitsubedge()    Insert a point on an edge of the surface mesh.          //
14286 //                                                                           //
14287 // The splitting edge is given by 'splitsh'. Assume its three corners are a, //
14288 // b, c, where ab is the edge will be split. ab may be a subsegment.         //
14289 //                                                                           //
14290 // To split edge ab is to split all subfaces conatining ab. If ab is not a   //
14291 // subsegment, there are only two subfaces need be split, otherwise, there   //
14292 // may have any number of subfaces need be split. Each splitting subface abc //
14293 // is shrunk to avc, a new subface vbc is created.  It is important to keep  //
14294 // the orientations of edge rings of avc and vbc be the same as abc's. If ab //
14295 // is a subsegment, it is shrunk to av and a new subsegment vb is created.   //
14296 //                                                                           //
14297 // If there are tetrahedra adjoining to the splitting subfaces, they should  //
14298 // be split before calling this routine, so the connection between the new   //
14299 // tetrahedra and the new subfaces can be correctly set.                     //
14300 //                                                                           //
14301 // On completion, 'splitsh' returns avc.  If 'flipqueue' is not NULL, it     //
14302 // returns all edges which may be non-Delaunay.                              //
14303 //                                                                           //
14305 
14306 void tetgenmesh::splitsubedge(point newpoint, face* splitsh, queue* flipqueue)
14307 {
14308   triface abcd, bace, vbcd, bvce;
14309   face startabc, spinabc, spinsh;
14310   face oldbc, bccasin, bccasout;
14311   face ab, bc;
14312   face avc, vbc, vbc1;
14313   face av, vb;
14314   point pa, pb;
14315 
14316   startabc = *splitsh;
14317   // Is there a subsegment?
14318   sspivot(startabc, ab);
14319   if (ab.sh != dummysh) {
14320     ab.shver = 0;
14321     if (sorg(startabc) != sorg(ab)) {
14322       sesymself(startabc);
14323     }
14324   }
14325   pa = sorg(startabc);
14326   pb = sdest(startabc);
14327 
14328   if (b->verbose > 1) {
14329     printf("  Inserting point %d on subedge (%d, %d) %s.\n",
14330            pointmark(newpoint), pointmark(pa), pointmark(pb),
14331            (ab.sh != dummysh ? "(seg)" : " "));
14332   }
14333 
14334   // Spin arround ab, split every subface containing ab.
14335   spinabc = startabc;
14336   do {
14337     // Adjust spinabc be edge ab.
14338     if (sorg(spinabc) != pa) {
14339       sesymself(spinabc);
14340     }
14341     // Save old configuration at edge bc, if bc has a subsegment, save the
14342     //   face link of it and dissolve it from bc.
14343     senext(spinabc, oldbc);
14344     spivot(oldbc, bccasout);
14345     sspivot(oldbc, bc);
14346     if (bc.sh != dummysh) {
14347       if (spinabc.sh != bccasout.sh) {
14348         // 'spinabc' is not self-bonded.
14349         spinsh = bccasout;
14350         do {
14351           bccasin = spinsh;
14352           spivotself(spinsh);
14353         } while (spinsh.sh != oldbc.sh);
14354       } else {
14355         bccasout.sh = dummysh;
14356       }
14357       ssdissolve(oldbc);
14358     }
14359     // Create a new subface.
14360     makeshellface(subfaces, &vbc);
14361     // Split abc.
14362     avc = spinabc;  // Update 'abc' to 'avc'.
14363     setsdest(avc, newpoint);
14364     // Make 'vbc' be in the same edge ring as 'avc'.
14365     vbc.shver = avc.shver;
14366     setsorg(vbc, newpoint); // Set 'vbc'.
14367     setsdest(vbc, pb);
14368     setsapex(vbc, sapex(avc));
14369     if (b->quality && varconstraint) {
14370       // Copy the area bound into the new subface.
14371       setareabound(vbc, areabound(avc));
14372     }
14373     // Copy the shell marker and shell type into the new subface.
14374     setshellmark(vbc, shellmark(avc));
14375     setshelltype(vbc, shelltype(avc));
14376     if (checkpbcs) {
14377       // Copy the pbcgroup into the new subface.
14378       setshellpbcgroup(vbc, shellpbcgroup(avc));
14379     }
14380     // Set the connection between updated and new subfaces.
14381     senext2self(vbc);
14382     sbond(vbc, oldbc);
14383     // Set the connection between new subface and casings.
14384     senext2self(vbc);
14385     if (bc.sh != dummysh) {
14386       if (bccasout.sh != dummysh) {
14387         // Insert 'vbc' into face link.
14388         sbond1(bccasin, vbc);
14389         sbond1(vbc, bccasout);
14390       } else {
14391         // Bond 'vbc' to itself.
14392         sbond(vbc, vbc);
14393       }
14394       ssbond(vbc, bc);
14395     } else {
14396       sbond(vbc, bccasout);
14397     }
14398     // Go to next subface at edge ab.
14399     spivotself(spinabc);
14400     if (spinabc.sh == dummysh) {
14401       break; // 'ab' is a hull edge.
14402     }
14403   } while (spinabc.sh != startabc.sh);
14404 
14405   // Get the new subface vbc above the updated subface avc (= startabc).
14406   senext(startabc, oldbc);
14407   spivot(oldbc, vbc);
14408   if (sorg(vbc) == newpoint) {
14409     sesymself(vbc);
14410   }
14411 #ifdef SELF_CHECK
14412   assert(sorg(vbc) == sdest(oldbc) && sdest(vbc) == sorg(oldbc));
14413 #endif
14414   senextself(vbc);
14415   // Set the face link for the new created subfaces around edge vb.
14416   spinabc = startabc;
14417   do {
14418     // Go to the next subface at edge av.
14419     spivotself(spinabc);
14420     if (spinabc.sh == dummysh) {
14421       break; // 'ab' is a hull edge.
14422     }
14423     if (sorg(spinabc) != pa) {
14424       sesymself(spinabc);
14425     }
14426     // Get the new subface vbc1 above the updated subface avc (= spinabc).
14427     senext(spinabc, oldbc);
14428     spivot(oldbc, vbc1);
14429     if (sorg(vbc1) == newpoint) {
14430       sesymself(vbc1);
14431     }
14432 #ifdef SELF_CHECK
14433     assert(sorg(vbc1) == sdest(oldbc) && sdest(vbc1) == sorg(oldbc));
14434 #endif
14435     senextself(vbc1);
14436     // Set the connection: vbc->vbc1.
14437     sbond1(vbc, vbc1);
14438     // For the next connection.
14439     vbc = vbc1;
14440   } while (spinabc.sh != startabc.sh);
14441 
14442   // Split ab if it is a subsegment.
14443   if (ab.sh != dummysh) {
14444     // Update subsegment ab to av.
14445     av = ab;
14446     setsdest(av, newpoint);
14447     // Create a new subsegment vb.
14448     makeshellface(subsegs, &vb);
14449     setsorg(vb, newpoint);
14450     setsdest(vb, pb);
14451     // vb gets the same mark and segment type as av.
14452     setshellmark(vb, shellmark(av));
14453     setshelltype(vb, shelltype(av));
14454     if (b->quality && varconstraint) {
14455       // Copy the area bound into the new subsegment.
14456       setareabound(vb, areabound(av));
14457     }
14458     // Save the old connection at ab (re-use the handles oldbc, bccasout).
14459     senext(av, oldbc);
14460     spivot(oldbc, bccasout);
14461     // Bond av and vb (bonded at their "fake" edges).
14462     senext2(vb, bccasin);
14463     sbond(bccasin, oldbc);
14464     if (bccasout.sh != dummysh) {
14465       // There is a subsegment connecting with ab at b. It will connect
14466       //   to vb at b after splitting.
14467       bccasout.shver = 0;
14468       if (sorg(bccasout) != pb) sesymself(bccasout);
14469 #ifdef SELF_CHECK
14470       assert(sorg(bccasout) == pb);
14471 #endif
14472       senext2self(bccasout);
14473       senext(vb, bccasin);
14474       sbond(bccasin, bccasout);
14475     }
14476     // Bond all new subfaces (vbc) to vb.
14477     spinabc = startabc;
14478     do {
14479       // Adjust spinabc be edge av.
14480       if (sorg(spinabc) != pa) {
14481         sesymself(spinabc);
14482       }
14483       // Get new subface vbc above the updated subface avc (= spinabc).
14484       senext(spinabc, oldbc);
14485       spivot(oldbc, vbc);
14486       if (sorg(vbc) == newpoint) {
14487         sesymself(vbc);
14488       }
14489       senextself(vbc);
14490       // Bond the new subface and the new subsegment.
14491       ssbond(vbc, vb);
14492       // Go to the next.
14493       spivotself(spinabc);
14494 #ifdef SELF_CHECK
14495       assert(spinabc.sh != dummysh);
14496 #endif
14497     } while (spinabc.sh != startabc.sh);
14498   }
14499 
14500   // Bond the new subfaces to new tetrahedra if they exist.  New tetrahedra
14501   //   should have been created before calling this routine.
14502   spinabc = startabc;
14503   do {
14504     // Adjust spinabc be edge av.
14505     if (sorg(spinabc) != pa) {
14506       sesymself(spinabc);
14507     }
14508     // Get new subface vbc above the updated subface avc (= spinabc).
14509     senext(spinabc, oldbc);
14510     spivot(oldbc, vbc);
14511     if (sorg(vbc) == newpoint) {
14512       sesymself(vbc);
14513     }
14514     senextself(vbc);
14515     // Get the adjacent tetrahedra at 'spinabc'.
14516     stpivot(spinabc, abcd);
14517     if (abcd.tet != dummytet) {
14518       findedge(&abcd, sorg(spinabc), sdest(spinabc));
14519       enextfnext(abcd, vbcd);
14520       fnextself(vbcd);
14521 #ifdef SELF_CHECK
14522       assert(vbcd.tet != dummytet);
14523 #endif
14524       tsbond(vbcd, vbc);
14525       sym(vbcd, bvce);
14526       sesymself(vbc);
14527       tsbond(bvce, vbc);
14528     } else {
14529       // One side is empty, check the other side.
14530       sesymself(spinabc);
14531       stpivot(spinabc, bace);
14532       if (bace.tet != dummytet) {
14533         findedge(&bace, sorg(spinabc), sdest(spinabc));
14534         enext2fnext(bace, bvce);
14535         fnextself(bvce);
14536 #ifdef SELF_CHECK
14537         assert(bvce.tet != dummytet);
14538 #endif
14539         sesymself(vbc);
14540         tsbond(bvce, vbc);
14541       }
14542     }
14543     // Go to the next.
14544     spivotself(spinabc);
14545     if (spinabc.sh == dummysh) {
14546       break; // 'ab' is a hull edge.
14547     }
14548   } while (spinabc.sh != startabc.sh);
14549 
14550   if (b->verbose > 3) {
14551     spinabc = startabc;
14552     do {
14553       // Adjust spinabc be edge av.
14554       if (sorg(spinabc) != pa) {
14555         sesymself(spinabc);
14556       }
14557       printf("    Updating abc:\n");
14558       printsh(&spinabc);
14559       // Get new subface vbc above the updated subface avc (= spinabc).
14560       senext(spinabc, oldbc);
14561       spivot(oldbc, vbc);
14562       if (sorg(vbc) == newpoint) {
14563         sesymself(vbc);
14564       }
14565       senextself(vbc);
14566       printf("    Creating vbc:\n");
14567       printsh(&vbc);
14568       // Go to the next.
14569       spivotself(spinabc);
14570       if (spinabc.sh == dummysh) {
14571         break; // 'ab' is a hull edge.
14572       }
14573     } while (spinabc.sh != startabc.sh);
14574   }
14575 
14576   if (flipqueue != (queue *) NULL) {
14577     spinabc = startabc;
14578     do {
14579       // Adjust spinabc be edge av.
14580       if (sorg(spinabc) != pa) {
14581         sesymself(spinabc);
14582       }
14583       senext2(spinabc, oldbc); // Re-use oldbc.
14584       enqueueflipedge(oldbc, flipqueue);
14585       // Get new subface vbc above the updated subface avc (= spinabc).
14586       senext(spinabc, oldbc);
14587       spivot(oldbc, vbc);
14588       if (sorg(vbc) == newpoint) {
14589         sesymself(vbc);
14590       }
14591       senextself(vbc);
14592       senext(vbc, oldbc); // Re-use oldbc.
14593       enqueueflipedge(oldbc, flipqueue);
14594       // Go to the next.
14595       spivotself(spinabc);
14596       if (spinabc.sh == dummysh) {
14597         break; // 'ab' is a hull edge.
14598       }
14599     } while (spinabc.sh != startabc.sh);
14600   }
14601 }
14602 
14604 //                                                                           //
14605 // unsplitsubedge()    Reverse the operation of splitting an edge of subface,//
14606 //                     so as to remove a point from the edge.                //
14607 //                                                                           //
14608 // Assume the original edge is ab, the subface containing it is abc. It was  //
14609 // split by a point v into avc, and vbc.  'splitsh' represents avc, further- //
14610 // more, if av is a subsegment, av should be the zero version of the split   //
14611 // subsegment (i.e., av.shver = 0), so we are sure that the destination (v)  //
14612 // of both avc and av is the deleting point.                                 //
14613 //                                                                           //
14614 // To remove point v is to expand avc to abc, delete vbc, do the same for    //
14615 // other subfaces containing av and vb. If av and vb are subsegments, expand //
14616 // av to ab, delete vb.  On completion, point v is not deleted.              //
14617 //                                                                           //
14619 
14620 void tetgenmesh::unsplitsubedge(face* splitsh)
14621 {
14622   face startavc, spinavc, spinbcv;
14623   face oldvc, bccasin, bccasout, spinsh;
14624   face av, vb, bc;
14625   point pa, pv, pb;
14626 
14627   startavc = *splitsh;
14628   sspivot(startavc, av);
14629   if (av.sh != dummysh) {
14630     // Orient the direction of subsegment to conform the subface.
14631     if (sorg(av) != sorg(startavc)) {
14632       sesymself(av);
14633     }
14634 #ifdef SELF_CHECK
14635     assert(av.shver == 0);
14636 #endif
14637   }
14638   senext(startavc, oldvc);
14639   spivot(oldvc, vb);  // vb is subface vbc
14640   if (sorg(vb) != sdest(oldvc)) {
14641     sesymself(vb);
14642   }
14643   senextself(vb);
14644   pa = sorg(startavc);
14645   pv = sdest(startavc);
14646   pb = sdest(vb);
14647 
14648   if (b->verbose > 1) {
14649     printf("  Removing point %d from subedge (%d, %d).\n",
14650            pointmark(pv), pointmark(pa), pointmark(pb));
14651   }
14652 
14653   // Spin arround av, unsplit every subface containing av.
14654   spinavc = startavc;
14655   do {
14656     // Adjust spinavc be edge av.
14657     if (sorg(spinavc) != pa) {
14658       sesymself(spinavc);
14659     }
14660     // Save old configuration at edge bc, if bc has a subsegment, save the
14661     //   face link of it.
14662     senext(spinavc, oldvc);
14663     spivot(oldvc, spinbcv);
14664     if (sorg(spinbcv) != sdest(oldvc)) {
14665       sesymself(spinbcv);
14666     }
14667     senext2self(spinbcv);
14668     spivot(spinbcv, bccasout);
14669     sspivot(spinbcv, bc);
14670     if (bc.sh != dummysh) {
14671       if (spinbcv.sh != bccasout.sh) {
14672         // 'spinbcv' is not self-bonded.
14673         spinsh = bccasout;
14674         do {
14675           bccasin = spinsh;
14676           spivotself(spinsh);
14677         } while (spinsh.sh != spinbcv.sh);
14678       } else {
14679         bccasout.sh = dummysh;
14680       }
14681     }
14682     // Expand avc to abc.
14683     setsdest(spinavc, pb);
14684     if (bc.sh != dummysh) {
14685       if (bccasout.sh != dummysh) {
14686         sbond1(bccasin, oldvc);
14687         sbond1(oldvc, bccasout);
14688       } else {
14689         // Bond 'oldbc' to itself.
14690         sbond(oldvc, oldvc);
14691       }
14692       ssbond(oldvc, bc);
14693     } else {
14694       sbond(oldvc, bccasout);
14695     }
14696     // Delete bcv.
14697     shellfacedealloc(subfaces, spinbcv.sh);
14698     // Go to next subface at edge av.
14699     spivotself(spinavc);
14700     if (spinavc.sh == dummysh) {
14701       break; // 'av' is a hull edge.
14702     }
14703   } while (spinavc.sh != startavc.sh);
14704 
14705   // Is there a subsegment need to be unsplit?
14706   if (av.sh != dummysh) {
14707     senext(av, oldvc);  // Re-use oldvc.
14708     spivot(oldvc, vb);
14709     vb.shver = 0;
14710 #ifdef SELF_CHECK
14711     assert(sdest(av) == sorg(vb));
14712 #endif
14713     senext(vb, spinbcv); // Re-use spinbcv.
14714     spivot(spinbcv, bccasout);
14715     // Expand av to ab.
14716     setsdest(av, pb);
14717     sbond(oldvc, bccasout);
14718     // Delete vb.
14719     shellfacedealloc(subsegs, vb.sh);
14720   }
14721 }
14722 
14724 //                                                                           //
14725 // insertsite()    Insert a point into the mesh.                             //
14726 //                                                                           //
14727 // The 'newpoint' is located.  If 'searchtet->tet' is not NULL, the search   //
14728 // for the containing tetrahedron begins from 'searchtet', otherwise, a full //
14729 // point location procedure is called.  If 'newpoint' is found inside a      //
14730 // tetrahedron, the tetrahedron is split into four (by splittetrahedron());  //
14731 // if 'newpoint' lies on a face, the face is split into three, thereby       //
14732 // splitting the two adjacent tetrahedra into six (by splittetface()); if    //
14733 // 'newpoint' lies on an edge, the edge is split into two, thereby, every    //
14734 // tetrahedron containing this edge is split into two. If 'newpoint' lies on //
14735 // an existing vertex, no action is taken, and the value DUPLICATEPOINT  is  //
14736 // returned and 'searchtet' is set to a handle whose origin is the vertex.   //
14737 //                                                                           //
14738 // If 'flipqueue' is not NULL, after 'newpoint' is inserted, it returns all  //
14739 // faces which may become non-Delaunay due to the newly inserted point. Flip //
14740 // operations can be performed as necessary on them to maintain the Delaunay //
14741 // property.                                                                 //
14742 //                                                                           //
14744 
14745 enum tetgenmesh::insertsiteresult tetgenmesh::insertsite(point newpoint,
14746   triface* searchtet, bool approx, queue* flipqueue)
14747 {
14748   enum locateresult intersect, exactloc;
14749   point checkpt;
14750   REAL epspp, checklen;
14751   int count;
14752 
14753   if (b->verbose > 1) {
14754     printf("  Insert point to mesh: (%.12g, %.12g, %.12g) %d.\n",
14755            newpoint[0], newpoint[1], newpoint[2], pointmark(newpoint));
14756   }
14757 
14758   if (searchtet->tet == (tetrahedron *) NULL) {
14759     // Search for a tetrahedron containing 'newpoint'.
14760     searchtet->tet = dummytet;
14761     exactloc = locate(newpoint, searchtet);
14762   } else {
14763     // Start searching from the tetrahedron provided by the caller.
14764     exactloc = preciselocate(newpoint, searchtet, tetrahedrons->items);
14765   }
14766   intersect = exactloc;
14767   if (approx && (exactloc != ONVERTEX)) {
14768     // Adjust the exact location to an approx. location wrt. epsilon.
14769     epspp = b->epsilon;
14770     count = 0;
14771     while (count < 16) {
14772       intersect = adjustlocate(newpoint, searchtet, exactloc, epspp);
14773       if (intersect == ONVERTEX) {
14774         checkpt = org(*searchtet);
14775         checklen = distance(checkpt, newpoint);
14776         if (checklen / longest > b->epsilon) {
14777           epspp *= 1e-2;
14778           count++;
14779           continue;
14780         }
14781       }
14782       break;
14783     }
14784   }
14785   // Keep current search state for next searching.
14786   recenttet = *searchtet;
14787 
14788   // Insert the point using the right routine
14789   switch (intersect) {
14790   case ONVERTEX:
14791     // There's already a vertex there. Return in 'searchtet' a tetrahedron
14792     //   whose origin is the existing vertex.
14793     if (b->verbose > 1) {
14794       printf("  Not insert for duplicating point.\n");
14795     }
14796     return DUPLICATEPOINT;
14797 
14798   case OUTSIDE:
14799     if (b->verbose > 1) {
14800       printf("  Not insert for locating outside the mesh.\n");
14801     }
14802     return OUTSIDEPOINT;
14803 
14804   case ONEDGE:
14805     // 'newpoint' falls on an edge.
14806     splittetedge(newpoint, searchtet, flipqueue);
14807     return SUCCESSONEDGE;
14808 
14809   case ONFACE:
14810     // 'newpoint' falls on a face.
14811     splittetface(newpoint, searchtet, flipqueue);
14812     return SUCCESSONFACE;
14813 
14814   case INTETRAHEDRON:
14815     // 'newpoint' falls inside a tetrahedron.
14816     splittetrahedron(newpoint, searchtet, flipqueue);
14817     return SUCCESSINTET;
14818 
14819   default:
14820     // Impossible case.
14821     return OUTSIDEPOINT;
14822   }
14823 }
14824 
14826 //                                                                           //
14827 // undosite()    Undo the most recently point insertion.                     //
14828 //                                                                           //
14829 // 'insresult' indicates in where the newpoint has been inserted, i.e., in a //
14830 // tetrahedron, on a face, or on an edge.  A correspoding routine will be    //
14831 // called to undo the point insertion.  'splittet' is a handle represent one //
14832 // of the resulting tetrahedra, but it may be changed after transformation,  //
14833 // even may be dead.  Four points 'torg', ... 'toppo' are the corners which  //
14834 // 'splittet' should have. On finish, 'newpoint' is not removed.             //
14835 //                                                                           //
14837 
14838 void tetgenmesh::undosite(enum insertsiteresult insresult, triface* splittet,
14839   point torg, point tdest, point tapex, point toppo)
14840 {
14841   // Set the four corners of 'splittet' exactly be 'torg', ... 'toppo'.
14842   findface(splittet, torg, tdest, tapex);
14843   if (oppo(*splittet) != toppo) {
14844     symself(*splittet);
14845 #ifdef SELF_CHECK
14846     assert(oppo(*splittet) == toppo);
14847 #endif
14848     // The sym() operation may inverse the edge, correct it if so.
14849     findedge(splittet, torg, tdest);
14850   }
14851 
14852   // Unsplit the tetrahedron according to 'insresult'.
14853   switch (insresult) {
14854   case SUCCESSINTET:
14855     // 'splittet' should be the face with 'newpoint' as its opposite.
14856     unsplittetrahedron(splittet);
14857     break;
14858   case SUCCESSONFACE:
14859     // 'splittet' should be the one of three splitted face with 'newpoint'
14860     //   as its apex.
14861     unsplittetface(splittet);
14862     break;
14863   case SUCCESSONEDGE:
14864     // 'splittet' should be the tet with destination is 'newpoint'.
14865     unsplittetedge(splittet);
14866     break;
14867   default: // To omit compile warnings.
14868     break;
14869   }
14870 }
14871 
14873 //                                                                           //
14874 // closeopenface()    Close "open" faces recursively.                        //
14875 //                                                                           //
14876 // This is the support routine of inserthullsite(). A point p which lies out-//
14877 // side of CH(T). p is inserted to T by forming a tet t from p and a visible //
14878 // CH face f. The three sides of f which have p as a vertex is called "open" //
14879 // face. Each open face will be closed by either creating a tet on top of it //
14880 // or become a new CH face.                                                  //
14881 //                                                                           //
14883 
14884 void tetgenmesh::closeopenface(triface* openface, queue* flipque)
14885 {
14886   triface newtet, oldhull;
14887   triface newopenface, closeface;
14888   point inspoint, pa, pb, pc;
14889   REAL attrib, volume;
14890   int i;
14891 
14892   // Get the new point p.
14893   inspoint = apex(*openface);
14894   // Find the old CH face f_o (f and f_o share the same edge).
14895   esym(*openface, oldhull);
14896   while (fnextself(oldhull)) ;
14897   if (apex(oldhull) != inspoint) {
14898     // Is f_o visible by p?
14899     pa = org(oldhull);
14900     pb = dest(oldhull);
14901     pc = apex(oldhull);
14902     if (orient3d(pa, pb, pc, inspoint) < 0.0) {
14903       // Yes. Create a new tet t above f_o.
14904       maketetrahedron(&newtet);
14905       setorg(newtet, pa);
14906       setdest(newtet, pb);
14907       setapex(newtet, pc);
14908       setoppo(newtet, inspoint);
14909       for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14910         attrib = elemattribute(oldhull.tet, i);
14911         setelemattribute(newtet.tet, i, attrib);
14912       }
14913       if (b->varvolume) {
14914         volume = volumebound(oldhull.tet);
14915         setvolumebound(newtet.tet, volume);
14916       }
14917       // Connect t to T.
14918       bond(newtet, oldhull);
14919       // Close f.
14920       fnext(newtet, newopenface);
14921       bond(newopenface, *openface);
14922       // f_o becomes an interior face.
14923       enqueueflipface(oldhull, flipque);
14924       // Hull face number decreases.
14925       hullsize--;
14926       // Two faces of t become open face.
14927       enextself(newtet);
14928       for (i = 0; i < 2; i++) {
14929         fnext(newtet, newopenface);
14930         sym(newopenface, closeface);
14931         if (closeface.tet == dummytet) {
14932           closeopenface(&newopenface, flipque);
14933         }
14934         enextself(newtet);
14935       }
14936     } else {
14937       // Inivisible. f becomes a new CH face.
14938       hullsize++;
14939       // Let 'dummytet' holds f for the next point location.
14940       dummytet[0] = encode(*openface);
14941     }
14942   } else {
14943     // f_o is co-incident with f --> f is closed by f_o.
14944     bond(*openface, oldhull);
14945     // f is an interior face.
14946     enqueueflipface(*openface, flipque);
14947   }
14948 }
14949 
14951 //                                                                           //
14952 // inserthullsite()    Insert a point which lies outside the convex hull.    //
14953 //                                                                           //
14954 // The 'inspoint' p lies outside the tetrahedralization T.  The 'horiz' f is //
14955 // on the convex hull of T, CH(T), which is visible by p (Imagine f is para- //
14956 // llel to the horizon). To insert p into T we have to enlarge the CH(T) and //
14957 // update T so that p is on the new CH(T).                                   //
14958 //                                                                           //
14959 // To enlarge the CH(T).  We need to find the set F of faces which are on CH //
14960 // (T) and visible by p (F can be formed by a depth-first search from f).  p //
14961 // is then inserted into T by mounting new tets formed by p and these faces. //
14962 // Faces of F become interior faces and may non-locally Delaunay.  They are  //
14963 // queued in 'flipqueue' for flip tests.                                     //
14964 //                                                                           //
14966 
14967 void tetgenmesh::inserthullsite(point inspoint, triface* horiz, queue* flipque)
14968 {
14969   triface firstnewtet;
14970   triface openface, closeface;
14971   REAL attrib, volume;
14972   int i;
14973 
14974   // Let f face to p.
14975   adjustedgering(*horiz, CW);
14976   // Create the first tet t (from f and p).
14977   maketetrahedron(&firstnewtet);
14978   setorg (firstnewtet, org(*horiz));
14979   setdest(firstnewtet, dest(*horiz));
14980   setapex(firstnewtet, apex(*horiz));
14981   setoppo(firstnewtet, inspoint);
14982   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14983     attrib = elemattribute(horiz->tet, i);
14984     setelemattribute(firstnewtet.tet, i, attrib);
14985   }
14986   if (b->varvolume) {
14987     volume = volumebound(horiz->tet);
14988     setvolumebound(firstnewtet.tet, volume);
14989   }
14990   // Connect t to T.
14991   bond(firstnewtet, *horiz);
14992   // f is not on CH(T) anymore.
14993   enqueueflipface(*horiz, flipque);
14994   // Hull face number decreases.
14995   hullsize--;
14996 
14997   // Call the faces of t which have p as a vertex "open" face.
14998   for (i = 0; i < 3; i++) {
14999     // Get an open face f_i of t.
15000     fnext(firstnewtet, openface);
15001     // Close f_i if it is still open.
15002     sym(openface, closeface);
15003     if (closeface.tet == dummytet) {
15004       closeopenface(&openface, flipque);
15005     }
15006     // Go to the next open face of t.
15007     enextself(firstnewtet);
15008   }
15009 }
15010 
15012 //                                                                           //
15013 // Terminology: BC(p) and CBC(p), B(p) and C(p).                             //
15014 //                                                                           //
15015 // Given an arbitrary point p,  the Bowyer-Watson cavity BC(p) is formed by  //
15016 // tets whose circumspheres containing p.  The outer faces of BC(p) form a   //
15017 // polyhedron B(p).                                                          //
15018 //                                                                           //
15019 // If p is on a facet F, the constrained Bowyer-Watson cavity CBC(p) on F is //
15020 // formed by subfaces of F whose circumspheres containing p. The outer edges //
15021 // of CBC(p) form a polygon C(p).  B(p) is separated into two parts by C(p), //
15022 // denoted as B_1(p) and B_2(p), one of them may be empty (F is on the hull).//
15023 //                                                                           //
15024 // If p is on a segment S which is shared by n facets.  There exist n C(p)s, //
15025 // each one is a non-closed polygon (without S). B(p) is split into n parts, //
15026 // each of them is denoted as B_i(p), some B_i(p) may be empty.              //
15027 //                                                                           //
15029 
15031 //                                                                           //
15032 // formbowatcavitysub()    Form CBC(p) and C(p) on a facet F.                //
15033 //                                                                           //
15034 // Parameters: bp = p, bpseg = S, sublist = CBC(p), subceillist = C(p).      //
15035 //                                                                           //
15036 // CBC(p) contains at least one subface on input; S may be NULL which means  //
15037 // that p is inside a facet. On output, all subfaces of CBC(p) are infected, //
15038 // and the edge rings are oriented to the same halfspace.                    //
15039 //                                                                           //
15041 
15042 void tetgenmesh::formbowatcavitysub(point bp, face* bpseg, list* sublist,
15043   list* subceillist)
15044 {
15045   triface adjtet;
15046   face startsh, neighsh;
15047   face checkseg;
15048   point pa, pb, pc, pd;
15049   REAL sign;
15050   int i, j;
15051 
15052   // Form CBC(p) and C(p) by a broadth-first searching.
15053   for (i = 0; i < sublist->len(); i++) {
15054     startsh = * (face *)(* sublist)[i]; // startsh = f.
15055     // Look for three neighbors of f.
15056     for (j = 0; j < 3; j++) {
15057       sspivot(startsh, checkseg);
15058       if (checkseg.sh == dummysh) {
15059         // Get its neighbor n.
15060         spivot(startsh, neighsh);
15061         // Is n already in CBC(p)?
15062         if (!sinfected(neighsh)) {
15063           stpivot(neighsh, adjtet);
15064           if (adjtet.tet == dummytet) {
15065             sesymself(neighsh);
15066             stpivot(neighsh, adjtet);
15067           }
15068           // For positive orientation that insphere() test requires.
15069           adjustedgering(adjtet, CW);
15070           pa = org(adjtet);
15071           pb = dest(adjtet);
15072           pc = apex(adjtet);
15073           pd = oppo(adjtet);
15074           sign = insphere(pa, pb, pc, pd, bp);
15075           if (sign >= 0.0) {
15076             // Orient edge ring of n according to that of f.
15077             if (sorg(neighsh) != sdest(startsh)) sesymself(neighsh);
15078             // Collect it into CBC(p).
15079             sinfect(neighsh);
15080             sublist->append(&neighsh);
15081           } else {
15082             subceillist->append(&startsh); // Found an edge of C(p).
15083           }
15084         }
15085       } else {
15086         // Do not cross a segment.
15087         if (bpseg != (face *) NULL) {
15088           if (checkseg.sh != bpseg->sh) {
15089             subceillist->append(&startsh); // Found an edge of C(p).
15090           }
15091         } else {
15092           subceillist->append(&startsh); // Found an edge of C(p).
15093         }
15094       }
15095       senextself(startsh);
15096     }
15097   }
15098 
15099   if (b->verbose > 2) {
15100     printf("    Collect CBC(%d): %d subfaces, %d edges.\n", pointmark(bp),
15101            sublist->len(), subceillist->len());
15102   }
15103 }
15104 
15106 //                                                                           //
15107 // formbowatcavityquad()    Form BC_i(p) and B_i(p) in a quadrant.           //
15108 //                                                                           //
15109 // Parameters: bp = p, tetlist = BC_i(p), ceillist = B_i(p).                 //
15110 //                                                                           //
15111 // BC_i(p) contains at least one tet on input. On finish, all tets collected //
15112 // in BC_i(p) are infected. B_i(p) may not closed when p is on segment or in //
15113 // facet. C(p) must be formed before this routine.  Check the infect flag of //
15114 // a subface to identify the unclosed side of B_i(p).  These sides will be   //
15115 // closed by new subfaces of C(p)s.                                          //
15116 //                                                                           //
15118 
15119 void tetgenmesh::formbowatcavityquad(point bp, list* tetlist, list* ceillist)
15120 {
15121   triface starttet, neightet;
15122   face checksh;
15123   point pa, pb, pc, pd;
15124   REAL sign;
15125   int i;
15126 
15127   // Form BC_i(p) and B_i(p) by a broadth-first searching.
15128   for (i = 0; i < tetlist->len(); i++) {
15129     starttet = * (triface *)(* tetlist)[i];
15130     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15131       // Try to collect the neighbor of the face (f).
15132       tspivot(starttet, checksh);
15133       if (checksh.sh == dummysh) {
15134         // Get its neighbor n.
15135         sym(starttet, neightet);
15136         // Is n already in BC_i(p)?
15137         if (!infected(neightet)) {
15138           // For positive orientation that insphere() test requires.
15139           adjustedgering(neightet, CW);
15140           pa = org(neightet);
15141           pb = dest(neightet);
15142           pc = apex(neightet);
15143           pd = oppo(neightet);
15144           sign = insphere(pa, pb, pc, pd, bp);
15145           if (sign >= 0.0) {
15146             // Collect it into BC_i(p).
15147             infect(neightet);
15148             tetlist->append(&neightet);
15149           } else {
15150             ceillist->append(&starttet); // Found a face of B_i(p).
15151           }
15152         }
15153       } else {
15154         // Do not cross a boundary face.
15155         if (!sinfected(checksh)) {
15156           ceillist->append(&starttet); // Found a face of B_i(p).
15157         }
15158       }
15159     }
15160   }
15161 
15162   if (b->verbose > 2) {
15163     printf("    Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15164            tetlist->len(), ceillist->len());
15165   }
15166 }
15167 
15169 //                                                                           //
15170 // formbowatcavitysegquad()    Form BC_i(p) and B_i(p) in a segment quadrant.//
15171 //                                                                           //
15172 // Parameters: bp = p, tetlist = BC_i(p), ceillist = B_i(p).                 //
15173 //                                                                           //
15174 // BC_i(p) contains at least one tet on input. On finish, all tets collected //
15175 // in BC_i(p) are infected. B_i(p) is not closed. C(p) must be formed before //
15176 // this routine. Check the infect flag of a subface to identify the unclosed //
15177 // sides of B_i(p).  These sides will be closed by new subfaces of C(p)s.    //
15178 //                                                                           //
15179 // During the repair of encroaching subsegments, there may exist locally non-//
15180 // Delaunay faces. These faces are collected in BC_i(p) either.  B_i(p) has  //
15181 // to be formed later than BC_i(p).                                          //
15182 //                                                                           //
15184 
15185 void tetgenmesh::formbowatcavitysegquad(point bp, list* tetlist,list* ceillist)
15186 {
15187   triface starttet, neightet, cavtet;
15188   face checksh;
15189   point pa, pb, pc, pd, pe;
15190   REAL sign;
15191   int i;
15192 
15193   // Form BC_i(p) by a broadth-first searching.
15194   for (i = 0; i < tetlist->len(); i++) {
15195     starttet = * (triface *)(* tetlist)[i];
15196     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15197       // Try to collect the neighbor of the face f.
15198       tspivot(starttet, checksh);
15199       if (checksh.sh == dummysh) {
15200         // Get its neighbor n.
15201         sym(starttet, neightet);
15202         // Is n already in BC_i(p)?
15203         if (!infected(neightet)) {
15204           // For positive orientation that insphere() test requires.
15205           adjustedgering(neightet, CW);
15206           pa = org(neightet);
15207           pb = dest(neightet);
15208           pc = apex(neightet);
15209           pd = oppo(neightet);
15210           sign = insphere(pa, pb, pc, pd, bp);
15211           if (sign >= 0.0) {
15212             // Collect it into BC_i(p).
15213             infect(neightet);
15214             tetlist->append(&neightet);
15215           } else {
15216             // Check if the face is locally non-Delaunay.
15217             pe = oppo(starttet);
15218             sign = insphere(pa, pb, pc, pd, pe);
15219             if (sign >= 0.0) {
15220               // Collect it into BC_i(p).
15221               infect(neightet);
15222               tetlist->append(&neightet);
15223             }
15224           }
15225         }
15226       }
15227     }
15228   }
15229 
15230   // Generate B_i(p).
15231   for (i = 0; i < tetlist->len(); i++) {
15232     cavtet = * (triface *)(* tetlist)[i];
15233     for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15234       tspivot(cavtet, checksh);
15235       if (checksh.sh == dummysh) {
15236         sym(cavtet, neightet);
15237         if (!infected(neightet)) {
15238           ceillist->append(&cavtet); // Found a face of B(p).
15239         }
15240       } else {
15241         // Do not cross a boundary face.
15242         if (!sinfected(checksh)) {
15243           ceillist->append(&cavtet); // Found a face of B(p).
15244         }
15245       }
15246     }
15247   }
15248 
15249   if (b->verbose > 2) {
15250     printf("    Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15251            tetlist->len(), ceillist->len());
15252   }
15253 }
15254 
15256 //                                                                           //
15257 // formbowatcavity()    Form BC(p), B(p), CBC(p)s, and C(p)s.                //
15258 //                                                                           //
15259 // If 'bpseg'(S) != NULL, p is on segment S, else, p is on facet containing  //
15260 // 'bpsh' (F).  'n' returns the number of quadrants in BC(p). 'nmax' is the  //
15261 // maximum pre-allocated array length for the lists.                         //
15262 //                                                                           //
15264 
15265 void tetgenmesh::formbowatcavity(point bp, face* bpseg, face* bpsh, int* n,
15266   int* nmax, list** sublists, list** subceillists, list** tetlists,
15267   list** ceillists)
15268 {
15269   list *sublist;
15270   triface adjtet;
15271   face startsh, spinsh;
15272   point pa, pb;
15273   int i, j;
15274 
15275   *n = 0;
15276   if (bpseg != (face *) NULL) {
15277     // p is on segment S.
15278     bpseg->shver = 0;
15279     pa = sorg(*bpseg);
15280     pb = sdest(*bpseg);
15281     // Count the number of facets sharing at S.
15282     spivot(*bpseg, startsh);
15283     spinsh = startsh;
15284     do {
15285       (*n)++; // spinshlist->append(&spinsh);
15286       spivotself(spinsh);
15287     } while (spinsh.sh != startsh.sh);
15288     // *n is the number of quadrants around S.
15289     if (*n > *nmax) {
15290       // Reallocate arrays. Should not happen very often.
15291       delete [] tetlists;
15292       delete [] ceillists;
15293       delete [] sublists;
15294       delete [] subceillists;
15295       tetlists = new list*[*n];
15296       ceillists = new list*[*n];
15297       sublists = new list*[*n];
15298       subceillists = new list*[*n];
15299       *nmax = *n;
15300     }
15301     // Form CBC(p)s and C(p)s.
15302     spinsh = startsh;
15303     for (i = 0; i < *n; i++) {
15304       sublists[i] = new list(sizeof(face), NULL, 256);
15305       subceillists[i] = new list(sizeof(face), NULL, 256);
15306       // Set a subface f to start search.
15307       startsh = spinsh;
15308       // Let f face to the quadrant of interest (used in forming BC(p)).
15309       findedge(&startsh, pa, pb);
15310       sinfect(startsh);
15311       sublists[i]->append(&startsh);
15312       formbowatcavitysub(bp, bpseg, sublists[i], subceillists[i]);
15313       // Go to the next facet.
15314       spivotself(spinsh);
15315     }
15316   } else if (sublists != (list **) NULL) {
15317     // p is on a facet.
15318     *n = 2;
15319     // Form CBC(p) and C(p).
15320     sublists[0] = new list(sizeof(face), NULL, 256);
15321     subceillists[0] = new list(sizeof(face), NULL, 256);
15322     sinfect(*bpsh);
15323     sublists[0]->append(bpsh);
15324     formbowatcavitysub(bp, NULL, sublists[0], subceillists[0]);
15325   } else {
15326     // p is inside a tet.
15327     *n = 1;
15328   }
15329 
15330   // Form BC_i(p) and B_i(p).
15331   for (i = 0; i < *n; i++) {
15332     tetlists[i] = new list(sizeof(triface), NULL, 256);
15333     ceillists[i] = new list(sizeof(triface), NULL, 256);
15334     if (sublists != (list **) NULL) {
15335       // There are C(p)s.
15336       sublist = ((bpseg == (face *) NULL) ? sublists[0] : sublists[i]);
15337       // Add all adjacent tets of C_i(p) into BC_i(p).
15338       for (j = 0; j < sublist->len(); j++) {
15339         startsh = * (face *)(* sublist)[j];
15340         // Adjust the side facing to the right quadrant for C(p).
15341         if ((bpseg == (face *) NULL) && (i == 1)) sesymself(startsh);
15342         stpivot(startsh, adjtet);
15343         if (adjtet.tet != dummytet) {
15344           if (!infected(adjtet)) {
15345             infect(adjtet);
15346             tetlists[i]->append(&adjtet);
15347           }
15348         }
15349       }
15350       if (bpseg != (face *) NULL) {
15351         // The quadrant is bounded by another facet.
15352         sublist = ((i < *n - 1) ? sublists[i + 1] : sublists[0]);
15353         for (j = 0; j < sublist->len(); j++) {
15354           startsh = * (face *)(* sublist)[j];
15355           // Adjust the side facing to the right quadrant for C(p).
15356           sesymself(startsh);
15357           stpivot(startsh, adjtet);
15358           if (adjtet.tet != dummytet) {
15359             if (!infected(adjtet)) {
15360               infect(adjtet);
15361               tetlists[i]->append(&adjtet);
15362             }
15363           }
15364         }
15365       }
15366     }
15367     // It is possible that BC_i(p) is empty.
15368     if (tetlists[i]->len() == 0) continue;
15369     // Collect the rest of tets of BC_i(p) and form B_i(p).
15370     // if (b->conformdel) {
15371       // formbowatcavitysegquad(bp, tetlists[i], ceillists[i]);
15372     // } else {
15373       formbowatcavityquad(bp, tetlists[i], ceillists[i]);
15374     // }
15375   }
15376 }
15377 
15379 //                                                                           //
15380 // releasebowatcavity()    Undo and free the memory allocated in routine     //
15381 //                         formbowatcavity().                                //
15382 //                                                                           //
15384 
15385 void tetgenmesh::releasebowatcavity(face* bpseg, int n, list** sublists,
15386   list** subceillist, list** tetlists, list** ceillists)
15387 {
15388   triface oldtet;
15389   face oldsh;
15390   int i, j;
15391 
15392   if (sublists != (list **) NULL) {
15393     // Release CBC(p)s.
15394     for (i = 0; i < n; i++) {
15395       // Uninfect subfaces of CBC(p).
15396       for (j = 0; j < sublists[i]->len(); j++) {
15397         oldsh = * (face *)(* (sublists[i]))[j];
15398 #ifdef SELF_CHECK
15399         assert(sinfected(oldsh));
15400 #endif
15401         suninfect(oldsh);
15402       }
15403       delete sublists[i];
15404       delete subceillist[i];
15405       sublists[i] = (list *) NULL;
15406       subceillist[i] = (list *) NULL;
15407       if (bpseg == (face *) NULL) break;
15408     }
15409   }
15410   // Release BC(p).
15411   for (i = 0; i < n; i++) {
15412     // Uninfect tets of BC_i(p).
15413     for (j = 0; j < tetlists[i]->len(); j++) {
15414       oldtet = * (triface *)(* (tetlists[i]))[j];
15415 #ifdef SELF_CHECK
15416       assert(infected(oldtet));
15417 #endif
15418       uninfect(oldtet);
15419     }
15420     delete tetlists[i];
15421     delete ceillists[i];
15422     tetlists[i] = (list *) NULL;
15423     ceillists[i] = (list *) NULL;
15424   }
15425 }
15426 
15428 //                                                                           //
15429 // validatebowatcavityquad()    Valid B_i(p).                                //
15430 //                                                                           //
15431 // B_i(p) is valid if all faces of B_i(p) are visible by p, else B_i(p) is   //
15432 // invalid.  Each tet of BC_i(p) which has such a face is marked (uninfect). //
15433 // They will be removed in updatebowatcavityquad().                          //
15434 //                                                                           //
15435 // Return TRUE if B(p) is valid, else, return FALSE.                         //
15436 //                                                                           //
15438 
15439 bool tetgenmesh::validatebowatcavityquad(point bp,list* ceillist,REAL maxcosd)
15440 {
15441   triface ceiltet;
15442   point pa, pb, pc;
15443   REAL ori, cosd;
15444   int remcount, i;
15445 
15446   // Check the validate of B(p), cut tets having invisible faces.
15447   remcount = 0;
15448   for (i = 0; i < ceillist->len(); i++) {
15449     ceiltet = * (triface *)(* ceillist)[i];
15450     if (infected(ceiltet)) {
15451       adjustedgering(ceiltet, CCW);
15452       pa = org(ceiltet);
15453       pb = dest(ceiltet);
15454       pc = apex(ceiltet);
15455       ori = orient3d(pa, pb, pc, bp);
15456       if (ori >= 0.0) {
15457         // Found an invisible face.
15458         uninfect(ceiltet);
15459         remcount++;
15460         continue;
15461       }
15462       // If a non-trival 'maxcosd' is given.
15463       if (maxcosd > -1.0) {
15464         // Get the maximal dihedral angle of tet abcp.
15465         tetalldihedral(pa, pb, pc, bp, NULL, &cosd, NULL);
15466         // Do not form the tet if the maximal dihedral angle is not reduced.
15467         if (cosd < maxcosd) {
15468           uninfect(ceiltet);
15469           remcount++;
15470         }
15471       }
15472     }
15473   }
15474   return remcount == 0;
15475 }
15476 
15478 //                                                                           //
15479 // updatebowatcavityquad()    Update BC_i(p) and reform B_i(p).              //
15480 //                                                                           //
15481 // B_i(p) is invalid and some tets in BC_i(p) have been marked to be removed //
15482 // in validatebowatcavityquad().  This routine actually remove the cut tets  //
15483 // of BC_i(p) and re-form the B_i(p).                                        //
15484 //                                                                           //
15486 
15487 void tetgenmesh::updatebowatcavityquad(list* tetlist, list* ceillist)
15488 {
15489   triface cavtet, neightet;
15490   face checksh;
15491   int remcount, i;
15492 
15493   remcount = 0;
15494   for (i = 0; i < tetlist->len(); i++) {
15495     cavtet = * (triface *)(* tetlist)[i];
15496     if (!infected(cavtet)) {
15497       tetlist->del(i, 1);
15498       remcount++;
15499       i--;
15500     }
15501   }
15502 
15503   // Are there tets have been cut in BC_i(p)?
15504   if (remcount > 0) {
15505     // Re-form B_i(p).
15506     ceillist->clear();
15507     for (i = 0; i < tetlist->len(); i++) {
15508       cavtet = * (triface *)(* tetlist)[i];
15509       for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15510         tspivot(cavtet, checksh);
15511         if (checksh.sh == dummysh) {
15512           sym(cavtet, neightet);
15513           if (!infected(neightet)) {
15514             ceillist->append(&cavtet); // Found a face of B_i(p).
15515           }
15516         } else {
15517           // Do not cross a boundary face.
15518           if (!sinfected(checksh)) {
15519             ceillist->append(&cavtet); // Found a face of B_i(p).
15520           }
15521         }
15522       }
15523     }
15524     if (b->verbose > 2) {
15525       printf("    Update BC_i(p): %d tets, %d faces.\n", tetlist->len(),
15526              ceillist->len());
15527     }
15528   }
15529 }
15530 
15532 //                                                                           //
15533 // updatebowatcavitysub()    Check and update CBC(p) and C(p).               //
15534 //                                                                           //
15535 // A CBC(p) is valid if all its subfaces are inside or on the hull of BC(p). //
15536 // A subface s of CBC(p) is invalid if it is in one of the two cases:        //
15537 //   (1) s is completely outside BC(p);                                      //
15538 //   (2) s has two adjacent tets but only one of them is in BC(p);           //
15539 // s is removed from CBC(p) if it is invalid. If there is an adjacent tet of //
15540 // s which is in BC(p), it gets removed from BC(p) too. If CBC(p) is updated,//
15541 // C(p) is re-formed.                                                        //
15542 //                                                                           //
15543 // A C(p) is valid if all its edges are on the hull of BC(p).  An edge e of  //
15544 // C(p) may be inside BC(p) if e is a segment and belongs to only one facet. //
15545 // To correct C(p), a tet of BC(p) which shields e gets removed.             //
15546 //                                                                           //
15547 // If BC(p) is formed with locally non-Delaunay check (b->conformdel > 0).   //
15548 // A boundary-consistent check is needed for non-segment edges of C(p). Let  //
15549 // e be such an edge, the subface f contains e and outside C(p) may belong   //
15550 // to B(p) due to the non-coplanarity of the facet definition.  The tet of   //
15551 // BC(p) containing f gets removed to avoid creating a degenerate new tet.   //
15552 //                                                                           //
15553 // 'cutcount' accumulates the total number of cuttets(not only by this call).//
15554 //                                                                           //
15556 
15557 void tetgenmesh::updatebowatcavitysub(list* sublist, list* subceillist,
15558   int* cutcount)
15559 {
15560   triface adjtet, rotface;
15561   face checksh, neighsh;
15562   face checkseg;
15563   point pa, pb, pc;
15564   REAL ori1, ori2;
15565   int remcount;
15566   int i, j;
15567 
15568   remcount = 0;
15569   // Check the validity of CBC(p).
15570   for (i = 0; i < sublist->len(); i++) {
15571     checksh = * (face *)(* sublist)[i];
15572     // Check two adjacent tets of s.
15573     for (j = 0; j < 2; j++) {
15574       stpivot(checksh, adjtet);
15575       if (adjtet.tet != dummytet) {
15576         if (!infected(adjtet)) {
15577           // Could be either case (1) or (2).
15578           suninfect(checksh); // s survives.
15579           // If the sym. adjtet exists, it should remove from BC(p) too.
15580           sesymself(checksh);
15581           stpivot(checksh, adjtet);
15582           if (adjtet.tet != dummytet) {
15583             if (infected(adjtet)) {
15584               // Found an adj. tet in BC(p), remove it.
15585               uninfect(adjtet);
15586               (*cutcount)++;
15587             }
15588           }
15589           // Remove s from C(p).
15590           sublist->del(i, 1);
15591           i--;
15592           remcount++;
15593           break;
15594         }
15595       }
15596       sesymself(checksh);
15597     }
15598   }
15599   if (remcount > 0) {
15600     if (b->verbose > 2) {
15601       printf("    Removed %d subfaces from CBC(p).\n", remcount);
15602     }
15603     // Re-generate C(p).
15604     subceillist->clear();
15605     for (i = 0; i < sublist->len(); i++) {
15606       checksh = * (face *)(* sublist)[i];
15607       for (j = 0; j < 3; j++) {
15608         spivot(checksh, neighsh);
15609         if (!sinfected(neighsh)) {
15610           subceillist->append(&checksh);
15611         }
15612         senextself(checksh);
15613       }
15614     }
15615     if (b->verbose > 2) {
15616       printf("    Update CBC(p): %d subs, %d edges.\n", sublist->len(),
15617              subceillist->len());
15618     }
15619   }
15620 
15621   // Check the validity of C(p).
15622   for (i = 0; i < subceillist->len(); i++) {
15623     checksh = * (face *)(* subceillist)[i];
15624     sspivot(checksh, checkseg);
15625     if (checkseg.sh != dummysh) {
15626       // A segment. Check if it is inside BC(p).
15627       stpivot(checksh, adjtet);
15628       if (adjtet.tet == dummytet) {
15629         sesym(checksh, neighsh);
15630         stpivot(neighsh, adjtet);
15631       }
15632       findedge(&adjtet, sorg(checkseg), sdest(checkseg));
15633       adjustedgering(adjtet, CCW);
15634       fnext(adjtet, rotface); // It's the same tet.
15635       // Rotate rotface (f), stop on either of the following cases:
15636       //   (a) meet a subface, or
15637       //   (b) enter an uninfected tet, or
15638       //   (c) rewind back to adjtet.
15639       do {
15640         if (!infected(rotface)) break; // case (b)
15641         tspivot(rotface, neighsh);
15642         if (neighsh.sh != dummysh) break; // case (a)
15643         // Go to the next tet of the facing ring.
15644         fnextself(rotface);
15645       } while (apex(rotface) != apex(adjtet));
15646       // Is it case (c)?
15647       if (apex(rotface) == apex(adjtet)) {
15648         // The segment is enclosed by BC(p), invalid cavity.
15649         pa = org(adjtet);
15650         pb = dest(adjtet);
15651         pc = apex(adjtet);
15652         // Find the shield tet and cut it. Notice that the shield tet may
15653         //   not be unique when there are four coplanar points, ie.,
15654         //   ori1 * ori2 == 0.0. In such case, choose either of them.
15655         fnext(adjtet, rotface);
15656         do {
15657           fnextself(rotface);
15658           assert(infected(rotface));
15659           ori1 = orient3d(pa, pb, pc, apex(rotface));
15660           ori2 = orient3d(pa, pb, pc, oppo(rotface));
15661         } while (ori1 * ori2 > 0.0);
15662         // Cut this tet from BC(p).
15663         uninfect(rotface);
15664         (*cutcount)++;
15665       }
15666     } else {
15667       /*// An edge. Check if boundary-consistency should be enforced.
15668       if (b->conformdel > 0) {
15669         // Get the adj-sub n at e, it must be outside C(p).
15670         spivot(checksh, neighsh);
15671         assert(!sinfected(neighsh));
15672         // Check if n is on B(p).
15673         for (j = 0; j < 2; j++) {
15674           stpivot(neighsh, adjtet);
15675           if (adjtet.tet != dummytet) {
15676             if (infected(adjtet)) {
15677               uninfect(adjtet);
15678               (*cutcount)++;
15679             }
15680           }
15681           sesymself(neighsh);
15682         }
15683       } */
15684     }
15685   }
15686 }
15687 
15689 //                                                                           //
15690 // trimbowatcavity()    Validate B(p), CBC(p)s and C(p)s, update BC(p).      //
15691 //                                                                           //
15692 // A B(p) is valid if all its faces are visible by p. If a face f of B(p) is //
15693 // found invisible by p, the tet of BC(p) containing f gets removed and B(p) //
15694 // is refromed. The new B(p) may still contain invisible faces by p. Iterat- //
15695 // ively do the above procedure until B(p) is satisfied.                     //
15696 //                                                                           //
15697 // A CBC(p) is valid if each subface of CBC(p) is either on the hull of BC(p)//
15698 // or completely inside BC(p). If a subface s of CBC(p) is not valid, it is  //
15699 // removed from CBC(p) and C(p) is reformed. If there exists a tet t of BC(p)//
15700 // containg s, t is removed from BC(p). The process for validating BC(p) and //
15701 // B(p) is re-excuted.                                                       //
15702 //                                                                           //
15703 // A C(p) is valid if each edge of C(p) is on the hull of BC(p). If an edge  //
15704 // e of C(p) is invalid (e should be a subsegment which only belong to one   //
15705 // facet), a tet of BC(p) which contains e and has two other faces shielding //
15706 // e is removed. The process for validating BC(p) and B(p) is re-excuted.    //
15707 //                                                                           //
15708 // If either BC(p) or CBC(p) becomes empty. No valid BC(p) is found, return  //
15709 // FALSE. else, return TRUE.                                                 //
15710 //                                                                           //
15712 
15713 bool tetgenmesh::trimbowatcavity(point bp, face* bpseg, int n, list** sublists,
15714   list** subceillists, list** tetlists, list** ceillists, REAL maxcosd)
15715 {
15716   bool valflag;
15717   int oldnum, cutnum, cutcount;
15718   int i;
15719 
15720   cutnum = 0; // Count the total number of cut-off tets of BC(p).
15721   valflag = true;
15722 
15723   do {
15724     // Validate BC(p), B(p).
15725     for (i = 0; i < n && valflag; i++) {
15726       oldnum = tetlists[i]->len();
15727       // Iteratively validate BC_i(p) and B_i(p).
15728       while (!validatebowatcavityquad(bp, ceillists[i], maxcosd)) {
15729         // Update BC_i(p) and B_i(p).
15730         updatebowatcavityquad(tetlists[i], ceillists[i]);
15731         valflag = tetlists[i]->len() > 0;
15732       }
15733       cutnum += (oldnum - tetlists[i]->len());
15734     }
15735     if (valflag && (sublists != (list **) NULL)) {
15736       // Validate CBC(p), C(p).
15737       cutcount = 0;
15738       for (i = 0; i < n; i++) {
15739         updatebowatcavitysub(sublists[i], subceillists[i], &cutcount);
15740         // Only do once if p is on a facet.
15741         if (bpseg == (face *) NULL) break;
15742       }
15743       // Are there cut tets?
15744       if (cutcount > 0) {
15745         // Squeeze all cut tets in BC(p), keep valflag once it gets FLASE.
15746         for (i = 0; i < n; i++) {
15747           if (tetlists[i]->len() > 0) {
15748             updatebowatcavityquad(tetlists[i], ceillists[i]);
15749             if (valflag) {
15750               valflag = tetlists[i]->len() > 0;
15751             }
15752           }
15753         }
15754         cutnum += cutcount;
15755         // Go back to valid the updated BC(p).
15756         continue;
15757       }
15758     }
15759     break; // Leave the while-loop.
15760   } while (true);
15761 
15762   // Check if any CBC(p) becomes non-empty.
15763   if (valflag && (sublists != (list **) NULL)) {
15764     for (i = 0; i < n && valflag; i++) {
15765       valflag = (sublists[i]->len() > 0);
15766       if (bpseg == (face *) NULL) break;
15767     }
15768   }
15769 
15770   if (valflag && (cutnum > 0)) {
15771     // Accumulate counters.
15772     if (bpseg != (face *) NULL) {
15773       updsegcount++;
15774     } else if (sublists != (list **) NULL) {
15775       updsubcount++;
15776     } else {
15777       updvolcount++;
15778     }
15779   }
15780 
15781   if (!valflag) {
15782     // Accumulate counters.
15783     if (bpseg != (face *) NULL) {
15784       failsegcount++;
15785     } else if (sublists != (list **) NULL) {
15786       failsubcount++;
15787     } else {
15788       failvolcount++;
15789     }
15790   }
15791 
15792   return valflag;
15793 }
15794 
15796 //                                                                           //
15797 // bowatinsertsite()    Insert a point using the Bowyer-Watson method.       //
15798 //                                                                           //
15799 // Parameters: 'bp' = p, 'splitseg' = S, 'n' = the number of quadrants,      //
15800 // 'sublists', an array of CBC_i(p)s, 'subceillists', an array of C_i(p)s,   //
15801 // 'tetlists', an array of BC_i(p)s, 'ceillists', an array of B_i(p)s.       //
15802 //                                                                           //
15803 // If p is inside the mesh domain, then S = NULL, n = 1, CBC(p) and C(p) are //
15804 //   NULLs. 'tetlists[0]' = BC(p), 'ceillists[0]' = B(p).                    //
15805 // If p is on a facet F, then S = NULL, n = 2, and 'subceillists[0]' = C(p), //
15806 //  'subceillists[1]' is not needed (set it to NULL). B_1(p) and B_2(p) are  //
15807 //  in 'ceillists[0]' and 'ceillists[1]'.                                    //
15808 // If p is on a segment S, then F(S) is a list of subfaces around S, and n = //
15809 //   len(F(S)), there are n C_i(p)s and B_i(p)s supplied in 'subceillists[i]'//
15810 //   and 'ceillists[i]'.                                                     //
15811 //                                                                           //
15812 // If 'verlist' != NULL, it returns a list of vertices which connect to p.   //
15813 //   This vertices are used for interpolating size of p.                     //
15814 //                                                                           //
15815 // If 'flipque' != NULL, it returns a list of internal faces of new tets in  //
15816 //   BC(p), faces on C(p)s are excluded. These faces may be locally non-     //
15817 //   Delaunay and will be flipped if they are flippable. Such non-Delaunay   //
15818 //   faces may exist when p is inserted to split an encroaching segment.     //
15819 //                                                                           //
15820 // 'chkencseg', 'chkencsub', and 'chkbadtet' are flags that indicate whether //
15821 // or not there should be checks for the creation of encroached subsegments, //
15822 // subfaces, or bad quality tets. If 'chkencseg' = TRUE, the encroached sub- //
15823 // segments are added to the list of subsegments to be split.                //
15824 //                                                                           //
15825 // On return, 'ceillists' returns Star(p).                                   //
15826 //                                                                           //
15828 
15829 void tetgenmesh::bowatinsertsite(point bp,face* splitseg,int n,list** sublists,
15830   list** subceillists, list** tetlists, list** ceillists, list* verlist,
15831   queue* flipque, bool chkencseg, bool chkencsub, bool chkbadtet)
15832 {
15833   list *ceillist, *subceillist;
15834   triface oldtet, newtet, newface, rotface, neightet;
15835   face oldsh, newsh, newedge, checksh;
15836   face spinsh, casingin, casingout;
15837   face *apsegshs, *pbsegshs;
15838   face apseg, pbseg, checkseg;
15839   point pa, pb, pc;
15840   REAL attrib, volume;
15841   int idx, i, j, k;
15842 
15843   apsegshs = NULL;
15844   pbsegshs = NULL;
15845 
15846   if (b->verbose > 1) {
15847     printf("    Insert point %d (%.12g, %.12g, %.12g)", pointmark(bp), bp[0],
15848            bp[1], bp[2]);
15849   }
15850   if (splitseg != (face *) NULL) {
15851     if (b->verbose > 1) {
15852       printf(" on segment.\n");
15853     }
15854     bowatsegcount++;
15855   } else {
15856     if (subceillists != (list **) NULL) {
15857       if (b->verbose > 1) {
15858         printf(" on facet.\n");
15859       }
15860       bowatsubcount++;
15861     } else {
15862       if (b->verbose > 1) {
15863         printf(" in volume.\n");
15864       }
15865       bowatvolcount++;
15866     }
15867   }
15868 
15869   // Create new tets to fill B(p).
15870   for (k = 0; k < n; k++) {
15871     // Create new tets from each B_i(p).
15872     ceillist = ceillists[k];
15873     for (i = 0; i < ceillist->len(); i++) {
15874       oldtet = * (triface *)(* ceillist)[i];
15875       adjustedgering(oldtet, CCW);
15876       pa = org(oldtet);
15877       pb = dest(oldtet);
15878       pc = apex(oldtet);
15879       maketetrahedron(&newtet);
15880       setorg(newtet, pa);
15881       setdest(newtet, pb);
15882       setapex(newtet, pc);
15883       setoppo(newtet, bp);
15884       for (j = 0; j < in->numberoftetrahedronattributes; j++) {
15885         attrib = elemattribute(oldtet.tet, j);
15886         setelemattribute(newtet.tet, j, attrib);
15887       }
15888       if (b->varvolume) {
15889         volume = volumebound(oldtet.tet);
15890         if (volume > 0.0) {
15891           if (!b->fixedvolume && b->refine) {
15892             // '-r -a' switches and a .vol file case. Enlarge the maximum
15893             //   volume constraint for the new tets. Hence the new points
15894             //   only spread near the original constrained tet.
15895             volume *= 1.2;
15896           }
15897         }
15898         setvolumebound(newtet.tet, volume);
15899       }
15900       sym(oldtet, neightet);
15901       tspivot(oldtet, checksh);
15902       if (neightet.tet != dummytet) {
15903         bond(newtet, neightet);
15904       }
15905       if (checksh.sh != dummysh) {
15906         tsbond(newtet, checksh);
15907       }
15908       if (verlist != (list *) NULL) {
15909         // Collect vertices connecting to p.
15910         idx = pointmark(pa);
15911         if (idx >= 0) {
15912           setpointmark(pa, -idx - 1);
15913           verlist->append(&pa);
15914         }
15915         idx = pointmark(pb);
15916         if (idx >= 0) {
15917           setpointmark(pb, -idx - 1);
15918           verlist->append(&pb);
15919         }
15920         idx = pointmark(pc);
15921         if (idx >= 0) {
15922           setpointmark(pc, -idx - 1);
15923           verlist->append(&pc);
15924         }
15925       }
15926       // Replace the tet by the newtet for checking the quality.
15927       * (triface *)(* ceillist)[i] = newtet;
15928     }
15929   }
15930   if (verlist != (list *) NULL) {
15931     // Uninfect collected vertices.
15932     for (i = 0; i < verlist->len(); i++) {
15933       pa = * (point *)(* verlist)[i];
15934       idx = pointmark(pa);
15935       setpointmark(pa, -(idx + 1));
15936     }
15937   }
15938 
15939   // Connect new tets of B(p). Not all faces of new tets can be connected,
15940   //   e.g., if there are empty B_i(p)s.
15941   for (k = 0; k < n; k++) {
15942     ceillist = ceillists[k];
15943     for (i = 0; i < ceillist->len(); i++) {
15944       newtet = * (triface *)(* ceillist)[i];
15945       newtet.ver = 0;
15946       for (j = 0; j < 3; j++) {
15947         fnext(newtet, newface);
15948         sym(newface, neightet);
15949         if (neightet.tet == dummytet) {
15950           // Find the neighbor face by rotating the faces at edge ab.
15951           esym(newtet, rotface);
15952           pa = org(rotface);
15953           pb = dest(rotface);
15954           while (fnextself(rotface));
15955           // Do we meet a boundary face?
15956           tspivot(rotface, checksh);
15957           if (checksh.sh != dummysh) {
15958             // Walk through the boundary and continue to rotate faces.
15959             do {
15960               findedge(&checksh, pa, pb);
15961               sfnextself(checksh);
15962               assert((sorg(checksh) == pa) && (sdest(checksh) == pb));
15963               stpivot(checksh, rotface);
15964               if (infected(rotface)) {
15965                 // Meet an old tet of B_i(p). This side is on the hull and
15966                 //   will be connected to a new subface created in C(p).
15967                 break;
15968               }
15969               findedge(&rotface, pa, pb);
15970               while (fnextself(rotface));
15971               tspivot(rotface, checksh);
15972             } while (checksh.sh != dummysh);
15973           }
15974           // The rotface has edge ab, but it may not have newpt.
15975           if (apex(rotface) == apex(newface)) {
15976             // Bond the two tets together.
15977             bond(newface, rotface);
15978             // Queue (uniquely) this face if 'flipque' is given.
15979             if (flipque != (queue *) NULL) {
15980               enqueueflipface(newface, flipque);
15981             }
15982           }
15983         }
15984         enextself(newtet);
15985       }
15986     }
15987   }
15988 
15989   if (subceillists != (list **) NULL) {
15990     // There are C(p)s.
15991     if (splitseg != (face *) NULL) {
15992       // S (ab) is split by p.
15993       splitseg->shver = 0;
15994       pa = sorg(*splitseg);
15995       pb = sdest(*splitseg);
15996       // Allcate two arrays for saving the subface rings of the two new
15997       //   segments a->p and p->b.
15998       apsegshs = new face[n];
15999       pbsegshs = new face[n];
16000     }
16001 
16002     // For each C_k(p), do the following:
16003     //   (1) Create new subfaces to fill C_k(p), insert them into B(p);
16004     //   (2) Connect new subfaces to each other;
16005     for (k = 0; k < n; k++) {
16006       subceillist = subceillists[k];
16007 
16008       // Check if 'hullsize' should be updated.
16009       oldsh = * (face *)(* subceillist)[0];
16010       stpivot(oldsh, neightet);
16011       if (neightet.tet != dummytet) {
16012         sesymself(oldsh);
16013         stpivot(oldsh, neightet);
16014       }
16015       if (neightet.tet == dummytet) {
16016         // The hull size changes.
16017         hullsize += (subceillist->len() - sublists[k]->len());
16018       }
16019 
16020       // (1) Create new subfaces to fill C_k(p), insert them into B(p).
16021       for (i = 0; i < subceillist->len(); i++) {
16022         oldsh = * (face *)(* subceillist)[i];
16023         makeshellface(subfaces, &newsh);
16024         setsorg(newsh, sorg(oldsh));
16025         setsdest(newsh, sdest(oldsh));
16026         setsapex(newsh, bp);
16027         if (b->quality && varconstraint) {
16028           setareabound(newsh, areabound(oldsh));
16029         }
16030         setshellmark(newsh, shellmark(oldsh));
16031         setshelltype(newsh, shelltype(oldsh));
16032         if (checkpbcs) {
16033           setshellpbcgroup(newsh, shellpbcgroup(oldsh));
16034         }
16035         // Replace oldsh by newsh at the edge.
16036         spivot(oldsh, casingout);
16037         sspivot(oldsh, checkseg);
16038         if (checkseg.sh != dummysh) {
16039           // A segment. Insert s into the face ring, ie, s_in -> s -> s_out.
16040           if (oldsh.sh != casingout.sh) {
16041             // s is not bonded to itself.
16042             spinsh = casingout;
16043             do {
16044               casingin = spinsh;
16045               spivotself(spinsh);
16046             } while (sapex(spinsh) != sapex(oldsh));
16047             assert(casingin.sh != oldsh.sh);
16048             // Bond s_in -> s -> s_out (and dissolve s_in -> s_old -> s_out).
16049             sbond1(casingin, newsh);
16050             sbond1(newsh, casingout);
16051           } else {
16052             // Bond newsh -> newsh.
16053             sbond(newsh, newsh);
16054           }
16055           // Bond the segment.
16056           ssbond(newsh, checkseg);
16057         } else {
16058           // Bond s <-> s_out (and dissolve s_out -> s_old).
16059           sbond(newsh, casingout);
16060         }
16061 
16062         // Insert newsh into B(p). Use the coonections of oldsh.
16063         stpivot(oldsh, neightet);
16064         if (neightet.tet == dummytet) {
16065           sesymself(oldsh);
16066           sesymself(newsh); // Keep the same orientation as oldsh.
16067           stpivot(oldsh, neightet);
16068         }
16069         assert(infected(neightet));
16070         // Set on the rotating edge.
16071         findedge(&neightet, sorg(oldsh), sdest(oldsh));
16072         // Choose the rotating direction (to the inside of B(p)).
16073         adjustedgering(neightet, CCW);
16074         rotface = neightet;
16075         // Rotate face. Stop at a non-infected tet t (not in B(p)) or a
16076         //   hull face f (on B(p)). Get the neighbor n of t or f.  n is
16077         //   a new tet that has just been created to fill B(p).
16078         do {
16079           fnextself(rotface);
16080           sym(rotface, neightet);
16081           if (neightet.tet == dummytet) {
16082             tspivot(rotface, checksh);
16083             assert(checksh.sh != dummysh);
16084             stpivot(checksh, newtet);
16085             break;
16086           } else if (!infected(neightet)) {
16087             sym(neightet, newtet);
16088             break;
16089           }
16090         } while (true);
16091         assert(newtet.tet != rotface.tet);
16092         // Set the rotating edge of n.
16093         findedge(&newtet, sorg(oldsh), sdest(oldsh));
16094         // Choose the rotating direction (to the inside of B(p)).
16095         adjustedgering(newtet, CCW);
16096         fnext(newtet, newface);
16097         assert(apex(newface) == bp);
16098         // newsh has already been oriented toward n.
16099         tsbond(newface, newsh);
16100         sym(newface, neightet); // 'neightet' maybe outside.
16101         sesymself(newsh);
16102         tsbond(neightet, newsh); // Bond them anyway.
16103 
16104         // Replace oldsh by newsh in list.
16105         * (face *)(* subceillist)[i] = newsh;
16106       }
16107 
16108       // (2) Connect new subfaces to each other.
16109       for (i = 0; i < subceillist->len(); i++) {
16110         // Get a face cdp.
16111         newsh = * (face *)(* subceillist)[i];
16112         // Get a new tet containing cdp.
16113         stpivot(newsh, newtet);
16114         if (newtet.tet == dummytet) {
16115           sesymself(newsh);
16116           stpivot(newsh, newtet);
16117         }
16118         for (j = 0; j < 2; j++) {
16119           if (j == 0) {
16120             senext(newsh, newedge); // edge dp.
16121           } else {
16122             senext2(newsh, newedge); // edge pc.
16123             sesymself(newedge); // edge cp.
16124           }
16125           if (splitseg != (face *) NULL) {
16126             // Don not operate on newedge if it is ap or pb.
16127             if (sorg(newedge) == pa) {
16128               apsegshs[k] = newedge;
16129               continue;
16130             } else if (sorg(newedge) == pb) {
16131               pbsegshs[k] = newedge;
16132               continue;
16133             }
16134           }
16135           // There should no segment inside the cavity. Check it.
16136           sspivot(newedge, checkseg);
16137           assert(checkseg.sh == dummysh);
16138           spivot(newedge, casingout);
16139           if (casingout.sh == dummysh) {
16140             rotface = newtet;
16141             findedge(&rotface, sorg(newedge), sdest(newedge));
16142             // Rotate newtet until meeting a new subface which contains
16143             //   newedge. It must exist since newedge is not a seg.
16144             adjustedgering(rotface, CCW);
16145             do {
16146               fnextself(rotface);
16147               tspivot(rotface, checksh);
16148               if (checksh.sh != dummysh) break;
16149             } while (true);
16150             findedge(&checksh, sorg(newedge), sdest(newedge));
16151             sbond(newedge, checksh);
16152           }
16153         }
16154       }
16155       // Only do once if p is on a facet.
16156       if (splitseg == (face *) NULL) break;
16157     } // for (k = 0; k < n; k++)
16158 
16159     if (splitseg != (face *) NULL) {
16160       // Update a->b to be a->p.
16161       apseg = *splitseg;
16162       setsdest(apseg, bp);
16163       // Create a new subsegment p->b.
16164       makeshellface(subsegs, &pbseg);
16165       setsorg(pbseg, bp);
16166       setsdest(pbseg, pb);
16167       // p->b gets the same mark and segment type as a->p.
16168       setshellmark(pbseg, shellmark(apseg));
16169       setshelltype(pbseg, shelltype(apseg));
16170       if (b->quality && varconstraint) {
16171         // Copy the area bound into the new subsegment.
16172         setareabound(pbseg, areabound(apseg));
16173       }
16174       senext(apseg, checkseg);
16175       // Get the old connection at b of a->b.
16176       spivot(checkseg, casingout);
16177       // Bond a->p and p->b together.
16178       senext2(pbseg, casingin);
16179       sbond(casingin, checkseg);
16180       if (casingout.sh != dummysh) {
16181         // There is a subsegment connect at b of p->b.
16182         casingout.shver = 0;
16183 #ifdef SELF_CHECK
16184         assert(sorg(casingout) == pb);
16185 #endif
16186         senext2self(casingout);
16187         senext(pbseg, casingin);
16188         sbond(casingin, casingout);
16189       }
16190 
16191       // Bond all new subfaces to a->p and p->b.
16192       for (i = 0; i < n; i++) {
16193         spinsh = apsegshs[i];
16194         findedge(&spinsh, pa, bp);
16195         ssbond(spinsh, apseg);
16196         spinsh = pbsegshs[i];
16197         findedge(&spinsh, bp, pb);
16198         ssbond(spinsh, pbseg);
16199       }
16200       // Bond all subfaces share at a->p together.
16201       for (i = 0; i < n; i++) {
16202         spinsh = apsegshs[i];
16203         if (i < (n - 1)) {
16204           casingout = apsegshs[i + 1];
16205         } else {
16206           casingout = apsegshs[0];
16207         }
16208         sbond1(spinsh, casingout);
16209       }
16210       // Bond all subfaces share at p->b together.
16211       for (i = 0; i < n; i++) {
16212         spinsh = pbsegshs[i];
16213         if (i < (n - 1)) {
16214           casingout = pbsegshs[i + 1];
16215         } else {
16216           casingout = pbsegshs[0];
16217         }
16218         sbond1(spinsh, casingout);
16219       }
16220       delete [] apsegshs;
16221       delete [] pbsegshs;
16222 
16223       // Check for newly encroached subsegments if the flag is set.
16224       if (chkencseg) {
16225         // Check if a->p and p->b are encroached by other vertices.
16226         checkseg4encroach(&apseg, NULL, NULL, true);
16227         checkseg4encroach(&pbseg, NULL, NULL, true);
16228         // Check if the adjacent segments are encroached by p.
16229         tallencsegs(bp, n, ceillists);
16230       }
16231     } // if (splitseg != (face *) NULL)
16232 
16233     // Delete subfaces of old CBC_i(p)s.
16234     for (k = 0; k < n; k++) {
16235       for (i = 0; i < sublists[k]->len(); i++) {
16236         oldsh = * (face *)(* (sublists[k]))[i];
16237         shellfacedealloc(subfaces, oldsh.sh);
16238       }
16239       // Clear the list so that the subs will not get unmarked later in
16240       //   routine releasebowatcavity() which only frees the memory.
16241       sublists[k]->clear();
16242       // Only do once if p is on a facet.
16243       if (splitseg == (face *) NULL) break;
16244     }
16245 
16246     // Check for newly encroached subfaces if the flag is set.
16247     if (chkencsub) {
16248       // Check if new subfaces of C_i(p) are encroached by other vertices.
16249       for (k = 0; k < n; k++) {
16250         subceillist = subceillists[k];
16251         for (i = 0; i < subceillist->len(); i++) {
16252           newsh = * (face *)(* subceillist)[i];
16253           checksub4encroach(&newsh, NULL, true);
16254         }
16255         // Only do once if p is on a facet.
16256         if (splitseg == (face *) NULL) break;
16257       }
16258       // Check if the adjacent subfaces are encroached by p.
16259       tallencsubs(bp, n, ceillists);
16260     }
16261   } // if (subceillists != (list **) NULL)
16262 
16263   // Delete tets of old BC_i(p)s.
16264   for (k = 0; k < n; k++) {
16265     for (i = 0; i < tetlists[k]->len(); i++) {
16266       oldtet = * (triface *)(* (tetlists[k]))[i];
16267       tetrahedrondealloc(oldtet.tet);
16268     }
16269     // Clear the list so that the tets will not get unmarked later in
16270     //   routine releasebowatcavity() which only frees the memory.
16271     tetlists[k]->clear();
16272   }
16273 
16274   // check for bad quality tets if the flags is set.
16275   if (chkbadtet) {
16276     for (k = 0; k < n; k++) {
16277       ceillist = ceillists[k];
16278       for (i = 0; i < ceillist->len(); i++) {
16279         newtet = * (triface *)(* ceillist)[i];
16280         checktet4badqual(&newtet, true);
16281       }
16282     }
16283   }
16284 
16285   if (flipque != (queue *) NULL) {
16286     // Newly created internal faces of BC(p) (excluding faces on C(p)s) are
16287     //   in 'flipque'.  Some of these faces may be locally non-Delaunay due,
16288     //   to the existence of non-constrained tets. check and fix them.
16289     repairflipcount += flip(flipque, NULL);
16290   }
16291 }
16292 
16293 //
16294 // End of mesh transformation routines
16295 //
16296 
16297 //
16298 // Begin Delaunay tetrahedralization routines
16299 //
16300 
16302 //                                                                           //
16303 // formstarpolyhedron()    Get the star ployhedron of a point 'pt'.          //
16304 //                                                                           //
16305 // The polyhedron P is formed by faces of tets having 'pt' as a vertex.  If  //
16306 // 'complete' is TRUE, P is the complete star of 'pt'. Otherwise, P is boun- //
16307 // ded by subfaces, i.e. P is only part of the star of 'pt'.                 //
16308 //                                                                           //
16309 // 'tetlist' T returns the tets, it has one of such tets on input. Moreover, //
16310 // if t is in T, then oppo(t) = p.  Topologically, T is the star of p;  and  //
16311 // the faces of T is the link of p. 'verlist' V returns the vertices of T.   //
16312 //                                                                           //
16314 
16315 void tetgenmesh::formstarpolyhedron(point pt, list* tetlist, list* verlist,
16316   bool complete)
16317 {
16318   triface starttet, neightet;
16319   face checksh;
16320   point ver[3];
16321   int idx, i, j;
16322 
16323   // Get a tet t containing p.
16324   starttet = * (triface *)(* tetlist)[0];
16325   // Let oppo(t) = p.
16326   for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
16327     if (oppo(starttet) == pt) break;
16328   }
16329   assert(starttet.loc < 4);
16330   // Add t into T.
16331   * (triface *)(* tetlist)[0] = starttet;
16332   infect(starttet);
16333   if (verlist != (list *) NULL) {
16334     // Add three verts of t into V.
16335     ver[0] = org(starttet);
16336     ver[1] = dest(starttet);
16337     ver[2] = apex(starttet);
16338     for (i = 0; i < 3; i++) {
16339       // Mark the vert by inversing the index of the vert.
16340       idx = pointmark(ver[i]);
16341       setpointmark(ver[i], -idx - 1); // -1 to distinguish the zero.
16342       verlist->append(&(ver[i]));
16343     }
16344   }
16345 
16346   // Find other tets by a broadth-first search.
16347   for (i = 0; i < tetlist->len(); i++) {
16348     starttet = * (triface *)(* tetlist)[i];
16349     starttet.ver = 0;
16350     for (j = 0; j < 3; j++) {
16351       fnext(starttet, neightet);
16352       tspivot(neightet, checksh);
16353       // Should we cross a subface.
16354       if ((checksh.sh == dummysh) || complete) {
16355         // Get the neighbor n.
16356         symself(neightet);
16357         if ((neightet.tet != dummytet) && !infected(neightet)) {
16358           // Let oppo(n) = p.
16359           for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
16360             if (oppo(neightet) == pt) break;
16361           }
16362           assert(neightet.loc < 4);
16363           // Add n into T.
16364           infect(neightet);
16365           tetlist->append(&neightet);
16366           if (verlist != (list *) NULL) {
16367             // Add the apex vertex in n into V.
16368             ver[0] = org(starttet);
16369             ver[1] = dest(starttet);
16370             findedge(&neightet, ver[0], ver[1]);
16371             ver[2] = apex(neightet);
16372             idx = pointmark(ver[2]);
16373             if (idx >= 0) {
16374               setpointmark(ver[2], -idx - 1);
16375               verlist->append(&(ver[2]));
16376             }
16377           }
16378         }
16379       }
16380       enextself(starttet);
16381     }
16382   }
16383 
16384   // Uninfect tets.
16385   for (i = 0; i < tetlist->len(); i++) {
16386     starttet = * (triface *)(* tetlist)[i];
16387     uninfect(starttet);
16388   }
16389   if (verlist != (list *) NULL) {
16390     // Uninfect vertices.
16391     for (i = 0; i < verlist->len(); i++) {
16392       ver[0] = * (point *)(* verlist)[i];
16393       idx = pointmark(ver[0]);
16394       setpointmark(ver[0], -(idx + 1));
16395     }
16396   }
16397 }
16398 
16400 //                                                                           //
16401 // unifypoint()    Unify two distinct points if they're very close.          //
16402 //                                                                           //
16403 // This function is used for dealing with inputs from CAD tools.  Two points //
16404 // p and q are unified if: dist(p, q) / longest < eps.  Where dist() is the  //
16405 // Euclidean distance between p and q, longest is the maximum edge size of   //
16406 // the input point set, eps is the tolerrence specified by user, default is  //
16407 // 1e-6, it can be adjusted by '-T' switch.                                  //
16408 //                                                                           //
16410 
16411 bool tetgenmesh::unifypoint(point testpt, triface *starttet, enum locateresult
16412   loc, REAL eps)
16413 {
16414   triface symtet, spintet;
16415   point checkpt, tapex;
16416   REAL tol;
16417   bool merged;
16418   int hitbdry;
16419   int i;
16420 
16421   merged = false;
16422   tol = longest * eps;
16423   if ((loc == OUTSIDE) || (loc == INTETRAHEDRON) || (loc == ONFACE)) {
16424     // Check p is close to the four corners of the tet.
16425     for (i = 0; i < 4; i++) {
16426       checkpt = (point) starttet->tet[4 + i];
16427       if (distance(testpt, checkpt) < tol) {
16428         merged = true; // Found a merge point p'.
16429         break;
16430       }
16431     }
16432     if (!merged && (loc == ONFACE)) {
16433       // Check the opposite point of the neighbor tet if it exists.
16434       sym(*starttet, symtet);
16435       if (symtet.tet != dummytet) {
16436         checkpt = oppo(symtet);
16437         if (distance(testpt, checkpt) < tol) {
16438           merged = true; // Found a merge point p'.
16439         }
16440       }
16441     }
16442   } else if (loc == ONEDGE) {
16443     // Check two endpoints of the edge.
16444     checkpt = org(*starttet);
16445     if (distance(testpt, checkpt) < tol) {
16446       merged = true; // Found a merge point p'.
16447     }
16448     if (!merged) {
16449       checkpt = dest(*starttet);
16450       if (distance(testpt, checkpt) < tol) {
16451         merged = true; // Found a merge point p'.
16452       }
16453     }
16454     if (!merged) {
16455       // Check apexes of the faces having the edge.
16456       spintet = *starttet;
16457       tapex = apex(*starttet);
16458       hitbdry = 0;
16459       do {
16460         checkpt = apex(spintet);
16461         if (distance(testpt, checkpt) < tol) {
16462           merged = true; // Found a merge point p'.
16463           break;
16464         }
16465         if (!fnextself(spintet)) {
16466           hitbdry++;
16467           if (hitbdry < 2) {
16468             esym(*starttet, spintet);
16469             if (!fnextself(spintet)) {
16470               hitbdry++;
16471             }
16472           }
16473         }
16474       } while ((apex(spintet) != tapex) && (hitbdry < 2));
16475     }
16476   }
16477   if (merged) {
16478     if (b->object != tetgenbehavior::STL) {
16479       if (!b->quiet) {
16480         printf("Warning:  Point %d is unified to point %d.\n",
16481                pointmark(testpt), pointmark(checkpt));
16482       }
16483       // Count the number of duplicated points.
16484       dupverts++;
16485     }
16486     // Remember it is a duplicated point.
16487     setpointtype(testpt, DUPLICATEDVERTEX);
16488     // Set a pointer to the point it duplicates.
16489     setpoint2ppt(testpt, checkpt);
16490   }
16491   return merged;
16492 }
16493 
16495 //                                                                           //
16496 // incrflipdelaunay()   Construct a delaunay tetrahedrization from a set of  //
16497 //                      3D points by the incremental flip algorithm.         //
16498 //                                                                           //
16499 // The incremental flip algorithm (by Edelsbrunner and Shah) can be describ- //
16500 // ed as follows:                                                            //
16501 //                                                                           //
16502 //   S be a set of points in 3D, Let 4 <= i <= n and assume that the         //
16503 //   Delaunay tetrahedralization of the first i-1 points in S is already     //
16504 //   constructed; call it D(i-1). Add the i-th point p_i (belong to S) to    //
16505 //   D(i-1), and restore Delaunayhood by flipping; this result in D(i).      //
16506 //   Repeat this procedure until i = n.                                      //
16507 //                                                                           //
16508 // This strategy always leads to the Delaunay triangulation of a point set.  //
16509 // The return value is the number of convex hull faces of D.                 //
16510 //                                                                           //
16512 
16513 void tetgenmesh::incrflipdelaunay(triface* oldtet, point* insertarray,
16514   long arraysize, bool jump, bool merge, REAL eps, queue* flipque)
16515 {
16516   triface newtet, searchtet;
16517   point swappt, lastpt;
16518   enum locateresult loc;
16519   REAL det, n[3];
16520   REAL attrib, volume;
16521   int i, j;
16522 #ifdef SELF_CHECK
16523   clock_t loc_start, loc_end;
16524 #endif
16525 
16526   det = 0.0;
16527   if (b->verbose > 0) {
16528     printf("  Creating initial tetrahedralization.\n");
16529   }
16530 
16531   // The initial tetrahedralization T only has one tet formed by 4 affinely
16532   //   linear independent vertices of the point set V = 'insertarray'. The
16533   //   first point a = insertarray[0].
16534 
16535   // Get the second point b, that is not identical or very close to a.
16536   for (i = 1; i < arraysize; i++) {
16537     det = distance(insertarray[0], insertarray[i]);
16538     if (det > (longest * eps)) break;
16539   }
16540   if (i == arraysize) {
16541     printf("\nAll points seem to be identical.\n");
16542     return;
16543   } else {
16544     // Swap to move b from index i to index 1.
16545     swappt = insertarray[i];
16546     insertarray[i] = insertarray[1];
16547     insertarray[1] = swappt;
16548   }
16549   // Get the third point c, that is not collinear with a and b.
16550   for (i++; i < arraysize; i++) {
16551     if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
16552       break;
16553   }
16554   if (i == arraysize) {
16555     printf("\nAll points seem to be collinear.\n");
16556     return;
16557   } else {
16558     // Swap to move c from index i to index 2.
16559     swappt = insertarray[i];
16560     insertarray[i] = insertarray[2];
16561     insertarray[2] = swappt;
16562   }
16563   // Get the fourth point d, that is not coplanar with a, b, and c.
16564   for (i++; i < arraysize; i++) {
16565     det = orient3d(insertarray[0], insertarray[1], insertarray[2],
16566                    insertarray[i]);
16567     if (det == 0.0) continue;
16568     if (!iscoplanar(insertarray[0], insertarray[1], insertarray[2],
16569                     insertarray[i], det, eps)) break;
16570   }
16571   if (i == arraysize) {
16572     // It's a 2D problem.
16573     in->mesh_dim = 2;
16574     // All points are coplanar.
16575     if (b->plc) {
16576       // Create an abovepoint. Maybe a surface triangulation can be formed.
16577       facenormal(insertarray[0], insertarray[1], insertarray[2], n, &det);
16578       if (det != 0.0) for (j = 0; j < 3; j++) n[j] /= det;
16579       // Take the average edge length of the bounding box.
16580       det = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
16581       // Temporarily create a point. It will be removed by jettison();
16582       makepoint(&lastpt);
16583       for (j = 0; j < 3; j++) lastpt[j] = insertarray[0][j] + det * n[j];
16584       abovepoint = lastpt;
16585       det = orient3d(insertarray[0], insertarray[1], insertarray[2], lastpt);
16586       // The index of the next inserting point is 3.
16587       i = 3;
16588     } else {
16589       printf("\nAll points seem to be coplanar.\n");
16590       return;
16591     }
16592   } else {
16593     // Swap to move d from index i to index 3.
16594     swappt = insertarray[i];
16595     insertarray[i] = insertarray[3];
16596     insertarray[3] = swappt;
16597     lastpt = insertarray[3];
16598     // The index of the next inserting point is 4.
16599     i = 4;
16600   }
16601 
16602   // Create the initial tet.
16603   maketetrahedron(&newtet);
16604   if (det > 0.0) {
16605     // For keeping the positive orientation.
16606     swappt = insertarray[0];
16607     insertarray[0] = insertarray[1];
16608     insertarray[1] = swappt;
16609   }
16610   if (b->verbose > 2) {
16611     printf("  Create the first tet (%d, %d, %d, %d).\n",
16612            pointmark(insertarray[0]), pointmark(insertarray[1]),
16613            pointmark(insertarray[2]), pointmark(lastpt));
16614   }
16615   setorg(newtet, insertarray[0]);
16616   setdest(newtet, insertarray[1]);
16617   setapex(newtet, insertarray[2]);
16618   setoppo(newtet, lastpt);
16619   if (oldtet != (triface *) NULL) {
16620     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
16621       attrib = elemattribute(oldtet->tet, j);
16622       setelemattribute(newtet.tet, j, attrib);
16623     }
16624     if (b->varvolume) {
16625       volume = volumebound(oldtet->tet);
16626       setvolumebound(newtet.tet, volume);
16627     }
16628   }
16629   // Set vertex type be FREEVOLVERTEX if it has no type yet.
16630   if (pointtype(insertarray[0]) == UNUSEDVERTEX) {
16631     setpointtype(insertarray[0], FREEVOLVERTEX);
16632   }
16633   if (pointtype(insertarray[1]) == UNUSEDVERTEX) {
16634     setpointtype(insertarray[1], FREEVOLVERTEX);
16635   }
16636   if (pointtype(insertarray[2]) == UNUSEDVERTEX) {
16637     setpointtype(insertarray[2], FREEVOLVERTEX);
16638   }
16639   if (pointtype(lastpt) == UNUSEDVERTEX) {
16640     setpointtype(lastpt, FREEVOLVERTEX);
16641   }
16642   // Bond to 'dummytet' for point location.
16643   dummytet[0] = encode(newtet);
16644   if (b->verbose > 3) {
16645     printf("    Creating tetra ");
16646     printtet(&newtet);
16647   }
16648   // At init, all faces of this tet are hull faces.
16649   hullsize = 4;
16650 
16651   if (b->verbose > 0) {
16652     printf("  Incrementally inserting points.\n");
16653   }
16654 
16655   flip23s = flip32s = flip22s = flip44s = 0;
16656   searchtet.tet = (tetrahedron *) NULL;
16657 
16658   // Insert the rest of points, one by one.
16659   for (; i < arraysize; i++) {
16660     // Locate p_i in T.
16661 #ifdef SELF_CHECK
16662     loc_start = clock();
16663 #endif
16664     if (jump) {
16665       loc = locate(insertarray[i], &searchtet);
16666     } else {
16667       loc = preciselocate(insertarray[i], &searchtet, tetrahedrons->items);
16668     }
16669 #ifdef SELF_CHECK
16670     loc_end = clock();
16671     tloctime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16672 #endif
16673     // Keep current search state for next searching.
16674     recenttet = searchtet;
16675     if (loc == ONVERTEX) {
16676       if (b->object != tetgenbehavior::STL) {
16677         if (!b->quiet) {
16678           printf("Warning:  Point %d is identical with point %d.\n",
16679                  pointmark(insertarray[i]), pointmark(org(searchtet)));
16680         }
16681       }
16682       // Count the number of duplicated points.
16683       dupverts++;
16684       // Remember it is a duplicated point.
16685       setpointtype(insertarray[i], DUPLICATEDVERTEX);
16686       if (b->plc || b->refine) {
16687         // Set a pointer to the point it duplicates.
16688         setpoint2ppt(insertarray[i], org(searchtet));
16689       }
16690       continue; // p_i is not inserted.
16691     }
16692     if (merge) {
16693       // Unify p_i if it is too close to a point of T.
16694       if (unifypoint(insertarray[i], &searchtet, loc, eps)) {
16695         continue; // p_i is not inserted.
16696       }
16697     }
16698     // Insert p_i in T.
16699     if (loc != OUTSIDE) {
16700       if (b->verbose > 1) {
16701         printf("  Insert point %d in tetrahedralization.\n",
16702                pointmark(insertarray[i]));
16703       }
16704       if (loc == INTETRAHEDRON) {
16705         splittetrahedron(insertarray[i], &searchtet, flipque);
16706       } else if (loc == ONFACE) {
16707         splittetface(insertarray[i], &searchtet, flipque);
16708       } else if (loc == ONEDGE) {
16709         splittetedge(insertarray[i], &searchtet, flipque);
16710       }
16711     } else {
16712       if (b->verbose > 1) {
16713         printf("  Insert point %d on convex hull.\n",
16714                pointmark(insertarray[i]));
16715       }
16716       inserthullsite(insertarray[i], &searchtet, flipque);
16717     }
16718     if (pointtype(insertarray[i]) == UNUSEDVERTEX) {
16719       // p_i becomes a (volume) vertex of T.
16720       setpointtype(insertarray[i], FREEVOLVERTEX);
16721     }
16722 #ifdef SELF_CHECK
16723     loc_start = clock();
16724 #endif
16725     if (!b->noflip) {
16726       // Recover Delaunayness of T by flipping.
16727       flip(flipque, NULL);
16728     } else {
16729       lawson(NULL, flipque);
16730       // T remains regular.
16731       // flipque->clear();
16732     }
16733 #ifdef SELF_CHECK
16734     loc_end = clock();
16735     tfliptime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16736 #endif
16737   }
16738 
16739   if (b->verbose > 0) {
16740     printf("  %ld Flips (T23 %ld, T32 %ld, T22 %ld, T44 %ld)\n",
16741       flip23s+flip32s+flip22s+flip44s, flip23s, flip32s, flip22s, flip44s);
16742   }
16743 }
16744 
16746 //                                                                           //
16747 // delaunizevertices()    Form a Delaunay tetrahedralization.                //
16748 //                                                                           //
16749 // Given a point set V (saved in 'points').  The Delaunay tetrahedralization //
16750 // D of V is created by incrementally inserting vertices. Returns the number //
16751 // of triangular faces bounding the convex hull of D.                        //
16752 //                                                                           //
16754 
16755 long tetgenmesh::delaunizevertices()
16756 {
16757   queue *flipque;
16758   point *insertarray;
16759   long arraysize;
16760   int i, j;
16761 
16762   if (!b->quiet) {
16763     if (!b->noflip) {
16764       printf("Constructing Delaunay tetrahedralization.\n");
16765     } else {
16766       printf("Constructing regular tetrahedralization.\n");
16767     }
16768   }
16769 
16770   flipque = new queue(sizeof(badface));
16771   // Prepare the array of points for inserting.
16772   arraysize = points->items;
16773   insertarray = new point[arraysize];
16774   points->traversalinit();
16775 
16776   // Randomize the point order.
16777   // randomseed = b->srandseed;
16778   for (i = 0; i < arraysize; i++) {
16779     j = (int) randomnation(i + 1); // 0 <= j <= i;
16780     insertarray[i] = insertarray[j];
16781     insertarray[j] = pointtraverse();
16782   }
16783 
16784   // Use lawson flip.
16785   b->noflip = 1;
16786 
16787   // Form the DT by incremental flip Delaunay algorithm.
16788   incrflipdelaunay(NULL, insertarray, arraysize, true, b->plc, b->epsilon,
16789                    flipque);
16790 
16791   b->noflip = 0;
16792 
16793   delete [] insertarray;
16794   delete flipque;
16795   return hullsize;
16796 }
16797 
16798 //
16799 // End Delaunay tetrahedralization routines
16800 //
16801 
16802 //
16803 // Begin of surface triangulation routines
16804 //
16805 
16807 //                                                                           //
16808 // formstarpolygon()    Form the star polygon of a point in facet.           //
16809 //                                                                           //
16810 // The polygon P is formed by all coplanar subfaces having 'pt' as a vertex. //
16811 // P is bounded by segments, e.g, if no segments, P is the full star of pt.  //
16812 //                                                                           //
16813 // 'trilist' T returns the subfaces, it has one of such subfaces on input.   //
16814 // In addition, if f is in T, then sapex(f) = p. 'vertlist' V are verts of P.//
16815 // Topologically, T is the star of p; V and the edges of T are the link of p.//
16816 //                                                                           //
16818 
16819 void tetgenmesh::formstarpolygon(point pt, list* trilist, list* vertlist)
16820 {
16821   face steinsh, lnextsh, rnextsh;
16822   face checkseg;
16823   point pa, pb, pc, pd;
16824   int i;
16825 
16826   // Get a subface f containing p.
16827   steinsh = * (face *)(* trilist)[0];
16828   steinsh.shver = 0; // CCW
16829   // Let sapex(f) be p.
16830   for (i = 0; i < 3; i++) {
16831     if (sapex(steinsh) == pt) break;
16832     senextself(steinsh);
16833   }
16834   assert(i < 3);
16835   // Add the edge f into list.
16836   * (face *)(* trilist)[0] = steinsh;
16837   pa = sorg(steinsh);
16838   pb = sdest(steinsh);
16839   if (vertlist != (list *) NULL) {
16840     // Add two verts a, b into V,
16841     vertlist->append(&pa);
16842     vertlist->append(&pb);
16843   }
16844 
16845   // Rotate edge pa to the left (CW) until meet pb or a segment.
16846   lnextsh = steinsh;
16847   pc = pa;
16848   do {
16849     senext2self(lnextsh);
16850     assert(sorg(lnextsh) == pt);
16851     sspivot(lnextsh, checkseg);
16852     if (checkseg.sh != dummysh) break; // Do not cross a segment.
16853     // Get neighbor subface n (must exist).
16854     spivotself(lnextsh);
16855     if (lnextsh.sh == dummysh) break; // It's a hull edge.
16856     // Go to the edge ca opposite to p.
16857     if (sdest(lnextsh) != pt) sesymself(lnextsh);
16858     assert(sdest(lnextsh) == pt);
16859     senext2self(lnextsh);
16860     // Add n (at edge ca) to T.
16861     trilist->append(&lnextsh);
16862     // Add edge ca to E.
16863     pc = sorg(lnextsh);
16864     if (pc == pb) break; // Rotate back.
16865     if (vertlist != (list *) NULL) {
16866       // Add vert c into V.
16867       vertlist->append(&pc);
16868     }
16869   } while (true);
16870 
16871   if (pc != pb) {
16872     // Rotate edge bp to the right (CCW) until meet a segment.
16873     rnextsh = steinsh;
16874     do {
16875       senextself(rnextsh);
16876       assert(sdest(rnextsh) == pt);
16877       sspivot(rnextsh, checkseg);
16878       if (checkseg.sh != dummysh) break; // Do not cross a segment.
16879       // Get neighbor subface n (must exist).
16880       spivotself(rnextsh);
16881       if (rnextsh.sh == dummysh) break; // It's a hull edge.
16882       // Go to the edge bd opposite to p.
16883       if (sorg(rnextsh) != pt) sesymself(rnextsh);
16884       assert(sorg(rnextsh) == pt);
16885       senextself(rnextsh);
16886       // Add n (at edge bd) to T.
16887       trilist->append(&rnextsh);
16888       // Add edge bd to E.
16889       pd = sdest(rnextsh);
16890       if (pd == pa) break; // Rotate back.
16891       if (vertlist != (list *) NULL) {
16892         // Add vert d into V.
16893         vertlist->append(&pd);
16894       }
16895     } while (true);
16896   }
16897 }
16898 
16900 //                                                                           //
16901 // About the 'abovepoint'                                                    //
16902 //                                                                           //
16903 // The 'abovepoint' of a facet is a point which is exactly non-coplanar with //
16904 // the plane containing that facet.  With such an point, the 3D predicates:  //
16905 // orient3d(), and insphere() can be used to substitute the corresponding 2D //
16906 // siblings, e.g. orient2d(), and incircle().  Its location is not critical, //
16907 // but floating-point accuracy is improved if it is nicely placed over the   //
16908 // facet, not too close or too far away.                                     //
16909 //                                                                           //
16910 // We take the convention that the abovepoint of a facet always lies above   //
16911 // the facet. By this convention, given three points a, b, and c in a facet, //
16912 // we say c has the counterclockwise order with ab is corresponding to say   //
16913 // that c is below the plane abp, where p is the lift point.                 //
16914 //                                                                           //
16916 
16918 //                                                                           //
16919 // getfacetabovepoint()    Get a point above a plane pass through a facet.   //
16920 //                                                                           //
16921 // The calculcated point is saved in 'facetabovepointarray'. The 'abovepoint'//
16922 // is set on return.                                                         //
16923 //                                                                           //
16925 
16926 void tetgenmesh::getfacetabovepoint(face* facetsh)
16927 {
16928   list *verlist, *trilist, *tetlist;
16929   triface adjtet;
16930   face symsh;
16931   point p1, p2, p3, pa;
16932   enum locateresult loc;
16933   REAL smallcos, cosa;
16934   REAL largevol, volume;
16935   REAL v1[3], v2[3], len;
16936   int smallidx, largeidx;
16937   int shmark;
16938   int i, j;
16939 
16940   abovecount++;
16941   // Initialize working lists.
16942   verlist = new list(sizeof(point *), NULL);
16943   trilist = new list(sizeof(face), NULL);
16944   tetlist = new list(sizeof(triface), NULL);
16945 
16946   // Get three pivotal points p1, p2, and p3 in the facet as a base triangle
16947   //   which is non-trivil and has good base angle (close to 90 degree).
16948 
16949   // p1 is chosen as the one which has the smallest index in pa, pb, pc.
16950   p1 = sorg(*facetsh);
16951   pa = sdest(*facetsh);
16952   if (pointmark(pa) < pointmark(p1)) p1 = pa;
16953   pa = sapex(*facetsh);
16954   if (pointmark(pa) < pointmark(p1)) p1 = pa;
16955   // Form the star polygon of p1.
16956   trilist->append(facetsh);
16957   formstarpolygon(p1, trilist, verlist);
16958 
16959   // Get the second pivotal point p2.
16960   p2 = * (point *)(* verlist)[0];
16961   // Get vector v1 = p1->p2.
16962   for (i = 0; i < 3; i++) v1[i] = p2[i] - p1[i];
16963   len = sqrt(dot(v1, v1));
16964   assert(len > 0.0);  // p2 != p1.
16965   for (i = 0; i < 3; i++) v1[i] /= len;
16966 
16967   // Get the third pivotal point p3. p3 is chosen as the one in 'verlist'
16968   //   which forms an angle with v1 closer to 90 degree than others do.
16969   smallcos = 1.0; // The cosine value of 0 degree.
16970   smallidx = 1;   // Default value.
16971   for (i = 1; i < verlist->len(); i++) {
16972     p3 = * (point *)(* verlist)[i];
16973     for (j = 0; j < 3; j++) v2[j] = p3[j] - p1[j];
16974     len = sqrt(dot(v2, v2));
16975     if (len > 0.0) { // v2 is not too small.
16976       cosa = fabs(dot(v1, v2)) / len;
16977       if (cosa < smallcos) {
16978         smallidx = i;
16979         smallcos = cosa;
16980       }
16981     }
16982   }
16983   assert(smallcos < 1.0); // p1->p3 != p1->p2.
16984   p3 = * (point *)(* verlist)[smallidx];
16985   verlist->clear();
16986 
16987   if (tetrahedrons->items > 0l) {
16988     // Get a tet having p1 as a vertex.
16989     stpivot(*facetsh, adjtet);
16990     if (adjtet.tet == dummytet) {
16991       sesym(*facetsh, symsh);
16992       stpivot(symsh, adjtet);
16993     }
16994     if (adjtet.tet == dummytet) {
16995       decode(point2tet(p1), adjtet);
16996       if (isdead(&adjtet)) {
16997         adjtet.tet = dummytet;
16998       } else {
16999         if (!findorg(&adjtet, p1)) {
17000           adjtet.tet = dummytet;
17001         }
17002       }
17003     }
17004     if (adjtet.tet == dummytet) {
17005       loc = locate(p1, &adjtet);
17006       if (loc == ONVERTEX) {
17007         setpoint2tet(p1, encode(adjtet));
17008       } else {
17009         adjtet.tet = dummytet;
17010       }
17011     }
17012     if (adjtet.tet != dummytet) {
17013       // Get the star polyhedron of p1.
17014       tetlist->append(&adjtet);
17015       formstarpolyhedron(p1, tetlist, verlist, false);
17016     }
17017   }
17018 
17019   // Get the abovepoint in 'verlist'. It is the one form the largest valid
17020   //   volumw with the base triangle over other points in 'verlist.
17021   largevol = 0.0;
17022   largeidx = 0;
17023   for (i = 0; i < verlist->len(); i++) {
17024     pa = * (point *)(* verlist)[i];
17025     volume = orient3d(p1, p2, p3, pa);
17026     if (!iscoplanar(p1, p2, p3, pa, volume, b->epsilon * 1e+2)) {
17027       if (fabs(volume) > largevol) {
17028         largevol = fabs(volume);
17029         largeidx = i;
17030       }
17031     }
17032   }
17033 
17034   // Do we have the abovepoint?
17035   if (largevol > 0.0) {
17036     abovepoint = * (point *)(* verlist)[largeidx];
17037     if (b->verbose > 1) {
17038       printf("    Chosen abovepoint %d for facet %d.\n", pointmark(abovepoint),
17039              shellmark(*facetsh));
17040     }
17041   } else {
17042     // Calculate an abovepoint for this facet.
17043     facenormal(p1, p2, p3, v1, &len);
17044     if (len != 0.0) for (i = 0; i < 3; i++) v1[i] /= len;
17045     // Take the average edge length of the bounding box.
17046     len = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
17047     // Temporarily create a point. It will be removed by jettison();
17048     makepoint(&abovepoint);
17049     setpointtype(abovepoint, UNUSEDVERTEX);
17050     unuverts++;
17051     for (i = 0; i < 3; i++) abovepoint[i] = p1[i] + len * v1[i];
17052     if (b->verbose > 1) {
17053       printf("    Calculated abovepoint %d for facet %d.\n",
17054              pointmark(abovepoint), shellmark(*facetsh));
17055     }
17056   }
17057   // Save the abovepoint in 'facetabovepointarray'.
17058   shmark = shellmark(*facetsh);
17059   facetabovepointarray[shmark] = abovepoint;
17060 
17061   delete trilist;
17062   delete tetlist;
17063   delete verlist;
17064 }
17065 
17067 //                                                                           //
17068 // collectcavsubs()    Collect non-locally Delaunay subfaces wrt a point.    //
17069 //                                                                           //
17070 // 'cavsublist' returns the list of subfaces. On input, it conatins at least //
17071 // one subface.                                                              //
17072 //                                                                           //
17074 
17075 void tetgenmesh::collectcavsubs(point newpoint, list* cavsublist)
17076 {
17077   face startsub, neighsub;
17078   face checkseg;
17079   point pa, pb, pc;
17080   REAL sign, ori;
17081   int i, j;
17082 
17083   // First infect subfaces in 'cavsublist'.
17084   for (i = 0; i < cavsublist->len(); i++) {
17085     startsub = * (face *)(* cavsublist)[i];
17086     sinfect(startsub);
17087   }
17088   // Find the other subfaces by a broadth-first searching.
17089   for (i = 0; i < cavsublist->len(); i++) {
17090     startsub = * (face *)(* cavsublist)[i];
17091     for (j = 0; j < 3; j++) {
17092       sspivot(startsub, checkseg);
17093       // Is there a segment?
17094       if (checkseg.sh == dummysh) {
17095         // No segment. Get the neighbor.
17096         spivot(startsub, neighsub);
17097         if (!sinfected(neighsub)) {
17098           pa = sorg(neighsub);
17099           pb = sdest(neighsub);
17100           pc = sapex(neighsub);
17101           sign = insphere(pa, pb, pc, abovepoint, newpoint);
17102           ori = orient3d(pa, pb, pc, abovepoint);
17103           if (sign != 0.0) {
17104             // Correct the sign.
17105             sign = ori > 0.0 ? sign : -sign;
17106           }
17107           if (sign > 0.0) {
17108             // neighsub is encroached by newpoint.
17109             sinfect(neighsub);
17110             cavsublist->append(&neighsub);
17111           }
17112         }
17113       }
17114       senextself(startsub);
17115     }
17116   }
17117   // Having found all subfaces, uninfect them before return.
17118   for (i = 0; i < cavsublist->len(); i++) {
17119     startsub = * (face *)(* cavsublist)[i];
17120     suninfect(startsub);
17121   }
17122 }
17123 
17125 //                                                                           //
17126 // collectvisiblesubs()    Collect convex hull edges which are visible from  //
17127 //                         the inserting point. Construct new subfaces from  //
17128 //                         these edges and the point.                        //
17129 //                                                                           //
17130 // Let T be the current Delaunay triangulation (of vertices of a facet F).   //
17131 // 'shmark', the index of F in 'in->facetlist' (starts from 1);  'inspoint'  //
17132 // lies outside of T; 'horiz' is a hull edge of T which is visible by it.    //
17133 //                                                                           //
17135 
17136 void tetgenmesh::collectvisiblesubs(int shmark, point inspoint, face* horiz,
17137   queue* flipqueue)
17138 {
17139   face newsh, hullsh;
17140   face rightsh, leftsh, spinedge;
17141   point horg, hdest;
17142   bool aboveflag;
17143   REAL ori, sign;
17144 
17145   // Get the sign of abovepoint (so we can assume it is above the plane).
17146   adjustedgering(*horiz, CCW);
17147   horg = sorg(*horiz);
17148   hdest = sdest(*horiz);
17149   ori = orient3d(horg, hdest, sapex(*horiz), abovepoint);
17150   sign = ori > 0.0 ? -1 : 1;
17151 
17152   // Create a new subface above 'horiz'.
17153   makeshellface(subfaces, &newsh);
17154   setsorg(newsh, hdest);
17155   setsdest(newsh, horg);
17156   setsapex(newsh, inspoint);
17157   setshellmark(newsh, shmark);
17158   if (b->quality && varconstraint) {
17159     setareabound(newsh, areabound(*horiz));
17160   }
17161   if (checkpbcs) {
17162     setshellpbcgroup(newsh, shellpbcgroup(*horiz));
17163   }
17164   // Make the connection.
17165   sbond(newsh, *horiz);
17166   // 'horiz' becomes interior edge.
17167   enqueueflipedge(*horiz, flipqueue);
17168 
17169   // Finish the hull edges at the right side of the newsh.
17170   hullsh = *horiz;
17171   while (1) {
17172     senext(newsh, rightsh);
17173     // Get the right hull edge of 'horiz' by spinning inside edges around
17174     //   'horg' until reaching the 'dummysh'.
17175     spinedge = hullsh;
17176     do {
17177       hullsh = spinedge;
17178       senext2self(hullsh);
17179       spivot(hullsh, spinedge);
17180       if (spinedge.sh == dummysh) break;
17181       if (sorg(spinedge) != horg) sesymself(spinedge);
17182       assert(sorg(spinedge) == horg);
17183     } while (true);
17184     horg = sorg(hullsh);
17185     // Test whether 'inspoint' is visible by 'hullsh'.
17186     ori = orient3d(horg, sdest(hullsh), abovepoint, inspoint);
17187     ori *= sign;
17188     aboveflag = ori < 0.0;
17189     if (aboveflag) {
17190       // It's visible.
17191       makeshellface(subfaces, &newsh);
17192       setsorg(newsh, sdest(hullsh));
17193       setsdest(newsh, horg);
17194       setsapex(newsh, inspoint);
17195       setshellmark(newsh, shmark);
17196       if (b->quality && varconstraint) {
17197         setareabound(newsh, areabound(hullsh));
17198       }
17199       if (checkpbcs) {
17200         setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17201       }
17202       // Make the connection.
17203       sbond(newsh, hullsh);
17204       senext2(newsh, leftsh);
17205       sbond(leftsh, rightsh);
17206       // 'hullsh' becomes interior edge.
17207       enqueueflipedge(hullsh, flipqueue);
17208     } else {
17209       // 'rightsh' is a new hull edge.
17210       dummysh[0] = sencode(rightsh);
17211       break;
17212     }
17213   }
17214 
17215   // Finish the hull edges at the left side of the newsh.
17216   hullsh = *horiz;
17217   spivot(*horiz, newsh);
17218   while (1) {
17219     senext2(newsh, leftsh);
17220     // Get the left hull edge of 'horiz' by spinning edges around 'hdest'.
17221     spinedge = hullsh;
17222     do {
17223       hullsh = spinedge;
17224       senextself(hullsh);
17225       spivot(hullsh, spinedge);
17226       if (spinedge.sh == dummysh) break;
17227       if (sdest(spinedge) != hdest) sesymself(spinedge);
17228       assert(sdest(spinedge) == hdest);
17229     } while (true);
17230     // Update 'hdest'.
17231     hdest = sdest(hullsh);
17232     // Test whether 'inspoint' is visible from 'hullsh'.
17233     ori = orient3d(sorg(hullsh), hdest, abovepoint, inspoint);
17234     ori *= sign;
17235     aboveflag = ori < 0.0;
17236     if (aboveflag) {
17237       // It's a visible hull edge.
17238       makeshellface(subfaces, &newsh);
17239       setsorg(newsh, hdest);
17240       setsdest(newsh, sorg(hullsh));
17241       setsapex(newsh, inspoint);
17242       setshellmark(newsh, shmark);
17243       if (b->quality && varconstraint) {
17244         setareabound(newsh, areabound(hullsh));
17245       }
17246       if (checkpbcs) {
17247         setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17248       }
17249       // Make the connection.
17250       sbond(newsh, hullsh);
17251       senext(newsh, rightsh);
17252       sbond(rightsh, leftsh);
17253       // 'horiz' becomes interior edge.
17254       enqueueflipedge(hullsh, flipqueue);
17255     } else {
17256       // 'leftsh' is a new hull edge.
17257       dummysh[0] = sencode(leftsh);
17258       break;
17259     }
17260   }
17261 }
17262 
17264 //                                                                           //
17265 // incrflipdelaunaysub()    Create a DT from a 3D coplanar point set using   //
17266 //                          the incremental flip algorithm.                  //
17267 //                                                                           //
17268 // Let T be the current Delaunay triangulation (of vertices of a facet F).   //
17269 // 'shmark', the index of F in 'in->facetlist' (starts from 1).              //
17270 //                                                                           //
17272 
17273 void tetgenmesh::incrflipdelaunaysub(int shmark, REAL eps, list* ptlist,
17274   int holes, REAL* holelist, queue* flipque)
17275 {
17276   face newsh, startsh;
17277   point *insertarray;
17278   point swappt;
17279   pbcdata *pd;
17280   enum locateresult loc;
17281   REAL det, area;
17282   bool aboveflag;
17283   int arraysize;
17284   int epscount;
17285   int fmarker;
17286   int idx, i, j, k;
17287 
17288   // Get the point array (saved in 'ptlist').
17289   insertarray = (point *) ptlist->base;
17290   arraysize = ptlist->len();
17291   if (arraysize < 3) return;
17292 
17293   // Do calculation of 'abovepoint' if number of points > 3.
17294   aboveflag = (arraysize > 3);
17295 
17296   // The initial triangulation T only has one triangle formed by 3 not
17297   //   cillinear points of the set V = 'insertarray'. The first point:
17298   //   a = insertarray[0].
17299 
17300   epscount = 0;
17301   while (true) {
17302   for (i = 1; i < arraysize; i++) {
17303     det = distance(insertarray[0], insertarray[i]);
17304     if (det > (longest * eps)) break;
17305   }
17306   if (i < arraysize) {
17307     // Swap to move b from index i to index 1.
17308     swappt = insertarray[i];
17309     insertarray[i] = insertarray[1];
17310     insertarray[1] = swappt;
17311   }
17312   // Get the third point c, that is not collinear with a and b.
17313   for (i++; i < arraysize; i++) {
17314     if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
17315       break;
17316   }
17317   if (i < arraysize) {
17318     // Swap to move c from index i to index 2.
17319     swappt = insertarray[i];
17320     insertarray[i] = insertarray[2];
17321     insertarray[2] = swappt;
17322     i = 3; // The next inserting point.
17323   } else {
17324     // The set of vertices is not good (or nearly degenerate).  However,
17325     //   a trivial triangulation can be formed (using 3 vertices). It may
17326     //   be corrected (or deleted) by mergefacet().
17327     if ((eps == 0.0) || (epscount > 16)) {
17328       printf("Error:  Invalid PLC.\n");
17329       printf("  Facet (%d, %d, %d", pointmark(insertarray[0]),
17330              pointmark(insertarray[1]), pointmark(insertarray[2]));
17331       if (ptlist->len() > 3) {
17332         printf(", ...");
17333       }
17334       printf(") (%d) is not a valid polygon.\n", shmark);
17335       terminatetetgen(1);
17336     }
17337     // Decrease the eps, and continue to try.
17338     eps *= 1e-2;
17339     epscount++;
17340     continue;
17341   }
17342   break;
17343   } // while (true);
17344 
17345   // Create the initial triangle.
17346   makeshellface(subfaces, &newsh);
17347   setsorg(newsh, insertarray[0]);
17348   setsdest(newsh, insertarray[1]);
17349   setsapex(newsh, insertarray[2]);
17350   // Remeber the facet it belongs to.
17351   setshellmark(newsh, shmark);
17352   // Set vertex type be FREESUBVERTEX if it has no type yet.
17353   if (pointtype(insertarray[0]) == FREEVOLVERTEX) {
17354     setpointtype(insertarray[0], FREESUBVERTEX);
17355   }
17356   if (pointtype(insertarray[1]) == FREEVOLVERTEX) {
17357     setpointtype(insertarray[1], FREESUBVERTEX);
17358   }
17359   if (pointtype(insertarray[2]) == FREEVOLVERTEX) {
17360     setpointtype(insertarray[2], FREESUBVERTEX);
17361   }
17362   // Let 'dummysh' point to it (for point location).
17363   dummysh[0] = sencode(newsh);
17364 
17365   // Are there area constraints?
17366   if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
17367     idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker.
17368     for (k = 0; k < in->numberoffacetconstraints; k++) {
17369       fmarker = (int) in->facetconstraintlist[k * 2];
17370       if (fmarker == idx) {
17371         area = in->facetconstraintlist[k * 2 + 1];
17372         setareabound(newsh, area);
17373         break;
17374       }
17375     }
17376   }
17377 
17378   // Are there pbc conditions?
17379   if (checkpbcs) {
17380     idx = in->facetmarkerlist[shmark - 1]; // The actual facet marker.
17381     for (k = 0; k < in->numberofpbcgroups; k++) {
17382       pd = &subpbcgrouptable[k];
17383       for (j = 0; j < 2; j++) {
17384         if (pd->fmark[j] == idx) {
17385           setshellpbcgroup(newsh, k);
17386           pd->ss[j] = newsh;
17387         }
17388       }
17389     }
17390   }
17391 
17392   if (aboveflag) {
17393     // Compute the 'abovepoint' for orient3d().
17394     abovepoint = facetabovepointarray[shmark];
17395     if (abovepoint == (point) NULL) {
17396       getfacetabovepoint(&newsh);
17397     }
17398   }
17399 
17400   if (holes > 0) {
17401     // Project hole points onto the plane containing the facet.
17402     REAL prj[3];
17403     for (k = 0; k < holes; k++) {
17404       projpt2face(&(holelist[k * 3]), insertarray[0], insertarray[1],
17405                   insertarray[2], prj);
17406       for (j = 0; j < 3; j++) holelist[k * 3 + j] = prj[j];
17407     }
17408   }
17409 
17410   // Incrementally insert the rest of points into T.
17411   for (; i < arraysize; i++) {
17412     // Insert p_i.
17413     startsh.sh = dummysh;
17414     loc = locatesub(insertarray[i], &startsh, 0, 0.0);
17415     if (loc == ONFACE) {
17416       splitsubface(insertarray[i], &startsh, flipque);
17417     } else if (loc == ONEDGE) {
17418       splitsubedge(insertarray[i], &startsh, flipque);
17419     } else if (loc == OUTSIDE) {
17420       collectvisiblesubs(shmark, insertarray[i], &startsh, flipque);
17421     } else if (loc == ONVERTEX) {
17422       // !should not happen!
17423     }
17424     // Set p_i's type FREESUBVERTEX if it has no type yet.
17425     if (pointtype(insertarray[i]) == FREEVOLVERTEX) {
17426       setpointtype(insertarray[i], FREESUBVERTEX);
17427     }
17428     flipsub(flipque);
17429   }
17430 }
17431 
17433 //                                                                           //
17434 // finddirectionsub()    Find the first subface in a facet on the path from  //
17435 //                       one point to another.                               //
17436 //                                                                           //
17437 // Finds the subface in the facet that intersects a line segment drawn from  //
17438 // the origin of `searchsh' to the point `tend', and returns the result in   //
17439 // `searchsh'.  The origin of `searchsh' does not change,  even though the   //
17440 // subface returned may differ from the one passed in.                       //
17441 //                                                                           //
17442 // The return value notes whether the destination or apex of the found face  //
17443 // is collinear with the two points in question.                             //
17444 //                                                                           //
17446 
17447 enum tetgenmesh::finddirectionresult tetgenmesh::finddirectionsub(
17448   face* searchsh, point tend)
17449 {
17450   face checksh;
17451   point startpoint, leftpoint, rightpoint;
17452   REAL leftccw, rightccw;
17453   REAL ori, sign;
17454   int leftflag, rightflag;
17455 
17456   startpoint = sorg(*searchsh);
17457   // Find the sign to simulate that abovepoint is 'above' the facet.
17458   adjustedgering(*searchsh, CCW);
17459   // Make sure 'startpoint' is the origin.
17460   if (sorg(*searchsh) != startpoint) senextself(*searchsh);
17461   rightpoint = sdest(*searchsh);
17462   leftpoint = sapex(*searchsh);
17463   ori = orient3d(startpoint, rightpoint, leftpoint, abovepoint);
17464   sign = ori > 0.0 ? -1 : 1;
17465 
17466   // Is `tend' to the left?
17467   ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17468   leftccw = ori * sign;
17469   leftflag = leftccw > 0.0;
17470   // Is `tend' to the right?
17471   ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17472   rightccw = ori * sign;
17473   rightflag = rightccw > 0.0;
17474   if (leftflag && rightflag) {
17475     // `searchsh' faces directly away from `tend'.  We could go left or
17476     //   right.  Ask whether it's a triangle or a boundary on the left.
17477     senext2(*searchsh, checksh);
17478     spivotself(checksh);
17479     if (checksh.sh == dummysh) {
17480       leftflag = 0;
17481     } else {
17482       rightflag = 0;
17483     }
17484   }
17485   while (leftflag) {
17486     // Turn left until satisfied.
17487     senext2self(*searchsh);
17488     spivotself(*searchsh);
17489     if (searchsh->sh == dummysh) {
17490       printf("Internal error in finddirectionsub():  Unable to find a\n");
17491       printf("  subface leading from %d to %d.\n", pointmark(startpoint),
17492              pointmark(tend));
17493       internalerror();
17494     }
17495     if (sorg(*searchsh) != startpoint) sesymself(*searchsh);
17496     assert(sorg(*searchsh) == startpoint);
17497     leftpoint = sapex(*searchsh);
17498     rightccw = leftccw;
17499     ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17500     leftccw = ori * sign;
17501     leftflag = leftccw > 0.0;
17502   }
17503   while (rightflag) {
17504     // Turn right until satisfied.
17505     spivotself(*searchsh);
17506     if (searchsh->sh == dummysh) {
17507       printf("Internal error in finddirectionsub():  Unable to find a\n");
17508       printf("  subface leading from %d to %d.\n", pointmark(startpoint),
17509              pointmark(tend));
17510       internalerror();
17511     }
17512     if (sdest(*searchsh) != startpoint) sesymself(*searchsh);
17513     assert(sdest(*searchsh) == startpoint);
17514     senextself(*searchsh);
17515     rightpoint = sdest(*searchsh);
17516     leftccw = rightccw;
17517     ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17518     rightccw = ori * sign;
17519     rightflag = rightccw > 0.0;
17520   }
17521   if (leftccw == 0.0) {
17522     return LEFTCOLLINEAR;
17523   } else if (rightccw == 0.0) {
17524     return RIGHTCOLLINEAR;
17525   } else {
17526     return ACROSSEDGE;
17527   }
17528 }
17529 
17531 //                                                                           //
17532 // insertsubseg()    Create a subsegment and insert it between two subfaces. //
17533 //                                                                           //
17534 // The new subsegment ab is inserted at the edge of subface 'tri'.  If ab is //
17535 // not a hull edge, it is inserted between two subfaces.  If 'tri' is a hull //
17536 // face, the initial face ring of ab will be set only one face which is self-//
17537 // bonded.  The final face ring will be constructed in 'unifysegments()'.    //
17538 //                                                                           //
17540 
17541 void tetgenmesh::insertsubseg(face* tri)
17542 {
17543   face oppotri;
17544   face newsubseg;
17545   point pa, pb;
17546   REAL len;
17547   int e1, e2;
17548   int i;
17549 
17550   // Check if there's already a subsegment here.
17551   sspivot(*tri, newsubseg);
17552   if (newsubseg.sh == dummysh) {
17553     // Make new subsegment and initialize its vertices.
17554     makeshellface(subsegs, &newsubseg);
17555     pa = sorg(*tri);
17556     pb = sdest(*tri);
17557     setsorg(newsubseg, pa);
17558     setsdest(newsubseg, pb);
17559     // Are there length constraints?
17560     if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
17561       for (i = 0; i < in->numberofsegmentconstraints; i++) {
17562         e1 = (int) in->segmentconstraintlist[i * 3];
17563         e2 = (int) in->segmentconstraintlist[i * 3 + 1];
17564         if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
17565             ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
17566           len = in->segmentconstraintlist[i * 3 + 2];
17567           setareabound(newsubseg, len);
17568           break;
17569         }
17570       }
17571     }
17572     // Bond new subsegment to the two subfaces it is sandwiched between.
17573     ssbond(*tri, newsubseg);
17574     spivot(*tri, oppotri);
17575     // 'oppotri' might be "out space".
17576     if (oppotri.sh != dummysh) {
17577       ssbond(oppotri, newsubseg);
17578     } /* else {
17579       // Outside! Bond '*tri' to itself.
17580       sbond(*tri, *tri);
17581     } */
17582   }
17583 }
17584 
17586 //                                                                           //
17587 // scoutsegmentsub()    Scout the first triangle on the path from one point  //
17588 //                      to another, and check for completion (reaching the   //
17589 //                      second point), a collinear point,or the intersection //
17590 //                      of two segments.                                     //
17591 //                                                                           //
17592 // Returns true if the entire segment is successfully inserted, and false if //
17593 // the job must be finished by constrainededge().                            //
17594 //                                                                           //
17596 
17597 bool tetgenmesh::scoutsegmentsub(face* searchsh, point tend)
17598 {
17599   face newsubseg;
17600   face crosssub, crosssubseg;
17601   point leftpoint, rightpoint;
17602   enum finddirectionresult collinear;
17603 
17604   collinear = finddirectionsub(searchsh, tend);
17605   rightpoint = sdest(*searchsh);
17606   leftpoint = sapex(*searchsh);
17607   if (rightpoint == tend || leftpoint == tend) {
17608     // The segment is already an edge.
17609     if (leftpoint == tend) {
17610       senext2self(*searchsh);
17611     }
17612     // Insert a subsegment.
17613     insertsubseg(searchsh);
17614     return true;
17615   } else if (collinear == LEFTCOLLINEAR) {
17616     // We've collided with a vertex between the segment's endpoints.
17617     // Make the collinear vertex be the triangle's origin.
17618     senextself(*searchsh); // lprevself(*searchtri);
17619     // Insert a subsegment.
17620     insertsubseg(searchsh);
17621     // Insert the remainder of the segment.
17622     return scoutsegmentsub(searchsh, tend);
17623   } else if (collinear == RIGHTCOLLINEAR) {
17624     // We've collided with a vertex between the segment's endpoints.
17625     // Insert a subsegment.
17626     insertsubseg(searchsh);
17627     // Make the collinear vertex be the triangle's origin.
17628     senextself(*searchsh); // lnextself(*searchtri);
17629     // Insert the remainder of the segment.
17630     return scoutsegmentsub(searchsh, tend);
17631   } else {
17632     senext(*searchsh, crosssub); // lnext(*searchtri, crosstri);
17633     // Check for a crossing segment.
17634     sspivot(crosssub, crosssubseg);
17635 #ifdef SELF_CHECK
17636     assert(crosssubseg.sh == dummysh);
17637 #endif
17638     return false;
17639   }
17640 }
17641 
17643 //                                                                           //
17644 // flipedgerecursive()    Flip an edge.                                      //
17645 //                                                                           //
17646 // This is a support routine for inserting segments into a CDT.              //
17647 //                                                                           //
17648 // Let 'flipedge' be ab, and two triangles abc, abd share at it.  ab may not //
17649 // flipable if the four vertices a, b, c, and d are non-convex. If it is the //
17650 // case, recursively flip ad or bd. Return when ab is flipped.               //
17651 //                                                                           //
17653 
17654 void tetgenmesh::flipedgerecursive(face* flipedge, queue* flipqueue)
17655 {
17656   face fixupsh;
17657   point pa, pb, pc, pd;
17658   REAL oria, orib;
17659   bool doflip;
17660 
17661   pa = sorg(*flipedge);
17662   pb = sdest(*flipedge);
17663   pc = sapex(*flipedge);
17664   do {
17665     spivot(*flipedge, fixupsh);
17666     pd = sapex(fixupsh);
17667     oria = orient3d(pc, pd, abovepoint, pa);
17668     orib = orient3d(pc, pd, abovepoint, pb);
17669     doflip = (oria * orib < 0.0);
17670     if (doflip) {
17671       // Flip the edge (a, b) away.
17672       flip22sub(flipedge, flipqueue);
17673       // Fix flipedge on edge e (c, d).
17674       findedge(flipedge, pc, pd);
17675     } else {
17676       // ab is unflipable. Get the next edge (bd, or da) to flip.
17677       if (sorg(fixupsh) != pb) sesymself(fixupsh);
17678       assert(sdest(fixupsh) == pa);
17679       if (fabs(oria) > fabs(orib)) {
17680         // acd has larger area. Choose da.
17681         senextself(fixupsh);
17682       } else {
17683         // bcd has larger area. Choose bd.
17684         senext2self(fixupsh);
17685       }
17686       // Flip the edge.
17687       flipedgerecursive(&fixupsh, flipqueue);
17688     }
17689   } while (!doflip);
17690 }
17691 
17693 //                                                                           //
17694 // constrainededge()    Force a segment into a CDT.                          //
17695 //                                                                           //
17696 // The segment s is recovered by flipping away the edges it intersects, and  //
17697 // triangulating the polygons that form on each side of it.                  //
17698 //                                                                           //
17699 // Generates a single subsegment connecting `tstart' to `tend'. The triangle //
17700 // `startsh' has `tstart' as its origin.                                     //
17701 //                                                                           //
17703 
17704 void tetgenmesh::constrainededge(face* startsh, point tend, queue* flipqueue)
17705 {
17706   point tstart, tright, tleft;
17707   REAL rori, lori;
17708   bool collision;
17709 
17710   tstart = sorg(*startsh);
17711   do {
17712     // Loop edges oppo to tstart until find one crosses the segment.
17713     do {
17714       tright = sdest(*startsh);
17715       tleft = sapex(*startsh);
17716       // Is edge (tright, tleft) corss the segment.
17717       rori = orient3d(tstart, tright, abovepoint, tend);
17718       collision = (rori == 0.0);
17719       if (collision) break; // tright is on the segment.
17720       lori = orient3d(tstart, tleft, abovepoint, tend);
17721       collision = (lori == 0.0);
17722       if (collision) { //  tleft is on the segment.
17723         senext2self(*startsh);
17724         break;
17725       }
17726       if (rori * lori < 0.0) break; // Find the crossing edge.
17727       // Both points are at one side of the segment.
17728       finddirectionsub(startsh, tend);
17729     } while (true);
17730     if (collision) break;
17731     // Get the neighbor face at edge e (tright, tleft).
17732     senextself(*startsh);
17733     // Flip the crossing edge.
17734     flipedgerecursive(startsh, flipqueue);
17735     // After flip, sorg(*startsh) == tstart.
17736     assert(sorg(*startsh) == tstart);
17737   } while (sdest(*startsh) != tend);
17738 
17739   // Insert a subsegment to make the segment permanent.
17740   insertsubseg(startsh);
17741   // If there was a collision with an interceding vertex, install another
17742   //   segment connecting that vertex with endpoint2.
17743   if (collision) {
17744     // Insert the remainder of the segment.
17745     if (!scoutsegmentsub(startsh, tend)) {
17746       constrainededge(startsh, tend, flipqueue);
17747     }
17748   }
17749 }
17750 
17752 //                                                                           //
17753 // recoversegment()    Recover a segment in the surface triangulation.       //
17754 //                                                                           //
17756 
17757 void tetgenmesh::recoversegment(point tstart, point tend, queue* flipqueue)
17758 {
17759   face searchsh;
17760 
17761   if (b->verbose > 2) {
17762     printf("    Insert seg (%d, %d).\n", pointmark(tstart), pointmark(tend));
17763   }
17764 
17765   // Find a triangle whose origin is the segment's first endpoint.
17766   searchsh.sh = dummysh;
17767   // Search for the segment's first endpoint by point location.
17768   if (locatesub(tstart, &searchsh, 0, 0.0) != ONVERTEX) {
17769     // Possibly caused by a degenerate subface. Do a brute-force search.
17770     list *newshlist;
17771     int i, j;
17772     newshlist = new list(sizeof(face), NULL, 256);
17773     // Get new subfaces, do not remove protected segments.
17774     retrievenewsubs(newshlist, false);
17775     // Search for a sub contain tstart.
17776     for (i = 0; i < newshlist->len(); i++) {
17777       searchsh = * (face *)(* newshlist)[i];
17778       for (j = 0; j < 3; j++) {
17779         if (sorg(searchsh) == tstart) break;
17780         senextself(searchsh);
17781       }
17782       if (j < 3) break;
17783     }
17784     delete newshlist;
17785     if (sorg(searchsh) != tstart) {
17786       printf("Internal error in recoversegment():  Vertex location failed.\n");
17787       internalerror();
17788     }
17789   }
17790   // Scout the segment and insert it if it is found.
17791   if (scoutsegmentsub(&searchsh, tend)) {
17792     // The segment was easily inserted.
17793     return;
17794   }
17795   // Insert the segment into the triangulation by flips.
17796   constrainededge(&searchsh, tend, flipqueue);
17797   // Some edges may need flipping.
17798   flipsub(flipqueue);
17799 }
17800 
17802 //                                                                           //
17803 // infecthullsub()    Virally infect all of the triangles of the convex hull //
17804 //                    that are not protected by subsegments.                 //
17805 //                                                                           //
17807 
17808 void tetgenmesh::infecthullsub(memorypool* viri)
17809 {
17810   face hulltri, nexttri, starttri;
17811   face hullsubseg;
17812   shellface **deadshellface;
17813 
17814   // Find a triangle handle on the hull.
17815   hulltri.sh = dummysh;
17816   hulltri.shver = 0;
17817   spivotself(hulltri);
17818   adjustedgering(hulltri, CCW);
17819   // Remember where we started so we know when to stop.
17820   starttri = hulltri;
17821   // Go once counterclockwise around the convex hull.
17822   do {
17823     // Ignore triangles that are already infected.
17824     if (!sinfected(hulltri)) {
17825       // Is the triangle protected by a subsegment?
17826       sspivot(hulltri, hullsubseg);
17827       if (hullsubseg.sh == dummysh) {
17828         // The triangle is not protected; infect it.
17829         if (!sinfected(hulltri)) {
17830           sinfect(hulltri);
17831           deadshellface = (shellface **) viri->alloc();
17832           *deadshellface = hulltri.sh;
17833         }
17834       }
17835     }
17836     // To find the next hull edge, go clockwise around the next vertex.
17837     senextself(hulltri); // lnextself(hulltri);
17838     spivot(hulltri, nexttri); // oprev(hulltri, nexttri);
17839     if (nexttri.sh == hulltri.sh) {
17840       nexttri.sh = dummysh;  // 'hulltri' is self-bonded.
17841     } else {
17842       adjustedgering(nexttri, CCW);
17843       senextself(nexttri);
17844     }
17845     while (nexttri.sh != dummysh) {
17846       hulltri = nexttri;
17847       spivot(hulltri, nexttri); // oprev(hulltri, nexttri);
17848       if (nexttri.sh == hulltri.sh) {
17849         nexttri.sh = dummysh;  // 'hulltri' is self-bonded.
17850       } else {
17851         adjustedgering(nexttri, CCW);
17852         senextself(nexttri);
17853       }
17854     }
17855   } while (hulltri != starttri);
17856 }
17857 
17859 //                                                                           //
17860 // plaguesub()    Spread the virus from all infected triangles to any        //
17861 //                neighbors not protected by subsegments.  Delete all        //
17862 //                infected triangles.                                        //
17863 //                                                                           //
17864 // This is the procedure that actually creates holes and concavities.        //
17865 //                                                                           //
17867 
17868 void tetgenmesh::plaguesub(memorypool* viri)
17869 {
17870   face testtri, neighbor, ghostsh;
17871   face neighborsubseg;
17872   shellface **virusloop;
17873   shellface **deadshellface;
17874   int i;
17875 
17876   // Loop through all the infected triangles, spreading the virus to
17877   //   their neighbors, then to their neighbors' neighbors.
17878   viri->traversalinit();
17879   virusloop = (shellface **) viri->traverse();
17880   while (virusloop != (shellface **) NULL) {
17881     testtri.sh = *virusloop;
17882     // Check each of the triangle's three neighbors.
17883     for (i = 0; i < 3; i++) {
17884       // Find the neighbor.
17885       spivot(testtri, neighbor);
17886       // Check for a subsegment between the triangle and its neighbor.
17887       sspivot(testtri, neighborsubseg);
17888       // Check if the neighbor is nonexistent or already infected.
17889       if ((neighbor.sh == dummysh) || sinfected(neighbor)) {
17890         if (neighborsubseg.sh != dummysh) {
17891           // There is a subsegment separating the triangle from its
17892           //   neighbor, but both triangles are dying, so the subsegment
17893           //   dies too.
17894           shellfacedealloc(subsegs, neighborsubseg.sh);
17895           if (neighbor.sh != dummysh) {
17896             // Make sure the subsegment doesn't get deallocated again
17897             //   later when the infected neighbor is visited.
17898             ssdissolve(neighbor);
17899           }
17900         }
17901       } else {                   // The neighbor exists and is not infected.
17902         if (neighborsubseg.sh == dummysh) {
17903           // There is no subsegment protecting the neighbor, so the
17904           //   neighbor becomes infected.
17905           sinfect(neighbor);
17906           // Ensure that the neighbor's neighbors will be infected.
17907           deadshellface = (shellface **) viri->alloc();
17908           *deadshellface = neighbor.sh;
17909         } else {               // The neighbor is protected by a subsegment.
17910           // Remove this triangle from the subsegment.
17911           ssbond(neighbor, neighborsubseg);
17912         }
17913       }
17914       senextself(testtri);
17915     }
17916     virusloop = (shellface **) viri->traverse();
17917   }
17918 
17919   ghostsh.sh = dummysh; // A handle of outer space.
17920   viri->traversalinit();
17921   virusloop = (shellface **) viri->traverse();
17922   while (virusloop != (shellface **) NULL) {
17923     testtri.sh = *virusloop;
17924     // Record changes in the number of boundary edges, and disconnect
17925     //   dead triangles from their neighbors.
17926     for (i = 0; i < 3; i++) {
17927       spivot(testtri, neighbor);
17928       if (neighbor.sh != dummysh) {
17929         // Disconnect the triangle from its neighbor.
17930         // sdissolve(neighbor);
17931         sbond(neighbor, ghostsh);
17932       }
17933       senextself(testtri);
17934     }
17935     // Return the dead triangle to the pool of triangles.
17936     shellfacedealloc(subfaces, testtri.sh);
17937     virusloop = (shellface **) viri->traverse();
17938   }
17939   // Empty the virus pool.
17940   viri->restart();
17941 }
17942 
17944 //                                                                           //
17945 // carveholessub()    Find the holes and infect them.  Find the area         //
17946 //                    constraints and infect them.  Infect the convex hull.  //
17947 //                    Spread the infection and kill triangles.  Spread the   //
17948 //                    area constraints.                                      //
17949 //                                                                           //
17950 // This routine mainly calls other routines to carry out all these functions.//
17951 //                                                                           //
17953 
17954 void tetgenmesh::carveholessub(int holes, REAL* holelist, memorypool *viri)
17955 {
17956   face searchtri, triangleloop;
17957   shellface **holetri;
17958   enum locateresult intersect;
17959   int i;
17960 
17961   // Mark as infected any unprotected triangles on the boundary.
17962   //   This is one way by which concavities are created.
17963   infecthullsub(viri);
17964 
17965   if (holes > 0) {
17966     // Infect each triangle in which a hole lies.
17967     for (i = 0; i < 3 * holes; i += 3) {
17968       // Ignore holes that aren't within the bounds of the mesh.
17969       if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
17970           && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)
17971           && (holelist[i + 2] >= zmin) && (holelist[i + 2] <= zmax)) {
17972         // Start searching from some triangle on the outer boundary.
17973         searchtri.sh = dummysh;
17974         // Find a triangle that contains the hole.
17975         intersect = locatesub(&holelist[i], &searchtri, 0, 0.0);
17976         if ((intersect != OUTSIDE) && (!sinfected(searchtri))) {
17977           // Infect the triangle.  This is done by marking the triangle
17978           //   as infected and including the triangle in the virus pool.
17979           sinfect(searchtri);
17980           holetri = (shellface **) viri->alloc();
17981           *holetri = searchtri.sh;
17982         }
17983       }
17984     }
17985   }
17986 
17987   if (viri->items > 0) {
17988     // Carve the holes and concavities.
17989     plaguesub(viri);
17990   }
17991   // The virus pool should be empty now.
17992 }
17993 
17995 //                                                                           //
17996 // triangulate()    Triangulate a PSLG into a CDT.                           //
17997 //                                                                           //
17998 // A Planar Straight Line Graph (PSLG) P is actually a 2D polygonal region,  //
17999 // possibly contains holes, segments and vertices in its interior. P is tri- //
18000 // angulated into a set of _subfaces_ forming a CDT of P.                    //
18001 //                                                                           //
18002 // The vertices and segments of P are found in 'ptlist' and 'conlist', resp- //
18003 // ectively. 'holelist' contains a list of hole points. 'shmark' will be set //
18004 // to all subfaces of P.                                                     //
18005 //                                                                           //
18006 // The CDT is created directly in the pools 'subfaces' and 'subsegs'. It can //
18007 // be retrived by a broadth-first searching starting from 'dummysh[0]'(debug //
18008 // function 'outsurfmesh()' does it).                                        //
18009 //                                                                           //
18011 
18012 void tetgenmesh::triangulate(int shmark, REAL eps, list* ptlist, list* conlist,
18013   int holes, REAL* holelist, memorypool* viri, queue* flipqueue)
18014 {
18015   face newsh;
18016   point *cons;
18017   int i;
18018 
18019   if (b->verbose > 1) {
18020     printf("    %d vertices, %d segments", ptlist->len(), conlist->len());
18021     if (holes > 0) {
18022       printf(", %d holes", holes);
18023     }
18024     printf(", shmark: %d.\n", shmark);
18025   }
18026 
18027   // Create the DT of V by the 2D incremental flip algorithm.
18028   incrflipdelaunaysub(shmark, eps, ptlist, holes, holelist, flipqueue);
18029   // Recover boundary edges.
18030   if (ptlist->len() > 3) {
18031     // Insert segments into the DT.
18032     for (i = 0; i < conlist->len(); i++) {
18033       cons = (point *)(* conlist)[i];
18034       recoversegment(cons[0], cons[1], flipqueue);
18035     }
18036     // Carve holes and concavities.
18037     carveholessub(holes, holelist, viri);
18038   } else if (ptlist->len() == 3) {
18039     // Insert 3 segments directly.
18040     newsh.sh = dummysh;
18041     newsh.shver = 0;
18042     spivotself(newsh);
18043     for (i = 0; i < 3; i++) {
18044       insertsubseg(&newsh);
18045       senextself(newsh);
18046     }
18047   } else if (ptlist->len() == 2) {
18048     // This facet is actually a segment. It is not support by the mesh data
18049     //   strcuture. Hence the segment will not be maintained in the mesh.
18050     //   However, during segment recovery, the segment can be processed.
18051     cons = (point *)(* conlist)[0];
18052     makeshellface(subsegs, &newsh);
18053     setsorg(newsh, cons[0]);
18054     setsdest(newsh, cons[1]);
18055   }
18056 }
18057 
18059 //                                                                           //
18060 // retrievenewsubs()    Retrieve newly created subfaces.                     //
18061 //                                                                           //
18062 // The new subfaces created by triangulate() can be found by a broadth-first //
18063 // searching starting from 'dummysh[0]'.                                     //
18064 //                                                                           //
18065 // 'newshlist' (empty on input) returns the retrieved subfaces. Each edge on //
18066 // the hull is bound to 'dummysh' and protected by a segment. If 'removeseg' //
18067 // is TRUE, the segment is removed.                                          //
18068 //                                                                           //
18070 
18071 void tetgenmesh::retrievenewsubs(list* newshlist, bool removeseg)
18072 {
18073   face startsh, neighsh;
18074   face deadseg;
18075   int i, j;
18076 
18077   // The first new subface is found at dummysh[0].
18078   startsh.sh = dummysh;
18079   startsh.shver = 0;
18080   spivotself(startsh);
18081   assert(startsh.sh != dummysh);
18082   sinfect(startsh);
18083   newshlist->append(&startsh);
18084 
18085   // Find the rest of new subfaces by a broadth-first searching.
18086   for (i = 0; i < newshlist->len(); i++) {
18087     // Get a new subface s.
18088     startsh = * (face *)(* newshlist)[i];
18089     for (j = 0; j < 3; j++) {
18090       spivot(startsh, neighsh);
18091       if (neighsh.sh != dummysh) {
18092         if (!sinfected(neighsh)) {
18093           // Discovered a new subface.
18094           sinfect(neighsh);
18095           newshlist->append(&neighsh);
18096         }
18097       } else {
18098         // Found a boundary edge.
18099         if (removeseg) {
18100           // This side of s may be protected by a segment.
18101           sspivot(startsh, deadseg);
18102           if (deadseg.sh != dummysh) {
18103             // Detach it from s.
18104             ssdissolve(startsh);
18105             // Delete the segment.
18106             shellfacedealloc(subsegs, deadseg.sh);
18107           }
18108         }
18109       }
18110       senextself(startsh);
18111     }
18112   }
18113   for (i = 0; i < newshlist->len(); i++) {
18114     startsh = * (face *)(* newshlist)[i];
18115     suninfect(startsh);
18116   }
18117 }
18118 
18120 //                                                                           //
18121 // unifysegments()    Unify identical segments and build facet connections.  //
18122 //                                                                           //
18123 // After creating the surface mesh. Each facet has its own segments.  There  //
18124 // are duplicated segments between adjacent facets.  This routine has three  //
18125 // purposes:                                                                 //
18126 //   (1) identify the set of segments which have the same endpoints and      //
18127 //       unify them into one segment, remove redundant ones;                 //
18128 //   (2) create the face rings of the unified segments, hence setup the      //
18129 //       connections between facets; and                                     //
18130 //   (3) set a unique marker (1-based) for each segment.                     //
18131 // On finish, each segment is unique and the face ring around it (right-hand //
18132 // rule) is constructed. The connections between facets-facets are setup.    //
18133 //                                                                           //
18135 
18136 void tetgenmesh::unifysegments()
18137 {
18138   list *sfacelist;
18139   shellface **facesperverlist;
18140   face subsegloop, testseg;
18141   face sface, sface1, sface2;
18142   point torg, tdest;
18143   REAL da1, da2;
18144   int *idx2facelist;
18145   int segmarker;
18146   int idx, k, m;
18147 
18148   if (b->verbose > 0) {
18149     printf("  Unifying segments.\n");
18150   }
18151 
18152   // Compute a mapping from indices of vertices to subfaces.
18153   makesubfacemap(idx2facelist, facesperverlist);
18154   // Initialize 'sfacelist' for constructing the face link of each segment.
18155   sfacelist = new list(sizeof(face), NULL);
18156 
18157   segmarker = 1;
18158   subsegs->traversalinit();
18159   subsegloop.sh = shellfacetraverse(subsegs);
18160   while (subsegloop.sh != (shellface *) NULL) {
18161     subsegloop.shver = 0; // For sure.
18162     torg = sorg(subsegloop);
18163     tdest = sdest(subsegloop);
18164     idx = pointmark(torg) - in->firstnumber;
18165     // Loop through the set of subfaces containing 'torg'.  Get all the
18166     //   subfaces containing the edge (torg, tdest). Save and order them
18167     //   in 'sfacelist', the ordering is defined by the right-hand rule
18168     //   with thumb points from torg to tdest.
18169     for (k = idx2facelist[idx]; k < idx2facelist[idx + 1]; k++) {
18170       sface.sh = facesperverlist[k];
18171       sface.shver = 0;
18172       // sface may be died due to the removing of duplicated subfaces.
18173       if (!isdead(&sface) && isfacehasedge(&sface, torg, tdest)) {
18174         // 'sface' contains this segment.
18175         findedge(&sface, torg, tdest);
18176         // Save it in 'sfacelist'.
18177         if (sfacelist->len() < 2) {
18178           sfacelist->append(&sface);
18179         } else {
18180           for (m = 0; m < sfacelist->len() - 1; m++) {
18181             sface1 = * (face *)(* sfacelist)[m];
18182             sface2 = * (face *)(* sfacelist)[m + 1];
18183             da1 = facedihedral(torg, tdest, sapex(sface1), sapex(sface));
18184             da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
18185             if (da1 < da2) {
18186               break;  // Insert it after m.
18187             }
18188           }
18189           sfacelist->insert(m + 1, &sface);
18190         }
18191       }
18192     }
18193     if (b->verbose > 1) {
18194       printf("    Identifying %d segments of (%d  %d).\n", sfacelist->len(),
18195              pointmark(torg), pointmark(tdest));
18196     }
18197     // Set the connection between this segment and faces containing it,
18198     //   at the same time, remove redundant segments.
18199     for (k = 0; k < sfacelist->len(); k++) {
18200       sface = *(face *)(* sfacelist)[k];
18201       sspivot(sface, testseg);
18202       // If 'testseg' is not 'subsegloop', it is a redundant segment that
18203       //   needs be removed. BE CAREFUL it may already be removed. Do not
18204       //   remove it twice, i.e., do test 'isdead()' together.
18205       if ((testseg.sh != subsegloop.sh) && !isdead(&testseg)) {
18206         shellfacedealloc(subsegs, testseg.sh);
18207       }
18208       // 'ssbond' bonds the subface and the segment together, and dissloves
18209       //   the old bond as well.
18210       ssbond(sface, subsegloop);
18211     }
18212     // Set connection between these faces.
18213     sface = *(face *)(* sfacelist)[0];
18214     for (k = 1; k <= sfacelist->len(); k++) {
18215       if (k < sfacelist->len()) {
18216         sface1 = *(face *)(* sfacelist)[k];
18217       } else {
18218         sface1 = *(face *)(* sfacelist)[0];    // Form a face loop.
18219       }
18220       /*
18221       // Check if these two subfaces are the same. It is possible when user
18222       //   defines one facet (or polygon) two or more times. If they are,
18223       //   they should not be bonded together, instead of that, one of them
18224       //   should be delete from the surface mesh.
18225       if ((sfacelist->len() > 1) && sapex(sface) == sapex(sface1)) {
18226         // They are duplicated faces.
18227         if (b->verbose > 0) {
18228           printf("  A duplicated subface (%d, %d, %d) is removed.\n",
18229                  pointmark(torg), pointmark(tdest), pointmark(sapex(sface)));
18230         }
18231         if (k == sfacelist->len()) {
18232           // 'sface' is the last face, however, it is same as the first one.
18233           //   In order to form the ring, we have to let the second last
18234           //   face bond to the first one 'sface1'.
18235           shellfacedealloc(subfaces, sface.sh);
18236           assert(sfacelist->len() >= 2);
18237           assert(k == sfacelist->len());
18238           sface = *(face *)(* sfacelist)[k - 2];
18239         } else {
18240           // 'sface1' is in the middle and may be the last one.
18241           shellfacedealloc(subfaces, sface1.sh);
18242           // Skip this face and go to the next one.
18243           continue;
18244         }
18245       }
18246       */
18247       if (b->verbose > 2) {
18248         printf("    Bond subfaces (%d, %d, %d) and (%d, %d, %d).\n",
18249                pointmark(torg), pointmark(tdest), pointmark(sapex(sface)),
18250                pointmark(torg), pointmark(tdest), pointmark(sapex(sface1)));
18251       }
18252       sbond1(sface, sface1);
18253       sface = sface1;
18254     }
18255     // Set the unique segment marker into the unified segment.
18256     setshellmark(subsegloop, segmarker);
18257     // Increase the marker.
18258     segmarker++;
18259     // Clear the working list.
18260     sfacelist->clear();
18261     subsegloop.sh = shellfacetraverse(subsegs);
18262   }
18263 
18264   delete [] idx2facelist;
18265   delete [] facesperverlist;
18266   delete sfacelist;
18267 }
18268 
18270 //                                                                           //
18271 // mergefacets()    Merge adjacent facets to be one facet if they are        //
18272 //                  coplanar and have the same boundary marker.              //
18273 //                                                                           //
18274 // Segments between two merged facets will be removed from the mesh.  If all //
18275 // segments around a vertex have been removed, change its vertex type to be  //
18276 // FREESUBVERTEX. Edge flips will be performed to ensure the Delaunayness of //
18277 // the triangulation of merged facets.                                       //
18278 //                                                                           //
18280 
18281 void tetgenmesh::mergefacets(queue* flipqueue)
18282 {
18283   face parentsh, neighsh, neineighsh;
18284   face segloop;
18285   point eorg, edest;
18286   REAL ori;
18287   bool mergeflag, pbcflag;
18288   int* segspernodelist;
18289   int fidx1, fidx2;
18290   int i, j;
18291 
18292   if (b->verbose > 0) {
18293     printf("  Merging coplanar facets.\n");
18294   }
18295   // Create and initialize 'segspernodelist'.
18296   segspernodelist = new int[points->items + 1];
18297   for (i = 0; i < points->items + 1; i++) segspernodelist[i] = 0;
18298 
18299   // Loop the segments, counter the number of segments sharing each vertex.
18300   subsegs->traversalinit();
18301   segloop.sh = shellfacetraverse(subsegs);
18302   while (segloop.sh != (shellface *) NULL) {
18303     // Increment the number of sharing segments for each endpoint.
18304     for (i = 0; i < 2; i++) {
18305       j = pointmark((point) segloop.sh[3 + i]);
18306       segspernodelist[j]++;
18307     }
18308     segloop.sh = shellfacetraverse(subsegs);
18309   }
18310 
18311   // Loop the segments, find out dead segments.
18312   subsegs->traversalinit();
18313   segloop.sh = shellfacetraverse(subsegs);
18314   while (segloop.sh != (shellface *) NULL) {
18315     eorg = sorg(segloop);
18316     edest = sdest(segloop);
18317     spivot(segloop, parentsh);
18318     spivot(parentsh, neighsh);
18319     spivot(neighsh, neineighsh);
18320     if (parentsh.sh != neighsh.sh && parentsh.sh == neineighsh.sh) {
18321       // Exactly two subfaces at this segment.
18322       fidx1 = shellmark(parentsh) - 1;
18323       fidx2 = shellmark(neighsh) - 1;
18324       pbcflag = false;
18325       if (checkpbcs) {
18326         pbcflag = (shellpbcgroup(parentsh) >= 0)
18327           || (shellpbcgroup(neighsh) >= 0);
18328       }
18329       // Possibly merge them if they are not in the same facet.
18330       if ((fidx1 != fidx2) && !pbcflag) {
18331         // Test if they are coplanar.
18332         ori = orient3d(eorg, edest, sapex(parentsh), sapex(neighsh));
18333         if (ori != 0.0) {
18334           if (iscoplanar(eorg, edest, sapex(parentsh), sapex(neighsh), ori,
18335                          b->epsilon)) {
18336             ori = 0.0; // They are assumed as coplanar.
18337           }
18338         }
18339         if (ori == 0.0) {
18340           mergeflag = (in->facetmarkerlist == (int *) NULL ||
18341           in->facetmarkerlist[fidx1] == in->facetmarkerlist[fidx2]);
18342           if (mergeflag) {
18343             // This segment becomes dead.
18344             if (b->verbose > 1) {
18345               printf("  Removing segment (%d, %d).\n", pointmark(eorg),
18346                      pointmark(edest));
18347             }
18348             ssdissolve(parentsh);
18349             ssdissolve(neighsh);
18350             shellfacedealloc(subsegs, segloop.sh);
18351             j = pointmark(eorg);
18352             segspernodelist[j]--;
18353             if (segspernodelist[j] == 0) {
18354               setpointtype(eorg, FREESUBVERTEX);
18355             }
18356             j = pointmark(edest);
18357             segspernodelist[j]--;
18358             if (segspernodelist[j] == 0) {
18359               setpointtype(edest, FREESUBVERTEX);
18360             }
18361             // Add 'parentsh' to queue checking for flip.
18362             enqueueflipedge(parentsh, flipqueue);
18363           }
18364         }
18365       }
18366     }
18367     segloop.sh = shellfacetraverse(subsegs);
18368   }
18369 
18370   if (!flipqueue->empty()) {
18371     // Restore the Delaunay property in the facet triangulation.
18372     flipsub(flipqueue);
18373   }
18374 
18375   delete [] segspernodelist;
18376 }
18377 
18379 //                                                                           //
18380 // meshsurface()    Create the surface mesh of a PLC.                        //
18381 //                                                                           //
18382 // Let X be the PLC, the surface mesh S of X consists of triangulated facets.//
18383 // S is created mainly in the following steps:                               //
18384 //                                                                           //
18385 // (1) Form the CDT of each facet of X separately (by routine triangulate()).//
18386 // After it is done, the subfaces of each facet are connected to each other, //
18387 // however there is no connection between facets yet.  Notice each facet has //
18388 // its own segments, some of them are duplicated.                            //
18389 //                                                                           //
18390 // (2) Remove the redundant segments created in step (1) (by routine unify-  //
18391 // segment()). The subface ring of each segment is created,  the connection  //
18392 // between facets are established as well.                                   //
18393 //                                                                           //
18394 // The return value indicates the number of segments of X.                   //
18395 //                                                                           //
18397 
18398 long tetgenmesh::meshsurface()
18399 {
18400   list *ptlist, *conlist;
18401   queue *flipqueue;
18402   tetgenio::facet *f;
18403   tetgenio::polygon *p;
18404   memorypool *viri;
18405   point *idx2verlist;
18406   point tstart, tend, *cons;
18407   int *worklist;
18408   int end1, end2;
18409   int shmark, i, j;
18410 
18411   if (!b->quiet) {
18412     printf("Creating surface mesh.\n");
18413   }
18414 
18415   // Compute a mapping from indices to points.
18416   makeindex2pointmap(idx2verlist);
18417   // Compute a mapping from points to tets for computing abovepoints.
18418   makepoint2tetmap();
18419   // Initialize 'facetabovepointarray'.
18420   facetabovepointarray = new point[in->numberoffacets + 1];
18421   for (i = 0; i < in->numberoffacets + 1; i++) {
18422     facetabovepointarray[i] = (point) NULL;
18423   }
18424   if (checkpbcs) {
18425     // Initialize the global array 'subpbcgrouptable'.
18426     createsubpbcgrouptable();
18427   }
18428 
18429   // Initialize working lists.
18430   viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
18431   flipqueue = new queue(sizeof(badface));
18432   ptlist = new list(sizeof(point *), NULL, 256);
18433   conlist = new list(sizeof(point *) * 2, NULL, 256);
18434   worklist = new int[points->items + 1];
18435   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
18436 
18437   // Loop the facet list, triangulate each facet. On finish, all subfaces
18438   //   are in 'subfaces', all segments are in 'subsegs'. Notice: there're
18439   //   redundant segments.  Remember: All facet indices count from 1.
18440   for (shmark = 1; shmark <= in->numberoffacets; shmark++) {
18441     // Get a facet F.
18442     f = &in->facetlist[shmark - 1];
18443 
18444     // Process the duplicated points first, they are marked with type
18445     //   DUPLICATEDVERTEX by incrflipdelaunay().  Let p and q are dup.
18446     //   and the index of p is larger than q's, p is substituted by q.
18447     //   In a STL mesh, duplicated points are implicitly included.
18448     if ((b->object == tetgenbehavior::STL) || dupverts) {
18449       // Loop all polygons of this facet.
18450       for (i = 0; i < f->numberofpolygons; i++) {
18451         p = &(f->polygonlist[i]);
18452         // Loop other vertices of this polygon.
18453         for (j = 0; j < p->numberofvertices; j++) {
18454           end1 = p->vertexlist[j];
18455           tstart = idx2verlist[end1 - in->firstnumber];
18456           if (pointtype(tstart) == DUPLICATEDVERTEX) {
18457             // Reset the index of vertex-j.
18458             tend = point2ppt(tstart);
18459             end2 = pointmark(tend);
18460             p->vertexlist[j] = end2;
18461           }
18462         }
18463       }
18464     }
18465 
18466     // Loop polygons of F, get the set V of vertices and S of segments.
18467     for (i = 0; i < f->numberofpolygons; i++) {
18468       // Get a polygon.
18469       p = &(f->polygonlist[i]);
18470       // Get the first vertex.
18471       end1 = p->vertexlist[0];
18472       if ((end1 < in->firstnumber) ||
18473           (end1 >= in->firstnumber + in->numberofpoints)) {
18474         if (!b->quiet) {
18475           printf("Warning:  Invalid the 1st vertex %d of polygon", end1);
18476           printf(" %d in facet %d.\n", i + 1, shmark);
18477         }
18478         continue; // Skip this polygon.
18479       }
18480       tstart = idx2verlist[end1 - in->firstnumber];
18481       // Add tstart to V if it haven't been added yet.
18482       if (worklist[end1] == 0) {
18483         ptlist->append(&tstart);
18484         worklist[end1] = 1;
18485       }
18486       // Loop other vertices of this polygon.
18487       for (j = 1; j <= p->numberofvertices; j++) {
18488         // get a vertex.
18489         if (j < p->numberofvertices) {
18490           end2 = p->vertexlist[j];
18491         } else {
18492           end2 = p->vertexlist[0];  // Form a loop from last to first.
18493         }
18494         if ((end2 < in->firstnumber) ||
18495             (end2 >= in->firstnumber + in->numberofpoints)) {
18496           if (!b->quiet) {
18497             printf("Warning:  Invalid vertex %d in polygon %d", end2, i + 1);
18498             printf(" in facet %d.\n", shmark);
18499           }
18500         } else {
18501           if (end1 != end2) {
18502             // 'end1' and 'end2' form a segment.
18503             tend = idx2verlist[end2 - in->firstnumber];
18504             // Add tstart to V if it haven't been added yet.
18505             if (worklist[end2] == 0) {
18506               ptlist->append(&tend);
18507               worklist[end2] = 1;
18508             }
18509             // Save the segment in S (conlist).
18510             cons = (point *) conlist->append(NULL);
18511             cons[0] = tstart;
18512             cons[1] = tend;
18513             // Set the start for next continuous segment.
18514             end1 = end2;
18515             tstart = tend;
18516           } else {
18517             // Two identical vertices represent an isolated vertex of F.
18518             if (p->numberofvertices > 2) {
18519               // This may be an error in the input, anyway, we can continue
18520               //   by simply skipping this segment.
18521               if (!b->quiet) {
18522                 printf("Warning:  Polygon %d has two identical verts", i + 1);
18523                 printf(" in facet %d.\n", shmark);
18524               }
18525             }
18526             // Ignore this vertex.
18527           }
18528         }
18529         // Is the polygon degenerate (a segment or a vertex)?
18530         if (p->numberofvertices == 2) break;
18531       }
18532     }
18533     // Unmark vertices.
18534     for (i = 0; i < ptlist->len(); i++) {
18535       tstart = * (point *)(* ptlist)[i];
18536       end1 = pointmark(tstart);
18537       assert(worklist[end1] == 1);
18538       worklist[end1] = 0;
18539     }
18540 
18541     // Create a CDT of F.
18542     triangulate(shmark, b->epsilon * 1e+2, ptlist, conlist, f->numberofholes,
18543                 f->holelist, viri, flipqueue);
18544     // Clear working lists.
18545     ptlist->clear();
18546     conlist->clear();
18547     viri->restart();
18548   }
18549 
18550   // Unify segments in 'subsegs', remove redundant segments.  Face links
18551   //   of segments are also built.
18552   unifysegments();
18553   // Remember the number of input segments (for output).
18554   insegments = subsegs->items;
18555 
18556   if (checkpbcs) {
18557     // Create the global array 'segpbcgrouptable'.
18558     createsegpbcgrouptable();
18559   }
18560 
18561   if (b->object == tetgenbehavior::STL) {
18562     // Remove redundant vertices (for .stl input mesh).
18563     jettisonnodes();
18564   }
18565 
18566   if (!b->nomerge && !b->nobisect && !checkpbcs) {
18567     // No '-M' switch - merge adjacent facets if they are coplanar.
18568     mergefacets(flipqueue);
18569   }
18570 
18571   delete [] idx2verlist;
18572   delete [] worklist;
18573   delete ptlist;
18574   delete conlist;
18575   delete flipqueue;
18576   delete viri;
18577 
18578   return subsegs->items;
18579 }
18580 
18581 //
18582 // End of surface triangulation routines
18583 //
18584 
18586 //                                                                           //
18587 // interecursive()    Recursively do intersection test on a set of triangles.//
18588 //                                                                           //
18589 // Recursively split the set 'subfacearray' of subfaces into two sets using  //
18590 // a cut plane parallel to x-, or, y-, or z-axies.  The split criteria are   //
18591 // follows. Assume the cut plane is H, and H+ denotes the left halfspace of  //
18592 // H, and H- denotes the right halfspace of H; and s be a subface:           //
18593 //                                                                           //
18594 //    (1) If all points of s lie at H+, put it into left array;              //
18595 //    (2) If all points of s lie at H-, put it into right array;             //
18596 //    (3) If some points of s lie at H+ and some of lie at H-, or some       //
18597 //        points lie on H, put it into both arraies.                         //
18598 //                                                                           //
18599 // Partitions by x-axis if axis == '0'; by y-axis if axis == '1'; by z-axis  //
18600 // if axis == '2'. If current cut plane is parallel to the x-axis, the next  //
18601 // one will be parallel to y-axis, and the next one after the next is z-axis,//
18602 // and then alternately return back to x-axis.                               //
18603 //                                                                           //
18604 // Stop splitting when the number of triangles of the input array is not     //
18605 // decreased anymore. Do tests on the current set.                           //
18606 //                                                                           //
18608 
18609 void tetgenmesh::
18610 interecursive(shellface** subfacearray, int arraysize, int axis, REAL bxmin,
18611               REAL bxmax, REAL bymin, REAL bymax, REAL bzmin, REAL bzmax,
18612               int* internum)
18613 {
18614   shellface **leftarray, **rightarray;
18615   face sface1, sface2;
18616   point p1, p2, p3;
18617   point p4, p5, p6;
18618   enum interresult intersect;
18619   REAL split;
18620   bool toleft, toright;
18621   int leftsize, rightsize;
18622   int i, j;
18623 
18624   if (b->verbose > 1) {
18625     printf("  Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
18626            arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
18627            axis == 0 ? "x" : (axis == 1 ? "y" : "z"));
18628   }
18629 
18630   leftarray = new shellface*[arraysize];
18631   if (leftarray == NULL) {
18632     printf("Error in interecursive():  Insufficient memory.\n");
18633     terminatetetgen(1);
18634   }
18635   rightarray = new shellface*[arraysize];
18636   if (rightarray == NULL) {
18637     printf("Error in interecursive():  Insufficient memory.\n");
18638     terminatetetgen(1);
18639   }
18640   leftsize = rightsize = 0;
18641 
18642   if (axis == 0) {
18643     // Split along x-axis.
18644     split = 0.5 * (bxmin + bxmax);
18645   } else if (axis == 1) {
18646     // Split along y-axis.
18647     split = 0.5 * (bymin + bymax);
18648   } else {
18649     // Split along z-axis.
18650     split = 0.5 * (bzmin + bzmax);
18651   }
18652 
18653   for (i = 0; i < arraysize; i++) {
18654     sface1.sh = subfacearray[i];
18655     p1 = (point) sface1.sh[3];
18656     p2 = (point) sface1.sh[4];
18657     p3 = (point) sface1.sh[5];
18658     toleft = toright = false;
18659     if (p1[axis] < split) {
18660       toleft = true;
18661       if (p2[axis] >= split || p3[axis] >= split) {
18662         toright = true;
18663       }
18664     } else if (p1[axis] > split) {
18665       toright = true;
18666       if (p2[axis] <= split || p3[axis] <= split) {
18667         toleft = true;
18668       }
18669     } else {
18670       // p1[axis] == split;
18671       toleft = true;
18672       toright = true;
18673     }
18674     // At least one is true;
18675 #ifdef SELF_CHECK
18676     assert(!(toleft == false && toright == false));
18677 #endif
18678     if (toleft) {
18679       leftarray[leftsize] = sface1.sh;
18680       leftsize++;
18681     }
18682     if (toright) {
18683       rightarray[rightsize] = sface1.sh;
18684       rightsize++;
18685     }
18686   }
18687 
18688   if (leftsize < arraysize && rightsize < arraysize) {
18689     // Continue to partition the input set. Now 'subfacearray' has been
18690     //   split into two sets, it's memory can be freed. 'leftarray' and
18691     //   'rightarray' will be freed in the next recursive (after they're
18692     //   partitioned again or performing tests).
18693     delete [] subfacearray;
18694     // Continue to split these two sets.
18695     if (axis == 0) {
18696       interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax,
18697                     bzmin, bzmax, internum);
18698       interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax,
18699                     bzmin, bzmax, internum);
18700     } else if (axis == 1) {
18701       interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split,
18702                     bzmin, bzmax, internum);
18703       interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax,
18704                     bzmin, bzmax, internum);
18705     } else {
18706       interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax,
18707                     bzmin, split, internum);
18708       interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax,
18709                     split, bzmax, internum);
18710     }
18711   } else {
18712     if (b->verbose > 1) {
18713       printf("  Checking intersecting faces.\n");
18714     }
18715     // Perform a brute-force compare on the set.
18716     for (i = 0; i < arraysize; i++) {
18717       sface1.sh = subfacearray[i];
18718       p1 = (point) sface1.sh[3];
18719       p2 = (point) sface1.sh[4];
18720       p3 = (point) sface1.sh[5];
18721       for (j = i + 1; j < arraysize; j++) {
18722         sface2.sh = subfacearray[j];
18723         p4 = (point) sface2.sh[3];
18724         p5 = (point) sface2.sh[4];
18725         p6 = (point) sface2.sh[5];
18726         intersect = tri_tri_inter(p1, p2, p3, p4, p5, p6);
18727         if (intersect == INTERSECT || intersect == SHAREFACE) {
18728           if (!b->quiet) {
18729             if (intersect == INTERSECT) {
18730               printf("  Facet #%d intersects facet #%d at triangles:\n",
18731                      shellmark(sface1), shellmark(sface2));
18732               printf("    (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
18733                      pointmark(p1), pointmark(p2), pointmark(p3),
18734                      pointmark(p4), pointmark(p5), pointmark(p6));
18735             } else {
18736               printf("  Facet #%d duplicates facet #%d at triangle:\n",
18737                      shellmark(sface1), shellmark(sface2));
18738               printf("    (%4d, %4d, %4d)\n", pointmark(p1), pointmark(p2),
18739                      pointmark(p3));
18740             }
18741           }
18742           // Increase the number of intersecting pairs.
18743           (*internum)++;
18744           // Infect these two faces (although they may already be infected).
18745           sinfect(sface1);
18746           sinfect(sface2);
18747         }
18748       }
18749     }
18750     // Don't forget to free all three arrays. No further partition.
18751     delete [] leftarray;
18752     delete [] rightarray;
18753     delete [] subfacearray;
18754   }
18755 }
18756 
18758 //                                                                           //
18759 // detectinterfaces()    Detect intersecting triangles.                      //
18760 //                                                                           //
18761 // Given a set of triangles,  find the pairs of intersecting triangles from  //
18762 // them.  Here the set of triangles is in 'subfaces' which is a surface mesh //
18763 // of a PLC (.poly or .smesh).                                               //
18764 //                                                                           //
18765 // To detect whether two triangles are intersecting is done by the routine   //
18766 // 'tri_tri_inter()'.  The algorithm for the test is very simple and stable. //
18767 // It is based on geometric orientation test which uses exact arithmetics.   //
18768 //                                                                           //
18769 // Use divide-and-conquer algorithm for reducing the number of intersection  //
18770 // tests.  Start from the bounding box of the input point set, recursively   //
18771 // partition the box into smaller boxes, until the number of triangles in a  //
18772 // box is not decreased anymore. Then perform triangle-triangle tests on the //
18773 // remaining set of triangles.  The memory allocated in the input set is     //
18774 // freed immediately after it has been partitioned into two arrays.  So it   //
18775 // can be re-used for the consequent partitions.                             //
18776 //                                                                           //
18777 // On return, the pool 'subfaces' will be cleared, and only the intersecting //
18778 // triangles remain for output (to a .face file).                            //
18779 //                                                                           //
18781 
18782 void tetgenmesh::detectinterfaces()
18783 {
18784   shellface **subfacearray;
18785   face shloop;
18786   int internum;
18787   int i;
18788 
18789   if (!b->quiet) {
18790     printf("Detecting intersecting facets.\n");
18791   }
18792 
18793   // Construct a map from indices to subfaces;
18794   subfacearray = new shellface*[subfaces->items];
18795   subfaces->traversalinit();
18796   shloop.sh = shellfacetraverse(subfaces);
18797   i = 0;
18798   while (shloop.sh != (shellface *) NULL) {
18799     subfacearray[i] = shloop.sh;
18800     shloop.sh = shellfacetraverse(subfaces);
18801     i++;
18802   }
18803 
18804   internum = 0;
18805   // Recursively split the set of triangles into two sets using a cut plane
18806   //   parallel to x-, or, y-, or z-axies.  Stop splitting when the number
18807   //   of subfaces is not decreasing anymore. Do tests on the current set.
18808   interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax,
18809                 zmin, zmax, &internum);
18810 
18811   if (!b->quiet) {
18812     if (internum > 0) {
18813       printf("\n!! Found %d pairs of faces are intersecting.\n\n", internum);
18814     } else {
18815       printf("\nNo faces are intersecting.\n\n");
18816     }
18817   }
18818 
18819   if (internum > 0) {
18820     // Traverse all subfaces, deallocate those have not been infected (they
18821     //   are not intersecting faces). Uninfect those have been infected.
18822     //   After this loop, only intersecting faces remain.
18823     subfaces->traversalinit();
18824     shloop.sh = shellfacetraverse(subfaces);
18825     while (shloop.sh != (shellface *) NULL) {
18826       if (sinfected(shloop)) {
18827         suninfect(shloop);
18828       } else {
18829         shellfacedealloc(subfaces, shloop.sh);
18830       }
18831       shloop.sh = shellfacetraverse(subfaces);
18832     }
18833   } else {
18834     // Deallocate all subfaces.
18835     subfaces->restart();
18836   }
18837 }
18838 
18839 //
18840 // Begin of periodic boundary condition routines
18841 //
18842 
18844 //                                                                           //
18845 // createsubpbcgrouptable()    Create the 'subpbcgrouptable'.                //
18846 //                                                                           //
18847 // Allocate the memory for 'subpbcgrouptable'.  Each entry i (a pbcdata) of  //
18848 // the table represents a pbcgroup.  Most of the fields of a group-i are set //
18849 // in this routine. 'fmark[0]', 'fmark[1]', and 'transmat[0]' are directly   //
18850 // copied from the corresponding data of 'in->numberofpbcgroups'. 'transmat  //
18851 // [1]' is calculated as the inverse matrix of 'transmat[0]'.  'ss[0]' and   //
18852 // 'ss[1]' are initilized be 'dummysh'. They are set in 'trangulatefacet()'  //
18853 // (when -p is in use) or 'reconstructmesh()' (when -r is in use).           //
18854 //                                                                           //
18856 
18857 void tetgenmesh::createsubpbcgrouptable()
18858 {
18859   tetgenio::pbcgroup *pg;
18860   pbcdata *pd;
18861   REAL A[4][4], rhs[4], D;
18862   int indx[4];
18863   int i, j, k;
18864 
18865   subpbcgrouptable = new pbcdata[in->numberofpbcgroups];
18866   for (i = 0; i < in->numberofpbcgroups; i++) {
18867     pg = &(in->pbcgrouplist[i]);
18868     pd = &(subpbcgrouptable[i]);
18869     // Copy data from pg to pd.
18870     pd->fmark[0] = pg->fmark1;
18871     pd->fmark[1] = pg->fmark2;
18872     // Initialize array 'pd->ss'.
18873     pd->ss[0].sh = dummysh;
18874     pd->ss[1].sh = dummysh;
18875     // Copy the transform matrix from pg to pd->transmat[0].
18876     for (j = 0; j < 4; j++) {
18877       for (k = 0; k < 4; k++) {
18878         pd->transmat[0][j][k] = pg->transmat[j][k];
18879         // Prepare for inverting the matrix.
18880         A[j][k] = pg->transmat[j][k];
18881       }
18882     }
18883     // Calculate the inverse matrix (pd->transmat[1]) of pd->transmat[0].
18884     lu_decmp(A, 4, indx, &D, 0);
18885     for (j = 0; j < 4; j++) {
18886       for (k = 0; k < 4; k++) rhs[k] = 0.0;
18887       rhs[j] = 1.0;
18888       lu_solve(A, 4, indx, rhs, 0);
18889       for (k = 0; k < 4; k++) pd->transmat[1][k][j] = rhs[k];
18890     }
18891   }
18892 }
18893 
18895 //                                                                           //
18896 // getsubpbcgroup()    Get the pbcgroup of a subface.                        //
18897 //                                                                           //
18898 // 'pbcsub' has pbc defined. Its pbcgroup is returned in 'pd'. In addition,  //
18899 // 'f1' (0 or 1) indicates the position of 'pbcsub' in 'pd'; 'f2' (= 1 - f1) //
18900 // is the position where the symmetric subface of 'pbcsub' is found.         //
18901 //                                                                           //
18903 
18904 void tetgenmesh::getsubpbcgroup(face* pbcsub, pbcdata** pd, int *f1, int *f2)
18905 {
18906   int groupid, fmark, idx;
18907 
18908   groupid = shellpbcgroup(*pbcsub);
18909   *pd = &subpbcgrouptable[groupid];
18910 
18911   // Get the facet index (1 - based).
18912   idx = shellmark(*pbcsub);
18913   // Get the facet marker from array (0 - based).
18914   fmark = in->facetmarkerlist[idx - 1];
18915   if ((*pd)->fmark[0] == fmark) {
18916     *f1 = 0;
18917   } else {
18918 #ifdef SELF_CHECK
18919     assert((*pd)->fmark[1] == fmark);
18920 #endif
18921     *f1 = 1;
18922   }
18923   *f2 = 1 - (*f1);
18924 }
18925 
18927 //                                                                           //
18928 // getsubpbcsympoint()    Compute the symmetric point for a subface point.   //
18929 //                                                                           //
18930 // 'newpoint' lies on 'splitsub'. This routine calculates a 'sympoint' which //
18931 // locates on 'symsplitsub' and symmtric to 'newpoint'.  Return the location //
18932 // of sympoint wrt. symsplitsub.                                             //
18933 //                                                                           //
18935 
18936 enum tetgenmesh::locateresult tetgenmesh:: getsubpbcsympoint(point newpoint,
18937   face* splitsub, point sympoint, face* symsplitsub)
18938 {
18939   pbcdata *pd;
18940   face subloop;
18941   point pa, pb, pc;
18942   enum locateresult symloc;
18943   REAL ori;
18944   int f1, f2, i;
18945 
18946   // Get the pbcgroup of 'splitsub'.
18947   getsubpbcgroup(splitsub, &pd, &f1, &f2);
18948 
18949   // Transform newpoint from f1 -> f2.
18950   for (i = 0; i < 3; i++) {
18951     sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
18952                 + pd->transmat[f1][i][1] * newpoint[1]
18953                 + pd->transmat[f1][i][2] * newpoint[2]
18954                 + pd->transmat[f1][i][3] * 1.0;
18955   }
18956   // Locate sympoint in f2.
18957   symloc = OUTSIDE;
18958   *symsplitsub = pd->ss[f2];
18959   // Is the stored subface valid? Hole removal may delete the subface.
18960   if ((symsplitsub->sh != dummysh) && !isdead(symsplitsub)) {
18961     // 'symsplitsub' should lie on the symmetric facet. Check it.
18962     i = shellmark(*symsplitsub);
18963     if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18964       // 'symsplitsub' has the symmetric boundary marker.
18965       pa = sorg(*symsplitsub);
18966       pb = sdest(*symsplitsub);
18967       pc = sapex(*symsplitsub);
18968       // Test if they are (nearly) coplanar. Some facets may have the
18969       //   same boundary marker but not coplanar with this point.
18970       ori = orient3d(pa, pb, pc, sympoint);
18971       if (iscoplanar(pa, pb, pc, sympoint, ori, b->epsilon * 1e+2)) {
18972         // Locate sympoint in facet. Don't stop at subsegment.
18973         abovepoint = facetabovepointarray[shellmark(*symsplitsub)];
18974         if (abovepoint == (point) NULL) {
18975           getfacetabovepoint(symsplitsub);
18976         }
18977         symloc = locatesub(sympoint, symsplitsub, 0, b->epsilon * 1e+2);
18978       }
18979     }
18980   }
18981   if (symloc == OUTSIDE) {
18982     // Do a brute-force searching for the symmetric subface.
18983     REAL epspp = b->epsilon * 1e+2;
18984     int lcount = 0;
18985     do {
18986       // Locate sympoint in the pool of subfaces (with fmark pd->fmark[f2]).
18987       subfaces->traversalinit();
18988       subloop.sh = shellfacetraverse(subfaces);
18989       while (subloop.sh != (shellface *) NULL) {
18990         i = shellmark(subloop);
18991         if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18992           // Found a facet have the symmetric boundary marker.
18993           pa = sorg(subloop);
18994           pb = sdest(subloop);
18995           pc = sapex(subloop);
18996           // Test if they are (nearly) coplanar. Some facets may have the
18997           //   same boundary marker but not coplanar with this point.
18998           ori = orient3d(pa, pb, pc, sympoint);
18999           if (iscoplanar(pa, pb, pc, sympoint, ori, epspp)) {
19000             // Test if sympoint is (nearly) inside this facet.
19001             // Get the abovepoint of the facet.
19002             abovepoint = facetabovepointarray[shellmark(subloop)];
19003             // Do we need to calculate the abovepoint?
19004             if (abovepoint == (point) NULL) {
19005               getfacetabovepoint(&subloop);
19006             }
19007             // subloop is on the facet, search sympoint.
19008             symloc = locatesub(sympoint, &subloop, 0, epspp);
19009             if (symloc != OUTSIDE) break;
19010           }
19011         }
19012         subloop.sh = shellfacetraverse(subfaces);
19013       }
19014       lcount++;
19015       epspp *= 10.0;
19016     } while ((symloc == OUTSIDE) && (lcount < 3));
19017 #ifdef SELF_CHECK
19018     // sympoint should be inside the facet.
19019     assert(symloc != OUTSIDE);
19020 #endif
19021     // Set the returning subface.
19022     *symsplitsub = subloop;
19023     // Update the stored subface for next searching.
19024     pd->ss[f2] = *symsplitsub;
19025   }
19026 
19027   return adjustlocatesub(sympoint, symsplitsub, symloc, b->epsilon);
19028 }
19029 
19031 //                                                                           //
19032 // createsegpbcgrouptable()    Create the 'segpbcgrouptable'.                //
19033 //                                                                           //
19034 // Each segment may belong to more than one pbcgroups.  For example, segment //
19035 // ab may need to be symmteric to both segments cd, and ef, then  ab and cd, //
19036 // cd and ef, ef and ab form three pbcgroups.                                //
19037 //                                                                           //
19038 // 'segpbcgrouptable' is  implemented as a list of pbcdatas. Each item i is  //
19039 // a pbcgroup.                                                               //
19040 //                                                                           //
19042 
19043 void tetgenmesh::createsegpbcgrouptable()
19044 {
19045   shellface** segsperverlist;
19046   pbcdata *pd, *ppd, pd1, pd2;
19047   face segloop, symseg;
19048   face startsh, spinsh, symsh;
19049   point pa, pb, syma, symb;
19050   enum locateresult symloc;
19051   REAL testpt[3], sympt[3];
19052   bool inflag;
19053   int *idx2seglist;
19054   int segid1, segid2;
19055   int f1, f2;
19056   int i, j, k, l;
19057 
19058   // Allocate memory for 'subpbcgrouptable'.
19059   segpbcgrouptable = new list(sizeof(pbcdata), NULL, 256);
19060 
19061   if (b->refine) {
19062     // Create a point-to-seg map for quickly finding PBC seg pairs.
19063     makesegmentmap(idx2seglist, segsperverlist);
19064   }
19065 
19066   // Loop through the segment list.
19067   subsegs->traversalinit();
19068   segloop.sh = shellfacetraverse(subsegs);
19069   while (segloop.sh != (shellface *) NULL) {
19070     // Loop the subface ring of segloop ab.
19071     pa = sorg(segloop);
19072     pb = sdest(segloop);
19073     segid1 = shellmark(segloop);
19074     spivot(segloop, startsh);
19075     spinsh = startsh;
19076     do {
19077       // Adjust spinsh be edge ab.
19078       if (sorg(spinsh) != pa) {
19079         sesymself(spinsh);
19080       }
19081       // Does spinsh belong to a pbcgroup?
19082       if (shellpbcgroup(spinsh) != -1) {
19083         // Yes! There exists a segment cd. ab and cd form a pbcgroup.
19084         if (b->refine) {
19085           getsubpbcgroup(&spinsh, &pd, &f1, &f2);
19086           // Transform pa from f1 -> f2.
19087           for (i = 0; i < 3; i++) {
19088             sympt[i] = pd->transmat[f1][i][0] * pa[0]
19089                      + pd->transmat[f1][i][1] * pa[1]
19090                      + pd->transmat[f1][i][2] * pa[2]
19091                      + pd->transmat[f1][i][3] * 1.0;
19092           }
19093           syma = point2pbcpt(pa);
19094           // Is 'sympt == syma'?
19095           if (distance(sympt, syma) > (longest * b->epsilon)) {
19096             // No. Search the symmetric vertex of pa.
19097             symloc = getsubpbcsympoint(pa, &spinsh, sympt, &symsh);
19098             syma = sorg(symsh);
19099             if (symloc != ONVERTEX) {
19100               // Do a brute force search. Not done yet.
19101               assert(0);
19102             }
19103           }
19104           // Transform pb from f1 -> f2.
19105           for (i = 0; i < 3; i++) {
19106             sympt[i] = pd->transmat[f1][i][0] * pb[0]
19107                      + pd->transmat[f1][i][1] * pb[1]
19108                      + pd->transmat[f1][i][2] * pb[2]
19109                      + pd->transmat[f1][i][3] * 1.0;
19110           }
19111           // Search sym subface from the point-to-subface map.
19112           symseg.shver = 0;
19113           j = pointmark(syma) - in->firstnumber;
19114           for (i = idx2seglist[j]; i < idx2seglist[j + 1]; i++) {
19115             symseg.sh = segsperverlist[i];
19116             if (sorg(symseg) == syma) symb = sdest(symseg);
19117             else symb = sorg(symseg);
19118             if (distance(sympt, symb) <= (longest * b->epsilon)) break;
19119           }
19120           assert(i < idx2seglist[j + 1]);
19121         } else {
19122           //   'testpt' is the midpoint of ab used to find cd.
19123           for (i = 0; i < 3; i++) testpt[i] = 0.5 * (pa[i] + pb[i]);
19124           symloc = getsubpbcsympoint(testpt, &spinsh, sympt, &symsh);
19125 #ifdef SELF_CHECK
19126           assert(symloc == ONEDGE);
19127 #endif
19128           sspivot(symsh, symseg);
19129         }
19130 #ifdef SELF_CHECK
19131         assert(symseg.sh != dummysh);
19132 #endif
19133         // Check whether this group has already been created in list.
19134         segid2 = shellmark(symseg);
19135         inflag = false;
19136         for (i = 0; i < segpbcgrouptable->len() && !inflag; i++) {
19137           pd = (pbcdata *)(* segpbcgrouptable)[i];
19138           if (pd->segid[0] == segid1) {
19139             if (pd->segid[1] == segid2) inflag = true;
19140           } else if (pd->segid[0] == segid2) {
19141             if (pd->segid[1] == segid1) inflag = true;
19142           }
19143         }
19144         if (!inflag) {
19145           // Create a segment pbcgroup in list for ab and cd.
19146           pd = (pbcdata *) segpbcgrouptable->append(NULL);
19147           // Save the markers of ab and cd.
19148           pd->segid[0] = segid1;
19149           pd->segid[1] = segid2;
19150           // Save the handles of ab and cd.
19151           pd->ss[0] = segloop;
19152           pd->ss[1] = symseg;
19153           // Find the map from ab to cd.
19154           getsubpbcgroup(&spinsh, &ppd, &f1, &f2);
19155           pd->fmark[0] = ppd->fmark[f1];
19156           pd->fmark[1] = ppd->fmark[f2];
19157           // Set the map from ab to cd.
19158           for (i = 0; i < 4; i++) {
19159             for (j = 0; j < 4; j++) {
19160               pd->transmat[0][i][j] = ppd->transmat[f1][i][j];
19161             }
19162           }
19163           // Set the map from cd to ab.
19164           for (i = 0; i < 4; i++) {
19165             for (j = 0; j < 4; j++) {
19166               pd->transmat[1][i][j] = ppd->transmat[f2][i][j];
19167             }
19168           }
19169         }
19170       }
19171       // Go to the next subface in the ring of ab.
19172       spivotself(spinsh);
19173     } while (spinsh.sh != startsh.sh);
19174     segloop.sh = shellfacetraverse(subsegs);
19175   }
19176 
19177   if (b->refine) {
19178     delete [] segsperverlist;
19179     delete [] idx2seglist;
19180   }
19181 
19182   // Create the indirect segment pbcgroups.
19183   // Bug-fixed (08 Sept. 2006). The total size of 'segpbcgrouptable' may get
19184   //   increased. Do not use pointers for 'pd1' and 'pd2'. The addresses may
19185   //   be invaild after realloc().
19186   for (i = 0; i < segpbcgrouptable->len(); i++) {
19187     pd1 = * (pbcdata *)(* segpbcgrouptable)[i];
19188     for (f1 = 0; f1 < 2; f1++) {
19189       // Search for a group (except i) contains pd1.segid[f1].
19190       for (j = 0; j < segpbcgrouptable->len(); j++) {
19191         if (j == i) continue;
19192         pd2 = * (pbcdata *)(* segpbcgrouptable)[j];
19193         f2 = -1;
19194         if (pd1.segid[f1] == pd2.segid[0]) {
19195           f2 = 0;
19196         } else if (pd1.segid[f1] == pd2.segid[1]) {
19197           f2 = 1;
19198         }
19199         if (f2 != -1) {
19200 #ifdef SELF_CHECK
19201           assert(pd1.segid[f1] == pd2.segid[f2]);
19202 #endif
19203           segid1 = pd1.segid[1 - f1];
19204           segid2 = pd2.segid[1 - f2];
19205           // Search for the existence of segment pbcgroup (segid1, segid2).
19206           inflag = false;
19207           for (k = 0; k < segpbcgrouptable->len() && !inflag; k++) {
19208             pd = (pbcdata *)(* segpbcgrouptable)[k];
19209             if (pd->segid[0] == segid1) {
19210               if (pd->segid[1] == segid2) inflag = true;
19211             } else if (pd->segid[0] == segid2) {
19212               if (pd->segid[1] == segid1) inflag = true;
19213             }
19214           }
19215           if (!inflag) {
19216             pd = (pbcdata *) segpbcgrouptable->append(NULL);
19217             pd->segid[0] = pd1.segid[1 - f1];
19218             pd->segid[1] = pd2.segid[1 - f2];
19219             pd->ss[0] = pd1.ss[1 - f1];
19220             pd->ss[1] = pd2.ss[1 - f2];
19221             // Invalid the fmark[0] == fmark[1].
19222             pd->fmark[0] = pd->fmark[1] = 0;
19223             // Translate matrix pd->transmat[0] = m2 * m1, where m1 =
19224             //   pd1.transmat[1 - f1], m2 = pd2.transmat[f2].
19225             for (k = 0; k < 4; k++) {
19226               for (l = 0; l < 4; l++) {
19227                 pd->transmat[0][k][l] = pd2.transmat[f2][k][l];
19228               }
19229             }
19230             m4xm4(pd->transmat[0], pd1.transmat[1 - f1]);
19231             // Translate matrix pd->transmat[1] = m4 * m3, where m3 =
19232             //   pd2.transmat[1 - f2], m4 = pd1.transmat[f1].
19233             for (k = 0; k < 4; k++) {
19234               for (l = 0; l < 4; l++) {
19235                 pd->transmat[1][k][l] = pd1.transmat[f1][k][l];
19236               }
19237             }
19238             m4xm4(pd->transmat[1], pd2.transmat[1 - f2]);
19239           }
19240         }
19241       }
19242     }
19243   }
19244 
19245   // Form a map from segment index to pbcgroup list of this segment.
19246   idx2segpglist = new int[subsegs->items + 1];
19247   for (i = 0; i < subsegs->items + 1; i++) idx2segpglist[i] = 0;
19248   // Loop through 'segpbcgrouptable', counter the number of pbcgroups of
19249   //   each segment.
19250   for (i = 0; i < segpbcgrouptable->len(); i++) {
19251     pd = (pbcdata *)(* segpbcgrouptable)[i];
19252     for (j = 0; j < 2; j++) {
19253       k = pd->segid[j] - 1;
19254       idx2segpglist[k]++;
19255     }
19256   }
19257   // Calculate the total length of array 'segpglist'.
19258   j = idx2segpglist[0];
19259   idx2segpglist[0] = 0;  // Array starts from 0 element.
19260   for (i = 0; i < subsegs->items; i++) {
19261     k = idx2segpglist[i + 1];
19262     idx2segpglist[i + 1] = idx2segpglist[i] + j;
19263     j = k;
19264   }
19265   // The total length is in the last unit of idx2segpglist.
19266   segpglist = new int[idx2segpglist[i]];
19267   // Loop the set of pbcgroups again, set the data into segpglist.
19268   for (i = 0; i < segpbcgrouptable->len(); i++) {
19269     pd = (pbcdata *)(* segpbcgrouptable)[i];
19270     for (j = 0; j < 2; j++) {
19271       k = pd->segid[j] - 1;
19272       segpglist[idx2segpglist[k]] = i;
19273       idx2segpglist[k]++;
19274     }
19275   }
19276   // Contents in 'idx2segpglist' are shifted, now shift them back.
19277   for (i = subsegs->items - 1; i >= 0; i--) {
19278     idx2segpglist[i + 1] = idx2segpglist[i];
19279   }
19280   idx2segpglist[0] = 0;
19281 }
19282 
19284 //                                                                           //
19285 // getsegpbcsympoint()    Compute the symmetric point for a segment point.   //
19286 //                                                                           //
19287 // 'newpoint' lies on 'splitseg'. This routine calculates a 'sympoint' which //
19288 // locates on 'symsplitseg' and symmtric to 'newpoint'.  Return the location //
19289 // of sympoint wrt. symsplitseg.                                             //
19290 //                                                                           //
19292 
19293 enum tetgenmesh::locateresult tetgenmesh::
19294 getsegpbcsympoint(point newpoint, face* splitseg, point sympoint,
19295                   face* symsplitseg, int groupid)
19296 {
19297   pbcdata *pd;
19298   enum locateresult symloc;
19299   int segid, f1, f2, i;
19300 
19301   pd = (pbcdata *)(* segpbcgrouptable)[groupid];
19302   segid = shellmark(*splitseg);
19303   if (pd->segid[0] == segid) {
19304     f1 = 0;
19305   } else {
19306 #ifdef SELF_CHECK
19307     assert(pd->segid[1] == segid);
19308 #endif
19309     f1 = 1;
19310   }
19311   f2 = 1 - f1;
19312 
19313   // Transform newpoint from f1 -> f2.
19314   for (i = 0; i < 3; i++) {
19315     sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
19316                 + pd->transmat[f1][i][1] * newpoint[1]
19317                 + pd->transmat[f1][i][2] * newpoint[2]
19318                 + pd->transmat[f1][i][3] * 1.0;
19319   }
19320   // Locate sympoint in f2.
19321   *symsplitseg = pd->ss[f2];
19322 #ifdef SELF_CHECK
19323   assert(symsplitseg->sh != dummysh);
19324 #endif
19325   // Locate sympoint in facet. Stop at subsegment.
19326   symloc = locateseg(sympoint, symsplitseg);
19327   symloc = adjustlocateseg(sympoint, symsplitseg, symloc, b->epsilon * 1e+2);
19328   return symloc;
19329 }
19330 
19331 //
19332 // End of periodic boundary condition routines
19333 //
19334 
19335 //
19336 // Begin of vertex perturbation routines
19337 //
19338 
19340 //                                                                           //
19341 // randgenerator()    Generate a random REAL number between (0, |range|).    //
19342 //                                                                           //
19344 
19345 REAL tetgenmesh::randgenerator(REAL range)
19346 {
19347   REAL worknumber, result;
19348   int expo;
19349 
19350   if (range == 0.0) return 0.0;
19351 
19352   expo = 0;
19353   worknumber = fabs(range);
19354   // Normalize worknumber (i.e., 1.xxxExx)
19355   if (worknumber > 10.0) {
19356     while (worknumber > 10.0) {
19357       worknumber /= 10.0;
19358       expo++;
19359     }
19360   } else if (worknumber < 1.0) {
19361     while (worknumber < 1.0) {
19362       worknumber *= 10.0;
19363       expo--;
19364     }
19365   }
19366 #ifdef SELF_CHECK
19367   assert(worknumber >= 1.0 && worknumber <= 10.0);
19368 #endif
19369 
19370   // Enlarge worknumber 1000 times.
19371   worknumber *= 1e+3;
19372   expo -= 3;
19373   // Generate a randome number between (0, worknumber).
19374   result = (double) randomnation((int) worknumber);
19375 
19376   // Scale result back into the original size.
19377   if (expo > 0) {
19378     while (expo != 0) {
19379       result *= 10.0;
19380       expo--;
19381     }
19382   } else if (expo < 0) {
19383     while (expo != 0) {
19384       result /= 10.0;
19385       expo++;
19386     }
19387   }
19388 #ifdef SELF_CHECK
19389   assert((result >= 0.0) && (result <= fabs(range)));
19390 #endif
19391 
19392   return result;
19393 }
19394 
19396 //                                                                           //
19397 // checksub4cocir()    Test a subface to find co-circular pair of subfaces.  //
19398 //                                                                           //
19399 // 'eps' is a relative tolerance for testing approximately cospherical case. //
19400 // Set it to zero if only exact test is desired.                             //
19401 //                                                                           //
19402 // An edge(not a segment) of 'testsub' is locally degenerate if the opposite //
19403 // vertex of the adjacent subface is cocircular with the vertices of testsub.//
19404 // If 'once' is TRUE, operate on the edge only if the pointer 'testsub->sh'  //
19405 // is smaller than its neighbor (for each edge is considered only once).     //
19406 //                                                                           //
19407 // Return TRUE if find an edge of testsub is locally degenerate.             //
19408 //                                                                           //
19410 
19411 bool tetgenmesh::checksub4cocir(face* testsub, REAL eps, bool once,
19412   bool enqflag)
19413 {
19414   badface *cocirsub;
19415   face subloop, neighsub;
19416   face checkseg;
19417   point pa, pb, pc, pd;
19418   REAL sign;
19419   int i;
19420 
19421   subloop = *testsub;
19422   subloop.shver = 0; // Keep the CCW orientation.
19423   // Get the abovepoint of the facet.
19424   abovepoint = facetabovepointarray[shellmark(subloop)];
19425   // Do we need to calculate the abovepoint?
19426   if (abovepoint == (point) NULL) {
19427     getfacetabovepoint(&subloop);
19428   }
19429   // Check the three edges of subloop.
19430   for (i = 0; i < 3; i++) {
19431     sspivot(subloop, checkseg);
19432     if (checkseg.sh == dummysh) {
19433       // It is not a segment, get the adjacent subface.
19434       spivot(subloop, neighsub);
19435       // assert(neighsub.sh != dummysh);
19436       if (!once || (once && (neighsub.sh > subloop.sh))) {
19437         pa = sorg(subloop);
19438         pb = sdest(subloop);
19439         pc = sapex(subloop);
19440         pd = sapex(neighsub);
19441         sign = insphere(pa, pb, pc, abovepoint, pd);
19442         if ((sign != 0.0) && (eps > 0.0)) {
19443           if (iscospheric(pa, pb, pc, abovepoint, pd, sign, eps)) sign = 0.0;
19444         }
19445         if (sign == 0.0) {
19446           // It's locally degenerate!
19447           if (enqflag && badsubfaces != (memorypool *) NULL) {
19448             // Save it.
19449             cocirsub = (badface *) badsubfaces->alloc();
19450             cocirsub->ss = subloop;
19451             cocirsub->forg = pa;
19452             cocirsub->fdest = pb;
19453             cocirsub->fapex = pc;
19454             cocirsub->foppo = pd;
19455             setshell2badface(cocirsub->ss, cocirsub);
19456           }
19457           if (b->verbose > 1) {
19458             printf("    Found set (%d, %d, %d, %d).\n", pointmark(pa),
19459                    pointmark(pb), pointmark(pc), pointmark(pd));
19460           }
19461           return true;
19462         }
19463       }
19464     }
19465     senextself(subloop);
19466   }
19467 
19468   return false;
19469 }
19470 
19472 //                                                                           //
19473 // tallcocirsubs()    Find all co-circular subfaces and save them in list.   //
19474 //                                                                           //
19476 
19477 void tetgenmesh::tallcocirsubs(REAL eps, bool enqflag)
19478 {
19479   face subloop;
19480 
19481   // Loop over all subfaces.
19482   subfaces->traversalinit();
19483   subloop.sh = shellfacetraverse(subfaces);
19484   while (subloop.sh != (shellface *) NULL) {
19485     checksub4cocir(&subloop, eps, true, enqflag);
19486     subloop.sh = shellfacetraverse(subfaces);
19487   }
19488 }
19489 
19491 //                                                                           //
19492 // tallencsegsfsubs()    Check for encroached segs from a list of subfaces.  //
19493 //                                                                           //
19495 
19496 bool tetgenmesh::tallencsegsfsubs(point testpt, list* cavsublist)
19497 {
19498   face startsub, checkseg;
19499   long oldencnum;
19500   int i, j;
19501 
19502   // Remember the current number of encroached segments.
19503   oldencnum = badsubsegs->items;
19504 
19505   // Check segments in the list of subfaces.
19506   for (i = 0; i < cavsublist->len(); i++) {
19507     startsub = * (face *)(* cavsublist)[i];
19508     // Test all three edges of startsub.
19509     for (j = 0; j < 3; j++) {
19510       sspivot(startsub, checkseg);
19511       if (checkseg.sh != dummysh) {
19512         if (!shell2badface(checkseg)) {
19513           checkseg4encroach(&checkseg, testpt, NULL, true);
19514         }
19515       }
19516       senextself(startsub);
19517     }
19518   }
19519 
19520   return (badsubsegs->items > oldencnum);
19521 }
19522 
19524 //                                                                           //
19525 // collectflipedges()    Collect edges of split subfaces for flip checking.  //
19526 //                                                                           //
19527 // 'inspoint' is a newly inserted segment point (inserted by insertsite()).  //
19528 // 'splitseg' is one of the two split subsegments. Some subfaces may be non- //
19529 // Delaunay since they're still not bonded to CDT. This routine collect all  //
19530 // such possible subfaces in 'flipqueue'.                                    //
19531 //                                                                           //
19533 
19534 void tetgenmesh::
19535 collectflipedges(point inspoint, face* splitseg, queue* flipqueue)
19536 {
19537   face startsh, spinsh, checksh;
19538   face nextseg;
19539   point pa, pb;
19540 
19541   // Let the dest of splitseg be inspoint.
19542   splitseg->shver = 0;
19543   if (sdest(*splitseg) != inspoint) {
19544     sesymself(*splitseg);
19545   }
19546 #ifdef SELF_CHECK
19547   assert(sdest(*splitseg) == inspoint);
19548 #endif
19549   pa = sorg(*splitseg);
19550   spivot(*splitseg, startsh);
19551   spinsh = startsh;
19552   do {
19553     findedge(&spinsh, pa, inspoint);
19554     senext2(spinsh, checksh);
19555     enqueueflipedge(checksh, flipqueue);
19556     spivotself(spinsh);
19557   } while (spinsh.sh != startsh.sh);
19558 
19559   // Get the next subsegment.
19560   senext(*splitseg, nextseg);
19561   spivotself(nextseg);
19562 #ifdef SELF_CHECK
19563   assert(nextseg.sh != (shellface *) NULL);
19564 #endif
19565 
19566   // Let the org of nextseg be inspoint.
19567   nextseg.shver = 0;
19568   if (sorg(nextseg) != inspoint) {
19569     sesymself(nextseg);
19570   }
19571 #ifdef SELF_CHECK
19572   assert(sorg(nextseg) == inspoint);
19573 #endif
19574   pb = sdest(nextseg);
19575   spivot(nextseg, startsh);
19576   spinsh = startsh;
19577   do {
19578     findedge(&spinsh, inspoint, pb);
19579     senext(spinsh, checksh);
19580     enqueueflipedge(checksh, flipqueue);
19581     spivotself(spinsh);
19582   } while (spinsh.sh != startsh.sh);
19583 }
19584 
19586 //                                                                           //
19587 // perturbrepairencsegs()    Repair all encroached segments.                 //
19588 //                                                                           //
19589 // All encroached segments are stored in 'badsubsegs'.  Each segment will be //
19590 // split by adding a perturbed point near its circumcenter.                  //
19591 //                                                                           //
19593 
19594 void tetgenmesh::perturbrepairencsegs(queue* flipqueue)
19595 {
19596   badface *encloop;
19597   tetrahedron encodedtet;
19598   triface splittet;
19599   face splitsub, symsplitsub;
19600   face splitseg, symsplitseg;
19601   point newpoint, sympoint;
19602   point pa, pb, pc;
19603   enum insertsiteresult success;
19604   enum locateresult loc, symloc;
19605   REAL cent[3], d1, ps, rs;
19606   int i, j;
19607 
19608   // Note that steinerleft == -1 if an unlimited number of Steiner points
19609   //   is allowed.  Loop until 'badsubsegs' is empty.
19610   badsubsegs->traversalinit();
19611   encloop = badfacetraverse(badsubsegs);
19612   while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19613     splitseg = encloop->ss;
19614 #ifdef SELF_CHECK
19615     assert(shell2badface(splitseg) == encloop);
19616 #endif
19617     setshell2badface(splitseg, NULL);
19618     pa = sorg(splitseg);
19619     pb = sdest(splitseg);
19620     if ((pa == encloop->forg) && (pb == encloop->fdest)) {
19621       if (b->verbose > 1) {
19622         printf("  Get seg (%d, %d).\n", pointmark(pa), pointmark(pb));
19623       }
19624       // Create the newpoint.
19625       makepoint(&newpoint);
19626       // Get the circumcenter and radius of ab.
19627       for (i = 0; i < 3; i++) cent[i] = 0.5 * (pa[i] + pb[i]);
19628       d1 = 0.5 * distance(pa, pb);
19629       // Add a random perturbation to newpoint along the vector ab.
19630       ps = randgenerator(d1 * 1.0e-3);
19631       rs = ps / d1;
19632       // Set newpoint (be at the perturbed circumcenter of ab).
19633       for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19634       setpointtype(newpoint, FREESEGVERTEX);
19635       // Set splitseg into the newpoint.
19636       setpoint2sh(newpoint, sencode(splitseg));
19637 
19638       // Is there periodic boundary condition?
19639       if (checkpbcs) {
19640         // Insert points on other segments of incident pbcgroups.
19641         i = shellmark(splitseg) - 1;
19642         for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
19643           makepoint(&sympoint);
19644           symloc = getsegpbcsympoint(newpoint, &splitseg, sympoint,
19645                                      &symsplitseg, segpglist[j]);
19646 #ifdef SELF_CHECK
19647           assert(symloc != OUTSIDE);
19648 #endif
19649           // Note: the symsplitseg and splitseg may be identical, in case
19650           //   when the the splitseg is the axis of the rotational sym.
19651           if ((symloc == ONEDGE) && (symsplitseg.sh != splitseg.sh)) {
19652             setpointtype(sympoint, FREESEGVERTEX);
19653             setpoint2sh(sympoint, sencode(symsplitseg));
19654             // Insert sympoint into DT.
19655             pc = sorg(symsplitseg);
19656             splittet.tet = dummytet;
19657             // Find a good start point to search.
19658             encodedtet = point2tet(pc);
19659             if (encodedtet != (tetrahedron) NULL) {
19660               decode(encodedtet, splittet);
19661               if (isdead(&splittet)) {
19662                 splittet.tet = dummytet;
19663               }
19664             }
19665             // Locate sympoint in DT.  Do exact location.
19666             success = insertsite(sympoint, &splittet, false, flipqueue);
19667 #ifdef SELF_CHECK
19668             assert(success != DUPLICATEPOINT);
19669 #endif
19670             if (success == OUTSIDEPOINT) {
19671               inserthullsite(sympoint, &splittet, flipqueue);
19672             }
19673             if (steinerleft > 0) steinerleft--;
19674             // Let sympoint remember splittet.
19675             setpoint2tet(sympoint, encode(splittet));
19676             // Do flip in DT.
19677             flip(flipqueue, NULL);
19678             // Insert sympoint into F.
19679             symloc = locateseg(sympoint, &symsplitseg);
19680             if (symloc == ONEDGE) {
19681               symsplitseg.shver = 0;
19682               spivot(symsplitseg, symsplitsub);
19683               // sympoint should on the edge of symsplitsub.
19684               splitsubedge(sympoint, &symsplitsub, flipqueue);
19685             } else {
19686               // insertsite() has done the whole job.
19687 #ifdef SELF_CHECK
19688               assert(symloc == ONVERTEX);
19689               assert(checksubfaces);
19690 #endif
19691               // Some edges may need to be flipped.
19692               collectflipedges(sympoint, &symsplitseg, flipqueue);
19693             }
19694             // Do flip in facet.
19695             flipsub(flipqueue);
19696           } else { // if (symloc == ONVERTEX) {
19697             // The symmtric point already exists. It is possible when two
19698             //   pbc group are idebtical. Omit sympoint.
19699             pointdealloc(sympoint);
19700           }
19701         }
19702       }
19703 
19704       // Insert newpoint into DT.
19705       splittet.tet = dummytet;
19706       // Find a good start point to search.
19707       encodedtet = point2tet(pa);
19708       if (encodedtet != (tetrahedron) NULL) {
19709         decode(encodedtet, splittet);
19710         if (isdead(&splittet)) {
19711           splittet.tet = dummytet;
19712         }
19713       }
19714       if (splittet.tet == dummytet) { // Try pb.
19715         encodedtet = point2tet(pb);
19716         if (encodedtet != (tetrahedron) NULL) {
19717           decode(encodedtet, splittet);
19718           if (isdead(&splittet)) {
19719             splittet.tet = dummytet;
19720           }
19721         }
19722       }
19723       // Locate the newpoint in DT.  Do exact location.
19724       success = insertsite(newpoint, &splittet, false, flipqueue);
19725 #ifdef SELF_CHECK
19726       assert(success != DUPLICATEPOINT);
19727 #endif
19728       if (success == OUTSIDEPOINT) {
19729         // A convex hull edge is mssing, and the inserting point lies
19730         //   (slightly) outside the convex hull due to the significant
19731         //   digits lost in the calculation. Enlarge the convex hull.
19732         inserthullsite(newpoint, &splittet, flipqueue);
19733       }
19734       if (steinerleft > 0) steinerleft--;
19735       // Let newpoint remember splittet.
19736       setpoint2tet(newpoint, encode(splittet));
19737       // Do flip in DT.
19738       flip(flipqueue, NULL);
19739       // Insert newpoint into F.
19740       loc = locateseg(newpoint, &splitseg);
19741       if (loc == ONEDGE) {
19742         splitseg.shver = 0;
19743         spivot(splitseg, splitsub);
19744         // newpoint should on the edge of splitsub.
19745         splitsubedge(newpoint, &splitsub, flipqueue);
19746       } else {
19747         // insertsite() has done the whole job.
19748 #ifdef SELF_CHECK
19749         assert(loc == ONVERTEX);
19750         assert(checksubfaces);
19751 #endif
19752         // Some edges may need to be flipped.
19753         collectflipedges(newpoint, &splitseg, flipqueue);
19754       }
19755       // Do flip in facet.
19756       flipsub(flipqueue);
19757     }
19758     // Remove this entry from list.
19759     badfacedealloc(badsubsegs, encloop);
19760     // Get the next encroached segments.
19761     encloop = badfacetraverse(badsubsegs);
19762   }
19763 }
19764 
19766 //                                                                           //
19767 // perturbrepairencsubs()    Repair all encroached subfaces.                 //
19768 //                                                                           //
19769 // All encroached subfaces are stored in 'badsubfaces'. Each subface will be //
19770 // split by adding a perturbed point near its circumcenter. However, if the  //
19771 // point encroaches some segments, it will not be inserted.  Instead, the    //
19772 // encroached segments are split.                                            //
19773 //                                                                           //
19775 
19776 void tetgenmesh::perturbrepairencsubs(list* cavsublist, queue* flipqueue)
19777 {
19778   badface *encloop, *encsubseg;
19779   tetrahedron encodedtet;
19780   triface splittet;
19781   face splitsub, symsplitsub;
19782   face checkseg, symsplitseg;
19783   point newpoint, sympoint;
19784   point pa, pb, pc, pd;
19785   enum insertsiteresult success;
19786   enum locateresult loc, symloc;
19787   REAL cent[3], d1, ps, rs;
19788   bool reject;
19789   int i;
19790 
19791   // Note that steinerleft == -1 if an unlimited number of Steiner points
19792   //   is allowed.  Loop until the list 'badsubfaces' is empty.
19793   while ((badsubfaces->items > 0) && (steinerleft != 0)) {
19794     badsubfaces->traversalinit();
19795     encloop = badfacetraverse(badsubfaces);
19796     while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19797       splitsub = encloop->ss;
19798 #ifdef SELF_CHECK
19799       assert(shell2badface(splitsub) == encloop);
19800 #endif
19801       setshell2badface(splitsub, NULL);
19802       pa = sorg(splitsub);
19803       pb = sdest(splitsub);
19804       pc = sapex(splitsub);
19805       // The subface may be not the same one when it was determined to be
19806       //   encroached.  If its adjacent encroached subface was split, the
19807       //   consequent flips may change it into another subface.
19808       if ((pa == encloop->forg) && (pb == encloop->fdest) &&
19809           (pc == encloop->fapex)) {
19810         if (b->verbose > 1) {
19811           printf("  Get subface (%d, %d, %d).\n", pointmark(pa),
19812                  pointmark(pb), pointmark(pc));
19813         }
19814         // Create the newpoint.
19815         makepoint(&newpoint);
19816         // Get the circumcenter of abc.
19817         circumsphere(pa, pb, pc, NULL, cent, &d1);
19818 #ifdef SELF_CHECK
19819         assert(d1 > 0.0);
19820 #endif
19821         // Add a random perturbation to newpoint along the vector a->cent.
19822         //   This way, the perturbed point still lies in the plane of abc.
19823         ps = randgenerator(d1 * 1.0e-3);
19824         rs = ps / d1;
19825         // Set newpoint (be at the perturbed circumcenter of abc).
19826         for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19827         // Get the abovepoint of the facet.
19828         abovepoint = facetabovepointarray[shellmark(splitsub)];
19829         // Do we need to calculate the abovepoint?
19830         if (abovepoint == (point) NULL) {
19831           getfacetabovepoint(&splitsub);
19832         }
19833         loc = locatesub(newpoint, &splitsub, 1, 0.0);
19834 #ifdef SELF_CHECK
19835         assert(loc != ONVERTEX);
19836 #endif
19837         if (loc != OUTSIDE) {
19838           // Add 'splitsub' into 'cavsublist'.
19839           cavsublist->append(&splitsub);
19840           // Collect all subfaces that encroached by newpoint.
19841           collectcavsubs(newpoint, cavsublist);
19842           // Find if there are encroached segments.
19843           reject = tallencsegsfsubs(newpoint, cavsublist);
19844           // Clear cavsublist for the next use.
19845           cavsublist->clear();
19846         } else {
19847           // newpoint lies outside. splitsub contains the boundary segment.
19848           sspivot(splitsub, checkseg);
19849 #ifdef SELF_CHECK
19850           assert(checkseg.sh != dummysh);
19851 #endif
19852           // Add this segment into list for splitting.
19853           if (b->verbose > 2) {
19854             printf("    Queuing boundary segment (%d, %d).\n",
19855                    pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
19856           }
19857           encsubseg = (badface *) badsubsegs->alloc();
19858           encsubseg->ss = checkseg;
19859           encsubseg->forg = sorg(checkseg);
19860           encsubseg->fdest = sdest(checkseg);
19861           encsubseg->foppo = (point) NULL;
19862           setshell2badface(encsubseg->ss, encsubseg);
19863           // Reject newpoint.
19864           reject = true;
19865         }
19866 
19867         if (!reject) {
19868           // newpoint is going to be inserted.
19869 
19870           // Is there periodic boundary condition?
19871           if (checkpbcs) {
19872             if (shellpbcgroup(splitsub) >= 0) {
19873               // Insert a point on another facet of the pbcgroup.
19874               makepoint(&sympoint);
19875               // Note: 'abovepoint' will be changed.
19876               symloc = getsubpbcsympoint(newpoint, &splitsub, sympoint,
19877                                          &symsplitsub);
19878 #ifdef SELF_CHECK
19879               assert(symloc != ONVERTEX);
19880 #endif
19881               setpoint2pbcpt(newpoint, sympoint);
19882               setpoint2pbcpt(sympoint, newpoint);
19883               setpointtype(sympoint, FREESUBVERTEX);
19884               // setpoint2sh(sympoint, sencode(symsplitsub));
19885               // Insert sympoint into DT.
19886               pd = sorg(symsplitsub);
19887               splittet.tet = dummytet;
19888               // Find a good start point to search.
19889               encodedtet = point2tet(pd);
19890               if (encodedtet != (tetrahedron) NULL) {
19891                 decode(encodedtet, splittet);
19892                 if (isdead(&splittet)) {
19893                   splittet.tet = dummytet;
19894                 }
19895               }
19896               // Locate sympoint in DT.  Do exact location.
19897               success = insertsite(sympoint, &splittet, false, flipqueue);
19898 #ifdef SELF_CHECK
19899               assert(success != DUPLICATEPOINT);
19900 #endif
19901               if (success == OUTSIDEPOINT) {
19902                 inserthullsite(sympoint, &splittet, flipqueue);
19903               }
19904               if (steinerleft > 0) steinerleft--;
19905               // Let sympoint remember splittet.
19906               setpoint2tet(sympoint, encode(splittet));
19907               // Do flip in DT.
19908               flip(flipqueue, NULL);
19909               // Insert sympoint into F.
19910               // getabovepoint(&symsplitsub);
19911               // symloc = locatesub(sympoint, &symsplitsub, 1, 0.0);
19912               if (symloc == ONFACE) {
19913                 splitsubface(sympoint, &symsplitsub, flipqueue);
19914               } else if (symloc == ONEDGE) {
19915                 splitsubedge(sympoint, &symsplitsub, flipqueue);
19916               } else {
19917                 // 'insertsite()' has done the whole job.
19918 #ifdef SELF_CHECK
19919                 assert(symloc == ONVERTEX);
19920                 assert(checksubfaces);
19921 #endif
19922                 // Split subfaces have been flipped.
19923                 flipqueue->clear();
19924               }
19925               // Do flip in facet.
19926               flipsub(flipqueue);
19927             }
19928           }
19929 
19930           // Insert newpoint into DT.
19931           splittet.tet = dummytet;
19932           // Find a good start point to search.
19933           encodedtet = point2tet(pa);
19934           if (encodedtet != (tetrahedron) NULL) {
19935             decode(encodedtet, splittet);
19936             if (isdead(&splittet)) {
19937               splittet.tet = dummytet;
19938             }
19939           }
19940           if (splittet.tet == dummytet) { // Try pb.
19941             encodedtet = point2tet(pb);
19942             if (encodedtet != (tetrahedron) NULL) {
19943               decode(encodedtet, splittet);
19944               if (isdead(&splittet)) {
19945                 splittet.tet = dummytet;
19946               }
19947             }
19948           }
19949           // Locate the newpoint in DT.  Do exact location.
19950           success = insertsite(newpoint, &splittet, false, flipqueue);
19951 #ifdef SELF_CHECK
19952           assert(success != DUPLICATEPOINT);
19953 #endif
19954           if (success == OUTSIDEPOINT) {
19955             inserthullsite(newpoint, &splittet, flipqueue);
19956           }
19957           if (steinerleft > 0) steinerleft--;
19958           // Let newpoint remember splittet.
19959           setpoint2tet(newpoint, encode(splittet));
19960           // Do flip in DT.
19961           flip(flipqueue, NULL);
19962           // Insert newpoint into F.
19963           // if (checkpbcs) {
19964             // 'abovepoint' has been changed.
19965             // getabovepoint(&splitsub);
19966             // loc = locatesub(newpoint, &splitsub, 1, 0.0);
19967           // }
19968           if (loc == ONFACE) {
19969             // Insert the newpoint in facet.
19970             splitsubface(newpoint, &splitsub, flipqueue);
19971           } else if (loc == ONEDGE) {
19972             // Insert the newpoint in facet.
19973             splitsubedge(newpoint, &splitsub, flipqueue);
19974           } else {
19975             // 'insertsite()' has done the whole job.
19976 #ifdef SELF_CHECK
19977             assert(loc == ONVERTEX);
19978             assert(checksubfaces);
19979 #endif
19980             // Split subfaces have been flipped.
19981             flipqueue->clear();
19982           }
19983           // Set the type of the newpoint.
19984           setpointtype(newpoint, FREESUBVERTEX);
19985           // Set splitsub into the newpoint.
19986           // setpoint2sh(newpoint, sencode(splitsub));
19987           // Do flip in the facet.
19988           flipsub(flipqueue);
19989 
19990           // Remove this entry from list.
19991           badfacedealloc(badsubfaces, encloop);
19992         } else {
19993           // newpoint is rejected. Remove it from points.
19994           pointdealloc(newpoint);
19995           // Repair all encroached segments.
19996           perturbrepairencsegs(flipqueue);
19997           // Do not remove 'encloop'. Later it will be tested again.
19998           setshell2badface(encloop->ss, encloop);
19999         }
20000       } else {
20001         // This subface has been changed. Remove this entry from list.
20002         badfacedealloc(badsubfaces, encloop);
20003         // It may be co-circular with its neighbors.
20004         // checksub4cocir(&splitsub, eps, false, true);
20005       }
20006       // Get the next encroached subfaces.
20007       encloop = badfacetraverse(badsubfaces);
20008     }
20009   }
20010 }
20011 
20013 //                                                                           //
20014 // incrperturbvertices()    Remove the local degeneracies in DT.             //
20015 //                                                                           //
20016 // A local degeneracy of a DT D is a set of 5 or more vertices which share a //
20017 // common sphere S and no other vertex of D in S.  D is not unique if it has //
20018 // local degeneracies. This routine removes the local degeneracies from D by //
20019 // inserting break points (as described in reference [2]).                   //
20020 //                                                                           //
20021 // 'eps' is a user-provided error tolerance. It is used to detect whether or //
20022 // not five points are approximate cospherical (evaluated in iscospheric()). //
20023 // Set it to 0.0 to disable it, i.e., only test pure degenerate point set.   //
20024 //                                                                           //
20026 
20027 void tetgenmesh::incrperturbvertices(REAL eps)
20028 {
20029   queue *flipqueue;
20030   list *cavsublist;
20031   long vertcount;
20032 
20033   if (!b->quiet) {
20034     printf("Perturbing vertices.\n");
20035   }
20036 
20037   vertcount = points->items;
20038   // Create a map from points to tets for fastening search.
20039   // makepoint2tetmap();  // This has been done in meshsurface().
20040 
20041   // Initialize working queues, lists.
20042   flipqueue = new queue(sizeof(badface));
20043   cavsublist = new list(sizeof(face), NULL, 256);
20044   // Initialize the pool of encroached subfaces and subsegments.
20045   badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20046   badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20047   // Find all pairs of co-circular subfaces.
20048   tallcocirsubs(eps, true);
20049   if (b->verbose && badsubfaces->items > 0) {
20050     printf("  Removing degenerate subfaces.\n");
20051   }
20052   perturbrepairencsubs(cavsublist, flipqueue);
20053 
20054   if (b->verbose > 0) {
20055     printf("  %ld break points.\n", points->items - vertcount);
20056   }
20057 
20058   delete cavsublist;
20059   delete flipqueue;
20060   delete badsubfaces;
20061   delete badsubsegs;
20062   badsubsegs = (memorypool *) NULL;
20063   badsubfaces = (memorypool *) NULL;
20064 }
20065 
20066 //
20067 // End of vertex perturbation routines
20068 //
20069 
20070 //
20071 // Begin of segment recovery routines
20072 //
20073 
20075 //                                                                           //
20076 // markacutevertices()    Mark acute vertices.                               //
20077 //                                                                           //
20078 // A vertex v is called acute if there are two segments sharing at v forming //
20079 // an acute angle (i.e. smaller than 90 degree).                             //
20080 //                                                                           //
20081 // This routine finds all acute vertices in the PLC and marks them as point- //
20082 // type ACUTEVERTEX. The other vertices of segments which are non-acute will //
20083 // be marked as NACUTEVERTEX.  Vertices which are not endpoints of segments  //
20084 // (such as DUPLICATEDVERTEX, UNUSEDVERTEX, etc) are not infected.           //
20085 //                                                                           //
20086 // NOTE: This routine should be called before Steiner points are introduced. //
20087 // That is, no point has type like FREESEGVERTEX, etc.                       //
20088 //                                                                           //
20090 
20091 void tetgenmesh::markacutevertices(REAL acuteangle)
20092 {
20093   shellface **segsperverlist;
20094   face segloop, nextseg;
20095   point pointloop, edest, eapex;
20096   REAL cosbound, anglearc;
20097   REAL v1[3], v2[3], L, D;
20098   bool isacute;
20099   int *idx2seglist;
20100   int acutecount;
20101   int idx, i, j, k;
20102 
20103   if (b->verbose > 0) {
20104     printf("  Marking acute vertices.\n");
20105   }
20106 
20107   anglearc = acuteangle * PI / 180.0;
20108   cosbound = cos(anglearc);
20109   acutecount = 0;
20110   // Constructing a map from vertex to segments.
20111   makesegmentmap(idx2seglist, segsperverlist);
20112 
20113   // Loop over the set of vertices.
20114   points->traversalinit();
20115   pointloop = pointtraverse();
20116   while (pointloop != (point) NULL) {
20117     idx = pointmark(pointloop) - in->firstnumber;
20118     // Only do test if p is an endpoint of some segments.
20119     if (idx2seglist[idx + 1] > idx2seglist[idx]) {
20120       // Init p to be non-acute.
20121       setpointtype(pointloop, NACUTEVERTEX);
20122       isacute = false;
20123       // Loop through all segments sharing at p.
20124       for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isacute; i++) {
20125         segloop.sh = segsperverlist[i];
20126         // segloop.shver = 0;
20127         if (sorg(segloop) != pointloop) sesymself(segloop);
20128         edest = sdest(segloop);
20129         for (j = i + 1; j < idx2seglist[idx + 1] && !isacute; j++) {
20130           nextseg.sh = segsperverlist[j];
20131           // nextseg.shver = 0;
20132           if (sorg(nextseg) != pointloop) sesymself(nextseg);
20133           eapex = sdest(nextseg);
20134           // Check the angle formed by segs (p, edest) and (p, eapex).
20135           for (k = 0; k < 3; k++) {
20136             v1[k] = edest[k] - pointloop[k];
20137             v2[k] = eapex[k] - pointloop[k];
20138           }
20139           L = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
20140           for (k = 0; k < 3; k++) v1[k] /= L;
20141           L = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
20142           for (k = 0; k < 3; k++) v2[k] /= L;
20143           D = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
20144           // Is D acute?
20145           isacute = (D >= cosbound);
20146         }
20147       }
20148       if (isacute) {
20149         // Mark p to be acute.
20150         setpointtype(pointloop, ACUTEVERTEX);
20151         acutecount++;
20152       }
20153     }
20154     pointloop = pointtraverse();
20155   }
20156 
20157   delete [] idx2seglist;
20158   delete [] segsperverlist;
20159 
20160   if ((b->verbose > 0) && (acutecount > 0)) {
20161     printf("  %d acute vertices.\n", acutecount);
20162   }
20163 }
20164 
20166 //                                                                           //
20167 // finddirection()    Find the first tetrahedron on the path from one point  //
20168 //                    to another.                                            //
20169 //                                                                           //
20170 // Find the tetrahedron that intersects a line segment L (from the origin of //
20171 // 'searchtet' to the point 'tend'), and returns the result in 'searchtet'.  //
20172 // The origin of 'searchtet' does not change, even though the tetrahedron    //
20173 // returned may differ from the one passed in.  This routine is used to find //
20174 // the direction to move in to get from one point to another.                //
20175 //                                                                           //
20176 // The return value notes the location of the line segment L with respect to //
20177 // 'searchtet':                                                              //
20178 //   - Returns RIGHTCOLLINEAR indicates L is collinear with the line segment //
20179 //     from the origin to the destination of 'searchtet'.                    //
20180 //   - Returns LEFTCOLLINEAR indicates L is collinear with the line segment  //
20181 //     from the origin to the apex of 'searchtet'.                           //
20182 //   - Returns TOPCOLLINEAR indicates L is collinear with the line segment   //
20183 //     from the origin to the opposite of 'searchtet'.                       //
20184 //   - Returns ACROSSEDGE indicates L intersects with the line segment from  //
20185 //     the destination to the apex of 'searchtet'.                           //
20186 //   - Returns ACROSSFACE indicates L intersects with the face opposite to   //
20187 //     the origin of 'searchtet'.                                            //
20188 //   - Returns BELOWHULL indicates L crosses outside the mesh domain. This   //
20189 //     can only happen when the domain is non-convex.                        //
20190 //                                                                           //
20191 // NOTE: This routine only works correctly when the mesh is exactly Delaunay.//
20192 //                                                                           //
20193 // If 'maxtetnumber' > 0, stop the searching process if the number of passed //
20194 // tets is larger than it. Return BELOWHULL.                                 //
20195 //                                                                           //
20197 
20198 enum tetgenmesh::finddirectionresult tetgenmesh::
20199 finddirection(triface *searchtet, point tend, long maxtetnumber)
20200 {
20201   triface neightet;
20202   point tstart, tdest, tapex, toppo;
20203   REAL ori1, ori2, ori3;
20204   long tetnumber;
20205 
20206   tstart = org(*searchtet);
20207 #ifdef SELF_CHECK
20208   assert(tstart != tend);
20209 #endif
20210   adjustedgering(*searchtet, CCW);
20211   if (tstart != org(*searchtet)) {
20212     enextself(*searchtet); // For keeping the same origin.
20213   }
20214   tdest = dest(*searchtet);
20215   if (tdest == tend) {
20216     return RIGHTCOLLINEAR;
20217   }
20218   tapex = apex(*searchtet);
20219   if (tapex == tend) {
20220     return LEFTCOLLINEAR;
20221   }
20222 
20223   ori1 = orient3d(tstart, tdest, tapex, tend);
20224   if (ori1 > 0.0) {
20225     // 'tend' is below the face, get the neighbor of this side.
20226     sym(*searchtet, neightet);
20227     if (neightet.tet != dummytet) {
20228       findorg(&neightet, tstart);
20229       adjustedgering(neightet, CCW);
20230       if (org(neightet) != tstart) {
20231         enextself(neightet); // keep the same origin.
20232       }
20233       // Set the changed configuratiuon.
20234       *searchtet = neightet;
20235       ori1 = -1.0;
20236       tdest = dest(*searchtet);
20237       tapex = apex(*searchtet);
20238     } else {
20239       // A hull face. Only possible for a nonconvex mesh.
20240 #ifdef SELF_CHECK
20241       assert(nonconvex);
20242 #endif
20243       return BELOWHULL;
20244     }
20245   }
20246 
20247   // Repeatedly change the 'searchtet', remain 'tstart' be its origin, until
20248   //   find a tetrahedron contains 'tend' or is crossed by the line segment
20249   //   from 'tstart' to 'tend'.
20250   tetnumber = 0l;
20251   while ((maxtetnumber > 0) && (tetnumber <= maxtetnumber)) {
20252     tetnumber++;
20253     toppo = oppo(*searchtet);
20254     if (toppo == tend) {
20255       return TOPCOLLINEAR;
20256     }
20257     ori2 = orient3d(tstart, toppo, tdest, tend);
20258     if (ori2 > 0.0) {
20259       // 'tend' is below the face, get the neighbor at this side.
20260       fnext(*searchtet, neightet);
20261       symself(neightet);
20262       if (neightet.tet != dummytet) {
20263         findorg(&neightet, tstart);
20264         adjustedgering(neightet, CCW);
20265         if (org(neightet) != tstart) {
20266           enextself(neightet); // keep the same origin.
20267         }
20268         // Set the changed configuration.
20269         *searchtet = neightet;
20270         ori1 = -1.0;
20271         tdest = dest(*searchtet);
20272         tapex = apex(*searchtet);
20273         // Continue the search from the changed 'searchtet'.
20274         continue;
20275       } else {
20276         // A hull face. Only possible for a nonconvex mesh.
20277 #ifdef SELF_CHECK
20278         assert(nonconvex);
20279 #endif
20280         return BELOWHULL;
20281       }
20282     }
20283     ori3 = orient3d(tapex, toppo, tstart, tend);
20284     if (ori3 > 0.0) {
20285       // 'tend' is below the face, get the neighbor at this side.
20286       enext2fnext(*searchtet, neightet);
20287       symself(neightet);
20288       if (neightet.tet != dummytet) {
20289         findorg(&neightet, tstart);
20290         adjustedgering(neightet, CCW);
20291         if (org(neightet) != tstart) {
20292           enextself(neightet); // keep the same origin.
20293         }
20294         // Set the changed configuration.
20295         *searchtet = neightet;
20296         ori1 = -1.0;
20297         tdest = dest(*searchtet);
20298         tapex = apex(*searchtet);
20299         // Continue the search from the changed 'searchtet'.
20300         continue;
20301       } else {
20302         // A hull face. Only possible for a nonconvex mesh.
20303 #ifdef SELF_CHECK
20304         assert(nonconvex);
20305 #endif
20306         return BELOWHULL;
20307       }
20308     }
20309     // Now 'ori1', 'ori2' and 'ori3' are possible be 0.0 or all < 0.0;
20310     if (ori1 < 0.0) {
20311       // Possible cases are: ACROSSFACE, ACROSSEDGE, TOPCOLLINEAR.
20312       if (ori2 < 0.0) {
20313         if (ori3 < 0.0) {
20314           return ACROSSFACE;
20315         } else { // ori3 == 0.0;
20316           // Cross edge (apex, oppo)
20317           enext2fnextself(*searchtet);
20318           esymself(*searchtet); // org(*searchtet) == tstart;
20319           return ACROSSEDGE;
20320         }
20321       } else { // ori2 == 0.0;
20322         if (ori3 < 0.0) {
20323           // Cross edge (dest, oppo)
20324           fnextself(*searchtet);
20325           esymself(*searchtet);
20326           enextself(*searchtet); // org(*searchtet) == tstart;
20327           return ACROSSEDGE;
20328         } else { // ori3 == 0.0;
20329           // Collinear with edge (org, oppo)
20330           return TOPCOLLINEAR;
20331         }
20332       }
20333     } else { // ori1 == 0.0;
20334       // Possible cases are: RIGHTCOLLINEAR, LEFTCOLLINEAR, ACROSSEDGE.
20335       if (ori2 < 0.0) {
20336         if (ori3 < 0.0) {
20337           // Cross edge (tdest, tapex)
20338           return ACROSSEDGE;
20339         } else { // ori3 == 0.0
20340           // Collinear with edge (torg, tapex)
20341           return LEFTCOLLINEAR;
20342         }
20343       } else { // ori2 == 0.0;
20344 #ifdef SELF_CHECK
20345         assert(ori3 != 0.0);
20346 #endif
20347         // Collinear with edge (torg, tdest)
20348         return RIGHTCOLLINEAR;
20349       }
20350     }
20351   }
20352   // Loop breakout. It may happen when the mesh is non-Delaunay.
20353   return BELOWHULL;
20354 }
20355 
20357 //                                                                           //
20358 // getsearchtet()    Find a tetrahedron whose origin is either 'p1' or 'p2'. //
20359 //                                                                           //
20360 // On return, the origin of 'searchtet' is either 'p1' or 'p2',  and 'tend'  //
20361 // returns the other point.  'searchtet' serves as the starting tetrahedron  //
20362 // for searching of the line segment from 'p1' to 'p2' or vice versa.        //
20363 //                                                                           //
20365 
20366 void tetgenmesh::getsearchtet(point p1, point p2, triface* searchtet,
20367   point* tend)
20368 {
20369   tetrahedron encodedtet1, encodedtet2;
20370 
20371   // Is there a valid handle provided by the user?
20372   if ((searchtet->tet != (tetrahedron *) NULL) && !isdead(searchtet)) {
20373     // Find which endpoint the handle holds.
20374     if (findorg(searchtet, p1)) {
20375       *tend = p2;
20376       return;
20377     } else {
20378       if (findorg(searchtet, p2)) {
20379         *tend = p1;
20380         return;
20381       }
20382     }
20383   }
20384   // If not, search the tet handle stored in 'p1' or 'p2'.
20385   *tend = (point) NULL;
20386   encodedtet1 = point2tet(p1);
20387   encodedtet2 = point2tet(p2);
20388   if (encodedtet1 != (tetrahedron) NULL) {
20389     decode(encodedtet1, *searchtet);
20390     // Be careful, here 'searchtet' may be dead.
20391     if (findorg(searchtet, p1)) {
20392       *tend = p2;
20393     }
20394   } else if (encodedtet2 != (tetrahedron) NULL) {
20395     decode(encodedtet2, *searchtet);
20396     // Be careful, here 'searchtet' may be dead.
20397     if (findorg(searchtet, p2)) {
20398       *tend = p1;
20399     }
20400   }
20401   // If still not, perform a full point location.  The starting tet is
20402   //   chosen as follows: Use the handle stored in 'p1' or 'p2' if it is
20403   //   alive; otherwise, start from a tet on the convex hull.
20404   if (*tend == (point) NULL) {
20405     if (encodedtet1 != (tetrahedron) NULL) {
20406       decode(encodedtet1, *searchtet);
20407       // Be careful, here 'searchtet' may be dead.
20408     }
20409     if (isdead(searchtet)) {
20410       if (encodedtet2 != (tetrahedron) NULL) {
20411         decode(encodedtet2, *searchtet);
20412         // Be careful, here 'searchtet' may be dead.
20413       }
20414       if (isdead(searchtet)) {
20415         searchtet->tet = dummytet;
20416         searchtet->loc = 0;
20417         symself(*searchtet);
20418       }
20419 #ifdef SELF_CHECK
20420       assert(!isdead(searchtet));
20421 #endif
20422     }
20423     if (locate(p1, searchtet) != ONVERTEX) {
20424       printf("Internal error in getsearchtet():  Failed to locate point\n");
20425       internalerror();
20426     }
20427     // Remember this handle in 'p1' to enhance the search speed.
20428     setpoint2tet(p1, encode(*searchtet));
20429     *tend = p2;
20430   }
20431 }
20432 
20434 //                                                                           //
20435 // isedgeencroached()    Check whether or not a subsegment is encroached.    //
20436 //                                                                           //
20437 // A segment with endpoints 'p1' and 'p2' is encroached by the point 'testpt'//
20438 // if it lies in the diametral sphere of this segment.  The degenerate case  //
20439 // that 'testpt' lies on the sphere is treated as encroached if 'degflag' is //
20440 // set to be TRUE.                                                           //
20441 //                                                                           //
20443 
20444 bool tetgenmesh::isedgeencroached(point p1, point p2, point testpt,
20445   bool degflag)
20446 {
20447   REAL dotproduct;
20448 
20449   // Check if the segment is facing an angle larger than 90 degree?
20450   dotproduct = (p1[0] - testpt[0]) * (p2[0] - testpt[0])
20451              + (p1[1] - testpt[1]) * (p2[1] - testpt[1])
20452              + (p1[2] - testpt[2]) * (p2[2] - testpt[2]);
20453   if (dotproduct < 0) {
20454     return true;
20455   } else if (dotproduct == 0 && degflag) {
20456     return true;
20457   } else {
20458     return false;
20459   }
20460 }
20461 
20463 //                                                                           //
20464 // scoutrefpoint()    Search the reference point of a missing segment.       //
20465 //                                                                           //
20466 // A segment S is missing in current Delaunay tetrahedralization DT and will //
20467 // be split by inserting a point V in it.  The two end points of S are the   //
20468 // origin of 'searchtet' and 'tend'. And we know that S is crossing the face //
20469 // of 'searchtet' opposite to its origin (may be intersecting with the edge  //
20470 // from the destination to the apex of the 'searchtet').  The search of P is //
20471 // completed by walking through all faces of DT across by S.                 //
20472 //                                                                           //
20473 // Warning:  This routine is correct when the tetrahedralization is Delaunay //
20474 // and convex. Otherwise, the search loop may not terminate.                 //
20475 //                                                                           //
20477 
20478 tetgenmesh::point tetgenmesh::scoutrefpoint(triface* searchtet, point tend)
20479 {
20480   triface checkface;
20481   point tstart, testpt, refpoint;
20482   REAL cent[3], radius, largest;
20483   REAL ahead;
20484   bool ncollinear;
20485   int sides;
20486 
20487   if (b->verbose > 2) {
20488     printf("  Scout the reference point of segment (%d, %d).\n",
20489            pointmark(org(*searchtet)), pointmark(tend));
20490   }
20491 
20492   tstart = org(*searchtet);
20493   refpoint = (point) NULL;
20494   largest = 0; // avoid compile warning.
20495 
20496   // Check the three vertices of the crossing face.
20497   testpt = apex(*searchtet);
20498   if (isedgeencroached(tstart, tend, testpt, true)) {
20499     ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20500 #ifdef SELF_CHECK
20501     assert(ncollinear);
20502 #endif
20503     refpoint = testpt;
20504     largest = radius;
20505   }
20506   testpt = dest(*searchtet);
20507   if (isedgeencroached(tstart, tend, testpt, true)) {
20508     ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20509 #ifdef SELF_CHECK
20510     assert(ncollinear);
20511 #endif
20512     if (refpoint == (point) NULL) {
20513       refpoint = testpt;
20514       largest = radius;
20515     } else {
20516       if (radius > largest) {
20517         refpoint = testpt;
20518         largest = radius;
20519       }
20520     }
20521   }
20522   testpt = oppo(*searchtet);
20523   if (isedgeencroached(tstart, tend, testpt, true)) {
20524     ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20525 #ifdef SELF_CHECK
20526     assert(ncollinear);
20527 #endif
20528     if (refpoint == (point) NULL) {
20529       refpoint = testpt;
20530       largest = radius;
20531     } else {
20532       if (radius > largest) {
20533         refpoint = testpt;
20534         largest = radius;
20535       }
20536     }
20537   }
20538   // Check the opposite vertex of the neighboring tet in case the segment
20539   //   crosses the edge (leftpoint, rightpoint) of the crossing face.
20540   sym(*searchtet, checkface);
20541   if (checkface.tet != dummytet) {
20542     testpt = oppo(checkface);
20543     if (isedgeencroached(tstart, tend, testpt, true)) {
20544       ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20545 #ifdef SELF_CHECK
20546       assert(ncollinear);
20547 #endif
20548       if (refpoint == (point) NULL) {
20549         refpoint = testpt;
20550         largest = radius;
20551       } else {
20552         if (radius > largest) {
20553           refpoint = testpt;
20554           largest = radius;
20555         }
20556       }
20557     }
20558   }
20559 
20560   // Walk through all crossing faces.
20561   enextfnext(*searchtet, checkface);
20562   sym(checkface, *searchtet);
20563   while (true) {
20564     // Check if we are reaching the boundary of the triangulation.
20565 #ifdef SELF_CHECK
20566     assert(searchtet->tet != dummytet);
20567 #endif
20568     // Search for an adjoining tetrahedron we can walk through.
20569     searchtet->ver = 0;
20570     // 'testpt' is the shared vertex for the following orientation tests.
20571     testpt = oppo(*searchtet);
20572     if (testpt == tend) {
20573       // The searching is finished.
20574       break;
20575     } else {
20576       // 'testpt' may encroach the segment.
20577       if ((testpt != tstart) && (testpt != refpoint)) {
20578         if (isedgeencroached(tstart, tend, testpt, true)) {
20579           ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20580           if (!ncollinear) {
20581             // 'testpt' is collinear with the segment. It may happen when a
20582             //   set of collinear and continuous segments is defined by two
20583             //   extreme endpoints.  In this case, we should choose 'testpt'
20584             //   as the splitting point immediately.  No new point should be
20585             //   created.
20586             refpoint = testpt;
20587             break;
20588           }
20589           if (refpoint == (point) NULL) {
20590             refpoint = testpt;
20591             largest = radius;
20592           } else {
20593             if (radius > largest) {
20594               refpoint = testpt;
20595               largest = radius;
20596             }
20597           }
20598         }
20599       }
20600     }
20601     // Check three side-faces of 'searchtet' to find the one through
20602     //   which we can walk next.
20603     for (sides = 0; sides < 3; sides++) {
20604       fnext(*searchtet, checkface);
20605       ahead = orient3d(org(checkface), dest(checkface), testpt, tend);
20606       if (ahead < 0.0) {
20607         // We can walk through this face and continue the searching.
20608         sym(checkface, *searchtet);
20609         break;
20610       }
20611       enextself(*searchtet);
20612     }
20613 #ifdef SELF_CHECK
20614     assert (sides < 3);
20615 #endif
20616   }
20617 
20618 #ifdef SELF_CHECK
20619   assert(refpoint != (point) NULL);
20620 #endif
20621   return refpoint;
20622 }
20623 
20625 //                                                                           //
20626 // getsegmentorigin()    Return the origin of the (unsplit) segment.         //
20627 //                                                                           //
20628 // After a segment (or a subsegment) is split. Two resulting subsegments are //
20629 // connecting each other through the pointers saved in their data fields.    //
20630 // With these pointers, the whole (unsplit) segment can be found. 'splitseg' //
20631 // may be a split subsegment.  Returns the origin of the unsplit segment.    //
20632 //                                                                           //
20634 
20635 tetgenmesh::point tetgenmesh::getsegmentorigin(face* splitseg)
20636 {
20637   face workseg;
20638   point farorg;
20639 
20640   farorg = sorg(*splitseg);
20641   if ((pointtype(farorg) != ACUTEVERTEX) &&
20642       (pointtype(farorg) != NACUTEVERTEX)) {
20643     workseg = *splitseg;
20644     do {
20645       senext2self(workseg);
20646       spivotself(workseg);
20647       if (workseg.sh != dummysh) {
20648         workseg.shver = 0;  // It's a subsegment.
20649         if (sdest(workseg) != farorg) {
20650           sesymself(workseg);
20651 #ifdef SELF_CHECK
20652           assert(sdest(workseg) == farorg);
20653 #endif
20654         }
20655         farorg = sorg(workseg);
20656         if ((pointtype(farorg) == ACUTEVERTEX) ||
20657             (pointtype(farorg) == NACUTEVERTEX)) break;
20658       }
20659     } while (workseg.sh != dummysh);
20660   }
20661 #ifdef SELF_CHECK
20662   assert((pointtype(farorg) == ACUTEVERTEX) ||
20663          (pointtype(farorg) == NACUTEVERTEX));
20664 #endif
20665   return farorg;
20666 }
20667 
20669 //                                                                           //
20670 // getsplitpoint()    Get a point for splitting a segment.                   //
20671 //                                                                           //
20672 // 'splitseg' is the segment will be split. 'refpoint' is a reference point  //
20673 // for splitting this segment. Moreover, it should not collinear with the    //
20674 // splitting segment. (The collinear case will be detected by iscollinear()  //
20675 // before entering this routine.)  The calculation of the splitting point is //
20676 // governed by three rules introduced in my paper.                           //
20677 //                                                                           //
20678 // After the position is calculated, a new point is created at this location.//
20679 // The new point has one of the two pointtypes: FREESEGVERTEX indicating it  //
20680 // is an inserting vertex on segment, and NACUTEVERTEX indicating it is an   //
20681 // endpoint of a segment which original has type-3 now becomes type-2.       //
20682 //                                                                           //
20684 
20685 tetgenmesh::point tetgenmesh::getsplitpoint(face* splitseg, point refpoint)
20686 {
20687   point splitpoint;
20688   point farorg, fardest;
20689   point ei, ej, ek, c;
20690   REAL v[3], r, split;
20691   REAL d1, d2, ps, rs;
20692   bool acuteorg, acutedest;
20693   int stype, rule;
20694   int i;
20695 
20696   // First determine the type of the segment (type-1, type-2, or type-3).
20697   farorg = getsegmentorigin(splitseg);
20698   acuteorg = (pointtype(farorg) == ACUTEVERTEX);
20699   sesymself(*splitseg);
20700   fardest = getsegmentorigin(splitseg);
20701   acutedest = (pointtype(fardest) == ACUTEVERTEX);
20702   sesymself(*splitseg);
20703 
20704   ek = (point) NULL; // avoid a compilation warning.
20705 
20706   if (acuteorg) {
20707     if (acutedest) {
20708       stype = 3;
20709     } else {
20710       stype = 2;
20711       ek = farorg;
20712     }
20713   } else {
20714     if (acutedest) {
20715       stype = 2;
20716       // Adjust splitseg, so that its origin is acute.
20717       sesymself(*splitseg);
20718       ek = fardest;
20719     } else {
20720       stype = 1;
20721     }
20722   }
20723   ei = sorg(*splitseg);
20724   ej = sdest(*splitseg);
20725 
20726   if (b->verbose > 1) {
20727     printf("  Splitting segment (%d, %d) type-%d with refpoint %d.\n",
20728            pointmark(ei), pointmark(ej), stype, pointmark(refpoint));
20729   }
20730 
20731   if (stype == 1 || stype == 3) {
20732     // Use rule-1.
20733     REAL eij, eip, ejp;
20734     eij = distance(ei, ej);
20735     eip = distance(ei, refpoint);
20736     ejp = distance(ej, refpoint);
20737     if ((eip < ejp) && (eip < 0.5 * eij)) {
20738       c = ei;
20739       r = eip;
20740     } else if ((eip > ejp) && (ejp < 0.5 * eij)) {
20741       c = ej;
20742       ej = ei;
20743       r = ejp;
20744     } else {
20745       c = ei;
20746       r = 0.5 * eij;
20747     }
20748     split = r / eij;
20749     for (i = 0; i < 3; i++) {
20750       v[i] = c[i] + split * (ej[i] - c[i]);
20751     }
20752     rule = 1;
20753   } else {
20754     // Use rule-2 or rule-3.
20755     REAL eki, ekj, ekp, evj, evp, eiv;
20756     c = ek;
20757     eki = distance(ek, ei);  // eki may equal zero.
20758     ekj = distance(ek, ej);
20759     ekp = distance(ek, refpoint);
20760     // Calculate v (the going to split position between ei, ej).
20761     r = ekp;
20762     // Check the validity of the position.
20763     if (!(eki < r && r < ekj)) {
20764       printf("Error:  Invalid PLC.\n");
20765       printf("  Hint:  Use -d switch to check it.\n");
20766       terminatetetgen(1);
20767     }
20768     split = r / ekj;
20769     for (i = 0; i < 3; i++) {
20770       v[i] = c[i] + split * (ej[i] - c[i]);
20771     }
20772     rule = 2;
20773     evj = ekj - r; // distance(v, ej);
20774     evp = distance(v, refpoint);
20775     if (evj < evp) {
20776       // v is rejected, use rule-3.
20777       eiv = distance(ei, v);
20778       if (evp <= 0.5 * eiv) {
20779         r = eki + eiv - evp;
20780       } else {
20781         r = eki + 0.5 * eiv;
20782       }
20783 #ifdef SELF_CHECK
20784       assert(eki < r && r < ekj);
20785 #endif
20786       split = r / ekj;
20787       for (i = 0; i < 3; i++) {
20788         v[i] = c[i] + split * (ej[i] - c[i]);
20789       }
20790       if (b->verbose > 1) {
20791         printf("    Using rule-3.\n");
20792       }
20793       rule = 3;
20794     }
20795   }
20796 
20797   // Accumulate the corresponding counters.
20798   if (rule == 1) r1count++;
20799   else if (rule == 2) r2count++;
20800   else if (rule == 3) r3count++;
20801 
20802   if (b->verbose > 1) {
20803     if (stype == 2) {
20804       printf("    Split = %.12g.\n", distance(ei, v) / distance(ei, ej));
20805     } else {
20806       printf("    Split = %.12g.\n", distance(c, v) / distance(c, ej));
20807     }
20808   }
20809 
20810   // Create the newpoint.
20811   makepoint(&splitpoint);
20812   // Add a random perturbation on splitpoint.
20813   d1 = distance(c, v);
20814   d2 = distance(refpoint, v);
20815   if (stype == 1 || stype == 3) {
20816     ps = randgenerator(d1 * 1.0e-3);
20817   } else {
20818     // For type-2 segment, add a smaller perturbation.
20819     // ps = randgenerator(d1 * 1.0e-5);
20820     // REAL d2 = distance(refpoint, v);
20821     ps = randgenerator(d2 * 1.0e-5);
20822   }
20823   rs = ps / d1;
20824   // Perturb splitpoint away from c.
20825   for (i = 0; i < 3; i++) {
20826     splitpoint[i] = c[i] + (1.0 + rs) * (v[i] - c[i]);
20827   }
20828   // for (i = 0; i < in->numberofpointattributes; i++) {
20829   //   splitpoint[i + 3] = c[i + 3] + (split + rs) * (ej[i + 3] - c[i + 3]);
20830   // }
20831   if (stype == 3) {
20832     // Change a type-3 segment into two type-2 segments.
20833     setpointtype(splitpoint, NACUTEVERTEX);
20834   } else {
20835     // Set it's type be FREESEGVERTEX.
20836     setpointtype(splitpoint, FREESEGVERTEX);
20837   }
20838   setpoint2sh(splitpoint, sencode(*splitseg));
20839 
20840   return splitpoint;
20841 }
20842 
20844 //                                                                           //
20845 // insertsegment()    Insert segment into DT. Queue it if it does not exist. //
20846 //                                                                           //
20848 
20849 bool tetgenmesh::insertsegment(face *insseg, list *misseglist)
20850 {
20851   badface *misseg;
20852   triface searchtet, spintet;
20853   point tend, checkpoint;
20854   point p1, p2;
20855   enum finddirectionresult collinear;
20856   int hitbdry;
20857 
20858   // Search segment ab in DT.
20859   p1 = (point) insseg->sh[3];
20860   p2 = (point) insseg->sh[4];
20861   getsearchtet(p1, p2, &searchtet, &tend);
20862   collinear = finddirection(&searchtet, tend, tetrahedrons->items);
20863   if (collinear == LEFTCOLLINEAR) {
20864     checkpoint = apex(searchtet);
20865     enext2self(searchtet);
20866     esymself(searchtet);
20867   } else if (collinear == RIGHTCOLLINEAR) {
20868     checkpoint = dest(searchtet);
20869   } else if (collinear == TOPCOLLINEAR) {
20870     checkpoint = oppo(searchtet);
20871     fnextself(searchtet);
20872     enext2self(searchtet);
20873     esymself(searchtet);
20874   } else {
20875     // assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
20876     checkpoint = (point) NULL;
20877   }
20878   if (checkpoint == tend) {
20879     // Segment exist. Bond it to all tets containing it.
20880     hitbdry = 0;
20881     adjustedgering(searchtet, CCW);
20882     fnextself(searchtet);
20883     spintet = searchtet;
20884     do {
20885       tssbond1(spintet, *insseg);
20886       if (!fnextself(spintet)) {
20887         hitbdry++;
20888         if (hitbdry < 2) {
20889           esym(searchtet, spintet);
20890           if (!fnextself(spintet)) {
20891             hitbdry++;
20892           }
20893         }
20894       }
20895     } while ((apex(spintet) != apex(searchtet)) && (hitbdry < 2));
20896     return true;
20897   } else {
20898     // Segment is missing.
20899     if (misseglist != (list *) NULL) {
20900       if (b->verbose > 2) {
20901         printf("    Queuing missing segment (%d, %d).\n", pointmark(p1),
20902                pointmark(p2));
20903       }
20904       misseg = (badface *) misseglist->append(NULL);
20905       misseg->ss = *insseg;
20906       misseg->forg = p1;
20907       misseg->fdest = p2;
20908       misseg->foppo = (point) NULL; // Not used.
20909       // setshell2badface(misseg->ss, misseg);
20910     }
20911     return false;
20912   }
20913 }
20914 
20916 //                                                                           //
20917 // tallmissegs()    Find and queue all missing segments in DT.               //
20918 //                                                                           //
20920 
20921 void tetgenmesh::tallmissegs(list *misseglist)
20922 {
20923   face segloop;
20924 
20925   if (b->verbose) {
20926     printf("  Queuing missing segments.\n");
20927   }
20928 
20929   subsegs->traversalinit();
20930   segloop.sh = shellfacetraverse(subsegs);
20931   while (segloop.sh != (shellface *) NULL) {
20932     insertsegment(&segloop, misseglist);
20933     segloop.sh = shellfacetraverse(subsegs);
20934   }
20935 }
20936 
20938 //                                                                           //
20939 // delaunizesegments()    Split segments repeatedly until they appear in a   //
20940 //                        Delaunay tetrahedralization.                       //
20941 //                                                                           //
20942 // Given a PLC X, which has a set V of vertices and a set of segments. Start //
20943 // from a Delaunay tetrahedralization D of V, this routine recovers segments //
20944 // of X in D by incrementally inserting points on missing segments, updating //
20945 // D with the newly inserted points into D', which remains to be a Delaunay  //
20946 // tetrahedralization and respects the segments of X. Hence, each segment of //
20947 // X appears as a union of edges in D'.                                      //
20948 //                                                                           //
20949 // This routine dynamically maintains two meshes, one is DT, another is the  //
20950 // surface mesh F of X.  DT and F have exactly the same vertices.  They are  //
20951 // updated simultaneously with the newly inserted points.                    //
20952 //                                                                           //
20953 // Missing segments are found by looping the set S of segments, checking the //
20954 // existence of each segment in DT.  Once a segment is found missing in DT,  //
20955 // it is split into two subsegments by inserting a point into both DT and F, //
20956 // and S is updated accordingly.  However, the inserted point may cause some //
20957 // other existing segments be non-Delaunay,  hence are missing from the DT.  //
20958 // In order to force all segments to appear in DT, we have to loop S again   //
20959 // after some segments are split. (A little ugly method)  Use a handle to    //
20960 // remember the last segment be split in one loop, hence all segments after  //
20961 // it are existing and need not be checked.                                  //
20962 //                                                                           //
20963 // In priciple, a segment on the convex hull should exist in DT. However, if //
20964 // there are four coplanar points on the convex hull, and the DT only can    //
20965 // contain one diagonal edge which is unfortunately not the segment, then it //
20966 // is missing. During the recovery of the segment, it is possible that the   //
20967 // calculated inserting point for recovering this convex hull segment is not //
20968 // exact enough and lies (slightly) outside the DT. In order to insert the   //
20969 // point, we enlarge the convex hull of the DT, so it can contain the point  //
20970 // and remains convex.  'inserthullsite()' is called for this case.          //
20971 //                                                                           //
20973 
20974 void tetgenmesh::delaunizesegments()
20975 {
20976   list *misseglist;
20977   queue *flipqueue;
20978   badface *misloop;
20979   tetrahedron encodedtet;
20980   triface searchtet, splittet;
20981   face splitsh, symsplitsub;
20982   face segloop, symsplitseg;
20983   point refpoint, splitpoint, sympoint;
20984   point tend, checkpoint;
20985   point p1, p2, pa;
20986   enum finddirectionresult collinear;
20987   enum insertsiteresult success;
20988   enum locateresult symloc;
20989   bool coll;
20990   long vertcount;
20991   int i, j;
20992 
20993   if (!b->quiet) {
20994     printf("Delaunizing segments.\n");
20995   }
20996 
20997   // Construct a map from points to tets for speeding point location.
20998   makepoint2tetmap();
20999   // Initialize a flipqueue.
21000   flipqueue = new queue(sizeof(badface));
21001   // Initialize the pool of missing segments.
21002   misseglist = new list(sizeof(badface), NULL, SUBPERBLOCK);
21003   // Looking for missing segments.
21004   tallmissegs(misseglist);
21005   // The DT contains segments now.
21006   checksubsegs = 1;
21007   // Remember the current number of points.
21008   vertcount = points->items;
21009   // Initialize the counters.
21010   r1count = r2count = r3count = 0l;
21011 
21012   // Loop until 'misseglist' is empty.
21013   while (misseglist->items > 0) {
21014     // Randomly pick a missing segment to recover.
21015     i = randomnation(misseglist->items);
21016     misloop = (badface *)(* misseglist)[i];
21017     segloop = misloop->ss;
21018     // Fill the "hole" in the list by filling the last one.
21019     *misloop = *(badface *)(* misseglist)[misseglist->items - 1];
21020     misseglist->items--;
21021     // Now recover the segment.
21022       p1 = (point) segloop.sh[3];
21023       p2 = (point) segloop.sh[4];
21024       if (b->verbose > 1) {
21025         printf("  Recover segment (%d, %d).\n", pointmark(p1), pointmark(p2));
21026       }
21027       getsearchtet(p1, p2, &searchtet, &tend);
21028       collinear = finddirection(&searchtet, tend, tetrahedrons->items);
21029       if (collinear == LEFTCOLLINEAR) {
21030         checkpoint = apex(searchtet);
21031       } else if (collinear == RIGHTCOLLINEAR) {
21032         checkpoint = dest(searchtet);
21033       } else if (collinear == TOPCOLLINEAR) {
21034         checkpoint = oppo(searchtet);
21035       } else {
21036 #ifdef SELF_CHECK
21037         assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
21038 #endif
21039         checkpoint = (point) NULL;
21040       }
21041       if (checkpoint != tend) {
21042         // ab is missing.
21043         splitpoint = (point) NULL;
21044         if (checkpoint != (point) NULL) {
21045           // An existing point c is found on the segment. It can happen when
21046           //   ab is defined by a long segment with c inside it. Use c to
21047           //   split ab. No new point is created.
21048           splitpoint = checkpoint;
21049           if (pointtype(checkpoint) == FREEVOLVERTEX) {
21050             // c is not a segment vertex yet. It becomes NACUTEVERTEX.
21051             setpointtype(splitpoint, NACUTEVERTEX);
21052           } else if (pointtype(checkpoint) == ACUTEVERTEX) {
21053             // c is an acute vertex. The definition of PLC is wrong.
21054           } else if (pointtype(checkpoint) == NACUTEVERTEX) {
21055             // c is an nonacute vertex. The definition of PLC is wrong.
21056           } else {
21057             // assert(0);
21058           }
21059         } else {
21060           // Find a reference point p of ab.
21061           refpoint = scoutrefpoint(&searchtet, tend);
21062           if (pointtype(refpoint) == FREEVOLVERTEX) {
21063             // p is an input point, check if it is nearly collinear with ab.
21064             coll = iscollinear(p1, p2, refpoint, b->epsilon);
21065             if (coll) {
21066               // a, b, and p are collinear. We insert p into ab. p becomes
21067               //   a segment vertex with type NACUTEVERTEX.
21068               splitpoint = refpoint;
21069               setpointtype(splitpoint, NACUTEVERTEX);
21070             }
21071           }
21072           if (splitpoint == (point) NULL) {
21073             // Calculate a split point v using rule 1, or 2, or 3.
21074             splitpoint = getsplitpoint(&segloop, refpoint);
21075 
21076             // Is there periodic boundary conditions?
21077             if (checkpbcs) {
21078               // Yes! Insert points on other segments of incident pbcgroups.
21079               i = shellmark(segloop) - 1;
21080               for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
21081                 makepoint(&sympoint);
21082                 symloc = getsegpbcsympoint(splitpoint, &segloop, sympoint,
21083                                            &symsplitseg, segpglist[j]);
21084 #ifdef SELF_CHECK
21085                 assert(symloc != OUTSIDE);
21086 #endif
21087                 if ((symloc == ONEDGE) && (symsplitseg.sh != segloop.sh)) {
21088 #ifdef SELF_CHECK
21089                   assert(symsplitseg.sh != dummysh);
21090 #endif
21091                   setpointtype(sympoint, FREESEGVERTEX);
21092                   setpoint2sh(sympoint, sencode(symsplitseg));
21093                   // Insert sympoint into DT.
21094                   pa = sorg(symsplitseg);
21095                   splittet.tet = dummytet;
21096                   // Find a good start point to search.
21097                   encodedtet = point2tet(pa);
21098                   if (encodedtet != (tetrahedron) NULL) {
21099                     decode(encodedtet, splittet);
21100                     if (isdead(&splittet)) {
21101                       splittet.tet = dummytet;
21102                     }
21103                   }
21104                   // Locate sympoint in DT.  Do exact location.
21105                   success = insertsite(sympoint, &splittet, false, flipqueue);
21106 #ifdef SELF_CHECK
21107                   assert(success != DUPLICATEPOINT);
21108 #endif
21109                   if (success == OUTSIDEPOINT) {
21110                     inserthullsite(sympoint, &splittet, flipqueue);
21111                   }
21112                   if (steinerleft > 0) steinerleft--;
21113                   // Let sympoint remember splittet.
21114                   setpoint2tet(sympoint, encode(splittet));
21115                   // Do flip in DT.
21116                   lawson(misseglist, flipqueue);
21117                   // Insert sympoint into F.
21118                   symsplitseg.shver = 0;
21119                   spivot(symsplitseg, symsplitsub);
21120                   // sympoint should on the edge of symsplitsub.
21121                   splitsubedge(sympoint, &symsplitsub, flipqueue);
21122                   // Do flip in facet.
21123                   flipsub(flipqueue);
21124                   // Insert the two subsegments.
21125                   symsplitseg.shver = 0;
21126                   insertsegment(&symsplitseg, misseglist);
21127                   senextself(symsplitseg);
21128                   spivotself(symsplitseg);
21129                   symsplitseg.shver = 0;
21130                   insertsegment(&symsplitseg, misseglist);
21131                 } else { // if (symloc == ONVERTEX) {
21132                   // The sympoint already exists. It is possible when two
21133                   //   pbc groups are exactly the same. Omit this point.
21134                   pointdealloc(sympoint);
21135                 }
21136               }
21137             }
21138 
21139             // Insert 'splitpoint' into DT.
21140             if (isdead(&searchtet)) searchtet.tet = dummytet;
21141             success = insertsite(splitpoint, &searchtet, false, flipqueue);
21142             if (success == OUTSIDEPOINT) {
21143               // A convex hull edge is missing, and the inserting point lies
21144               //   (slightly) outside the convex hull due to the significant
21145               //   digits lost in the calculation. Enlarge the convex hull.
21146               inserthullsite(splitpoint, &searchtet, flipqueue);
21147             }
21148             if (steinerleft > 0) steinerleft--;
21149             // Remember a handle in 'splitpoint' to enhance the speed of
21150             //   consequent point location.
21151             setpoint2tet(splitpoint, encode(searchtet));
21152             // Maintain Delaunayness in DT.
21153             lawson(misseglist, flipqueue);
21154           }
21155         }
21156         // Insert 'splitpoint' into F.
21157         spivot(segloop, splitsh);
21158         splitsubedge(splitpoint, &splitsh, flipqueue);
21159         flipsub(flipqueue);
21160         // Insert the two subsegments.
21161         segloop.shver = 0;
21162         insertsegment(&segloop, misseglist);
21163         senextself(segloop);
21164         spivotself(segloop);
21165         segloop.shver = 0;
21166         insertsegment(&segloop, misseglist);
21167       }
21168   }
21169 
21170   // Detach all segments from tets.
21171   tetrahedrons->traversalinit();
21172   searchtet.tet = tetrahedrontraverse();
21173   while (searchtet.tet != (tetrahedron *) NULL) {
21174     for (i = 0; i < 6; i++) {
21175       searchtet.tet[8 + i] = (tetrahedron) dummysh;
21176     }
21177     searchtet.tet = tetrahedrontraverse();
21178   }
21179   // No segments now.
21180   checksubsegs = 0;
21181 
21182   if (b->verbose > 0) {
21183     printf("  %ld protect points.\n", points->items - vertcount);
21184     printf("  R1: %ld,  R2: %ld,  R3: %ld.\n", r1count, r2count, r3count);
21185   }
21186 
21187   delete flipqueue;
21188   delete misseglist;
21189 }
21190 
21191 //
21192 // End of segments recovery routines
21193 //
21194 
21195 //
21196 // Begin of facet recovery routines
21197 //
21198 
21200 //                                                                           //
21201 // insertsubface()    Fix a subface in place.                                //
21202 //                                                                           //
21203 // Search a subface s in current tetrahedralization T.  If s is found a face //
21204 // face of T, it is inserted into T.  Return FALSE if s is not found in T.   //
21205 //                                                                           //
21207 
21208 bool tetgenmesh::insertsubface(face* insertsh, triface* searchtet)
21209 {
21210   triface spintet, symtet;
21211   face testsh, testseg;
21212   face spinsh, casin, casout;
21213   point tapex, checkpoint;
21214   enum finddirectionresult collinear;
21215   int hitbdry;
21216 
21217   // Search an edge of s.
21218   getsearchtet(sorg(*insertsh), sdest(*insertsh), searchtet, &checkpoint);
21219   collinear = finddirection(searchtet, checkpoint, tetrahedrons->items);
21220   if (collinear == LEFTCOLLINEAR) {
21221     enext2self(*searchtet);
21222     esymself(*searchtet);
21223   } else if (collinear == TOPCOLLINEAR) {
21224     fnextself(*searchtet);
21225     enext2self(*searchtet);
21226     esymself(*searchtet);
21227   }
21228   if (dest(*searchtet) != checkpoint) {
21229     // The edge doesn't exist => s is missing.
21230     return false;
21231   }
21232 
21233   // Search s by spinning faces around the edge.
21234   tapex = sapex(*insertsh);
21235   spintet = *searchtet;
21236   hitbdry = 0;
21237   do {
21238     if (apex(spintet) == tapex) {
21239       // Found s in T. Check if s has already been inserted.
21240       tspivot(spintet, testsh);
21241       if (testsh.sh == dummysh) {
21242         adjustedgering(spintet, CCW);
21243         findedge(insertsh, org(spintet), dest(spintet));
21244         tsbond(spintet, *insertsh);
21245         sym(spintet, symtet); // 'symtet' maybe outside, use it anyway.
21246         sesymself(*insertsh);
21247         tsbond(symtet, *insertsh);
21248       } else {
21249         // Found a duplicated subface (due to the redundant input).
21250         if (!b->quiet) {
21251           printf("Warning:  Two subfaces are found duplicated at ");
21252           printf("(%d, %d, %d)\n", pointmark(sorg(testsh)),
21253                  pointmark(sdest(testsh)), pointmark(sapex(testsh)));
21254           printf("  Subface of facet #%d is deleted.\n", shellmark(*insertsh));
21255           // printf("  Hint: -d switch can find all duplicated facets.\n");
21256         }
21257         shellfacedealloc(subfaces, insertsh->sh);
21258       }
21259       return true;
21260     }
21261     if (!fnextself(spintet)) {
21262       hitbdry ++;
21263       if (hitbdry < 2) {
21264         esym(*searchtet, spintet);
21265         if (!fnextself(spintet)) {
21266           hitbdry ++;
21267         }
21268       }
21269     }
21270   } while (hitbdry < 2 && apex(spintet) != apex(*searchtet));
21271 
21272   // s is missing.
21273   return false;
21274 }
21275 
21277 //                                                                           //
21278 // tritritest()    Test if two triangles are intersecting in their interior. //
21279 //                                                                           //
21280 // One triangle t1 is the face of 'checktet', the other t2 is given by three //
21281 // corners 'p1', 'p2' and 'p3'. This routine calls tri_tri_inter() to detect //
21282 // whether t1 and t2 exactly intersect in their interior. Cases like share a //
21283 // vertex, share an edge, or coincidence are considered not intersect.       //
21284 //                                                                           //
21286 
21287 bool tetgenmesh::tritritest(triface* checktet, point p1, point p2, point p3)
21288 {
21289   point forg, fdest, fapex;
21290   enum interresult intersect;
21291 
21292   forg = org(*checktet);
21293   fdest = dest(*checktet);
21294   fapex = apex(*checktet);
21295 
21296 #ifdef SELF_CHECK
21297   REAL ax, ay, az, bx, by, bz;
21298   REAL n[3];
21299   // face (torg, tdest, tapex) should not be degenerate. However p1, p2,
21300   //   and p3 may be collinear. Check it.
21301   ax = forg[0] - fdest[0];
21302   ay = forg[1] - fdest[1];
21303   az = forg[2] - fdest[2];
21304   bx = forg[0] - fapex[0];
21305   by = forg[1] - fapex[1];
21306   bz = forg[2] - fapex[2];
21307   n[0] = ay * bz - by * az;
21308   n[1] = az * bx - bz * ax;
21309   n[2] = ax * by - bx * ay;
21310   assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21311   // The components of n should not smaller than the machine epsilon.
21312 
21313   ax = p1[0] - p2[0];
21314   ay = p1[1] - p2[1];
21315   az = p1[2] - p2[2];
21316   bx = p1[0] - p3[0];
21317   by = p1[1] - p3[1];
21318   bz = p1[2] - p3[2];
21319   n[0] = ay * bz - by * az;
21320   n[1] = az * bx - bz * ax;
21321   n[2] = ax * by - bx * ay;
21322   assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21323   // The components of n should not smaller than the machine epsilon.
21324 #endif
21325 
21326   intersect = tri_tri_inter(forg, fdest, fapex, p1, p2, p3);
21327   return intersect == INTERSECT;
21328 }
21329 
21331 //                                                                           //
21332 // initializecavity()    Initialize the cavity.                              //
21333 //                                                                           //
21334 // A cavity C is bounded by a list of faces, called fronts.  Each front f is //
21335 // hold by a tet t adjacent to C, t is not in C (uninfected). If f is a hull //
21336 // face, t does't exist, a fake tet t' is created to hold f. t' has the same //
21337 // vertices as f but no opposite.  t' will be removed automatically after C  //
21338 // is filled with new tets (by carvecavity()).                               //
21339 //                                                                           //
21340 // The faces of C are given in two lists. 'floorlist' is a set of subfaces,  //
21341 // each subface has been oriented to face to the inside of C.  'ceillist' is //
21342 // a set of tetrahedral faces. 'frontlist' returns the initialized fronts.   //
21343 //                                                                           //
21345 
21346 void tetgenmesh::initializecavity(list* floorlist, list* ceillist,
21347   list* frontlist)
21348 {
21349   triface neightet, casingtet;
21350   triface faketet;
21351   face worksh;
21352   int i;
21353 
21354   // Initialize subfaces of C.
21355   for (i = 0; i < floorlist->len(); i++) {
21356     // Get a subface s.
21357     worksh = * (face *)(* floorlist)[i];
21358 #ifdef SELF_CHECK
21359     // Current side of s should be empty.
21360     stpivot(worksh, neightet);
21361     assert(neightet.tet == dummytet);
21362 #endif
21363     // Get the adjacent tet t.
21364     sesymself(worksh);
21365     stpivot(worksh, casingtet);
21366     // Does t exist?
21367     if (casingtet.tet == dummytet) {
21368       // Create a fake tet t' to hold f temporarily.
21369       maketetrahedron(&faketet);
21370       setorg(faketet, sorg(worksh));
21371       setdest(faketet, sdest(worksh));
21372       setapex(faketet, sapex(worksh));
21373       setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21374       tsbond(faketet, worksh);
21375       frontlist->append(&faketet);
21376     } else {
21377       frontlist->append(&casingtet);
21378     }
21379   }
21380   // Initialize tet faces of C.
21381   for (i = 0; i < ceillist->len(); i++) {
21382     // Get a tet face c.
21383     neightet = * (triface *) (* ceillist)[i];
21384 #ifdef SELF_CHECK
21385     // The tet of c must be inside C (going to be deleted).
21386     assert(infected(neightet));
21387 #endif
21388     // Get the adjacent tet t.
21389     sym(neightet, casingtet);
21390     // Does t exist?
21391     if (casingtet.tet == dummytet) {
21392       // No. Create a fake tet t' to hold f temporarily.
21393       maketetrahedron(&faketet);
21394       // Be sure that the vertices of t' are CCW oriented.
21395       adjustedgering(neightet, CW); // CW edge ring.
21396       setorg(faketet, org(neightet));
21397       setdest(faketet, dest(neightet));
21398       setapex(faketet, apex(neightet));
21399       setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21400       // Bond t' to a subface if it exists.
21401       tspivot(neightet, worksh);
21402       if (worksh.sh != dummysh) {
21403         sesymself(worksh);
21404         tsbond(faketet, worksh);
21405       }
21406       // Bond c <--> t'. So we're able to find t' and remove it.
21407       bond(faketet, neightet);
21408       // c may become uninfected due to the bond().
21409       infect(neightet);
21410       frontlist->append(&faketet);
21411     } else {
21412       frontlist->append(&casingtet);
21413     }
21414   }
21415 }
21416 
21418 //                                                                           //
21419 // retrievenewtets()    Retrieve the newly created tets.                     //
21420 //                                                                           //
21421 // On input, 'newtetlist' contains at least one alive new tet. From this tet,//
21422 // other new tets can be found by a broadth-first searching.                 //
21423 //                                                                           //
21425 
21426 void tetgenmesh::retrievenewtets(list* newtetlist)
21427 {
21428   triface searchtet, casingtet;
21429   int i;
21430 
21431   // There may be dead tets due to flip32(). Delete them first.
21432   for (i = 0; i < newtetlist->len(); i++) {
21433     searchtet = * (triface *)(* newtetlist)[i];
21434     if (isdead(&searchtet)) {
21435       newtetlist->del(i, 0); i--;
21436       continue;
21437     }
21438     infect(searchtet);
21439   }
21440   // Find all new tets.
21441   for (i = 0; i < newtetlist->len(); i++) {
21442     searchtet = * (triface *)(* newtetlist)[i];
21443     for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
21444       sym(searchtet, casingtet);
21445       if ((casingtet.tet != dummytet) && !infected(casingtet)) {
21446         infect(casingtet);
21447         newtetlist->append(&casingtet);
21448       }
21449     }
21450   }
21451   // Uninfect new tets.
21452   for (i = 0; i < newtetlist->len(); i++) {
21453     searchtet = * (triface *)(* newtetlist)[i];
21454     uninfect(searchtet);
21455   }
21456 }
21457 
21459 //                                                                           //
21460 // delaunizecavvertices()    Form a DT of the vertices of a cavity.          //
21461 //                                                                           //
21462 // 'floorptlist' and 'ceilptlist' are the vertices of the cavity.            //
21463 //                                                                           //
21464 // The tets of the DT are created directly in the pool 'tetrahedrons', i.e., //
21465 // no auxiliary data structure and memory are required.  The trick is at the //
21466 // time they're created, there are no connections between them to the other  //
21467 // tets in the pool. You can imagine they form an ioslated island.           //
21468 //                                                                           //
21470 
21471 void tetgenmesh::delaunizecavvertices(triface* oldtet, list* floorptlist,
21472   list* ceilptlist, list* newtetlist, queue* flipque)
21473 {
21474   point *insertarray;
21475   triface bakhulltet, newtet;
21476   long bakhullsize;
21477   long arraysize;
21478   int bakchksub;
21479   int i, j;
21480 
21481   // Prepare the array of points for inserting.
21482   arraysize = floorptlist->len();
21483   if (ceilptlist != (list *) NULL) {
21484     arraysize += ceilptlist->len();
21485   }
21486   insertarray = new point[arraysize];
21487   for (i = 0; i < floorptlist->len(); i++) {
21488     insertarray[i] = * (point *)(* floorptlist)[i];
21489   }
21490   if (ceilptlist != (list *) NULL) {
21491     for (j = 0; j < ceilptlist->len(); j++) {
21492       insertarray[i + j] = * (point *)(* ceilptlist)[j];
21493     }
21494   }
21495 
21496   // The incrflipdelaunay() is re-used. Backup global variables.
21497   decode(dummytet[0], bakhulltet);
21498   bakhullsize = hullsize;
21499   bakchksub = checksubfaces;
21500   checksubfaces = 0;
21501   b->verbose--;
21502 
21503   // Form the DT by incremental flip Delaunay algorithm. Do not jump for
21504   //   point location, do not merge points.
21505   incrflipdelaunay(oldtet, insertarray, arraysize, false, false, 0.0, flipque);
21506 
21507   // Get a tet in D.
21508   decode(dummytet[0], newtet);
21509   newtetlist->append(&newtet);
21510   // Get all tets of D.
21511   retrievenewtets(newtetlist);
21512 
21513   // Restore global variables.
21514   dummytet[0] = encode(bakhulltet);
21515   hullsize = bakhullsize;
21516   checksubfaces = bakchksub;
21517   b->verbose++;
21518 
21519   delete [] insertarray;
21520 }
21521 
21523 //                                                                           //
21524 // insertauxsubface()    Fix an auxilary subface in place.                   //
21525 //                                                                           //
21526 // An auxilary subface s is fixed in D as it is a real subface, but s has no //
21527 // vertices and neighbors. It has two uses: (1) it protects an identfied     //
21528 // front f in D; (2) it serves the link to bond a tet in C and f later. The  //
21529 // first neighbor of s (s->sh[0]) stores a pointer to f.                     //
21530 //                                                                           //
21531 // 'front' is a front f of C. idfront' t is a tet in D where f is identified //
21532 // be a face of it. s will be fixed between t and its neighbor.              //
21533 //                                                                           //
21535 
21536 void tetgenmesh::insertauxsubface(triface* front, triface* idfront)
21537 {
21538   triface neightet;
21539   face auxsh;
21540 
21541   // Create the aux subface s.
21542   makeshellface(subfaces, &auxsh);
21543   // Bond s <--> t.
21544   tsbond(*idfront, auxsh);
21545   // Does t's neighbor n exist?
21546   sym(*idfront, neightet);
21547   if (neightet.tet != dummytet) {
21548     // Bond s <--> n.
21549     sesymself(auxsh);
21550     tsbond(neightet, auxsh);
21551   }
21552   // Let s remember f.
21553   auxsh.sh[0] = (shellface) encode(*front);
21554 }
21555 
21557 //                                                                           //
21558 // scoutfront()    Scout a face in D.                                        //
21559 //                                                                           //
21560 // Search a 'front' f in D. If f is found, return TRUE and the face of D is  //
21561 // returned in 'idfront'. Otherwise, return FALSE.                           //
21562 //                                                                           //
21564 
21565 bool tetgenmesh::scoutfront(triface* front, triface* idfront, list* newtetlist)
21566 {
21567   triface spintet;
21568   point pa, pb, pc;
21569   enum locateresult loc;
21570   enum finddirectionresult col;
21571   int hitbdry;
21572   int i;
21573 
21574   // Let the front we're searching is abc.
21575   pa = org(*front);
21576   pb = dest(*front);
21577   // Get a tet in D for searching.
21578   *idfront = recenttet;
21579   // Make sure the tet is valid (it may be killed by flips).
21580   if (isdead(idfront)) {
21581     // The tet is dead. Search a live tet in D. !!!
21582     for (i = 0; i < newtetlist->len(); i++) {
21583       recenttet = * (triface *)(* newtetlist)[i];
21584       if (!isdead(&recenttet)) break;
21585     }
21586     assert(i < newtetlist->len());
21587   }
21588 
21589   // Search a tet having vertex a.
21590   loc = preciselocate(pa, idfront, (long) newtetlist->len());
21591   assert(loc == ONVERTEX);
21592   recenttet = *idfront;
21593   // Search a tet having edge ab.
21594   col = finddirection(idfront, pb, (long) newtetlist->len());
21595   if (col == RIGHTCOLLINEAR) {
21596     // b is just the destination.
21597   } else if (col == LEFTCOLLINEAR) {
21598     enext2self(*idfront);
21599     esymself(*idfront);
21600   } else if (col == TOPCOLLINEAR) {
21601     fnextself(*idfront);
21602     enext2self(*idfront);
21603     esymself(*idfront);
21604   }
21605 
21606   if (dest(*idfront) == pb) {
21607     // Search a tet having face abc
21608     pc = apex(*front);
21609     spintet = *idfront;
21610     hitbdry = 0;
21611     do {
21612       if (apex(spintet) == pc) {
21613         // Found abc. Insert an auxilary subface s at idfront.
21614         // insertauxsubface(front, &spintet);
21615         *idfront = spintet;
21616         return true;
21617       }
21618       if (!fnextself(spintet)) {
21619         hitbdry ++;
21620         if (hitbdry < 2) {
21621           esym(*idfront, spintet);
21622           if (!fnextself(spintet)) {
21623             hitbdry ++;
21624           }
21625         }
21626       }
21627       if (apex(spintet) == apex(*idfront)) break;
21628     } while (hitbdry < 2);
21629   }
21630 
21631   // f is missing in D.
21632   if (b->verbose > 2) {
21633     printf("    Front (%d, %d, %d) is missing.\n", pointmark(pa),
21634            pointmark(pb), pointmark(apex(*front)));
21635   }
21636   return false;
21637 }
21638 
21640 //                                                                           //
21641 // gluefronts()    Glue two fronts together.                                 //
21642 //                                                                           //
21643 // This is a support routine for identifyfront().  Two fronts f and f1 are   //
21644 // found indentical. This is caused by the non-coplanarity of vertices of a  //
21645 // facet. Hence f and f1 are a subface and a tet. They are not fronts of the //
21646 // cavity anymore. This routine glues f and f1 together.                     //
21647 //                                                                           //
21649 
21650 void tetgenmesh::gluefronts(triface* front, triface* front1)
21651 {
21652   face consh;
21653 
21654   // Glue f and f1 together. There're four cases:
21655   //   (1) both f and f1 are not fake;
21656   //   (2) f is not fake, f1 is fake;
21657   //   (3) f is fake and f1 is not fake;
21658   //   (4) both f and f1 are fake.
21659   // Case (4) should be not possible.
21660 
21661   // Is there a concrete subface c at f.
21662   tspivot(*front, consh);
21663   if (consh.sh != dummysh) {
21664     sesymself(consh);
21665     tsbond(*front1, consh); // Bond: f1 <--> c.
21666     sesymself(consh);
21667   }
21668   // Does f hold by a fake tet.
21669   if (oppo(*front) == (point) NULL) {
21670     // f is fake. Case (3) or (4).
21671     assert(oppo(*front1) != (point) NULL); // Eliminate (4).
21672     // Case (3).
21673     if (consh.sh != dummysh) {
21674       stdissolve(consh);  // Dissolve: c -x-> f.
21675     }
21676     // Dealloc f.
21677     tetrahedrondealloc(front->tet);
21678     // f1 becomes a hull. let 'dummytet' bond to it.
21679     dummytet[0] = encode(*front1);
21680   } else {
21681     // Case (1) or (2).
21682     bond(*front, *front1); // Bond f1 <--> f.
21683   }
21684   // Is f a fake tet?
21685   if (!isdead(front)) {
21686     // No. Check for case (2).
21687     tspivot(*front1, consh);
21688     // Is f1 fake?
21689     if (oppo(*front1) == (point) NULL) {
21690       // Case (2) or (4)
21691       assert(oppo(*front) != (point) NULL); // Eliminate (4).
21692       // Case (2).
21693       if (consh.sh != dummysh) {
21694         stdissolve(consh);  // Dissolve: c -x-> f1.
21695         sesymself(consh); // Bond: f <--> c.
21696         tsbond(*front, consh);
21697       }
21698       // Dissolve: f -x->f1.
21699       dissolve(*front);
21700       // Dealloc f1.
21701       tetrahedrondealloc(front1->tet);
21702       // f becomes a hull. let 'dummytet' bond to it.
21703       dummytet[0] = encode(*front);
21704     } else {
21705       // Case (1).
21706       if (consh.sh != dummysh) {
21707         sesymself(consh);
21708         tsbond(*front, consh); // Bond: f <--> c.
21709       }
21710     }
21711   }
21712 }
21713 
21715 //                                                                           //
21716 // identifyfronts()    Identify cavity faces in D.                           //
21717 //                                                                           //
21718 // 'frontlist' are fronts of C need indentfying.  This routine searches each //
21719 // front f in D. Once f is found, an auxilary subface s is inserted in D at  //
21720 // the face. If f is not found in D, remove it from frontlist and save it in //
21721 // 'misfrontlist'.                                                           //
21722 //                                                                           //
21724 
21725 bool tetgenmesh::identifyfronts(list* frontlist, list* misfrontlist,
21726   list* newtetlist)
21727 {
21728   triface front, front1, tfront;
21729   triface idfront, neightet;
21730   face auxsh;
21731   int len, i, j;
21732 
21733   misfrontlist->clear();
21734   // Set a new tet in D for searching.
21735   recenttet = * (triface *)(* newtetlist)[0];
21736 
21737   // Identify all fronts in D.
21738   for (i = 0; i < frontlist->len(); i++) {
21739     // Get a front f.
21740     front = * (triface *)( *frontlist)[i];
21741     if (scoutfront(&front, &idfront, newtetlist)) {
21742       // Found f. Insert an aux subface s.
21743       assert((idfront.tet != dummytet) && !isdead(&idfront));
21744       // Does s already exist?
21745       tspivot(idfront, auxsh);
21746       if (auxsh.sh != dummysh) {
21747         // There're two identical fronts, f (front) and f1 (s.sh[0])!
21748         decode((tetrahedron) auxsh.sh[0], front1);
21749         assert((front1.tet != dummytet) && !infected(front1));
21750         // Detach s in D.
21751         tsdissolve(idfront);
21752         sym(idfront, neightet);
21753         if (neightet.tet != dummytet) {
21754           tsdissolve(neightet);
21755         }
21756         // s has fulfilled its duty. Can be deleted.
21757         shellfacedealloc(subfaces, auxsh.sh);
21758         // Remove f from frontlist.
21759         frontlist->del(i, 1); i--;
21760         // Remove f1 from frontlist.
21761         len = frontlist->len();
21762         for (j = 0; j < frontlist->len(); j++) {
21763           tfront = * (triface *)(* frontlist)[j];
21764           if ((tfront.tet == front1.tet) && (tfront.loc == front1.loc)) {
21765             // Found f1 in list.  Check f1 != f.
21766             assert((tfront.tet != front.tet) || (tfront.loc != front.loc));
21767             frontlist->del(j, 1); i--;
21768             break;
21769           }
21770         }
21771         assert((frontlist->len() + 1) == len);
21772         // Glue f and f1 together.
21773         gluefronts(&front, &front1);
21774       } else {
21775         // Insert an aux subface to protect f in D.
21776         insertauxsubface(&front, &idfront);
21777       }
21778     } else {
21779       // f is missing.
21780       frontlist->del(i, 1); i--;
21781       // Are there two identical fronts, f (front) and f1 (front1)?
21782       for (j = 0; j < misfrontlist->len(); j++) {
21783         front1 = * (triface *)(* misfrontlist)[j];
21784         if (isfacehaspoint(&front1, org(front)) &&
21785             isfacehaspoint(&front1, dest(front)) &&
21786             isfacehaspoint(&front1, apex(front))) break;
21787       }
21788       if (j < misfrontlist->len()) {
21789         // Found an identical front f1. Remove f1 from the list.
21790         misfrontlist->del(j, 1);
21791         // Glue f and f1 together.
21792         gluefronts(&front, &front1);
21793       } else {
21794         // Add f into misfrontlist.
21795         misfrontlist->append(&front);
21796       }
21797     }
21798   }
21799   return misfrontlist->len() == 0;
21800 }
21801 
21803 //                                                                           //
21804 // detachauxsubfaces()    Detach auxilary subfaces in D.                     //
21805 //                                                                           //
21806 // This is a reverse routine of identifyfronts(). Some fronts are missing in //
21807 // D. C can not be easily tetrahedralized. It needs remediation (expansion,  //
21808 // or constrained flips, or adding a Steiner point).  This routine detaches  //
21809 // the auxilary subfaces have been inserted in D and delete them.            //
21810 //                                                                           //
21812 
21813 void tetgenmesh::detachauxsubfaces(list* newtetlist)
21814 {
21815   triface newtet, neightet;
21816   face auxsh;
21817   int i;
21818 
21819   for (i = 0; i < newtetlist->len(); i++) {
21820     // Get a new tet t.
21821     newtet = * (triface *)(* newtetlist)[i];
21822     // t may e dead due to flips.
21823     if (isdead(&newtet)) continue;
21824     assert(!infected(newtet));
21825     // Check the four faces of t.
21826     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
21827       tspivot(newtet, auxsh);
21828       if (auxsh.sh != dummysh) {
21829         // An auxilary subface s.
21830         assert(sorg(auxsh) == (point) NULL);
21831         tsdissolve(newtet);  // t -x-> s.
21832         sym(newtet, neightet);
21833         if (neightet.tet != dummytet) {
21834           assert(!isdead(&neightet));
21835           tsdissolve(neightet); // n -x-> s.
21836         }
21837         // Delete s.
21838         shellfacedealloc(subfaces, auxsh.sh);
21839       }
21840     }
21841   }
21842 }
21843 
21845 //                                                                           //
21846 // expandcavity()    Expand the cavity by adding new fronts.                 //
21847 //                                                                           //
21848 // This is the support routine for delaunizecavity().  Some fronts of C are  //
21849 // missing in D since they're not strongly Delaunay. Such fronts are removed //
21850 // and the faces of the tets abutting to them are added. C is then expanded. //
21851 // Some removed faces may be subfaces, they're queued to recover later. D is //
21852 // expanded simultaneously with the new vertices of the new fronts.          //
21853 //                                                                           //
21855 
21856 void tetgenmesh::expandcavity(list* frontlist, list* misfrontlist,
21857   list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
21858 {
21859   triface misfront, newfront, casingtet, crosstet;
21860   triface searchtet, faketet, bakhulltet;
21861   face checksh;
21862   point pd;
21863   enum insertsiteresult success;
21864   long bakhullsize;
21865   int bakchksub;
21866   int i, j, k;
21867 
21868   if (b->verbose > 1) {
21869     printf("    Expand cavity (%d missing fronts).\n", misfrontlist->len());
21870   }
21871   // Increase the number of expanded times.
21872   expcavcount++;
21873   // The incrflipdelaunay() is re-used. Backup global variables.
21874   decode(dummytet[0], bakhulltet);
21875   bakhullsize = hullsize;
21876   bakchksub = checksubfaces;
21877   checksubfaces = 0;
21878   b->verbose--;
21879 
21880   // Choose a tet in D for searching.
21881   recenttet = * (triface *)(* newtetlist)[0];
21882   assert((recenttet.tet != dummytet) && !isdead(&recenttet));
21883 
21884   // Loop through 'misfrontlist'.
21885   for (i = 0; i < misfrontlist->len(); i++) {
21886     // Get a missing front f.
21887     misfront = * (triface *)(* misfrontlist)[i];
21888     // C will be expanded at f.
21889     if (b->verbose > 1) {
21890       printf("    Get misfront (%d, %d, %d).\n", pointmark(org(misfront)),
21891              pointmark(dest(misfront)), pointmark(apex(misfront)));
21892     }
21893     // Is f has a subface s?
21894     tspivot(misfront, checksh);
21895     if (checksh.sh != dummysh) {
21896       // A subface s is found. Check whether f is expandable at s.
21897       sym(misfront, crosstet);
21898       if (!infected(crosstet)) {
21899         // f is not expandable. In principle is should not happen. However,
21900         //   it can happen when PBC is in use.
21901         assert(checkpbcs);
21902         // Skip expanding f. It will be processed later.
21903         continue;
21904       }
21905       // Temporarily remove s. Queue and recover it later.
21906       if (b->verbose > 1) {
21907         printf("    Queuing subface (%d, %d, %d).\n",
21908                pointmark(sorg(checksh)), pointmark(sdest(checksh)),
21909                pointmark(sapex(checksh)));
21910       }
21911       // Detach s from tets at its both sides.
21912       tsdissolve(misfront);
21913       tsdissolve(crosstet);
21914       // Detach tets at from s.
21915       stdissolve(checksh);
21916       sesymself(checksh);
21917       stdissolve(checksh);
21918       // Mark and queue it.
21919       sinfect(checksh);
21920       missingshqueue->push(&checksh);
21921     }
21922     // f may already be processed (become a cross tet of C).
21923     if (infected(misfront)) continue;
21924     // Get the point p = oppo(t), t is the tet holds f.
21925     pd = oppo(misfront);
21926 #ifdef SELF_CHECK
21927     // t must not be fake.
21928     assert(pd != (point) NULL);
21929 #endif
21930     // Insert p in D. p may not be inserted if it is one of the two cases:
21931     //   (1) p is already a vertex of D;
21932     //   (2) p lies outside the CH of D;
21933     searchtet = recenttet;
21934     // Make sure the tet is valid (it may be killed by flips).
21935     if (isdead(&searchtet)) {
21936       // The tet is dead. Get a live tet in D. !!!
21937       for (j = 0; j < newtetlist->len(); j++) {
21938         recenttet = * (triface *)(* newtetlist)[j];
21939         if (!isdead(&recenttet)) break;
21940       }
21941       assert(j < newtetlist->len());
21942       searchtet = recenttet;
21943     }
21944     success = insertsite(pd, &searchtet, false, flipque);
21945     if (success == OUTSIDEPOINT) {
21946       // case (2). Insert p onto CH of D.
21947       inserthullsite(pd, &searchtet, flipque);
21948     }
21949     if (success != DUPLICATEPOINT) {
21950       // p is inserted. Recover Delaunness of D by flips.
21951       flip(flipque, NULL);
21952     }
21953     // Expand C by adding new fronts. The three faces of t which have p as a
21954     //   vertex become new fronts. However, if a new front is coincident with
21955     //   an old front of C, it is not added and the old front is removed.
21956     adjustedgering(misfront, CCW);
21957     for (j = 0; j < 3; j++) {
21958       // Notice: Below I mis-used the names. 'newfront' is not exactly a new
21959       //   front, instead the 'casingtet' should be called new front.
21960       // Get a new front f_n.
21961       fnext(misfront, newfront);
21962       // Get the neighbor tet n at f_n.
21963       sym(newfront, casingtet);
21964       // Is n a cross tet?
21965       if (!infected(casingtet)) {
21966         // f_n becomes a new front of C.
21967         // Does n exist?
21968         if (casingtet.tet == dummytet) {
21969           // Create a fake tet n' to hold f_n temporarily.
21970           maketetrahedron(&faketet);
21971           // Be sure that the vertices of fake tet are CCW oriented.
21972           adjustedgering(newfront, CW); // CW edge ring.
21973           setorg(faketet, org(newfront));
21974           setdest(faketet, dest(newfront));
21975           setapex(faketet, apex(newfront));
21976           setoppo(faketet, (point) NULL); // Indicates it is 'fake'.
21977           // Bond n' to a subface if it exists.
21978           tspivot(newfront, checksh);
21979           if (checksh.sh != dummysh) {
21980             sesymself(checksh);
21981             tsbond(faketet, checksh);
21982           }
21983           // Bond f_n <--> n'. So we're able to find n' and remove it.
21984           bond(faketet, newfront);
21985           frontlist->append(&faketet);
21986         } else {
21987           // Add n to frontlist.
21988           frontlist->append(&casingtet);
21989         }
21990       } else {
21991         // f_n is coincident with an existing front f' of C. f' is no longer
21992         //   a front, remove it from frontlist.  Use the inverse order to
21993         //   search f' (most likely, a newly added front may be f').
21994         for (k = frontlist->len() - 1; k >= 0; k--) {
21995           searchtet = * (triface *)(* frontlist)[k];
21996           if ((newfront.tet == searchtet.tet) &&
21997               (newfront.loc == searchtet.loc)) {
21998             frontlist->del(k, 0);
21999             break;
22000           }
22001         }
22002         // Is f_n a subface?
22003         tspivot(newfront, checksh);
22004         if (checksh.sh != dummysh) {
22005           // Temporarily remove checksh. Make it missing. recover it later.
22006           if (b->verbose > 2) {
22007             printf("    Queuing subface (%d, %d, %d).\n",
22008                    pointmark(sorg(checksh)), pointmark(sdest(checksh)),
22009                    pointmark(sapex(checksh)));
22010           }
22011           tsdissolve(newfront);
22012           tsdissolve(casingtet);
22013           // Detach tets at the both sides of checksh.
22014           stdissolve(checksh);
22015           sesymself(checksh);
22016           stdissolve(checksh);
22017           sinfect(checksh);
22018           missingshqueue->push(&checksh);
22019         }
22020       }
22021       enextself(misfront);
22022     }
22023     // C has been expanded at f. t becomes a cross tet.
22024     if (!infected(misfront)) {
22025       // t will be deleted, queue it.
22026       infect(misfront);
22027       crosstetlist->append(&misfront);
22028     }
22029   }
22030 
22031   // Loop through misfrontlist, remove infected misfronts.
22032   for (i = 0; i < misfrontlist->len(); i++) {
22033     misfront = * (triface *)(* misfrontlist)[i];
22034     if (infected(misfront)) {
22035       // Remove f, keep original list order.
22036       misfrontlist->del(i, 1);
22037       i--;
22038     }
22039   }
22040 
22041   // Are we done?
22042   if (misfrontlist->len() > 0) {
22043     // No. There are unexpandable fronts.
22044     // expandcavity_sos(misfrontlist);
22045     assert(0); // Not done yet.
22046   }
22047 
22048   // D has been updated (by added new tets or dead tets) (due to flips).
22049   retrievenewtets(newtetlist);
22050 
22051   // Restore global variables.
22052   dummytet[0] = encode(bakhulltet);
22053   hullsize = bakhullsize;
22054   checksubfaces = bakchksub;
22055   b->verbose++;
22056 }
22057 
22059 //                                                                           //
22060 // carvecavity()    Remove redundant (outside) tetrahedra from D.            //
22061 //                                                                           //
22062 // The fronts of C have been identified in D. Hence C can be tetrahedralized //
22063 // by removing the tets outside C. The CDT is then updated by filling C with //
22064 // the remaining tets (inside C) of D.                                       //
22065 //                                                                           //
22066 // Each front is protected by an auxilary subface s in D. s has a pointer to //
22067 // f (s.sh[0]). f can be used to classified the in- and out- tets of C (the  //
22068 // CW orientation of f faces to the inside of C). The classified out-tets of //
22069 // C are marked (infected) for removing.                                     //
22070 //                                                                           //
22071 // Notice that the out-tets may not only the tets on the CH of C,  but also  //
22072 // tets completely inside D, eg., there is a "hole" in D.  Such tets must be //
22073 // marked during classification. The hole tets are poped up and removed too. //
22074 //                                                                           //
22076 
22077 void tetgenmesh::carvecavity(list* newtetlist, list* outtetlist,
22078   queue* flipque)
22079 {
22080   triface newtet, neightet, front, outtet;
22081   face auxsh, consh;
22082   point pointptr;
22083   REAL ori;
22084   int i;
22085 
22086   // Clear work list.
22087   outtetlist->clear();
22088 
22089   // Classify in- and out- tets in D. Mark and queue classified out-tets.
22090   for (i = 0; i < newtetlist->len(); i++) {
22091     // Get a new tet t.
22092     newtet = * (triface *)(* newtetlist)[i];
22093     assert(!isdead(&newtet));
22094     // Look for aux subfaces attached at t.
22095     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22096       tspivot(newtet, auxsh);
22097       if (auxsh.sh != dummysh) {
22098         // Has this side a neighbor n?
22099         sym(newtet, neightet);
22100         if (neightet.tet != dummytet) {
22101           // Classify t and n (one is "in" and another is "out").
22102           // Get the front f.
22103           decode((tetrahedron) auxsh.sh[0], front);
22104           // Let f face to the inside of C.
22105           adjustedgering(front, CW);
22106           ori = orient3d(org(front), dest(front), apex(front), oppo(newtet));
22107           assert(ori != 0.0);
22108           if (ori < 0.0) {
22109             // t is in-tet. n is out-tet.
22110             outtet = neightet;
22111           } else {
22112             // n is in-tet. t is out-tet.
22113             outtet = newtet;
22114           }
22115           // Add the out-tet into list.
22116           if (!infected(outtet)) {
22117             infect(outtet);
22118             outtetlist->append(&outtet);
22119           }
22120         }
22121       }
22122     }
22123   }
22124 
22125   // Find and mark all out-tets.
22126   for (i = 0; i < outtetlist->len(); i++) {
22127     outtet = * (triface *)(* outtetlist)[i];
22128     for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22129       sym(outtet, neightet);
22130       // Does the neighbor exist and unmarked?
22131       if ((neightet.tet != dummytet) && !infected(neightet)) {
22132         // Is it protected by an aux subface?
22133         tspivot(outtet, auxsh);
22134         if (auxsh.sh == dummysh) {
22135           // It's an out-tet.
22136           infect(neightet);
22137           outtetlist->append(&neightet);
22138         }
22139       }
22140     }
22141   }
22142 
22143   // Remove the out- (and hole) tets.
22144   for (i = 0; i < outtetlist->len(); i++) {
22145     // Get an out-tet t.
22146     outtet = * (triface *)(* outtetlist)[i];
22147     // Detach t from the in-tets.
22148     for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22149       // Is there an aux subface s?
22150       tspivot(outtet, auxsh);
22151       if (auxsh.sh != dummysh) {
22152         // Get the neighbor n.
22153         sym(outtet, neightet);
22154         assert(!infected(neightet)); // t must be in-tet.
22155         // Detach n -x-> t.
22156         dissolve(neightet);
22157       }
22158     }
22159     // Dealloc the tet.
22160     tetrahedrondealloc(outtet.tet);
22161   }
22162 
22163   // Connect the in-tets of C to fronts. Remove aux subfaces and fake tets.
22164   for (i = 0; i < newtetlist->len(); i++) {
22165     // Get a new tet t.
22166     newtet = * (triface *)(* newtetlist)[i];
22167     // t may be an out-tet and has got deleted.
22168     if (isdead(&newtet)) continue;
22169     // t is an in-tet. Look for aux subfaces attached at t.
22170     for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22171       // Is there an aux subface s?
22172       tspivot(newtet, auxsh);
22173       if (auxsh.sh != dummysh) {
22174         // Get the front f.
22175         decode((tetrahedron) auxsh.sh[0], front);
22176         assert((front.tet != dummytet) && !infected(front));
22177         // s has fulfilled its duty. Can be deleted.
22178         tsdissolve(newtet); // dissolve: t -x-> s.
22179         // Delete s.
22180         shellfacedealloc(subfaces, auxsh.sh);
22181         // Connect the newtet t and front f.
22182         // Is there a concrete subface c at f.
22183         tspivot(front, consh);
22184         if (consh.sh != dummysh) {
22185           sesymself(consh);
22186           // Bond: t <--> c.
22187           tsbond(newtet, consh);
22188         }
22189         // Does f hold by a fake tet.
22190         if (oppo(front) == (point) NULL) {
22191           // f is fake.
22192           if (consh.sh != dummysh) {
22193             sesymself(consh);
22194             // Dissolve: c -x-> f.
22195             stdissolve(consh);
22196           }
22197           // Dealloc f.
22198           tetrahedrondealloc(front.tet);
22199           // f becomes a hull. let 'dummytet' bond to it.
22200           dummytet[0] = encode(newtet);
22201         } else {
22202           // Bond t <--> f.
22203           bond(newtet, front);
22204         }
22205         // t may be non-locally Delaunay and flipable.
22206         if (flipque != (queue *) NULL) {
22207           enqueueflipface(newtet, flipque);
22208         }
22209       }
22210     }
22211     // Let the corners of t2 point to it for fast searching.
22212     pointptr = org(newtet);
22213     setpoint2tet(pointptr, encode(newtet));
22214     pointptr = dest(newtet);
22215     setpoint2tet(pointptr, encode(newtet));
22216     pointptr = apex(newtet);
22217     setpoint2tet(pointptr, encode(newtet));
22218     pointptr = oppo(newtet);
22219     setpoint2tet(pointptr, encode(newtet));
22220   }
22221   // The cavity has been re-tetrahedralized.
22222 }
22223 
22225 //                                                                           //
22226 // delaunizecavity()    Tetrahedralize a cavity by Delaunay tetrahedra.      //
22227 //                                                                           //
22228 // The cavity C is bounded by a set of triangles in 'floorlist' (a list of   //
22229 // coplanar subfaces) and 'ceillist' (a list of tetrahedral faces lie above  //
22230 // the subfaces). 'floorptlist' and 'ceilptlist' are the vertices of C.      //
22231 //                                                                           //
22233 
22234 void tetgenmesh::delaunizecavity(list* floorlist, list* ceillist,
22235   list* ceilptlist, list* floorptlist, list* frontlist, list* misfrontlist,
22236   list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
22237 {
22238   int vertnum;
22239 
22240   vertnum = floorptlist->len();
22241   vertnum += (ceilptlist != (list *) NULL ? ceilptlist->len() : 0);
22242   if (b->verbose > 1) {
22243     printf("    Delaunizing cavity (%d floors, %d ceilings, %d vertices).\n",
22244            floorlist->len(), ceillist->len(), vertnum);
22245   }
22246   // Save the size of the largest cavity.
22247   if ((floorlist->len() + ceillist->len()) > maxcavfaces) {
22248     maxcavfaces = floorlist->len() + ceillist->len();
22249   }
22250   if (vertnum > maxcavverts) {
22251     maxcavverts = vertnum;
22252   }
22253 
22254   // Clear these lists.
22255   frontlist->clear();
22256   misfrontlist->clear();
22257   newtetlist->clear();
22258 
22259   // Initialize the cavity C.
22260   initializecavity(floorlist, ceillist, frontlist);
22261   // Form the D of the vertices of C.
22262   delaunizecavvertices(NULL, floorptlist, ceilptlist, newtetlist, flipque);
22263   // Identify faces of C in D.
22264   while (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
22265     // Remove protecting subfaces, keep new tets.
22266     detachauxsubfaces(newtetlist);
22267     // Expand C and updateing D.
22268     expandcavity(frontlist, misfrontlist, newtetlist, crosstetlist,
22269                  missingshqueue, flipque);
22270   }
22271   // All fronts have identified in D. Get the shape of C by removing out
22272   //   tets of C. 'misfrontlist' is reused for removing out tets.
22273   carvecavity(newtetlist, misfrontlist, NULL);
22274 }
22275 
22277 //                                                                           //
22278 // formmissingregion()    Form the missing region.                           //
22279 //                                                                           //
22280 // 'missingsh' is a missing subface.  Start from it we can form the missing  //
22281 // region R (a set of connected missing subfaces).  Because all missing sub- //
22282 // faces have been marked (infected) before. R can be formed by checking the //
22283 // neighbors of 'missingsh', and the neighbors of the neighbors, and so on.  //
22284 // Stop checking further at either a segment or an unmarked subface.         //
22285 //                                                                           //
22286 // 'missingshlist' returns R. The edge ring of subfaces of R are oriented in //
22287 // the same direction. 'equatptlist' returns the vertices of R, each vertex  //
22288 // is marked with '1' (in 'worklist').                                       //
22289 //                                                                           //
22291 
22292 void tetgenmesh::formmissingregion(face* missingsh, list* missingshlist,
22293   list* equatptlist, int* worklist)
22294 {
22295   face neighsh, worksh, workseg;
22296   point workpt[3];
22297   int idx, i, j;
22298 
22299   // Add 'missingsh' into 'missingshlist'.
22300   missingshlist->append(missingsh);
22301   // Save and mark its three vertices.
22302   workpt[0] = sorg(*missingsh);
22303   workpt[1] = sdest(*missingsh);
22304   workpt[2] = sapex(*missingsh);
22305   for (i = 0; i < 3; i++) {
22306     idx = pointmark(workpt[i]) - in->firstnumber;
22307     worklist[idx] = 1;
22308     equatptlist->append(&workpt[i]);
22309   }
22310   // Temporarily uninfect it (avoid to save it again).
22311   suninfect(*missingsh);
22312 
22313   // Find the other missing subfaces.
22314   for (i = 0; i < missingshlist->len(); i++) {
22315     // Get a missing subface.
22316     worksh = * (face *)(* missingshlist)[i];
22317     // Check three neighbors of this face.
22318     for (j = 0; j < 3; j++) {
22319       sspivot(worksh, workseg);
22320       if (workseg.sh == dummysh) {
22321         spivot(worksh, neighsh);
22322         if (sinfected(neighsh)) {
22323           // Find a missing subface, adjust the face orientation.
22324           if (sorg(neighsh) != sdest(worksh)) {
22325             sesymself(neighsh);
22326           }
22327           if (b->verbose > 2) {
22328             printf("    Add missing subface (%d, %d, %d).\n",
22329                    pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
22330                    pointmark(sapex(neighsh)));
22331           }
22332           missingshlist->append(&neighsh);
22333           // Save and mark its apex.
22334           workpt[0] = sapex(neighsh);
22335           idx = pointmark(workpt[0]) - in->firstnumber;
22336           // Has workpt[0] been added?
22337           if (worklist[idx] == 0) {
22338             worklist[idx] = 1;
22339             equatptlist->append(&workpt[0]);
22340           }
22341           // Temporarily uninfect it (avoid to save it again).
22342           suninfect(neighsh);
22343         }
22344       }
22345       senextself(worksh);
22346     }
22347   }
22348 
22349   // R has been formed. Infect missing subfaces again.
22350   for (i = 0; i < missingshlist->len(); i++) {
22351     worksh = * (face *)(* missingshlist)[i];
22352     sinfect(worksh);
22353   }
22354 }
22355 
22357 //                                                                           //
22358 // rearrangesubfaces()    Rearrange the set of subfaces of a missing region  //
22359 //                        so that they conform to the faces of DT.           //
22360 //                                                                           //
22361 // The missing region formed by subfaces of 'missingshlist' contains a set   //
22362 // of degenerate vertices, hence the set of subfaces don't match the set of  //
22363 // faces in DT.  Instead of forcing them to present in DT, we re-arrange the //
22364 // connection of them so that the new subfaces conform to the faces of DT.   //
22365 // 'boundedgelist' is a set of boundary edges of the region, these edges(may //
22366 // be subsegments) must exist in DT.                                         //
22367 //                                                                           //
22368 // On completion, we have created and inserted a set of new subfaces which   //
22369 // conform to faces of DT. The set of old subfaces in 'missingshlist' are    //
22370 // deleted. The region vertices in 'equatptlist' are unmarked.               //
22371 //                                                                           //
22373 
22374 void tetgenmesh::rearrangesubfaces(list* missingshlist, list* boundedgelist,
22375   list* equatptlist, int* worklist)
22376 {
22377   link *boundedgelink;
22378   link *newshlink;
22379   triface starttet, spintet, neightet, worktet;
22380   face shloop, newsh, neighsh, spinsh, worksh;
22381   face workseg, casingin, casingout;
22382   point torg, tdest, workpt;
22383   point spt1, spt2, spt3;
22384   enum finddirectionresult collinear;
22385   enum shestype shtype;
22386   REAL area;
22387   bool matchflag, finishflag;
22388   int shmark, pbcgp, idx, hitbdry;
22389   int i, j;
22390 
22391   // Initialize the boundary edge link.
22392   boundedgelink = new link(sizeof(face), NULL, 256);
22393   // Initialize the new subface link.
22394   newshlink = new link(sizeof(face), NULL, 256);
22395   // Remember the type (skinny or not) of replaced subfaces.  They should
22396   //   all have the same type since there is no segment inside the region.
22397   worksh = * (face *)(* missingshlist)[0];
22398   shtype = shelltype(worksh);
22399   // The following loop is only for checking purpose.
22400   for (i = 1; i < missingshlist->len(); i++) {
22401     worksh = * (face *)(* missingshlist)[i];
22402     assert(shelltype(worksh) == shtype);
22403   }
22404   // To avoid compilation warnings.
22405   shmark = pbcgp = 0;
22406   area = 0.0;
22407 
22408   // Create an initial boundary link.
22409   for (i = 0; i < boundedgelist->len(); i++) {
22410     shloop = * (face *)(* boundedgelist)[i];
22411     if (i == 0) {
22412       // 'shmark' will be set to all new created subfaces.
22413       shmark = shellmark(shloop);
22414       if (b->quality && varconstraint) {
22415         // area will be copied to all new created subfaces.
22416         area = areabound(shloop);
22417       }
22418       if (checkpbcs) {
22419         // pbcgp will be copied to all new created subfaces.
22420         pbcgp = shellpbcgroup(shloop);
22421       }
22422       // Get the abovepoint of this facet.
22423       abovepoint = facetabovepointarray[shellmark(shloop)];
22424       if (abovepoint == (point) NULL) {
22425         getfacetabovepoint(&shloop);
22426       }
22427     }
22428     sspivot(shloop, workseg);
22429     if (workseg.sh == dummysh) {
22430       // This edge is an interior edge.
22431       spivot(shloop, neighsh);
22432       boundedgelink->add(&neighsh);
22433     } else {
22434       // This side has a segment, the edge exists.
22435       boundedgelink->add(&shloop);
22436     }
22437   }
22438 
22439   // Each edge ab of boundedgelink will be finished by finding a vertex c
22440   //   which is a vertex of the missing region, such that:
22441   //   (1) abc is inside the missing region, i.e., abc intersects at least
22442   //       one of missing subfaces (saved in missingshlist);
22443   //   (2) abc is not intersect with any previously created new subfaces
22444   //       in the missing region (saved in newshlink).
22445   //   After abc is created, it will be inserted into both the surface mesh
22446   //   and the DT. The boundedgelink will be updated, ab is removed, bc and
22447   //   ca will be added if they are open.
22448 
22449   while (boundedgelink->len() > 0) {
22450     // Remove an edge (ab) from the link.
22451     shloop = * (face *) boundedgelink->del(1);
22452     // 'workseg' indicates it is a segment or not.
22453     sspivot(shloop, workseg);
22454     torg = sorg(shloop);  // torg = a;
22455     tdest = sdest(shloop);  // tdest = b;
22456     // Find a tetrahedron containing ab.
22457     getsearchtet(torg, tdest, &starttet, &workpt);
22458     collinear = finddirection(&starttet, workpt, tetrahedrons->items);
22459     if (collinear == LEFTCOLLINEAR) {
22460       enext2self(starttet);
22461       esymself(starttet);
22462     } else if (collinear == TOPCOLLINEAR) {
22463       fnextself(starttet);
22464       enext2self(starttet);
22465       esymself(starttet);
22466     }
22467     assert(dest(starttet) == workpt);
22468     // Checking faces around ab until a valid face is found.
22469     matchflag = false;
22470     spintet = starttet;
22471     hitbdry = 0;
22472     do {
22473       workpt = apex(spintet);
22474       idx = pointmark(workpt) - in->firstnumber;
22475       if (worklist[idx] == 1) {
22476         // (trog, tdest, workpt) is on the facet. Check if it satisfies (1).
22477         finishflag = false;
22478         for (i = 0; i < missingshlist->len(); i++) {
22479           worksh = * (face *)(* missingshlist)[i];
22480           spt1 = sorg(worksh);
22481           spt2 = sdest(worksh);
22482           spt3 = sapex(worksh);
22483           // Does bc intersect the face?
22484           if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22485               == INTERSECT) {
22486             finishflag = true; break;
22487           }
22488           // Does ca intersect the face?
22489           if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22490               == INTERSECT) {
22491             finishflag = true; break;
22492           }
22493           // Does c inside the face?
22494           if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22495               == INTERSECT) {
22496             finishflag = true; break;
22497           }
22498         }
22499         if (finishflag) {
22500           // Satisfying (1). Check if it satisfies (2).
22501           matchflag = true;
22502           for (i = 0; i < newshlink->len() && matchflag; i++) {
22503             worksh = * (face *) newshlink->getnitem(i + 1);
22504             spt1 = sorg(worksh);
22505             spt2 = sdest(worksh);
22506             spt3 = sapex(worksh);
22507             // Does bc intersect the face?
22508             if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22509                 == INTERSECT) {
22510               matchflag = false; break;
22511             }
22512             // Does ca intersect the face?
22513             if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22514                 == INTERSECT) {
22515               matchflag = false; break;
22516             }
22517             // Does c inside the face?
22518             if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22519                 == INTERSECT) {
22520               matchflag = false; break;
22521             }
22522           }
22523         }
22524         if (matchflag == true) {
22525           // Satisfying both (1) and (2). Find abc.
22526           break;
22527         }
22528       }
22529       if (!fnextself(spintet)) {
22530         hitbdry ++;
22531         if (hitbdry < 2) {
22532           esym(starttet, spintet);
22533           if (!fnextself(spintet)) {
22534             hitbdry ++;
22535           }
22536         }
22537       }
22538     } while (hitbdry < 2 && apex(spintet) != apex(starttet));
22539     assert(matchflag == true);
22540     tspivot(spintet, neighsh);
22541     if (neighsh.sh != dummysh) {
22542       printf("Error:  Invalid PLC.\n");
22543       printf("  Facet #%d and facet #%d overlap each other.\n",
22544              shellmark(neighsh), shellmark(shloop));
22545       printf("  It might be caused by a facet is defined more than once.\n");
22546       printf("  Hint:  Use -d switch to find all overlapping facets.\n");
22547       exit(1);
22548     }
22549     // The side of 'spintet' is at which a new subface will be attached.
22550     adjustedgering(spintet, CCW);
22551     // Create the new subface.
22552     makeshellface(subfaces, &newsh);
22553     setsorg(newsh, org(spintet));
22554     setsdest(newsh, dest(spintet));
22555     setsapex(newsh, apex(spintet));
22556     if (b->quality && varconstraint) {
22557       setareabound(newsh, area);
22558     }
22559     if (checkpbcs) {
22560       setshellpbcgroup(newsh, pbcgp);
22561     }
22562     setshellmark(newsh, shmark);
22563     setshelltype(newsh, shtype);  // It may be a skinny subface.
22564     // Add newsh into newshlink for intersecting checking.
22565     newshlink->add(&newsh);
22566     // Insert it into the current mesh.
22567     tsbond(spintet, newsh);
22568     sym(spintet, neightet);
22569     if (neightet.tet != dummytet) {
22570       sesym(newsh, neighsh);
22571       tsbond(neightet, neighsh);
22572     }
22573     // Insert it into the surface mesh.
22574     sspivot(shloop, workseg);
22575     if (workseg.sh == dummysh) {
22576       sbond(shloop, newsh);
22577     } else {
22578       // There is a subsegment, 'shloop' is the subface which is going to
22579       //   die. Insert the 'newsh' at the place of 'shloop' into its face
22580       //   link, so as to dettach 'shloop'.   The original connection is:
22581       //   -> casingin -> shloop -> casingout ->, it will be changed with:
22582       //   -> casingin ->  newsh -> casingout ->.  Pay attention to the
22583       //   case when this subsegment is dangling in the mesh, i.e., 'shloop'
22584       //   is bonded to itself.
22585       spivot(shloop, casingout);
22586       if (shloop.sh != casingout.sh) {
22587         // 'shloop' is not bonded to itself.
22588         spinsh = casingout;
22589         do {
22590           casingin = spinsh;
22591           spivotself(spinsh);
22592         } while (sapex(spinsh) != sapex(shloop));
22593         assert(casingin.sh != shloop.sh);
22594         // Bond casingin -> newsh -> casingout.
22595         sbond1(casingin, newsh);
22596         sbond1(newsh, casingout);
22597       } else {
22598         // Bond newsh -> newsh.
22599         sbond(newsh, newsh);
22600       }
22601       // Bond the segment.
22602       ssbond(newsh, workseg);
22603     }
22604     // Check other two sides of this new subface.  If a side is not bonded
22605     //   to any edge in the link, it will be added to the link.
22606     for (i = 0; i < 2; i++) {
22607       if (i == 0) {
22608         senext(newsh, worksh);
22609       } else {
22610         senext2(newsh, worksh);
22611       }
22612       torg = sorg(worksh);
22613       tdest = sdest(worksh);
22614       finishflag = false;
22615       for (j = 0; j < boundedgelink->len() && !finishflag; j++) {
22616         neighsh = * (face *) boundedgelink->getnitem(j + 1);
22617         if ((sorg(neighsh) == torg && sdest(neighsh) == tdest) ||
22618             (sorg(neighsh) == tdest && sdest(neighsh) == torg)) {
22619           // Find a boundary edge.  Bond them and exit the loop.
22620           sspivot(neighsh, workseg);
22621           if (workseg.sh == dummysh) {
22622             sbond(neighsh, worksh);
22623           } else {
22624             // There is a subsegment, 'neighsh' is the subface which is
22625             //   going to die. Do the same as above for 'worksh'.
22626             spivot(neighsh, casingout);
22627             if (neighsh.sh != casingout.sh) {
22628               // 'neighsh' is not bonded to itself.
22629               spinsh = casingout;
22630               do {
22631                 casingin = spinsh;
22632                 spivotself(spinsh);
22633               } while (sapex(spinsh) != sapex(neighsh));
22634               assert(casingin.sh != neighsh.sh);
22635               // Bond casingin -> worksh -> casingout.
22636               sbond1(casingin, worksh);
22637               sbond1(worksh, casingout);
22638             } else {
22639               // Bond worksh -> worksh.
22640               sbond(worksh, worksh);
22641             }
22642             // Bond the segment.
22643             ssbond(worksh, workseg);
22644           }
22645           // Remove this boundary edge from the link.
22646           boundedgelink->del(j + 1);
22647           finishflag = true;
22648         }
22649       }
22650       if (!finishflag) {
22651         // It's a new boundary edge, add it to link.
22652         boundedgelink->add(&worksh);
22653       }
22654     }
22655   }
22656 
22657   // Deallocate the set of old missing subfaces.
22658   for (i = 0; i < missingshlist->len(); i++) {
22659     worksh = * (face *)(* missingshlist)[i];
22660     shellfacedealloc(subfaces, worksh.sh);
22661   }
22662   // Unmark region vertices in 'worklist'.
22663   for (i = 0; i < equatptlist->len(); i++) {
22664     workpt = * (point *)(* equatptlist)[i];
22665     idx = pointmark(workpt) - in->firstnumber;
22666     worklist[idx] = 0;
22667   }
22668 
22669   delete boundedgelink;
22670   delete newshlink;
22671 }
22672 
22674 //                                                                           //
22675 // scoutcrossingedge()    Search an edge crossing the missing region.        //
22676 //                                                                           //
22677 // 'missingshlist' forms the missing region R. This routine searches for an  //
22678 // edge crossing R.  It first forms a 'boundedgelist' consisting of the      //
22679 // boundary edges of R. Such edges are existing in CDT.  A crossing edge is  //
22680 // found by rotating faces around one of the boundary edges. It is possible  //
22681 // there is no edge crosses R (e.g. R has a degenerate point set).           //
22682 //                                                                           //
22683 // If find a croosing edge, return TRUE, 'crossedgelist' contains this edge. //
22684 // Otherwise, return FALSE.                                                  //
22685 //                                                                           //
22687 
22688 bool tetgenmesh::scoutcrossingedge(list* missingshlist, list* boundedgelist,
22689   list* crossedgelist, int* worklist)
22690 {
22691   triface starttet, spintet, worktet;
22692   face startsh, neighsh, worksh, workseg;
22693   point torg, tdest, tapex;
22694   point workpt[3], pa, pb, pc;
22695   enum finddirectionresult collinear;
22696   REAL ori1, ori2;
22697   bool crossflag;
22698   int hitbdry;
22699   int i, j, k;
22700 
22701   // Form the 'boundedgelist'. Loop through 'missingshlist', check each
22702   //   edge of these subfaces. If an edge is a segment or the neighbor
22703   //   subface is uninfected, add it to 'boundedgelist'.
22704   for (i = 0; i < missingshlist->len(); i++) {
22705     worksh = * (face *)(* missingshlist)[i];
22706     for (j = 0; j < 3; j++) {
22707       sspivot(worksh, workseg);
22708       if (workseg.sh == dummysh) {
22709         spivot(worksh, neighsh);
22710         if (!sinfected(neighsh)) {
22711           boundedgelist->append(&worksh);
22712         }
22713       } else {
22714         boundedgelist->append(&worksh);
22715       }
22716       senextself(worksh);
22717     }
22718   }
22719 
22720   crossflag = false;
22721   // Find a crossing edge. It is possible there is no such edge. We need to
22722   //   loop through all edges of 'boundedgelist' for sure we don't miss any.
22723   for (i = 0; i < boundedgelist->len() && !crossflag; i++) {
22724     startsh = * (face *)(* boundedgelist)[i];
22725     // 'startsh' (abc) holds an existing edge of the DT, find it.
22726     torg = sorg(startsh);
22727     tdest = sdest(startsh);
22728     tapex = sapex(startsh);
22729     getsearchtet(torg, tdest, &starttet, &workpt[0]);
22730     collinear = finddirection(&starttet, workpt[0], tetrahedrons->items);
22731     if (collinear == LEFTCOLLINEAR) {
22732       enext2self(starttet);
22733       esymself(starttet);
22734     } else if (collinear == TOPCOLLINEAR) {
22735       fnextself(starttet);
22736       enext2self(starttet);
22737       esymself(starttet);
22738     }
22739 #ifdef SELF_CHECK
22740     assert(dest(starttet) == workpt[0]);
22741 #endif
22742     // Now starttet holds edge ab. Find is edge de crossing R.
22743     spintet = starttet;
22744     hitbdry = 0;
22745     do {
22746       if (fnextself(spintet)) {
22747         // splittet = abde. Check if de crosses abc.
22748         workpt[1] = apex(spintet);  // workpt[1] = d.
22749         workpt[2] = oppo(spintet);  // workpt[2] = e.
22750         j = pointmark(workpt[1]) - in->firstnumber;
22751         k = pointmark(workpt[2]) - in->firstnumber;
22752         if (worklist[j] == 1) {
22753           ori1 = 0.0; // d is a vertex of the missing region.
22754         } else {
22755           // Get the orientation of d wrt. abc.
22756           ori1 = orient3d(torg, tdest, tapex, workpt[1]);
22757         }
22758         if (worklist[k] == 1) {
22759           ori2 = 0.0; // e is a vertex of the missing region.
22760         } else {
22761           // Get the orientation of e wrt. abc.
22762           ori2 = orient3d(torg, tdest, tapex, workpt[2]);
22763         }
22764         // Only do check if d and e locate on different sides of abc.
22765         if (ori1 * ori2 < 0.0) {
22766           // Check if de crosses any subface of R.
22767           for (j = 0; j < missingshlist->len(); j++) {
22768             worksh = * (face *)(* missingshlist)[j];
22769             pa = sorg(worksh);
22770             pb = sdest(worksh);
22771             pc = sapex(worksh);
22772             crossflag = (tri_tri_inter(pa, pb, pc, workpt[0], workpt[1],
22773                                        workpt[2]) == INTERSECT);
22774             if (crossflag) {
22775               // Find a crossing edge. We're done.
22776               worktet = spintet;
22777               adjustedgering(worktet, CCW);
22778               enextfnextself(worktet);
22779               enextself(worktet);
22780               // Add this edge (worktet) into 'crossedgelist'.
22781               crossedgelist->append(&worktet);
22782               break;
22783             }
22784           }
22785           if (crossflag) break;
22786         }
22787         if (apex(spintet) == apex(starttet)) break;
22788       } else {
22789         hitbdry++;
22790         // It is only possible to hit boundary once.
22791         if (hitbdry < 2) {
22792           esym(starttet, spintet);
22793         }
22794       }
22795     } while (hitbdry < 2);
22796   }
22797 
22798   return crossflag;
22799 }
22800 
22802 //                                                                           //
22803 // formcavity()    Form the cavity for recovering the missing region.        //
22804 //                                                                           //
22805 // The cavity C is bounded by faces of current CDT.  All tetrahedra inside C //
22806 // will be removed, intead a set of constrained Delaunay tetrahedra will be  //
22807 // filled in and the missing region are recovered.                           //
22808 //                                                                           //
22809 // 'missingshlist' contains a set of subfaces forming the missing region R.  //
22810 // C is formed by first finding all the tetrahedra in CDT that intersect the //
22811 // relative interior of R; then deleting them from the CDT, this will form C //
22812 // inside the CDT. At the beginning, 'crossedgelist' contains an edge which  //
22813 // is crossing R. All tets containing this edge must cross R. Start from it, //
22814 // other crossing edges can be found incrementally.  The discovered crossing //
22815 // tets are saved in 'crosstetlist'.                                         //
22816 //                                                                           //
22817 // Notice that not all tets in 'crosstetlist' are crossing R. The discovered //
22818 // tets are connected each other. However, there may be other tets crossing  //
22819 // R but disjoint with the found tets. Due to this fact we need to check the //
22820 // 'missingshlist' once more. Only recover those subfaces which are crossed  //
22821 // by the set of discovered tets, i.e., R may be shrinked to conform the set //
22822 // of discovered tets. The extra subfaces of R will be recovered later.      //
22823 //                                                                           //
22824 // Notice that some previous recovered subfaces may completely included in C.//
22825 // This can happen when R is very big and these subfaces lie above R and so  //
22826 // close to it. Such subfaces have to be queued (and sinfected()) to recover //
22827 // them later. Otherwise, we lost the connection to these subfaces forever.  //
22828 //                                                                           //
22830 
22831 void tetgenmesh::formcavity(list* missingshlist, list* crossedgelist,
22832   list* equatptlist, list* crossshlist, list* crosstetlist,
22833   list* belowfacelist, list* abovefacelist, list* horizptlist,
22834   list* belowptlist, list* aboveptlist, queue* missingshqueue, int* worklist)
22835 {
22836   triface starttet, spintet, neightet, worktet;
22837   face startsh, neighsh, worksh, workseg;
22838   point torg, tdest, tapex, workpt[3];
22839   REAL checksign, orgori, destori;
22840   bool crossflag, inlistflag;
22841   bool belowflag, aboveflag;
22842   int idx, share;
22843   int i, j, k;
22844 
22845   // Get a face at horizon.
22846   startsh = * (face *)(* missingshlist)[0];
22847   torg = sorg(startsh);
22848   tdest = sdest(startsh);
22849   tapex = sapex(startsh);
22850 
22851   // Collect the set of crossing tetrahedra by rotating crossing edges.
22852   for (i = 0; i < crossedgelist->len(); i++) {
22853     // Get a tet abcd, ab is a crossing edge.
22854     starttet = * (triface *)(* crossedgelist)[i];
22855     adjustedgering(starttet, CCW);
22856     if (b->verbose > 2) {
22857       printf("    Collect tets containing edge (%d, %d).\n",
22858              pointmark(org(starttet)), pointmark(dest(starttet)));
22859     }
22860     orgori = orient3d(torg, tdest, tapex, org(starttet));
22861     destori = orient3d(torg, tdest, tapex, dest(starttet));
22862 #ifdef SELF_CHECK
22863     assert(orgori * destori < 0.0);
22864 #endif
22865     spintet = starttet;
22866     do {
22867       // The face rotation should not meet boundary.
22868       fnextself(spintet);
22869       // Check the validity of the PLC.
22870       tspivot(spintet, worksh);
22871       if (worksh.sh != dummysh) {
22872         printf("Error:  Invalid PLC.\n");
22873         printf("  Two subfaces (%d, %d, %d) and (%d, %d, %d)\n",
22874                pointmark(torg), pointmark(tdest), pointmark(tapex),
22875                pointmark(sorg(worksh)), pointmark(sdest(worksh)),
22876                pointmark(sapex(worksh)));
22877         printf("  are found intersecting each other.\n");
22878         printf("  Hint:  Use -d switch to find all intersecting facets.\n");
22879         terminatetetgen(1);
22880       }
22881       if (!infected(spintet)) {
22882         if (b->verbose > 2) {
22883           printf("      Add crossing tet (%d, %d, %d, %d).\n",
22884                  pointmark(org(spintet)), pointmark(dest(spintet)),
22885                  pointmark(apex(spintet)), pointmark(oppo(spintet)));
22886         }
22887         infect(spintet);
22888         crosstetlist->append(&spintet);
22889       }
22890       // Check whether other two edges of 'spintet' is a crossing edge.
22891       //   It can be quickly checked from the apex of 'spintet', if it is
22892       //   not on the facet, then there exists a crossing edge.
22893       workpt[0] = apex(spintet);
22894       idx = pointmark(workpt[0]) - in->firstnumber;
22895       if (worklist[idx] != 1) {
22896         // Either edge (dest, apex) or edge (apex, org) crosses.
22897         checksign = orient3d(torg, tdest, tapex, workpt[0]);
22898 #ifdef SELF_CHECK
22899         assert(checksign != 0.0);
22900 #endif
22901         if (checksign * orgori < 0.0) {
22902           enext2(spintet, worktet); // edge (apex, org).
22903           workpt[1] = org(spintet);
22904         } else {
22905 //#ifdef SELF_CHECK // commented out to get gcc 4.6 working
22906           assert(checksign * destori < 0.0);
22907 //#endif
22908           enext(spintet, worktet);  // edge (dest, apex).
22909           workpt[1] = dest(spintet);
22910         }
22911         // 'worktet' represents the crossing edge. Add it into list only
22912         //   it doesn't exist in 'crossedgelist'.
22913         inlistflag = false;
22914         for (j = 0; j < crossedgelist->len() && !inlistflag; j++) {
22915           neightet = * (triface *)(* crossedgelist)[j];
22916           if (org(neightet) == workpt[0]) {
22917             if (dest(neightet) == workpt[1]) inlistflag = true;
22918           } else if (org(neightet) == workpt[1]) {
22919             if (dest(neightet) == workpt[0]) inlistflag = true;
22920           }
22921         }
22922         if (!inlistflag) {
22923           crossedgelist->append(&worktet);
22924         }
22925       }
22926     } while (apex(spintet) != apex(starttet));
22927   }
22928 
22929   // Identifying the boundary faces and vertices of C. Sort them into
22930   //   'abovefacelist', 'aboveptlist, 'belowfacelist', and 'belowptlist',
22931   //    respectively. "above" and "below" are wrt.(torg, tdest, tapex).
22932   for (i = 0; i < crosstetlist->len(); i++) {
22933     // Get a tet abcd, ab is the crossing edge.
22934     starttet = * (triface *)(* crosstetlist)[i];
22935 #ifdef SELF_CHECK
22936     assert(infected(starttet));
22937 #endif
22938     adjustedgering(starttet, CCW);
22939     // abc and abd are sharing the crossing edge, the two neighbors must
22940     //   be crossing tetrahedra too. They can't be boundaries of C.
22941     for (j = 0; j < 2; j++) {
22942       if (j == 0) {
22943         enextfnext(starttet, worktet); // Check bcd.
22944       } else {
22945         enext2fnext(starttet, worktet); // Check acd.
22946       }
22947       sym(worktet, neightet);
22948       // If the neighbor doesn't exist or exists but doesn't be infected,
22949       //   it's a boundary face of C, save it.
22950       if ((neightet.tet == dummytet) || !infected(neightet)) {
22951         workpt[0] = org(worktet);
22952         workpt[1] = dest(worktet);
22953         workpt[2] = apex(worktet);
22954         belowflag = aboveflag = false;
22955         share = 0;
22956         for (k = 0; k < 3; k++) {
22957           idx = pointmark(workpt[k]) - in->firstnumber;
22958           if (worklist[idx] == 0) {
22959             // It's not a vertices of facet, find which side it lies.
22960             checksign = orient3d(torg, tdest, tapex, workpt[k]);
22961 #ifdef SELF_CHECK
22962             assert(checksign != 0.0);
22963 #endif
22964             if (checksign > 0.0) {
22965               // It lies "below" the facet wrt. 'startsh'.
22966               worklist[idx] = 2;
22967               belowptlist->append(&workpt[k]);
22968             } else if (checksign < 0.0) {
22969               // It lies "above" the facet wrt. 'startsh'.
22970               worklist[idx] = 3;
22971               aboveptlist->append(&workpt[k]);
22972             }
22973           }
22974           if (worklist[idx] == 2) {
22975             // This face lies "below" the facet wrt. 'startsh'.
22976             belowflag = true;
22977           } else if (worklist[idx] == 3) {
22978             // This face lies "above" the facet wrt. 'startsh'.
22979             aboveflag = true;
22980           } else {
22981 #ifdef SELF_CHECK
22982             // In degenerate case, this face may just be the equator.
22983             assert(worklist[idx] == 1);
22984 #endif
22985             share++;
22986           }
22987         }
22988 #ifdef SELF_CHECK
22989         // The degenerate case has been ruled out.
22990         assert(share < 3);
22991         // Only one flag is possible for a cavity face.
22992         assert(belowflag ^ aboveflag);
22993 #endif
22994         if (belowflag) {
22995           belowfacelist->append(&worktet);
22996         } else if (aboveflag) {
22997           abovefacelist->append(&worktet);
22998         }
22999       }
23000     }
23001   }
23002 
23003   // Shrink R if not all its subfaces are crossing by the discovered tets.
23004   //   'crossshlist' and 'horizptlist' represent the set of subfaces and
23005   //   vertices of the shrinked missing region, respectively.
23006   for (i = 0; i < missingshlist->len(); i++) {
23007     worksh = * (face *)(* missingshlist)[i];
23008 #ifdef SELF_CHECK
23009     assert(sinfected(worksh));
23010 #endif
23011     workpt[0] = sorg(worksh);
23012     workpt[1] = sdest(worksh);
23013     workpt[2] = sapex(worksh);
23014     crossflag = false;
23015     for (j = 0; j < crosstetlist->len() && !crossflag; j++) {
23016       // Get a tet abcd, ab is a crossing edge.
23017       starttet = * (triface *)(* crosstetlist)[j];
23018       adjustedgering(starttet, CCW);
23019       // Only need to check two sides of worktet.
23020       for (k = 0; k < 2 && !crossflag; k++) {
23021         if (k == 0) {
23022           worktet = starttet; // Check abc.
23023         } else {
23024           fnext(starttet, worktet); // Check abd.
23025         }
23026         crossflag = tritritest(&worktet, workpt[0], workpt[1], workpt[2]);
23027       }
23028     }
23029     if (crossflag) {
23030       // 'worksh' is crossed by 'worktet', uninfect it.
23031       suninfect(worksh);
23032       crossshlist->append(&worksh);
23033       // Add its corners into 'horizptlist'.
23034       for (k = 0; k < 3; k++) {
23035         idx = pointmark(workpt[k]) - in->firstnumber;
23036         if (worklist[idx] != 4) {
23037           worklist[idx] = 4;
23038           horizptlist->append(&workpt[k]);
23039         }
23040       }
23041     }
23042   }
23043 
23044   // Check 'crossingtetlist'. Queue subfaces inside them.
23045   for (i = 0; i < crosstetlist->len(); i++) {
23046     starttet = * (triface *)(* crosstetlist)[i];
23047     for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
23048       sym(starttet, neightet);
23049       // If the neighbor exist and is infected, check it.
23050       if ((neightet.tet != dummytet) && infected(neightet)) {
23051         tspivot(starttet, worksh);
23052         if (worksh.sh != dummysh) {
23053           // Temporarily remove worksh. Make it missing. recover it later.
23054           if (b->verbose > 2) {
23055             printf("    Queuing subface (%d, %d, %d).\n",
23056                    pointmark(sorg(worksh)), pointmark(sdest(worksh)),
23057                    pointmark(sapex(worksh)));
23058           }
23059           tsdissolve(neightet);
23060           tsdissolve(starttet);
23061           // Detach tets at the both sides of this subface.
23062           stdissolve(worksh);
23063           sesymself(worksh);
23064           stdissolve(worksh);
23065           sinfect(worksh);
23066           missingshqueue->push(&worksh);
23067         }
23068       }
23069     }
23070   }
23071 
23072   // Clear flags set in 'worklist'.
23073   for (i = 0; i < equatptlist->len(); i++) {
23074     workpt[0] = * (point *)(* equatptlist)[i];
23075     idx = pointmark(workpt[0]) - in->firstnumber;
23076 #ifdef SELF_CHECK
23077     assert((worklist[idx] == 1) || (worklist[idx] == 4));
23078 #endif
23079     worklist[idx] = 0;
23080   }
23081   for (i = 0; i < belowptlist->len(); i++) {
23082     workpt[0] = * (point *)(* belowptlist)[i];
23083     idx = pointmark(workpt[0]) - in->firstnumber;
23084 #ifdef SELF_CHECK
23085     assert(worklist[idx] == 2);
23086 #endif
23087     worklist[idx] = 0;
23088   }
23089   for (i = 0; i < aboveptlist->len(); i++) {
23090     workpt[0] = * (point *)(* aboveptlist)[i];
23091     idx = pointmark(workpt[0]) - in->firstnumber;
23092 #ifdef SELF_CHECK
23093     assert(worklist[idx] == 3);
23094 #endif
23095     worklist[idx] = 0;
23096   }
23097 }
23098 
23100 //                                                                           //
23101 // insertallsubfaces()    Insert all subfaces, queue missing subfaces.       //
23102 //                                                                           //
23103 // Loop through all subfaces, insert each into the DT. If one already exists,//
23104 // bond it to the tetrahedra having it. Otherwise, it is missing, infect it  //
23105 // and save it in 'missingshqueue'.                                          //
23106 //                                                                           //
23108 
23109 void tetgenmesh::insertallsubfaces(queue* missingshqueue)
23110 {
23111   triface searchtet;
23112   face subloop;
23113 
23114   searchtet.tet = (tetrahedron *) NULL;
23115   subfaces->traversalinit();
23116   subloop.sh = shellfacetraverse(subfaces);
23117   while (subloop.sh != (shellface *) NULL) {
23118     if (!insertsubface(&subloop, &searchtet)) {
23119       if (b->verbose > 1) {
23120         printf("    Queuing subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23121                pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23122       }
23123       sinfect(subloop);
23124       missingshqueue->push(&subloop);
23125     }
23126     subloop.sh = shellfacetraverse(subfaces);
23127   }
23128 }
23129 
23131 //                                                                           //
23132 // constrainedfacets()    Recover subfaces in a Delaunay tetrahedralization. //
23133 //                                                                           //
23134 // This routine creates a CDT by incrementally updating a DT D into a CDT T. //
23135 // The process of recovering facets can be imagined by "merging" the surface //
23136 // mesh F into D. At the beginning, F and D are completely seperated.  Some  //
23137 // faces of them are matching some are not because they are crossed by some  //
23138 // tetrahedra of D. The non-matching subfaces will be forced to appear in T  //
23139 // by locally retetrahedralizing the regions where F and D are intersecting. //
23140 //                                                                           //
23141 // When a subface s of F is found missing in D, probably some other subfaces //
23142 // near to s are missing too.  The set of adjoining coplanar missing faces   //
23143 // forms a missing region R (R may not simply connected).                    //
23144 //                                                                           //
23145 // There are two possibilities can result a mssing region R: (1) Some edges  //
23146 // of D cross R; (2) No edge of D crosses R, but some faces of D spans R, ie,//
23147 // D is locally degenerate at R. In case (1), D is modified so that it resp- //
23148 // ects R (done by a cavity retetrahedralization algorithm).  In case (2), F //
23149 // is modified so that the set of subfaces of R matches faces in D (done by  //
23150 // a face rearrangment algorithm).                                           //
23151 //                                                                           //
23153 
23154 void tetgenmesh::constrainedfacets()
23155 {
23156   queue *missingshqueue, *flipque;
23157   list *missingshlist, *equatptlist;
23158   list *boundedgelist, *crossedgelist, *crosstetlist;
23159   list *crossshlist, *belowfacelist, *abovefacelist;
23160   list *horizptlist, *belowptlist, *aboveptlist;
23161   list *frontlist, *misfrontlist, *newtetlist;
23162   triface searchtet, worktet;
23163   face subloop, worksh;
23164   int *worklist;
23165   int i;
23166 
23167   if (!b->quiet) {
23168     printf("Constraining facets.\n");
23169   }
23170 
23171   // Initialize queues.
23172   missingshqueue = new queue(sizeof(face));
23173   flipque = new queue(sizeof(badface));
23174   // Initialize the working lists.
23175   missingshlist = new list(sizeof(face), NULL);
23176   boundedgelist = new list(sizeof(face), NULL);
23177   crossedgelist = new list(sizeof(triface), NULL);
23178   equatptlist = new list((char*) "point *");
23179   crossshlist = new list(sizeof(face), NULL);
23180   crosstetlist = new list(sizeof(triface), NULL);
23181   belowfacelist = new list(sizeof(triface), NULL);
23182   abovefacelist = new list(sizeof(triface), NULL);
23183   horizptlist = new list((char*)"point *");
23184   belowptlist = new list((char*)"point *");
23185   aboveptlist = new list((char*)"point *");
23186   frontlist = new list(sizeof(triface), NULL);
23187   misfrontlist = new list(sizeof(triface), NULL);
23188   newtetlist = new list(sizeof(triface), NULL);
23189   // Initialize the array for marking vertices.
23190   worklist = new int[points->items + 1];
23191   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
23192 
23193   // Compute a mapping from points to tetrahedra for fast searching.
23194   makepoint2tetmap();
23195 
23196   // Match subfaces in D, queue all missing subfaces.
23197   insertallsubfaces(missingshqueue);
23198 
23199   // Recover all missing subfaces.
23200   while (!missingshqueue->empty()) {
23201     // Get a queued face s.
23202     subloop = * (face *) missingshqueue->pop();
23203     // s may have been deleted in a face rearrangment operation.
23204     if (isdead(&subloop)) continue;
23205     // s may have been recovered in a previous missing region.
23206     if (!sinfected(subloop)) continue;
23207     // s may match a face in D now due to previous transformations.
23208     if (insertsubface(&subloop, &searchtet)) {
23209       suninfect(subloop);
23210       continue;
23211     }
23212     if (b->verbose > 1) {
23213       printf("    Recover subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23214              pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23215     }
23216     // Form the missing region R containing s.
23217     formmissingregion(&subloop, missingshlist, equatptlist, worklist);
23218     // Is R crossing by any tetrahedron?
23219     if (scoutcrossingedge(missingshlist, boundedgelist, crossedgelist,
23220                           worklist)) {
23221       // Form the cavity C containing R.
23222       formcavity(missingshlist, crossedgelist, equatptlist, crossshlist,
23223                  crosstetlist, belowfacelist, abovefacelist, horizptlist,
23224                  belowptlist, aboveptlist, missingshqueue, worklist);
23225       // Recover the above part of C.
23226       delaunizecavity(crossshlist, abovefacelist, aboveptlist, horizptlist,
23227                       frontlist, misfrontlist, newtetlist, crosstetlist,
23228                       missingshqueue, flipque);
23229       // Inverse the direction of subfaces in R.
23230       for (i = 0; i < crossshlist->len(); i++) {
23231         worksh = * (face *)(* crossshlist)[i];
23232         sesymself(worksh);
23233         * (face *)(* crossshlist)[i] = worksh;
23234       }
23235       // Recover the below part of C.
23236       delaunizecavity(crossshlist, belowfacelist, belowptlist, horizptlist,
23237                       frontlist, misfrontlist, newtetlist, crosstetlist,
23238                       missingshqueue, flipque);
23239       // Delete tetrahedra in C.
23240       for (i = 0; i < crosstetlist->len(); i++) {
23241         worktet = * (triface *)(* crosstetlist)[i];
23242         tetrahedrondealloc(worktet.tet);
23243       }
23244       // There may have some un-recovered subfaces of R. Put them back into
23245       //   queue. Otherwise, they will be missing on the boundary.
23246       for (i = 0; i < missingshlist->len(); i++) {
23247         worksh = * (face *)(* missingshlist)[i];
23248         if (sinfected(worksh)) {
23249           // An unrecovered subface, put it back into queue.
23250           missingshqueue->push(&worksh);
23251         }
23252       }
23253       crossshlist->clear();
23254       belowfacelist->clear();
23255       abovefacelist->clear();
23256       horizptlist->clear();
23257       belowptlist->clear();
23258       aboveptlist->clear();
23259       crosstetlist->clear();
23260     } else {
23261       // No. Rearrange subfaces of F conforming to that of D in R. It can
23262       //   happen when the facet has non-coplanar vertices.
23263       rearrangesubfaces(missingshlist, boundedgelist, equatptlist, worklist);
23264     }
23265     // Clear all working lists.
23266     missingshlist->clear();
23267     boundedgelist->clear();
23268     crossedgelist->clear();
23269     equatptlist->clear();
23270   }
23271 
23272   // Subfaces have been merged into D.
23273   checksubfaces = 1;
23274 
23275   if (b->verbose > 0) {
23276     printf("  The biggest cavity: %d faces, %d vertices\n", maxcavfaces,
23277            maxcavverts);
23278     printf("  Enlarged %d times\n", expcavcount);
23279   }
23280 
23281   delete missingshqueue;
23282   delete flipque;
23283   delete missingshlist;
23284   delete boundedgelist;
23285   delete crossedgelist;
23286   delete equatptlist;
23287   delete crossshlist;
23288   delete crosstetlist;
23289   delete belowfacelist;
23290   delete abovefacelist;
23291   delete horizptlist;
23292   delete belowptlist;
23293   delete aboveptlist;
23294   delete frontlist;
23295   delete misfrontlist;
23296   delete newtetlist;
23297   delete [] worklist;
23298 }
23299 
23300 //
23301 // End of facet recovery routines
23302 //
23303 
23304 //
23305 // Begin of carving out holes and concavities routines
23306 //
23307 
23309 //                                                                           //
23310 // infecthull()    Virally infect all of the tetrahedra of the convex hull   //
23311 //                 that are not protected by subfaces.  Where there are      //
23312 //                 subfaces, set boundary markers as appropriate.            //
23313 //                                                                           //
23314 // Memorypool 'viri' is used to return all the infected tetrahedra.          //
23315 //                                                                           //
23317 
23318 void tetgenmesh::infecthull(memorypool *viri)
23319 {
23320   triface tetloop, tsymtet;
23321   tetrahedron **deadtet;
23322   face hullface;
23323   // point horg, hdest, hapex;
23324 
23325   if (b->verbose > 0) {
23326     printf("  Marking concavities for elimination.\n");
23327   }
23328   tetrahedrons->traversalinit();
23329   tetloop.tet = tetrahedrontraverse();
23330   while (tetloop.tet != (tetrahedron *) NULL) {
23331     // Is this tetrahedron on the hull?
23332     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
23333       sym(tetloop, tsymtet);
23334       if (tsymtet.tet == dummytet) {
23335         // Is the tetrahedron protected by a subface?
23336         tspivot(tetloop, hullface);
23337         if (hullface.sh == dummysh) {
23338           // The tetrahedron is not protected; infect it.
23339           if (!infected(tetloop)) {
23340             infect(tetloop);
23341             deadtet = (tetrahedron **) viri->alloc();
23342             *deadtet = tetloop.tet;
23343             break;  // Go and get next tet.
23344           }
23345         } else {
23346           // The tetrahedron is protected; set boundary markers if appropriate.
23347           if (shellmark(hullface) == 0) {
23348             setshellmark(hullface, 1);
23349             /*
23350             horg = sorg(hullface);
23351             hdest = sdest(hullface);
23352             hapex = sapex(hullface);
23353             if (pointmark(horg) == 0) {
23354               setpointmark(horg, 1);
23355             }
23356             if (pointmark(hdest) == 0) {
23357               setpointmark(hdest, 1);
23358             }
23359             if (pointmark(hapex) == 0) {
23360               setpointmark(hapex, 1);
23361             }
23362             */
23363           }
23364         }
23365       }
23366     }
23367     tetloop.tet = tetrahedrontraverse();
23368   }
23369 }
23370 
23372 //                                                                           //
23373 // plague()    Spread the virus from all infected tets to any neighbors not  //
23374 //             protected by subfaces.                                        //
23375 //                                                                           //
23376 // This routine identifies all the tetrahedra that will die, and marks them  //
23377 // as infected.  They are marked to ensure that each tetrahedron is added to //
23378 // the virus pool only once, so the procedure will terminate. 'viri' returns //
23379 // all infected tetrahedra which are outside the domian.                     //
23380 //                                                                           //
23382 
23383 void tetgenmesh::plague(memorypool *viri)
23384 {
23385   tetrahedron **virusloop;
23386   tetrahedron **deadtet;
23387   triface testtet, neighbor;
23388   face neighsh, testseg;
23389   face spinsh, casingin, casingout;
23390   int firstdadsub;
23391   int i;
23392 
23393   if (b->verbose > 0) {
23394     printf("  Marking neighbors of marked tetrahedra.\n");
23395   }
23396   firstdadsub = 0;
23397   // Loop through all the infected tetrahedra, spreading the virus to
23398   //   their neighbors, then to their neighbors' neighbors.
23399   viri->traversalinit();
23400   virusloop = (tetrahedron **) viri->traverse();
23401   while (virusloop != (tetrahedron **) NULL) {
23402     testtet.tet = *virusloop;
23403     // Temporarily uninfect this tetrahedron, not necessary.
23404     uninfect(testtet);
23405     // Check each of the tetrahedron's four neighbors.
23406     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23407       // Find the neighbor.
23408       sym(testtet, neighbor);
23409       // Check for a shell between the tetrahedron and its neighbor.
23410       tspivot(testtet, neighsh);
23411       // Check if the neighbor is nonexistent or already infected.
23412       if ((neighbor.tet == dummytet) || infected(neighbor)) {
23413         if (neighsh.sh != dummysh) {
23414           // There is a subface separating the tetrahedron from its neighbor,
23415           //   but both tetrahedra are dying, so the subface dies too.
23416           // Before deallocte this subface, dissolve the connections between
23417           //   other subfaces, subsegments and tetrahedra.
23418           neighsh.shver = 0;
23419           if (!firstdadsub) {
23420             firstdadsub = 1; // Report the problem once.
23421             if (!b->quiet) {
23422               printf("Warning:  Detecting an open face (%d, %d, %d).\n",
23423                      pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
23424                      pointmark(sapex(neighsh)));
23425             }
23426           }
23427           // For keep the same enext() direction.
23428           findedge(&testtet, sorg(neighsh), sdest(neighsh));
23429           for (i = 0; i < 3; i++) {
23430             sspivot(neighsh, testseg);
23431             if (testseg.sh != dummysh) {
23432               // A subsegment is found at this side, dissolve this subface
23433               //   from the face link of this subsegment.
23434               testseg.shver = 0;
23435               spinsh = neighsh;
23436               if (sorg(spinsh) != sorg(testseg)) {
23437                 sesymself(spinsh);
23438               }
23439               spivot(spinsh, casingout);
23440               if (casingout.sh == spinsh.sh) {
23441                 // This is a trivial face link, only 'neighsh' itself,
23442                 //   the subsegment at this side is also died.
23443                 shellfacedealloc(subsegs, testseg.sh);
23444               } else {
23445                 spinsh = casingout;
23446                 do {
23447                   casingin = spinsh;
23448                   spivotself(spinsh);
23449                 } while (spinsh.sh != neighsh.sh);
23450                 // Set the link casingin->casingout.
23451                 sbond1(casingin, casingout);
23452                 // Bond the subsegment anyway.
23453                 ssbond(casingin, testseg);
23454               }
23455             }
23456             senextself(neighsh);
23457             enextself(testtet);
23458           }
23459           if (neighbor.tet != dummytet) {
23460             // Make sure the subface doesn't get deallocated again later
23461             //   when the infected neighbor is visited.
23462             tsdissolve(neighbor);
23463           }
23464           // This subface has been separated.
23465           if (in->mesh_dim > 2) {
23466             shellfacedealloc(subfaces, neighsh.sh);
23467           } else {
23468             // Dimension is 2. keep it for output.
23469             // Dissolve tets at both sides of this subface.
23470             stdissolve(neighsh);
23471             sesymself(neighsh);
23472             stdissolve(neighsh);
23473           }
23474         }
23475       } else {                   // The neighbor exists and is not infected.
23476         if (neighsh.sh == dummysh) {
23477           // There is no subface protecting the neighbor, infect it.
23478           infect(neighbor);
23479           // Ensure that the neighbor's neighbors will be infected.
23480           deadtet = (tetrahedron **) viri->alloc();
23481           *deadtet = neighbor.tet;
23482         } else {               // The neighbor is protected by a subface.
23483           // Remove this tetrahedron from the subface.
23484           stdissolve(neighsh);
23485           // The subface becomes a boundary.  Set markers accordingly.
23486           if (shellmark(neighsh) == 0) {
23487             setshellmark(neighsh, 1);
23488           }
23489           // This side becomes hull. Update the handle in dummytet.
23490           dummytet[0] = encode(neighbor);
23491         }
23492       }
23493     }
23494     // Remark the tetrahedron as infected, so it doesn't get added to the
23495     //   virus pool again.
23496     infect(testtet);
23497     virusloop = (tetrahedron **) viri->traverse();
23498   }
23499 }
23500 
23502 //                                                                           //
23503 // regionplague()    Spread regional attributes and/or volume constraints    //
23504 //                   (from a .poly file) throughout the mesh.                //
23505 //                                                                           //
23506 // This procedure operates in two phases.  The first phase spreads an attri- //
23507 // bute and/or a volume constraint through a (facet-bounded) region.  The    //
23508 // second phase uninfects all infected tetrahedra, returning them to normal. //
23509 //                                                                           //
23511 
23512 void tetgenmesh::
23513 regionplague(memorypool *regionviri, REAL attribute, REAL volume)
23514 {
23515   tetrahedron **virusloop;
23516   tetrahedron **regiontet;
23517   triface testtet, neighbor;
23518   face neighsh;
23519 
23520   if (b->verbose > 1) {
23521     printf("  Marking neighbors of marked tetrahedra.\n");
23522   }
23523   // Loop through all the infected tetrahedra, spreading the attribute
23524   //   and/or volume constraint to their neighbors, then to their neighbors'
23525   //   neighbors.
23526   regionviri->traversalinit();
23527   virusloop = (tetrahedron **) regionviri->traverse();
23528   while (virusloop != (tetrahedron **) NULL) {
23529     testtet.tet = *virusloop;
23530     // Temporarily uninfect this tetrahedron, not necessary.
23531     uninfect(testtet);
23532     if (b->regionattrib) {
23533       // Set an attribute.
23534       setelemattribute(testtet.tet, in->numberoftetrahedronattributes,
23535                        attribute);
23536     }
23537     if (b->varvolume) {
23538       // Set a volume constraint.
23539       setvolumebound(testtet.tet, volume);
23540     }
23541     // Check each of the tetrahedron's four neighbors.
23542     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23543       // Find the neighbor.
23544       sym(testtet, neighbor);
23545       // Check for a subface between the tetrahedron and its neighbor.
23546       tspivot(testtet, neighsh);
23547       // Make sure the neighbor exists, is not already infected, and
23548       //   isn't protected by a subface, or is protected by a nonsolid
23549       //   subface.
23550       if ((neighbor.tet != dummytet) && !infected(neighbor)
23551           && (neighsh.sh == dummysh)) {
23552         // Infect the neighbor.
23553         infect(neighbor);
23554         // Ensure that the neighbor's neighbors will be infected.
23555         regiontet = (tetrahedron **) regionviri->alloc();
23556         *regiontet = neighbor.tet;
23557       }
23558     }
23559     // Remark the tetrahedron as infected, so it doesn't get added to the
23560     //   virus pool again.
23561     infect(testtet);
23562     virusloop = (tetrahedron **) regionviri->traverse();
23563   }
23564 
23565   // Uninfect all tetrahedra.
23566   if (b->verbose > 1) {
23567     printf("  Unmarking marked tetrahedra.\n");
23568   }
23569   regionviri->traversalinit();
23570   virusloop = (tetrahedron **) regionviri->traverse();
23571   while (virusloop != (tetrahedron **) NULL) {
23572     testtet.tet = *virusloop;
23573     uninfect(testtet);
23574     virusloop = (tetrahedron **) regionviri->traverse();
23575   }
23576   // Empty the virus pool.
23577   regionviri->restart();
23578 }
23579 
23581 //                                                                           //
23582 // removeholetets()    Remove tetrahedra which are outside the domain.       //
23583 //                                                                           //
23585 
23586 void tetgenmesh::removeholetets(memorypool* viri)
23587 {
23588   tetrahedron **virusloop;
23589   triface testtet, neighbor;
23590   point checkpt;
23591   int *tetspernodelist;
23592   int i, j;
23593 
23594   if (b->verbose > 0) {
23595     printf("  Deleting marked tetrahedra.\n");
23596   }
23597 
23598   // Create and initialize 'tetspernodelist'.
23599   tetspernodelist = new int[points->items + 1];
23600   for (i = 0; i < points->items + 1; i++) tetspernodelist[i] = 0;
23601 
23602   // Loop the tetrahedra list, counter the number of tets sharing each node.
23603   tetrahedrons->traversalinit();
23604   testtet.tet = tetrahedrontraverse();
23605   while (testtet.tet != (tetrahedron *) NULL) {
23606     // Increment the number of sharing tets for each endpoint.
23607     for (i = 0; i < 4; i++) {
23608       j = pointmark((point) testtet.tet[4 + i]);
23609       tetspernodelist[j]++;
23610     }
23611     testtet.tet = tetrahedrontraverse();
23612   }
23613 
23614   viri->traversalinit();
23615   virusloop = (tetrahedron **) viri->traverse();
23616   while (virusloop != (tetrahedron **) NULL) {
23617     testtet.tet = *virusloop;
23618     // Record changes in the number of boundary faces, and disconnect
23619     //   dead tetrahedra from their neighbors.
23620     for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23621       sym(testtet, neighbor);
23622       if (neighbor.tet == dummytet) {
23623         // There is no neighboring tetrahedron on this face, so this face
23624         //   is a boundary face.  This tetrahedron is being deleted, so this
23625         //   boundary face is deleted.
23626         hullsize--;
23627       } else {
23628         // Disconnect the tetrahedron from its neighbor.
23629         dissolve(neighbor);
23630         // There is a neighboring tetrahedron on this face, so this face
23631         //   becomes a boundary face when this tetrahedron is deleted.
23632         hullsize++;
23633       }
23634     }
23635     // Check the four corners of this tet if they're isolated.
23636     for (i = 0; i < 4; i++) {
23637       checkpt = (point) testtet.tet[4 + i];
23638       j = pointmark(checkpt);
23639       tetspernodelist[j]--;
23640       if (tetspernodelist[j] == 0) {
23641         // If it is added volume vertex or '-j' is not used, delete it.
23642         if ((pointtype(checkpt) == FREEVOLVERTEX) || !b->nojettison) {
23643           setpointtype(checkpt, UNUSEDVERTEX);
23644           unuverts++;
23645         }
23646       }
23647     }
23648     // Return the dead tetrahedron to the pool of tetrahedra.
23649     tetrahedrondealloc(testtet.tet);
23650     virusloop = (tetrahedron **) viri->traverse();
23651   }
23652 
23653   delete [] tetspernodelist;
23654 }
23655 
23657 //                                                                           //
23658 // assignregionattribs()    Assign each tetrahedron a region number.         //
23659 //                                                                           //
23660 // This routine is called when '-AA' switch is specified.  Every tetrahedron //
23661 // of a (bounded) region will get a integer number to that region.  Default, //
23662 // regions are numbered as 1, 2, 3, etc. However, if a number has already    //
23663 // been used (set by user in the region section in .poly or .smesh), it is   //
23664 // skipped and the next available number will be used.                       //
23665 //                                                                           //
23667 
23668 void tetgenmesh::assignregionattribs()
23669 {
23670   list *regionnumlist;
23671   list *regiontetlist;
23672   triface tetloop, regiontet, neightet;
23673   face checksh;
23674   bool flag;
23675   int regionnum, num;
23676   int attridx, count;
23677   int i;
23678 
23679   if (b->verbose > 0) {
23680     printf("  Assign region numbers.\n");
23681   }
23682 
23683   regionnumlist = new list(sizeof(int), NULL, 256);
23684   regiontetlist = new list(sizeof(triface), NULL, 1024);
23685   attridx = in->numberoftetrahedronattributes;
23686 
23687   // Loop through all tets. Infect tets which already have a region number,
23688   //   and save the used numbers in 'regionnumlist'.
23689   tetrahedrons->traversalinit();
23690   tetloop.tet = tetrahedrontraverse();
23691   while (tetloop.tet != (tetrahedron *) NULL) {
23692     if (!infected(tetloop)) {
23693       regionnum = (int) elemattribute(tetloop.tet, attridx);
23694       if (regionnum != 0.0) {
23695         // Found a numbered region tet.
23696         infect(tetloop);
23697         regiontetlist->append(&tetloop);
23698         // Found and infect all tets in this region.
23699         for (i = 0; i < regiontetlist->len(); i++) {
23700           regiontet = * (triface *)(* regiontetlist)[i];
23701           for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23702             // Is there a boundary face?
23703             tspivot(regiontet, checksh);
23704             if (checksh.sh == dummysh) {
23705               sym(regiontet, neightet);
23706               if ((neightet.tet != dummytet) && !infected(neightet)) {
23707 #ifdef SELF_CHECK
23708                 // neightet should have the same region number. Check it.
23709                 num = (int) elemattribute(neightet.tet, attridx);
23710                 assert(num == regionnum);
23711 #endif
23712                 infect(neightet);
23713                 regiontetlist->append(&neightet);
23714               }
23715             }
23716           }
23717         }
23718         // Add regionnum to list if it is not exist.
23719         flag = false;
23720         for (i = 0; i < regionnumlist->len() && !flag; i++) {
23721           num = * (int *)(* regionnumlist)[i];
23722           flag = (num == regionnum);
23723         }
23724         if (!flag) regionnumlist->append(&regionnum);
23725         // Clear list for the next region.
23726         regiontetlist->clear();
23727       }
23728     }
23729     tetloop.tet = tetrahedrontraverse();
23730   }
23731 
23732   if (b->verbose > 0) {
23733     printf("  %d user-specified regions.\n", regionnumlist->len());
23734   }
23735 
23736   // Now loop the tets again. Assign region numbers to uninfected tets.
23737   tetrahedrons->traversalinit();
23738   tetloop.tet = tetrahedrontraverse();
23739   regionnum = 1;  // Start region number.
23740   count = 0;
23741   while (tetloop.tet != (tetrahedron *) NULL) {
23742     if (!infected(tetloop)) {
23743       // An unassigned region tet.
23744       count++;
23745       do {
23746         flag = false;
23747         // Check if the region number has been used.
23748         for (i = 0; i < regionnumlist->len() && !flag; i++) {
23749           num = * (int *)(* regionnumlist)[i];
23750           flag = (num == regionnum);
23751         }
23752         if (flag) regionnum++;
23753       } while (flag);
23754       setelemattribute(tetloop.tet, attridx, (REAL) regionnum);
23755       infect(tetloop);
23756       regiontetlist->append(&tetloop);
23757       // Found and infect all tets in this region.
23758       for (i = 0; i < regiontetlist->len(); i++) {
23759         regiontet = * (triface *)(* regiontetlist)[i];
23760         for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23761           // Is there a boundary face?
23762           tspivot(regiontet, checksh);
23763           if (checksh.sh == dummysh) {
23764             sym(regiontet, neightet);
23765             if ((neightet.tet != dummytet) && !infected(neightet)) {
23766 #ifdef SELF_CHECK
23767               // neightet should have not been assigned yet. Check it.
23768               num = (int) elemattribute(neightet.tet, attridx);
23769               assert(num == 0);
23770 #endif
23771               setelemattribute(neightet.tet, attridx, (REAL) regionnum);
23772               infect(neightet);
23773               regiontetlist->append(&neightet);
23774             }
23775           }
23776         }
23777       }
23778       regiontetlist->clear();
23779       regionnum++; // The next region number.
23780     }
23781     tetloop.tet = tetrahedrontraverse();
23782   }
23783 
23784   // Uninfect all tets.
23785   tetrahedrons->traversalinit();
23786   tetloop.tet = tetrahedrontraverse();
23787   while (tetloop.tet != (tetrahedron *) NULL) {
23788 #ifdef SELF_CHECK
23789     assert(infected(tetloop));
23790 #endif
23791     uninfect(tetloop);
23792     tetloop.tet = tetrahedrontraverse();
23793   }
23794 
23795   if (b->verbose > 0) {
23796     printf("  %d regions are numbered.\n", count);
23797   }
23798 
23799   delete regionnumlist;
23800   delete regiontetlist;
23801 }
23802 
23804 //                                                                           //
23805 // carveholes()    Find the holes and infect them.  Find the volume          //
23806 //                 constraints and infect them.  Infect the convex hull.     //
23807 //                 Spread the infection and kill tetrahedra.  Spread the     //
23808 //                 volume constraints.                                       //
23809 //                                                                           //
23810 // This routine mainly calls other routines to carry out all these functions.//
23811 //                                                                           //
23813 
23814 void tetgenmesh::carveholes()
23815 {
23816   memorypool *holeviri, *regionviri;
23817   tetrahedron *tptr, **holetet, **regiontet;
23818   triface searchtet, *holetets, *regiontets;
23819   enum locateresult intersect;
23820   int i;
23821 
23822   if (!b->quiet) {
23823     printf("Removing unwanted tetrahedra.\n");
23824     if (b->verbose && (in->numberofholes > 0)) {
23825       printf("  Marking holes for elimination.\n");
23826     }
23827   }
23828 
23829   // Initialize a pool of viri to be used for holes, concavities.
23830   holeviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23831   // Mark as infected any unprotected tetrahedra on the boundary.
23832   infecthull(holeviri);
23833 
23834   if (in->numberofholes > 0) {
23835     // Allocate storage for the tetrahedra in which hole points fall.
23836     holetets = (triface *) new triface[in->numberofholes];
23837     // Infect each tetrahedron in which a hole lies.
23838     for (i = 0; i < 3 * in->numberofholes; i += 3) {
23839       // Ignore holes that aren't within the bounds of the mesh.
23840       if ((in->holelist[i] >= xmin) && (in->holelist[i] <= xmax)
23841           && (in->holelist[i + 1] >= ymin)
23842           && (in->holelist[i + 1] <= ymax)
23843           && (in->holelist[i + 2] >= zmin)
23844           && (in->holelist[i + 2] <= zmax)) {
23845         searchtet.tet = dummytet;
23846         // Find a tetrahedron that contains the hole.
23847         intersect = locate(&in->holelist[i], &searchtet);
23848         if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23849           // Record the tetrahedron for processing carve hole.
23850           holetets[i / 3] = searchtet;
23851         }
23852       }
23853     }
23854     // Infect the hole tetrahedron.  This is done by marking the tet as
23855     //   infected and including the tetrahedron in the virus pool.
23856     for (i = 0; i < in->numberofholes; i++) {
23857       infect(holetets[i]);
23858       holetet = (tetrahedron **) holeviri->alloc();
23859       *holetet = holetets[i].tet;
23860     }
23861     // Free up memory.
23862     delete [] holetets;
23863   }
23864 
23865   // Mark as infected all tets of the holes and concavities.
23866   plague(holeviri);
23867   // The virus pool contains all outside tets now.
23868 
23869   // Is -A switch in use.
23870   if (b->regionattrib) {
23871     // Assign every tetrahedron a regional attribute of zero.
23872     tetrahedrons->traversalinit();
23873     tptr = tetrahedrontraverse();
23874     while (tptr != (tetrahedron *) NULL) {
23875       setelemattribute(tptr, in->numberoftetrahedronattributes, 0.0);
23876       tptr = tetrahedrontraverse();
23877     }
23878   }
23879 
23880   if (in->numberofregions > 0) {
23881     if (!b->quiet) {
23882       if (b->regionattrib) {
23883         if (b->varvolume) {
23884           printf("Spreading regional attributes and volume constraints.\n");
23885         } else {
23886           printf("Spreading regional attributes.\n");
23887         }
23888       } else {
23889         printf("Spreading regional volume constraints.\n");
23890       }
23891     }
23892     // Allocate storage for the tetrahedra in which region points fall.
23893     regiontets = (triface *) new triface[in->numberofregions];
23894     // Find the starting tetrahedron for each region.
23895     for (i = 0; i < in->numberofregions; i++) {
23896       regiontets[i].tet = dummytet;
23897       // Ignore region points that aren't within the bounds of the mesh.
23898       if ((in->regionlist[5 * i] >= xmin)
23899            && (in->regionlist[5 * i] <= xmax)
23900            && (in->regionlist[5 * i + 1] >= ymin)
23901            && (in->regionlist[5 * i + 1] <= ymax)
23902            && (in->regionlist[5 * i + 2] >= zmin)
23903            && (in->regionlist[5 * i + 2] <= zmax)) {
23904         searchtet.tet = dummytet;
23905         // Find a tetrahedron that contains the region point.
23906         intersect = locate(&in->regionlist[5 * i], &searchtet);
23907         if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23908           // Record the tetrahedron for processing after the
23909           //   holes have been carved.
23910           regiontets[i] = searchtet;
23911         }
23912       }
23913     }
23914     // Initialize a pool to be used for regional attrs, and/or regional
23915     //   volume constraints.
23916     regionviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23917     // Find and set all regions.
23918     for (i = 0; i < in->numberofregions; i++) {
23919       if (regiontets[i].tet != dummytet) {
23920         // Make sure the tetrahedron under consideration still exists.
23921         //   It may have been eaten by the virus.
23922         if (!isdead(&(regiontets[i]))) {
23923           // Put one tetrahedron in the virus pool.
23924           infect(regiontets[i]);
23925           regiontet = (tetrahedron **) regionviri->alloc();
23926           *regiontet = regiontets[i].tet;
23927           // Apply one region's attribute and/or volume constraint.
23928           regionplague(regionviri, in->regionlist[5 * i + 3],
23929                        in->regionlist[5 * i + 4]);
23930           // The virus pool should be empty now.
23931         }
23932       }
23933     }
23934     // Free up memory.
23935     delete [] regiontets;
23936     delete regionviri;
23937   }
23938 
23939   // Now acutually remove the outside and hole tets.
23940   removeholetets(holeviri);
23941   // The mesh is nonconvex now.
23942   nonconvex = 1;
23943 
23944   if (b->regionattrib) {
23945     if (b->regionattrib > 1) {
23946       // -AA switch. Assign each tet a region number (> 0).
23947       assignregionattribs();
23948     }
23949     // Note the fact that each tetrahedron has an additional attribute.
23950     in->numberoftetrahedronattributes++;
23951   }
23952 
23953   // Free up memory.
23954   delete holeviri;
23955 }
23956 
23957 //
23958 // End of carving out holes and concavities routines
23959 //
23960 
23961 //
23962 // Begin of boundary Steiner points removing routines
23963 //
23964 
23966 //                                                                           //
23967 // replacepolygonsubs()    Substitute the subfaces of a polygon.             //
23968 //                                                                           //
23969 // 'oldshlist' (T_old) contains the old subfaces of P.  It will be replaced  //
23970 // by 'newshlist' (T_new) of new subfaces. Each boundary edge of P is bonded //
23971 // to 'dummysh' in T_new.                                                    //
23972 //                                                                           //
23973 // Notice that Not every boundary edge of T_new is able to bond to a subface,//
23974 // e.g., when it is a segment recovered by removing a Steiner point in it.   //
23975 //                                                                           //
23977 
23978 void tetgenmesh::replacepolygonsubs(list* oldshlist, list* newshlist)
23979 {
23980   face newsh, oldsh, spinsh;
23981   face casingout, casingin;
23982   face checkseg;
23983   point pa, pb;
23984   int i, j, k, l;
23985 
23986   for (i = 0; i < newshlist->len(); i++) {
23987     // Get a new subface s.
23988     newsh = * (face *)(* newshlist)[i];
23989     // Check the three edges of s.
23990     for (k = 0; k < 3; k++) {
23991       spivot(newsh, casingout);
23992       // Is it a boundary edge?
23993       if (casingout.sh == dummysh) {
23994         // Find the old subface s_o having the same edge as s.
23995         pa = sorg(newsh);
23996         pb = sdest(newsh);
23997         for (j = 0; j < oldshlist->len(); j++) {
23998           oldsh = * (face *)(* oldshlist)[j];
23999       for (l = 0; l < 3; l++) {
24000             if (((sorg(oldsh) == pa) && (sdest(oldsh) == pb)) ||
24001                 ((sorg(oldsh) == pb) && (sdest(oldsh) == pa))) break;
24002             senextself(oldsh);
24003           }
24004           if (l < 3) break;
24005         }
24006         // Is there a matched edge?
24007         if (j < oldshlist->len()) {
24008           // Get the neighbor subface s_out.
24009           spivot(oldsh, casingout);
24010           sspivot(oldsh, checkseg);
24011           if (checkseg.sh != dummysh) {
24012             // A segment. Insert s into the face ring, ie, s_in -> s -> s_out.
24013             if (oldsh.sh != casingout.sh) {
24014               // s is not bonded to itself.
24015               spinsh = casingout;
24016               do {
24017                 casingin = spinsh;
24018                 spivotself(spinsh);
24019               } while (sapex(spinsh) != sapex(oldsh));
24020               assert(casingin.sh != oldsh.sh);
24021               // Bond s_in -> s -> s_out (and dissolve s_in -> s_old -> s_out).
24022               sbond1(casingin, newsh);
24023               sbond1(newsh, casingout);
24024             } else {
24025               // Bond newsh -> newsh.
24026               sbond(newsh, newsh);
24027             }
24028             // Bond the segment.
24029             ssbond(newsh, checkseg);
24030           } else {
24031             // Bond s <-> s_out (and dissolve s_out -> s_old).
24032             sbond(newsh, casingout);
24033           }
24034           // Unbound oldsh to indicate it's neighbor has been replaced.
24035           //   It will be used to indentfy the edge in the inverse.
24036           sdissolve(oldsh);
24037           ssdissolve(oldsh);
24038         }
24039       }
24040       // Go to the next edge of s.
24041       senextself(newsh);
24042     }
24043   }
24044 }
24045 
24047 //                                                                           //
24048 // orientnewsubs()    Orient new subfaces facing to the inside of cavity.    //
24049 //                                                                           //
24050 // 'newshlist' contains new subfaces of the cavity C (created by re-triangu- //
24051 // lation the polygon P). They're not necessary facing to the inside of C.   //
24052 // 'orientsh', faces to the inside of C, is used to adjust new subfaces. The //
24053 // normal of the new subfaces is returned in 'norm'.                         //
24054 //                                                                           //
24056 
24057 void tetgenmesh::orientnewsubs(list* newshlist, face* orientsh, REAL* norm)
24058 {
24059   face *newsh;
24060   point pa, pb, pc;
24061   REAL ref[3], ori, len;
24062   int i;
24063 
24064   // Calculate the normal of 'orientsh'.
24065   pa = sorg(*orientsh);
24066   pb = sdest(*orientsh);
24067   pc = sapex(*orientsh);
24068   facenormal(pa, pb, pc, norm, &len);
24069   for (i = 0; i < 3; i++) ref[i] = pa[i] + norm[i];
24070   for (i = 0; i < 3; i++) norm[i] /= len;
24071 
24072   // Orient new subfaces. Let the normal above each one.
24073   for (i = 0; i < newshlist->len(); i++) {
24074     newsh = (face *)(* newshlist)[i];
24075     pa = sorg(*newsh);
24076     pb = sdest(*newsh);
24077     pc = sapex(*newsh);
24078     ori = orient3d(pa, pb, pc, ref);
24079     assert(ori != 0.0);
24080     if (ori > 0.0) {
24081       sesymself(*newsh);
24082     }
24083   }
24084 }
24085 
24087 //                                                                           //
24088 // constrainedflip()    Flip a non-constrained face.                         //
24089 //                                                                           //
24090 // 'flipface' f (abc) is a face we want to flip. In addition, if 'front' is  //
24091 // given (not a NULL), f is a crossface. f may not be flippable if it is one //
24092 // of the following cases:                                                   //
24093 //   (1) f has an aux subface attached;                                      //
24094 //   (2) f is on the convex hull;                                            //
24095 //   (3) f is not locally Delaunay (f must be recovered by a previous flip,  //
24096 //       we should keep it, otherwise, we may fall into a flip loop);        //
24097 //   (4) f is T32 at ab, but abd or abe has an aux subface attached;         //
24098 //   (5) f is T22 or T44 at ab, but abd, or abe, or abf has an aux subface   //
24099 //       attached;                                                           //
24100 //   (6) f is unflipable at ab, and abd, abe, ... are all unflippable due to //
24101 //       the cases (1) - (5).                                                //
24102 // If f is a crssface ('front' != NULL) and it is unflipable due to case (3),//
24103 // (4), (5) and (6). Try to flip the next crossing face of front first.      //
24104 //                                                                           //
24106 
24107 bool tetgenmesh::constrainedflip(triface* flipface, triface* front,
24108   queue* flipque)
24109 {
24110   triface symface, spintet;
24111   face checksh;
24112   point pa, pb, pc, pd, pe;
24113   enum fliptype fc;
24114   REAL sign;
24115   bool doflip;
24116   int ia, ib, ic, id, ie;
24117   int i;
24118 
24119   // (1) Is f protected by an (auxilary) subface?
24120   tspivot(*flipface, checksh);
24121   if (checksh.sh != dummysh) return false;
24122   // (2) Is f on the convex hull?
24123   sym(*flipface, symface);
24124   if (symface.tet == dummytet) return false;
24125   // (3) Is f not locally Delaunay?
24126   adjustedgering(*flipface, CCW);
24127   pa = dest(*flipface);
24128   pb = org(*flipface);
24129   pc = apex(*flipface);
24130   pd = oppo(*flipface);
24131   pe = oppo(symface);
24132   // if (symbolic) {
24133     ia = pointmark(pa);
24134     ib = pointmark(pb);
24135     ic = pointmark(pc);
24136     id = pointmark(pd);
24137     ie = pointmark(pe);
24138     sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24139     assert(sign != 0.0);
24140   // } else {
24141   //   sign = insphere(pa, pb, pc, pd, pe);
24142   // }
24143   if (sign <= 0.0) {
24144     // Get the fliptype of f.
24145     checksubfaces = 0; // switch off subface test.
24146     fc = categorizeface(*flipface);
24147     checksubfaces = 1; // switch on subface test.
24148     if (fc == T23) {
24149       doflip = true;
24150       // Avoid one tet created by the 2-3 flip is nearly degenerate.
24151       /* pc = oppo(*flipface);
24152       pd = oppo(symface);
24153       adjustedgering(*flipface, CCW);
24154       for (i = 0; i < 3; i++) {
24155         pa = org(*flipface);
24156         pb = dest(*flipface);
24157         ori = orient3d(pa, pb, pc, pd);
24158         if (iscoplanar(pa, pb, pc, pd, ori, b->epsilon)) {
24159           doflip = false; break;
24160         }
24161         enextself(*flipface);
24162       } */
24163       if (doflip) {
24164         flip23(flipface, flipque);
24165         return true;
24166       }
24167     } else if (fc == T32) {
24168       // (4) Is abd, or abe protected?
24169       doflip = true;
24170       spintet = *flipface;
24171       for (i = 0; i < 2; i++) {
24172         fnextself(spintet);
24173         tspivot(spintet, checksh);
24174         if (checksh.sh != dummysh) {
24175           doflip = false; break; // f is protected. Unflipable.
24176         }
24177       }
24178       if (doflip) {
24179         flip32(flipface, flipque);
24180         return true;
24181       }
24182     } else if (fc == T22 || fc == T44) {
24183       // (5) Is abd, abe, or abf protected?
24184       doflip = true;
24185       if (fc == T22) {
24186         for (i = 0; i < 2; i++) {
24187           spintet = *flipface;
24188           if (i == 1) {
24189             esymself(spintet);
24190           }
24191           fnextself(spintet);
24192           tspivot(spintet, checksh);
24193           if (checksh.sh != dummysh) {
24194             doflip = false; break; // f is protected. Unflipable.
24195           }
24196         }
24197       } else if (fc == T44) {
24198         spintet = *flipface;
24199         for (i = 0; i < 3; i++) {
24200           fnextself(spintet);
24201           tspivot(spintet, checksh);
24202           if (checksh.sh != dummysh) {
24203             doflip = false; break; // f is protected. Unflipable.
24204           }
24205         }
24206       }
24207       if (doflip) {
24208         flip22(flipface, flipque);
24209         return true;
24210       }
24211     } else if (fc == N32) {
24212       // Is f a crossface?
24213       if (front != (triface *) NULL) {
24214         // (6) Is any obstacle face (abd, or abe, ...) flipable?
24215         spintet = *flipface;
24216         while (fnextself(spintet)) {
24217           if (apex(spintet) == apex(*flipface)) break;
24218           // Check if spintet is flipable, no recursive.
24219           if (constrainedflip(&spintet, NULL, flipque)) {
24220             // One obstacle face has been flipped.
24221             return true;
24222           }
24223           // Unflipable. Go to the next obstacle face.
24224           findedge(&spintet, org(*flipface), dest(*flipface));
24225         }
24226       }
24227     }
24228   }
24229 
24230   // f is unflipable. Is f a crossface?
24231   if (front != (triface *) NULL) {
24232     // Look if there is another crossface.
24233     pa = org(*front);
24234     pb = dest(*front);
24235     pc = apex(*front);
24236     // sym(*flipface, symface);
24237     // Have we reach the end of abc (We've started from edge ab).
24238     if (oppo(symface) != pc) {
24239       adjustedgering(symface, CCW);
24240       for (i = 0; i < 3; i++) {
24241         fnext(symface, spintet);
24242         // Is c ahead of this face?
24243         sign = orient3d(org(spintet), dest(spintet), apex(spintet), pc);
24244         if (sign < 0.0) {
24245           if (tritritest(&spintet, pa, pb, pc)) {
24246             if (b->verbose > 2) {
24247               printf("    Next crossface (%d, %d, %d).\n",
24248                      pointmark(org(spintet)), pointmark(dest(spintet)),
24249                      pointmark(apex(spintet)));
24250             }
24251             return constrainedflip(&spintet, front, flipque);
24252             // return constrainedflip(&spintet, NULL, flipque);
24253           }
24254         }
24255         enextself(symface);
24256       }
24257     }
24258   }
24259   return false;
24260 }
24261 
24263 //                                                                           //
24264 // recoverfront()    Recover a missing front by flips.                       //
24265 //                                                                           //
24266 // 'front' f is missing in D - it was crossed by faces of D. The cross faces //
24267 // may be flippable, so f can be recovered by flipping them away.            //
24268 //                                                                           //
24270 
24271 bool tetgenmesh::recoverfront(triface* front, list* newtetlist, queue* flipque)
24272 {
24273   triface idfront, starttet, spintet;
24274   point pa, pb, pc, pd, ref;
24275   enum locateresult loc;
24276   enum finddirectionresult col;
24277   REAL ori, ori1, ori2, sign;
24278   int hitbdry;
24279   int i, j;
24280 
24281   // Find an existing edge of f in D to start with.
24282   for (i = 0; i < 3; i++) {
24283     pa = org(*front);
24284     pb = dest(*front);
24285     // Get a tet for searching.
24286     idfront = recenttet;
24287     // Make sure the tet is valid (flip32() may kill a tet).
24288     if (isdead(&idfront)) {
24289       // The tet is dead. Get a live tet in D. !!!
24290       for (j = 0; j < newtetlist->len(); j++) {
24291         recenttet = * (triface *)(* newtetlist)[j];
24292         if (!isdead(&recenttet)) break;
24293       }
24294       assert(j < newtetlist->len());
24295     }
24296     loc = preciselocate(pa, &idfront, (long) newtetlist->len());
24297     if (loc != ONVERTEX) {
24298       // Do a brute-force search in D.
24299       for (j = 0; j < newtetlist->len(); j++) {
24300         idfront = * (triface *)(* newtetlist)[j];
24301         if (isdead(&idfront)) continue;
24302         if (findorg(&idfront, pa)) break;
24303       }
24304       assert(j < newtetlist->len()); // a must belong to one tet.
24305     }
24306     recenttet = idfront;
24307     // Search for a tet having edge ab.
24308     col = finddirection(&idfront, pb, (long) newtetlist->len());
24309     if (col == BELOWHULL) {
24310       // Do a brute-force search in D.
24311       for (j = 0; j < newtetlist->len(); j++) {
24312         idfront = * (triface *)(* newtetlist)[j];
24313         if (isdead(&idfront)) continue;
24314         if (findorg(&idfront, pa)) {
24315           assert(org(idfront) == pa);
24316           if (dest(idfront) == pb) {
24317             col = RIGHTCOLLINEAR; break;
24318           } else if (apex(idfront) == pb) {
24319             col = LEFTCOLLINEAR; break;
24320           } else if (oppo(idfront) == pb) {
24321             col = TOPCOLLINEAR; break;
24322           }
24323         }
24324       }
24325     }
24326     if (col == RIGHTCOLLINEAR) {
24327       // b is just the destination.
24328     } else if (col == LEFTCOLLINEAR) {
24329       enext2self(idfront);
24330       esymself(idfront);
24331     } else if (col == TOPCOLLINEAR) {
24332       fnextself(idfront);
24333       enext2self(idfront);
24334       esymself(idfront);
24335     }
24336     if (dest(idfront) == pb) break; // Found.
24337     // Missing. Go to the next edge of f.
24338     enextself(*front);
24339   }
24340   if (i == 3) {
24341     // All three edges of f are missing - unrecoverable.
24342     return false;
24343   }
24344 
24345   // Search for a tet having f (abc).
24346   pc = apex(*front);
24347   spintet = idfront;
24348   hitbdry = 0;
24349   do {
24350     if (apex(spintet) == pc) {
24351       // Found abc. Insert an auxilary subface s at idfront.
24352       insertauxsubface(front, &spintet);
24353       return true;
24354     }
24355     if (!fnextself(spintet)) {
24356       hitbdry ++;
24357       if (hitbdry < 2) {
24358         esym(idfront, spintet);
24359         if (!fnextself(spintet)) {
24360           hitbdry ++;
24361         }
24362       }
24363     }
24364     if (apex(spintet) == apex(idfront)) break;
24365   } while (hitbdry < 2);
24366 
24367   // Search for a crossing face to flip.
24368   pd = apex(idfront);
24369   assert(pd != pc);
24370   // Decide the orientation of d with abc.
24371   ori = orient3d(pa, pb, pc, pd);
24372   if (ori < 0.0) {
24373     // d is above abc. Rotate downwards.
24374     esym(idfront, starttet);
24375     sign = -1.0;
24376   } else if (ori > 0.0) {
24377     // d is below abc. Rotate upwards.
24378     starttet = idfront;
24379     sign = 1.0;
24380   } else {
24381     assert(ori == 0.0);
24382     // d is coplanar with abc. Do abc and abd intersect?
24383     ref = oppo(idfront);
24384     ori1 = orient3d(pa, pb, ref, pc);
24385     ori2 = orient3d(pa, pb, ref, pd);
24386     assert(ori1 * ori2 != 0.0);
24387     if (ori1 * ori2 > 0) {
24388       // abc and abd intersect.  There're two possible intersections:
24389       //   ad and bc, or ac and bd.  Find it out.
24390       ori1 = orient3d(pb, pc, ref, pd);
24391       ori2 = orient3d(pb, pc, ref, pa);
24392       assert(ori1 * ori2 != 0.0);
24393       if (ori1 * ori2 > 0) {
24394         // ac intersects bd.
24395         enextself(idfront); // go to edge bd.
24396       } else {
24397         // ad intersects bc.
24398         enext2self(idfront); // go to edge ad.
24399       }
24400       adjustedgering(idfront, CCW);
24401       fnextself(idfront); // face ade or bce need a 4-to-4 flip.
24402       if (b->verbose > 2) {
24403         printf("    Get crossface (%d, %d, %d).\n", pointmark(org(idfront)),
24404                pointmark(dest(idfront)), pointmark(apex(idfront)));
24405       }
24406       if (constrainedflip(&idfront, front, flipque)) {
24407         // A crossface has been flipped. Continue to recover f.
24408         return recoverfront(front, newtetlist, flipque);
24409       }
24410       // Unable to recover f.
24411       return false; // sign = 0.0;
24412     } else {
24413       // Not intersect. We can go either direction.
24414       starttet = idfront;
24415       if (fnextself(starttet)) {
24416         // Choose to rotate upwards.
24417         sign = 1.0;
24418       } else {
24419         // Hit convex hull. Choose to rotate downwrads.
24420         esym(idfront, starttet);
24421         sign = -1.0;
24422       }
24423     }
24424   }
24425 
24426   assert(sign != 0.0);
24427   if (sign == -1) {
24428     // The edge ab has be changed. Reverse it.
24429     pa = org(starttet);
24430     pb = dest(starttet);
24431     // The sign has been reversed as well.
24432     sign = -sign;
24433   }
24434   // Rotate face abd around edge ab. Moreover, we've chosen the rotate
24435   //   direction such that no convex hull face will be reach.
24436   spintet = starttet;
24437   while (fnextself(spintet)) {
24438     pd = apex(spintet);
24439     assert(pd != pc);
24440     // Check if the orientation of d (with abc) has changed.
24441     ori = orient3d(pa, pb, pc, pd);
24442     if (ori == 0.0) {
24443       // abc and abd must coplanar intersect (4-to-4 flip is needed).
24444       ref = oppo(spintet);
24445       ori1 = orient3d(pb, pc, ref, pd);
24446       ori2 = orient3d(pb, pc, ref, pa);
24447       assert(ori1 * ori2 != 0.0);
24448       if (ori1 * ori2 > 0) {
24449         // ac intersects bd.
24450         enextself(spintet); // go to edge bd.
24451       } else {
24452         // ad intersects bc.
24453         enext2self(spintet); // go to edge ad.
24454       }
24455       adjustedgering(spintet, CCW);
24456       fnextself(spintet); // face ade or bce need a 4-to-4 flip.
24457       if (b->verbose > 2) {
24458         printf("    Get crossface (%d, %d, %d).\n", pointmark(org(spintet)),
24459                pointmark(dest(spintet)), pointmark(apex(spintet)));
24460       }
24461       if (constrainedflip(&spintet, front, flipque)) {
24462         // A crossface has been flipped. Continue to recover f.
24463         return recoverfront(front, newtetlist, flipque);
24464       }
24465       // Unable to recover f.
24466       return false; // sign = 0.0;
24467     } else if (ori * sign < 0.0) {
24468       // Sign has changed. The face dea or deb must cross abc.
24469       adjustedgering(spintet, CCW);
24470       enextself(spintet);
24471       for (i = 0; i < 2; i++) {
24472         // Get the face dea or deb.
24473         fnext(spintet, starttet);
24474         if (tritritest(&starttet, pa, pb, pc)) {
24475           if (b->verbose > 2) {
24476             printf("    Get crossface (%d, %d, %d).\n",
24477                    pointmark(org(starttet)), pointmark(dest(starttet)),
24478                    pointmark(apex(starttet)));
24479           }
24480           if (constrainedflip(&starttet, front, flipque)) {
24481             // A crossface has been flipped. Continue to recover f.
24482             return recoverfront(front, newtetlist, flipque);
24483           }
24484         }
24485         enextself(spintet);
24486       }
24487       // Unable to recover f.
24488       return false;
24489     }
24490   }
24491   // Impossible to be here.
24492   assert(0);
24493   return false;
24494 }
24495 
24497 //                                                                           //
24498 // repairflips()    Flip non-Delaunay and non-constrained faces.             //
24499 //                                                                           //
24501 
24502 void tetgenmesh::repairflips(queue* flipque)
24503 {
24504   badface *qface;
24505   triface flipface, symface, spintet;
24506   face checksh;
24507   point pa, pb, pc, pd, pe;
24508   enum fliptype fc;
24509   REAL sign;
24510   long flipcount;
24511   bool doflip;
24512   int ia, ib, ic, id, ie;
24513   int i;
24514 
24515   if (b->verbose > 1) {
24516     printf("    Repair flip %ld faces.\n", flipque->len());
24517   }
24518   flipcount = flip23s + flip32s + flip22s + flip44s;
24519   // Loop until the queue is empty.
24520   while (!flipque->empty()) {
24521     qface = (badface *) flipque->pop();
24522     flipface = qface->tt;
24523     // Check the validity of this face.
24524     if (isdead(&flipface) || flipface.tet == dummytet ||
24525         (org(flipface) != qface->forg) ||
24526         (dest(flipface) != qface->fdest) ||
24527         (apex(flipface) != qface->fapex) ||
24528         (oppo(flipface) == (point) NULL)) continue;
24529     // (1) Is f protected by an (auxilary) subface?
24530     tspivot(flipface, checksh);
24531     if (checksh.sh != dummysh) continue;
24532     // (2) Is f on the convex hull?
24533     sym(flipface, symface);
24534     if (symface.tet == dummytet) continue;
24535     // For positive orientation that insphere() test requires.
24536     adjustedgering(flipface, CW);
24537     pa = org(flipface);
24538     pb = dest(flipface);
24539     pc = apex(flipface);
24540     pd = oppo(flipface);
24541     pe = oppo(symface);
24542     // if (symbolic) {
24543       ia = pointmark(pa);
24544       ib = pointmark(pb);
24545       ic = pointmark(pc);
24546       id = pointmark(pd);
24547       ie = pointmark(pe);
24548       sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24549       assert(sign != 0.0);
24550     // } else {
24551     //   sign = insphere(pa, pb, pc, pd, pe);
24552     // }
24553     if (sign > 0.0) {
24554       // f is non-lcally Delaunay. Get the fliptype of f.
24555       checksubfaces = 0; // switch off subface test.
24556       fc = categorizeface(flipface);
24557       checksubfaces = 1; // switch on subface test.
24558       if (fc == T23) {
24559         doflip = true;
24560         // Avoid to create a nearly degenerate tet.
24561         /* pc = oppo(flipface);
24562         pd = oppo(symface);
24563         adjustedgering(flipface, CCW);
24564         for (i = 0; i < 3; i++) {
24565           pa = org(flipface);
24566           pb = dest(flipface);
24567           ori = orient3d(pa, pb, pc, pd);
24568           if (iscoplanar(pa, pb, pc, pd, ori, b->epsilon)) {
24569             doflip = false; break;
24570           }
24571           enextself(flipface);
24572         } */
24573         if (doflip) {
24574           flip23(&flipface, flipque);
24575         }
24576       } else if (fc == T32) {
24577         // (4) Is abd, or abe protected?
24578         doflip = true;
24579         spintet = flipface;
24580         for (i = 0; i < 2; i++) {
24581           fnextself(spintet);
24582           tspivot(spintet, checksh);
24583           if (checksh.sh != dummysh) {
24584             doflip = false; break; // f is protected. Unflipable.
24585           }
24586         }
24587         if (doflip) {
24588           flip32(&flipface, flipque);
24589         }
24590       } else if (fc == T22 || fc == T44) {
24591         // (5) Is abd, abe, or abf protected?
24592         doflip = true;
24593         if (fc == T22) {
24594           for (i = 0; i < 2; i++) {
24595             spintet = flipface;
24596             if (i == 1) {
24597               esymself(spintet);
24598             }
24599             fnextself(spintet);
24600             tspivot(spintet, checksh);
24601             if (checksh.sh != dummysh) {
24602               doflip = false; break; // f is protected. Unflipable.
24603             }
24604           }
24605         } else if (fc == T44) {
24606           spintet = flipface;
24607           for (i = 0; i < 3; i++) {
24608             fnextself(spintet);
24609             tspivot(spintet, checksh);
24610             if (checksh.sh != dummysh) {
24611               doflip = false; break; // f is protected. Unflipable.
24612             }
24613           }
24614         }
24615         if (doflip) {
24616           flip22(&flipface, flipque);
24617         }
24618       }
24619     }
24620   }
24621   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
24622   if (b->verbose > 1) {
24623     printf("    %ld flips.\n", flipcount);
24624   }
24625 }
24626 
24628 //                                                                           //
24629 // constrainedcavity()    Tetrahedralize a cavity by constrained tetrahedra. //
24630 //                                                                           //
24631 // The cavity C is bounded by faces F in 'floorlist' and 'ceillist'. 'ptlist'//
24632 // V is the set of vertices of C.                                            //
24633 //                                                                           //
24635 
24636 bool tetgenmesh::constrainedcavity(triface* oldtet, list* floorlist,
24637   list* ceillist, list* ptlist, list* frontlist, list* misfrontlist,
24638   list* newtetlist, queue* flipque)
24639 {
24640   triface misfront, newtet;
24641   long facenum;
24642   int i;
24643 
24644   if (b->verbose > 1) {
24645     printf("    Constrained cavity (%d floors, %d ceilings, %d vertices).\n",
24646            floorlist->len(), ceillist->len(), ptlist->len());
24647   }
24648 
24649   // symbolic = 1;
24650 
24651   // Initialize the cavity C.
24652   initializecavity(floorlist, ceillist, frontlist);
24653   // Form the D of the vertices of C.
24654   delaunizecavvertices(oldtet, ptlist, NULL, newtetlist, flipque);
24655 
24656   // Identify faces of C in D.
24657   if (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
24658     // Some faces are missing.
24659     recenttet = * (triface *)(* newtetlist)[0];
24660     assert((recenttet.tet != dummytet) && !isdead(&recenttet));
24661     // Try to recover missing faces by flips.
24662     do {
24663       facenum = misfrontlist->len();
24664       for (i = 0; i < misfrontlist->len(); i++) {
24665         // Get a missing front f.
24666         misfront = * (triface *)(* misfrontlist)[i];
24667         // Let f face toward the inside of C.
24668         adjustedgering(misfront, CW);
24669         if (b->verbose > 1) {
24670           printf("    Recover face (%d, %d, %d).\n", pointmark(org(misfront)),
24671                  pointmark(dest(misfront)), pointmark(apex(misfront)));
24672         }
24673         if (recoverfront(&misfront, newtetlist, flipque)) {
24674           // f has been recovered.
24675           frontlist->append(&misfront);
24676           misfrontlist->del(i, 0); i--;
24677         }
24678         // Flip non-locally non-constrained Delaunay faces.
24679         repairflips(flipque);
24680       }
24681       // Have all faces been recovered?
24682       if (misfrontlist->len() == 0) break;
24683       // No! There are still un-recovered faces. Continue the loop if any
24684       //   face has been recovered.
24685     } while (misfrontlist->len() < facenum);
24686     // Retrieve new tets and purge dead tets in D.
24687     retrievenewtets(newtetlist);
24688   }
24689 
24690   // symbolic = 0;
24691 
24692   if (misfrontlist->len() == 0) {
24693     // All fronts have identified in D. Get the shape of C by removing out
24694     //   tets of C. 'misfrontlist' is reused for removing out tets.
24695     //   Don't do flip since the new tets may get deleted later.
24696     carvecavity(newtetlist, misfrontlist, NULL);
24697     // Recover locally Delaunay faces.
24698     // flip(flipque, NULL);
24699     return true;
24700   } else {
24701     // Fail to tetrahedralize C.
24702     // Remove aux subfaces.
24703     detachauxsubfaces(newtetlist);
24704     // Remove new tets.
24705     for (i = 0; i < newtetlist->len(); i++) {
24706       newtet = * (triface *)(* newtetlist)[i];
24707       assert(!isdead(&newtet));
24708       tetrahedrondealloc(newtet.tet);
24709     }
24710     newtetlist->clear();
24711     // Restore faces of C in frontlist.
24712     for (i = 0; i < misfrontlist->len(); i++) {
24713       misfront = * (triface *)(* misfrontlist)[i];
24714       frontlist->append(&misfront);
24715     }
24716     return false;
24717   }
24718 }
24719 
24721 //                                                                           //
24722 // expandsteinercavity()    Expand the cavity of a Steiner point.            //
24723 //                                                                           //
24724 // Expand the cavity C if there fronts (except fronts having subfaces) which //
24725 // are either (nearly) coplanar or invisible by the Steiner point.           //
24726 //                                                                           //
24728 
24729 void tetgenmesh::expandsteinercavity(point steinpt, REAL eps, list* frontlist,
24730   list* oldtetlist)
24731 {
24732   triface front, symfront, newfront, oldfront;
24733   face frontsh;
24734   point pa, pb, pc;
24735   REAL ori;
24736   bool expflag, newflag;
24737   int i, j;
24738 
24739   do {
24740     expflag = false;
24741     for (i = 0; i < frontlist->len(); i++) {
24742       // Get a front f.
24743       front =  * (triface *)(* frontlist)[i];
24744       // f can be expanded if it is not a subface.
24745       tspivot(front, frontsh);
24746       if (frontsh.sh == dummysh) {
24747         // Let f face to the inside of C.
24748         adjustedgering(front, CW);
24749         pa = org(front);
24750         pb = dest(front);
24751         pc = apex(front);
24752         ori = orient3d(pa, pb, pc, steinpt);
24753         if (ori != 0.0) {
24754           if (iscoplanar(pa, pb, pc, steinpt, ori, eps)) {
24755             ori = 0.0; // f is nearly coplanar with p.
24756           }
24757         }
24758         if (ori >= 0.0) {
24759           // f is either invisible or coplanar with p.
24760           if (b->verbose > 2) {
24761             printf("    Remove front (%d, %d, %d).\n", pointmark(pa),
24762                    pointmark(pb), pointmark(pc));
24763           }
24764           frontlist->del(i, 1);
24765           expflag = true;
24766           break;
24767         }
24768       }
24769     }
24770     if (expflag) {
24771       assert(!infected(front) && (oppo(front) != NULL));
24772       // Expand C at f by including new fronts.
24773       adjustedgering(front, CCW);
24774       for (i = 0; i < 3; i++) {
24775         newflag = true;
24776         // Get a new boundary n of the cavity.
24777         fnext(front, symfront);
24778         tspivot(symfront, frontsh);
24779         sym(symfront, newfront);
24780         if (frontsh.sh == dummysh) {
24781           assert(newfront.tet != dummytet);
24782           // Is n a front of the unexp. cavity?
24783           if (infected(newfront)) {
24784             for (j = 0; j < frontlist->len(); j++) {
24785               oldfront = * (triface *)(* frontlist)[j];
24786               if ((oldfront.tet == symfront.tet) &&
24787                   (oldfront.loc == symfront.loc)) {
24788                 // n is not a front anymore.
24789                 if (b->verbose > 2) {
24790                   printf("    Remove front (%d, %d, %d).\n",
24791                          pointmark(org(oldfront)), pointmark(dest(oldfront)),
24792                          pointmark(apex(oldfront)));
24793                 }
24794                 frontlist->del(j, 1);
24795                 newflag = false;
24796                 break;
24797               }
24798             }
24799           }
24800         } else {
24801           // n is a subface.
24802           if (newfront.tet == dummytet) {
24803             sesymself(frontsh);
24804             // Create a fake tet to hold n.
24805             maketetrahedron(&newfront);
24806             setorg(newfront, sorg(frontsh));
24807             setdest(newfront, sdest(frontsh));
24808             setapex(newfront, sapex(frontsh));
24809             setoppo(newfront, (point) NULL);
24810             tsbond(newfront, frontsh);
24811           } else {
24812             // n should not be a front of cavity yet.
24813             assert(!infected(newfront));
24814           }
24815         }
24816         if (newflag) {
24817           if (b->verbose > 2) {
24818             printf("    Add front (%d, %d, %d).\n", pointmark(org(newfront)),
24819                    pointmark(dest(newfront)), pointmark(apex(newfront)));
24820           }
24821           frontlist->append(&newfront);
24822         }
24823         enextself(front);
24824       }
24825       // Add f into oldtetlist (to be deleted).
24826       infect(front);
24827       oldtetlist->append(&front);
24828       expcavcount++;
24829     }
24830   } while (expflag);
24831 }
24832 
24834 //                                                                           //
24835 // findrelocatepoint()    Find new location for relocating a point.          //
24836 //                                                                           //
24837 // 'frontlist' contains the boundary faces of the cavity C.  Some fronts are //
24838 // visible by 'stpt' p, some are coplanar with p.                            //
24839 //                                                                           //
24841 
24842 bool tetgenmesh::findrelocatepoint(point sp, point np, REAL* n,
24843   list* frontlist, list* oldtetlist)
24844 {
24845   triface front;
24846   point pa, pb, pc;
24847   REAL tp[3], tvol, mvol;
24848   REAL ori, eps;
24849   bool visible;
24850   int i, j, k;
24851 
24852   if (b->verbose > 1) {
24853     printf("    Find new location for point %d.\n", pointmark(sp));
24854   }
24855 
24856   // Avoid compilation warnings.
24857   tvol = mvol = 0.0;
24858   visible = false;
24859 
24860   eps = b->epsilon;
24861   // Initialize np far enough from p (outside C).
24862   for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24863   // Let tp = np;
24864   for (i = 0; i < 3; i++) tp[i] = np[i];
24865   // Interation to adjust np until it is visible by all fronts.
24866   j = 0;
24867   do {
24868     for (i = 0; i < frontlist->len(); i++) {
24869       // Get a front face f.
24870       front = * (triface *)(* frontlist)[i];
24871       // Let f face to the interior of C.
24872       adjustedgering(front, CW);
24873       pa = org(front);
24874       pb = dest(front);
24875       pc = apex(front);
24876       ori = orient3d(pa, pb, pc, np);
24877       visible = (ori < 0.0);
24878       if (!visible) {
24879         // A front is invisible by np. Move it towards p along the normal.
24880         for (i = 0; i < 3; i++) np[i] = sp[i] + 0.5 * (sp[i] - np[i]);
24881         // Failed if tp = np.
24882         if ((tp[0] == np[0]) && (tp[1] == np[1]) && (tp[2] == np[2])) {
24883           // Try to expand the cavity.
24884           expandsteinercavity(sp, eps, frontlist, oldtetlist);
24885           eps *= 10.0;
24886           if (eps > b->epsilon * 1000.0) {
24887           // printf("Internal error: Fail to relocate pt %d.\n",pointmark(sp));
24888             // internalerror();
24889             return false;
24890           }
24891           // Restart the point relocation.
24892           for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24893         }
24894         if (j % 2) {
24895           // Set tp = np (at every 2 steps) to catch the stop state.
24896           for (i = 0; i < 3; i++) tp[i] = np[i];
24897         }
24898         break;
24899       } else {
24900         // Save the smallest volume.
24901         if (i == 0) {
24902           mvol = fabs(ori);
24903         } else {
24904           mvol = fabs(ori) < mvol ? fabs(ori) : mvol;
24905         }
24906       }
24907     }
24908     j++;
24909   } while (!visible);
24910 
24911   if (b->verbose > 1) {
24912     printf("    %d iterations. minvol = %.12g.\n", j, mvol);
24913   }
24914 
24915   // Continue to adjust np until the minimal volume of tets formed by
24916   //   fronts and np doesn't increase (all fronts are visible by np).
24917   k = 0;
24918   do {
24919     j = 0;
24920     do {
24921       if (k == 0) {
24922         // Initial tp := np + 0.9 * (p - np). Move toward p.
24923         for (i = 0; i < 3; i++) tp[i] = sp[i] + 0.9 * (np[i] - sp[i]);
24924       } else {
24925         // Initial tp := np + 1.1 * (p - np). Move away from p.
24926         for (i = 0; i < 3; i++) tp[i] = sp[i] + 1.1 * (np[i] - sp[i]);
24927       }
24928       // Get the minial volume formed by tp with one of the fronts.
24929       for (i = 0; i < frontlist->len(); i++) {
24930         // Get a front face f.
24931         front = * (triface *)(* frontlist)[i];
24932         // Let f face to the interior of C.
24933         adjustedgering(front, CW);
24934         pa = org(front);
24935         pb = dest(front);
24936         pc = apex(front);
24937         ori = orient3d(pa, pb, pc, tp);
24938         visible = (ori < 0.0);
24939         if (visible) {
24940           // Save the smallest volume.
24941           if (i == 0) {
24942             tvol = fabs(ori);
24943           } else {
24944             tvol = fabs(ori) < tvol ? fabs(ori) : tvol;
24945           }
24946         } else {
24947           // A front is invisible by tp. Stop.
24948           tvol = 0.0;
24949           break;
24950         }
24951       }
24952       if (tvol > mvol) {
24953         // Get a larger minimal volume.
24954         for (i = 0; i < 3; i++) np[i] = tp[i];
24955         mvol = tvol;
24956       } else {
24957         // Minimal volume decreases. Stop.
24958         break;
24959       }
24960       // Continue to adjust np.
24961       j++;
24962     } while (true);
24963     // Has np been adjusted?
24964     if (j > 0) break;
24965     // Try to move np to anoter direction.
24966     k++;
24967   } while (k < 2);
24968 
24969   if (b->verbose > 1) {
24970     printf("    %d adjust iterations. minvol = %.12g.\n", j, mvol);
24971   }
24972   return true;
24973 }
24974 
24976 //                                                                           //
24977 // relocatepoint()    Relocate a point into the cavity.                      //
24978 //                                                                           //
24979 // 'frontlist' contains the boundary faces of the cavity C. All fronts must  //
24980 // be visible by 'steinpt'.  Some fronts may hold by 'fake' tets (they are   //
24981 // hull faces).  Fake tets will be removed when they're finished.            //
24982 //                                                                           //
24984 
24985 void tetgenmesh::relocatepoint(point steinpt, triface* oldtet, list* frontlist,
24986   list* newtetlist, queue* flipque)
24987 {
24988   triface front, newtet, newface, neightet;
24989   face checksh;
24990   point pa, pb;
24991   REAL attrib, volume;
24992   bool bdflag;
24993   int i, j, k, l;
24994 
24995   if (b->verbose > 1) {
24996     printf("    Insert Steiner point (%.12g, %.12g, %.12g) %d.\n",
24997            steinpt[0], steinpt[1], steinpt[2], pointmark(steinpt));
24998   }
24999   // Clear the list first.
25000   newtetlist->clear();
25001 
25002   // Create the tets formed by fronts and 'steinpt'.
25003   for (i = 0; i < frontlist->len(); i++) {
25004     // Get a front f.
25005     front = * (triface *)(* frontlist)[i];
25006     // Let f face inside C. (f is a face of tet adjacent to C).
25007     adjustedgering(front, CW);
25008     if (b->verbose > 2) {
25009       printf("    Get front (%d, %d, %d).\n", pointmark(org(front)),
25010              pointmark(dest(front)), pointmark(apex(front)));
25011     }
25012     maketetrahedron(&newtet);
25013     newtetlist->append(&newtet);
25014     setorg(newtet, org(front));
25015     setdest(newtet, dest(front));
25016     setapex(newtet, apex(front));
25017     setoppo(newtet, steinpt);
25018     if (oldtet != (triface *) NULL) {
25019       for (j = 0; j < in->numberoftetrahedronattributes; j++) {
25020         attrib = elemattribute(oldtet->tet, j);
25021         setelemattribute(newtet.tet, j, attrib);
25022       }
25023       if (b->varvolume) {
25024         volume = volumebound(oldtet->tet);
25025         setvolumebound(newtet.tet, volume);
25026       }
25027     }
25028     // 'front' may be a 'fake' tet.
25029     tspivot(front, checksh);
25030     if (oppo(front) == (point) NULL) {
25031       if (checksh.sh != dummysh) {
25032         stdissolve(checksh);
25033       }
25034       // Dealloc the 'fake' tet.
25035       tetrahedrondealloc(front.tet);
25036       // This side (newtet) is a boundary face, let 'dummytet' bond to it.
25037       //   Otherwise, 'dummytet' may point to a dead tetrahedron after the
25038       //   old cavity tets are removed.
25039       dummytet[0] = encode(newtet);
25040     } else {
25041       // Bond two tetrahedra, also dissolve the old bond at 'front'.
25042       bond(newtet, front);
25043     }
25044     if (checksh.sh != dummysh) {
25045       sesymself(checksh);
25046       tsbond(newtet, checksh);
25047     }
25048     if (flipque != (queue *) NULL) {
25049       // f may be non-locally Delaunay and flipable.
25050       enqueueflipface(newtet, flipque);
25051     }
25052     // The three neighbors are open. Will be finished later.
25053   }
25054 
25055   // Connect new tets in C. All connecting faces must contain 'steinpt'.
25056   for (i = 0; i < newtetlist->len(); i++) {
25057     newtet = * (triface *)(* newtetlist)[i];
25058     newtet.ver = 0;
25059     for (j = 0; j < 3; j++) {
25060       fnext(newtet, newface);
25061       sym(newface, neightet);
25062       if (neightet.tet == dummytet) {
25063         // Find a neightet to connect it.
25064         bdflag = false;
25065         pa = org(newface);
25066         pb = dest(newface);
25067         assert(apex(newface) == steinpt);
25068         for (k = i + 1; k < newtetlist->len() && !bdflag; k++) {
25069           neightet = * (triface *)(* newtetlist)[k];
25070           neightet.ver = 0;
25071           for (l = 0; l < 3; l++) {
25072             if ((org(neightet) == pa && dest(neightet) == pb) ||
25073                 (org(neightet) == pb && dest(neightet) == pa)) {
25074               // Find the neighbor.
25075               fnextself(neightet);
25076               assert(apex(neightet) == steinpt);
25077               // Now neightet is a face same as newface, bond them.
25078               bond(newface, neightet);
25079               bdflag = true;
25080               break;
25081             }
25082             enextself(neightet);
25083           }
25084         }
25085         assert(bdflag);
25086       }
25087       enextself(newtet);
25088     }
25089     // Let the corners of newtet point to it for fast searching.
25090     pa = org(newtet);
25091     setpoint2tet(pa, encode(newtet));
25092     pa = dest(newtet);
25093     setpoint2tet(pa, encode(newtet));
25094     pa = apex(newtet);
25095     setpoint2tet(pa, encode(newtet));
25096     pa = oppo(newtet);
25097     setpoint2tet(pa, encode(newtet));
25098   }
25099 
25100   if (flipque != (queue *) NULL) {
25101     // Recover locally Delaunay faces.
25102     flip(flipque, NULL);
25103   }
25104 }
25105 
25107 //                                                                           //
25108 // findcollapseedge()    Find collapseable edge to suppress an endpoint.     //
25109 //                                                                           //
25111 
25112 bool tetgenmesh::findcollapseedge(point suppt, point *conpt, list* oldtetlist,
25113   list* ptlist)
25114 {
25115   triface front;
25116   point pt, pa, pb, pc;
25117   REAL *lenarray, ltmp, ori;
25118   bool visflag;
25119   int *idxarray, itmp;
25120   int n, i, j;
25121 
25122   if (b->verbose > 2) {
25123     printf("    Search an edge (in %d edges) for collapse %d.\n",
25124            ptlist->len(), pointmark(suppt));
25125   }
25126 
25127   // Candidate edges are p to the points of B(p) (in 'ptlist').
25128   n = ptlist->len();
25129   lenarray = new REAL[n];
25130   idxarray = new int[n];
25131   // Sort the points of B(p) by distance to p.
25132   for (i = 0; i < n; i++) {
25133     pt = * (point *)(* ptlist)[i];
25134     lenarray[i] = distance(suppt, pt);
25135     idxarray[i] = i;
25136   }
25137   // Bubble sort.
25138   for (i = 0; i < n - 1; i++) {
25139     for (j = 0; j < n - 1 - i; j++) {
25140       if (lenarray[j + 1] < lenarray[j]) {  // compare the two neighbors
25141         ltmp = lenarray[j];           // swap a[j] and a[j + 1]
25142         lenarray[j] = lenarray[j + 1];
25143         lenarray[j + 1] = ltmp;
25144         itmp = idxarray[j];           // swap a[j] and a[j + 1]
25145         idxarray[j] = idxarray[j + 1];
25146         idxarray[j + 1] = itmp;
25147       }
25148     }
25149   }
25150   // For each point q of B(p), test if the edge (p, q) can be collapseed.
25151   for (i = 0; i < n; i++) {
25152     pt = * (point *)(* ptlist)[idxarray[i]];
25153     // Is q visible by faces of B(p) not with q as a vertex.
25154     lenarray[i] = 0.0; // zero volume.
25155     visflag = true;
25156     for (j = 0; j < oldtetlist->len() && visflag; j++) {
25157       front = * (triface *)(* oldtetlist)[j];
25158       // Let f face to inside of B(p).
25159       adjustedgering(front, CCW);
25160       pa = org(front);
25161       pb = dest(front);
25162       pc = apex(front);
25163       // Is f contains q?
25164       if ((pa != pt) && (pb != pt) && (pc != pt)) {
25165         ori = orient3d(pa, pb, pc, pt);
25166         if (ori != 0.0) {
25167           if (iscoplanar(pa, pb, pc, pt, ori, b->epsilon * 1e+2)) ori = 0.0;
25168         }
25169         visflag = ori < 0.0;
25170         if (visflag) {
25171           // Visible, set the smallest volume.
25172           if (j == 0) {
25173             lenarray[i] = fabs(ori);
25174           } else {
25175             lenarray[i] = fabs(ori) < lenarray[i] ? fabs(ori) : lenarray[i];
25176           }
25177         } else {
25178           // Invisible. Do not collapse (p, q).
25179           lenarray[i] = 0.0;
25180         }
25181       }
25182     }
25183     if ((b->verbose > 2) && visflag) {
25184       printf("    Got candidate %d vol(%g).\n", pointmark(pt), lenarray[i]);
25185     }
25186   }
25187 
25188   // Select the largest non-zero volume (result in ltmp).
25189   ltmp = lenarray[0];
25190   itmp = idxarray[0];
25191   for (i = 1; i < n; i++) {
25192     if (lenarray[i] != 0.0) {
25193       if (lenarray[i] > ltmp) {
25194         ltmp = lenarray[i];
25195         itmp = idxarray[i]; // The index to find the point.
25196       }
25197     }
25198   }
25199 
25200   delete [] lenarray;
25201   delete [] idxarray;
25202 
25203   if (ltmp == 0.0) {
25204     // No edge can be collapseed.
25205     *conpt = (point) NULL;
25206     return false;
25207   } else {
25208     pt = * (point *)(* ptlist)[itmp];
25209     *conpt = pt;
25210     return true;
25211   }
25212 }
25213 
25215 //                                                                           //
25216 // collapseedge()    Remove a point by edge collapse.                        //
25217 //                                                                           //
25219 
25220 void tetgenmesh::collapseedge(point suppt, point conpt, list* oldtetlist,
25221   list* deadtetlist)
25222 {
25223   triface oldtet, deadtet;
25224   triface adjtet1, adjtet2;
25225   face adjsh;
25226   point pa, pb, pc;
25227   int i, j;
25228 
25229   if (b->verbose > 2) {
25230     printf("    Collapse edge (%d,%d).\n", pointmark(suppt), pointmark(conpt));
25231   }
25232 
25233   // Loop in B(p), replace p with np, queue dead tets, uninfect old tets.
25234   for (i = 0; i < oldtetlist->len(); i++) {
25235     oldtet = * (triface *)(* oldtetlist)[i]; // assert(infected(oldtet));
25236     uninfect(oldtet);
25237     pa = org(oldtet);
25238     pb = dest(oldtet);
25239     pc = apex(oldtet);
25240     assert(oppo(oldtet) == suppt);
25241     setoppo(oldtet, conpt);
25242     if ((pa == conpt) || (pb == conpt) || (pc == conpt)) {
25243       deadtetlist->append(&oldtet); // a collpased tet.
25244     }
25245   }
25246   // Loop in deadtetlist, glue adjacent tets of dead tets.
25247   for (i = 0; i < deadtetlist->len(); i++) {
25248     deadtet = * (triface *)(* deadtetlist)[i];
25249     // Get the adjacent tet n1 (outside B(p)).
25250     sym(deadtet, adjtet1);
25251     tspivot(deadtet, adjsh);
25252     // Find the edge in deadtet opposite to conpt.
25253     adjustedgering(deadtet, CCW);
25254     for (j = 0; j < 3; j++) {
25255       if (apex(deadtet) == conpt) break;
25256       enextself(deadtet);
25257     }
25258     assert(j < 3);
25259     // Get another adjacent tet n2.
25260     fnext(deadtet, adjtet2);
25261     symself(adjtet2);
25262     assert(adjtet2.tet != dummytet); // n2 is inside B(p).
25263     if (adjtet1.tet != dummytet) {
25264       bond(adjtet1, adjtet2); // Bond n1 <--> n2.
25265     } else {
25266       dissolve(adjtet2); // Dissolve at n2.
25267       dummytet[0] = encode(adjtet2); // Let dummytet holds n2.
25268     }
25269     if (adjsh.sh != dummysh) {
25270       tsbond(adjtet2, adjsh); // Bond s <--> n2.
25271     }
25272     // Collapse deadtet.
25273     tetrahedrondealloc(deadtet.tet);
25274   }
25275   deadtetlist->clear();
25276 }
25277 
25279 //                                                                           //
25280 // deallocfaketets()    Deleted fake tets at fronts.                         //
25281 //                                                                           //
25282 // This routine is only called when the findrelocatepoint() routine fails.   //
25283 // In other cases, the fake tets are removed automatically in carvecavity()  //
25284 // or relocatepoint().                                                       //
25285 //                                                                           //
25287 
25288 void tetgenmesh::deallocfaketets(list* frontlist)
25289 {
25290   triface front, neightet;
25291   face checksh;
25292   bool infectflag;
25293   int i;
25294 
25295   for (i = 0; i < frontlist->len(); i++) {
25296     // Get a front f.
25297     front = * (triface *)(* frontlist)[i];
25298     // Let f face inside C. (f is a face of tet adjacent to C).
25299     adjustedgering(front, CW);
25300     sym(front, neightet);
25301     tspivot(front, checksh);
25302     if (oppo(front) == (point) NULL) {
25303       if (b->verbose > 2) {
25304         printf("    Get fake tet (%d, %d, %d).\n", pointmark(org(front)),
25305                pointmark(dest(front)), pointmark(apex(front)));
25306       }
25307       if (neightet.tet != dummytet) {
25308         // The neightet may be infected. After dissolve it, the infect flag
25309         //   will be lost. Save the flag and restore it later.
25310         infectflag = infected(neightet);
25311         dissolve(neightet);
25312         if (infectflag) {
25313           infect(neightet);
25314         }
25315       }
25316       if (checksh.sh != dummysh) {
25317         infectflag = sinfected(checksh);
25318         stdissolve(checksh);
25319         if (infectflag) {
25320           sinfect(checksh);
25321         }
25322       }
25323       // Dealloc the 'fake' tet.
25324       tetrahedrondealloc(front.tet);
25325       // If 'neightet' is a hull face, let 'dummytet' bond to it. It is
25326       //   a 'dummytet' when this front was created from a new subface.
25327       //   In such case, it should not be bounded.
25328       if (neightet.tet != dummytet) {
25329         dummytet[0] = encode(neightet);
25330       }
25331     }
25332   }
25333 }
25334 
25336 //                                                                           //
25337 // restorepolyhedron()    Restore the tetrahedralization in a polyhedron.    //
25338 //                                                                           //
25339 // This routine is only called when the operation of suppressing a point is  //
25340 // aborted (eg., findrelocatepoint() routine fails). The polyhedron has been //
25341 // remeshed by new tets. This routine restore the old tets in it.            //
25342 //                                                                           //
25343 // 'oldtetlist' contains the list of old tets. Each old tet t_o assumes that //
25344 // it still connects to a tet t_b of the mesh, however, t_b does not connect //
25345 // to t_o, this routine resets the connection such that t_b <--> t_o.        //
25346 //                                                                           //
25348 
25349 void tetgenmesh::restorepolyhedron(list* oldtetlist)
25350 {
25351   triface oldtet, neightet, neineitet;
25352   face checksh;
25353   int i;
25354 
25355   for (i = 0; i < oldtetlist->len(); i++) {
25356     // Get an old tet t_o.
25357     oldtet = * (triface *)(* oldtetlist)[i];
25358     // Check the four sides of t_o.
25359     for (oldtet.loc = 0; oldtet.loc < 4; oldtet.loc++) {
25360       sym(oldtet, neightet);
25361       tspivot(oldtet, checksh);
25362       if (neightet.tet != dummytet) {
25363         sym(neightet, neineitet);
25364         if (neineitet.tet != oldtet.tet) {
25365           // This face of t_o is a boundary of P.
25366           bond(neightet, oldtet);
25367           if (checksh.sh != dummysh) {
25368             tsbond(oldtet, checksh);
25369           }
25370         }
25371       } else {
25372         // t_o has a hull face. It should be the boundary of P.
25373 #ifdef SELF_CHECK
25374         assert(checksh.sh != dummysh);
25375         stpivot(checksh, neineitet);
25376         assert(neineitet.tet != oldtet.tet);
25377 #endif
25378         tsbond(oldtet, checksh);
25379         // Let dummytet[0] points to it.
25380         dummytet[0] = encode(oldtet);
25381       }
25382     }
25383   }
25384 }
25385 
25387 //                                                                           //
25388 // suppressfacetpoint()    Suppress a point inside a facet.                  //
25389 //                                                                           //
25390 // The point p inside a facet F will be suppressed from F by either being    //
25391 // deleted from the mesh or being relocated into the volume.                 //
25392 //                                                                           //
25393 // 'supsh' is a subface f of F, and p = sapex(f); the other parameters are   //
25394 // working lists which are empty at the beginning and the end.               //
25395 //                                                                           //
25396 // 'optflag' is used for mesh optimization. If it is set, after removing p,  //
25397 // test the object function on each new tet, queue bad tets.                 //
25398 //                                                                           //
25400 
25401 bool tetgenmesh::suppressfacetpoint(face* supsh, list* frontlist,
25402   list* misfrontlist, list* ptlist, list* conlist, memorypool* viri,
25403   queue* flipque, bool noreloc, bool optflag)
25404 {
25405   list *oldtetlist[2], *newtetlist[2];
25406   list *oldshlist, *newshlist;
25407   triface oldtet, newtet;
25408   face oldsh, newsh;
25409   point suppt, newpt[2];
25410   point *cons;
25411   REAL norm[3];
25412   bool success;
25413   int shmark;
25414   int i, j;
25415 
25416   suppt = sapex(*supsh);
25417   if (b->verbose > 1) {
25418     printf("    Suppress point %d in facet.\n", pointmark(suppt));
25419   }
25420 
25421   // Initialize working lists, variables.
25422   for (i = 0; i < 2; i++) {
25423     oldtetlist[i] = (list *) NULL;
25424     newtetlist[i] = (list *) NULL;
25425     newpt[i] = (point) NULL;
25426   }
25427   oldshlist = new list(sizeof(face), NULL, 256);
25428   newshlist = new list(sizeof(face), NULL, 256);
25429   success = true; // Assume p can be suppressed.
25430 
25431   // Find subs of C(p).
25432   oldshlist->append(supsh);
25433   formstarpolygon(suppt, oldshlist, ptlist);
25434   // Get the edges of C(p). They form a closed polygon.
25435   for (i = 0; i < oldshlist->len(); i++) {
25436     oldsh = * (face *)(* oldshlist)[i];
25437     cons = (point *) conlist->append(NULL);
25438     cons[0] = sorg(oldsh);
25439     cons[1] = sdest(oldsh);
25440   }
25441   // Re-triangulate the old C(p).
25442   shmark = shellmark(*supsh);
25443   triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25444   // Get new subs of C(p), remove protected segments.
25445   retrievenewsubs(newshlist, true);
25446   // Substitute the old C(p) with the new C(p)
25447   replacepolygonsubs(oldshlist, newshlist);
25448   // Clear work lists.
25449   ptlist->clear();
25450   conlist->clear();
25451   flipque->clear();
25452   viri->restart();
25453 
25454   // B(p) (tets with p as a vertex) has been separated into two parts
25455   //   (B_0(p) and B_1(p)) by F. Process them individually.
25456   for (i = 0; i < 2 && success; i++) {
25457     if (i == 1) sesymself(*supsh);
25458     // Get a tet containing p.
25459     stpivot(*supsh, oldtet);
25460     // Is this part empty?
25461     if (oldtet.tet == dummytet) continue;
25462     // Allocate spaces for storing (old and new) B_i(p).
25463     oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25464     newtetlist[i] = new list(sizeof(triface), NULL, 256);
25465     // Form old B_i(p) in oldtetlist[i].
25466     assert(!isdead(&oldtet));
25467     oldtetlist[i]->append(&oldtet);
25468     formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25469     // Infect the tets in old B_i(p) (they're going to be delete).
25470     for (j = 0; j < oldtetlist[i]->len(); j++) {
25471       oldtet = * (triface *)(* (oldtetlist[i]))[j];
25472       infect(oldtet);
25473     }
25474     // Preparation for re-tetrahedralzing old B_i(p).
25475     orientnewsubs(newshlist, supsh, norm);
25476     // Tetrahedralize old B_i(p).
25477     success = constrainedcavity(&oldtet, newshlist, oldtetlist[i], ptlist,
25478                 frontlist, misfrontlist, newtetlist[i], flipque);
25479     // If p is not suppressed, do relocation if 'noreloc' is not set.
25480     if (!success && !noreloc) {
25481       // Try to relocate p into the old B_i(p).
25482       makepoint(&(newpt[i]));
25483       success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25484                                   oldtetlist[i]);
25485       // Initialize newpt = suppt.
25486       // for (j = 0; j < 3; j++) newpt[i][j] = suppt[j];
25487       // success = smoothvolpoint(newpt[i], frontlist, true);
25488       if (success) {
25489         // p is relocated by newpt[i]. Now insert it. Don't do flip since
25490         //   the new tets may get deleted again.
25491         relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25492         setpointtype(newpt[i], FREEVOLVERTEX);
25493         relverts++;
25494       } else {
25495         // Fail to relocate p. Clean fake tets and quit this option.
25496         deallocfaketets(frontlist);
25497         pointdealloc(newpt[i]);
25498         newpt[i] = (point) NULL;
25499         assert(newtetlist[i]->len() == 0);
25500       }
25501     }
25502     if (!success && noreloc) {
25503       // Failed and no point relocation. Clean fake tets.
25504       deallocfaketets(frontlist);
25505     }
25506     // Clear work lists.
25507     ptlist->clear();
25508     frontlist->clear();
25509     misfrontlist->clear();
25510     flipque->clear();
25511   }
25512 
25513   if (success) {
25514     // p has been removed! (Still in the pool).
25515     setpointtype(suppt, UNUSEDVERTEX);
25516     unuverts++;
25517     // Delete old C(p).
25518     for (i = 0; i < oldshlist->len(); i++) {
25519       oldsh = * (face *)(* oldshlist)[i];
25520       if (i == 0) {
25521         // Update the 'hullsize' if C(p) is on the hull.
25522         stpivot(oldsh, oldtet);
25523         if (oldtet.tet != dummytet) {
25524           sesymself(oldsh);
25525           stpivot(oldsh, oldtet);
25526         }
25527         if (oldtet.tet == dummytet) {
25528           // A boundary face. Update the 'hullsize'.
25529           j = oldshlist->len() - newshlist->len();
25530           assert(j > 0);
25531           hullsize -= j;
25532         }
25533       }
25534       shellfacedealloc(subfaces, oldsh.sh);
25535     }
25536     // Delete old B_i(p).
25537     for (i = 0; i < 2; i++) {
25538       if (oldtetlist[i] != (list *) NULL) {
25539         // Delete tets of the old B_i(p).
25540         for (j = 0; j < oldtetlist[i]->len(); j++) {
25541           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25542           assert(!isdead(&oldtet));
25543           tetrahedrondealloc(oldtet.tet);
25544         }
25545       }
25546     }
25547     if (optflag) {
25548       // Check for new bad-quality tets.
25549       for (i = 0; i < 2; i++) {
25550         if (newtetlist[i] != (list *) NULL) {
25551           for (j = 0; j < newtetlist[i]->len(); j++) {
25552             newtet = * (triface *)(* (newtetlist[i]))[j];
25553             if (!isdead(&newtet)) checktet4opt(&newtet, true);
25554           }
25555         }
25556       }
25557     }
25558   } else {
25559     // p is not suppressed. Recover the original state.
25560     unsupverts++;
25561     // Restore the old C(p).
25562     replacepolygonsubs(newshlist, oldshlist);
25563     // Delete subs of the new C(p)
25564     for (i = 0; i < newshlist->len(); i++) {
25565       newsh = * (face *)(* newshlist)[i];
25566       shellfacedealloc(subfaces, newsh.sh);
25567     }
25568     // Restore old B_i(p).
25569     for (i = 0; i < 2; i++) {
25570       if (oldtetlist[i] != (list *) NULL) {
25571         // Uninfect tets of old B_i(p).
25572         for (j = 0; j < oldtetlist[i]->len(); j++) {
25573           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25574           assert(infected(oldtet));
25575           uninfect(oldtet);
25576         }
25577         // Has it been re-meshed?
25578         if (newtetlist[i]->len() > 0) {
25579           // Restore the old B_i(p).
25580           restorepolyhedron(oldtetlist[i]);
25581           // Delete tets of the new B_i(p);
25582           for (j = 0; j < newtetlist[i]->len(); j++) {
25583             newtet = * (triface *)(* (newtetlist[i]))[j];
25584             // Some new tets may already be deleted (by carvecavity()).
25585             if (!isdead(&newtet)) {
25586               tetrahedrondealloc(newtet.tet);
25587             }
25588           }
25589         }
25590         // Dealloc newpt[i] if it exists.
25591         if (newpt[i] != (point) NULL) {
25592           pointdealloc(newpt[i]);
25593           relverts--;
25594         }
25595       }
25596     }
25597   }
25598 
25599   // Delete work lists.
25600   delete oldshlist;
25601   delete newshlist;
25602   for (i = 0; i < 2; i++) {
25603     if (oldtetlist[i] != (list *) NULL) {
25604       delete oldtetlist[i];
25605       delete newtetlist[i];
25606     }
25607   }
25608 
25609   return success;
25610 }
25611 
25613 //                                                                           //
25614 // suppresssegpoint()    Suppress a point on a segment.                      //
25615 //                                                                           //
25616 // The point p on a segment S will be suppressed from S by either being      //
25617 // deleted from the mesh or being relocated into the volume.                 //
25618 //                                                                           //
25619 // 'supseg' is the segment S, and p = sdest(S); the other parameters are     //
25620 // working lists which are empty at the beginning and the end.               //
25621 //                                                                           //
25623 
25624 bool tetgenmesh::suppresssegpoint(face* supseg, list* spinshlist,
25625   list* newsegshlist, list* frontlist, list* misfrontlist, list* ptlist,
25626   list* conlist, memorypool* viri, queue* flipque, bool noreloc, bool optflag)
25627 {
25628   list **oldtetlist, **newtetlist;
25629   list **oldshlist, **newshlist;
25630   list *pnewshlist, *dnewshlist;
25631   triface oldtet, newtet;
25632   face oldsh, newsh;
25633   face startsh, spinsh, segsh1, segsh2;
25634   face nsupseg, newseg, prevseg, nextseg;
25635   point suppt, *newpt;
25636   point pa, pb, *cons;
25637   REAL pnorm[2][3], norm[3];
25638   bool success;
25639   int shmark;
25640   int n, i, j, k;
25641 
25642   // Get the Steiner point p.
25643   assert(supseg->shver < 2);
25644   suppt = sdest(*supseg);
25645   // Find the segment ab split by p.
25646   senext(*supseg, nsupseg);
25647   spivotself(nsupseg);
25648   assert(nsupseg.sh != dummysh);
25649   nsupseg.shver = 0;
25650   if (sorg(nsupseg) != suppt) sesymself(nsupseg);
25651   assert(sorg(nsupseg) == suppt);
25652   pa = sorg(*supseg);
25653   pb = sdest(nsupseg);
25654   if (b->verbose > 1) {
25655     printf("    Remove point %d on segment (%d, %d).\n",
25656            pointmark(suppt), pointmark(pa), pointmark(pb));
25657   }
25658 
25659   // Let startsh s containing p.
25660   spivot(*supseg, startsh);
25661   spinsh = startsh;
25662   do {
25663     // Save it in list.
25664     spinshlist->append(&spinsh);
25665     // Go to the next facet.
25666     spivotself(spinsh);
25667   } while (spinsh.sh != startsh.sh);
25668   if (spinshlist->len() == 1) {
25669     // This case has not handled yet.
25670     // printf("Unhandled case: segment only belongs to one facet.\n");
25671     spinshlist->clear();
25672     unsupverts++;
25673     return false;
25674   }
25675 
25676   // Suppose ab is shared by n facets (n > 1), then there are n B(p) (tets
25677   //   with p as a vertex). Some B(p) may be empty, eg, outside.
25678   n = spinshlist->len();
25679   oldtetlist = new list*[n];
25680   newtetlist = new list*[n];
25681   oldshlist = new list*[n];
25682   newshlist = new list*[n];
25683   newpt = new point[n];
25684   for (i = 0; i < n; i++) {
25685     oldtetlist[i] = (list *) NULL;
25686     newtetlist[i] = (list *) NULL;
25687     oldshlist[i] = (list *) NULL;
25688     newshlist[i] = (list *) NULL;
25689     newpt[i] = (point) NULL;
25690   }
25691 
25692   // Create a new segment ab (result in newseg).
25693   makeshellface(subsegs, &newseg);
25694   setsorg(newseg, pa);
25695   setsdest(newseg, pb);
25696   // ab gets the same mark and segment type as ap.
25697   setshellmark(newseg, shellmark(*supseg));
25698   setshelltype(newseg, shelltype(*supseg));
25699   if (b->quality && varconstraint) {
25700     // Copy the areabound into the new subsegment.
25701     setareabound(newseg, areabound(*supseg));
25702   }
25703   // Save the old connection at a.
25704   senext2(*supseg, prevseg);
25705   spivotself(prevseg);
25706   if (prevseg.sh != dummysh) {
25707     prevseg.shver = 0;
25708     if (sdest(prevseg) != pa) sesymself(prevseg);
25709     assert(sdest(prevseg) == pa);
25710     senextself(prevseg);
25711     senext2self(newseg);
25712     sbond(newseg, prevseg);
25713     newseg.shver = 0;
25714   }
25715   // Save the old connection at b.
25716   senext(nsupseg, nextseg);
25717   spivotself(nextseg);
25718   if (nextseg.sh != dummysh) {
25719     nextseg.shver = 0;
25720     if (sorg(nextseg) != pb) sesymself(nextseg);
25721     assert(sorg(nextseg) == pb);
25722     senext2self(nextseg);
25723     senextself(newseg);
25724     sbond(newseg, nextseg);
25725     newseg.shver = 0;
25726   }
25727 
25728   // Re-triangulate C(p) (subs with p as a vertex) to remove p.
25729   for (i = 0; i < spinshlist->len(); i++) {
25730     spinsh = * (face *)(* spinshlist)[i];
25731     // Allocate spaces for C_i(p).
25732     oldshlist[i] = new list(sizeof(face), NULL, 256);
25733     newshlist[i] = new list(sizeof(face), NULL, 256);
25734     // Get the subs of C_i(p).
25735     oldshlist[i]->append(&spinsh);
25736     formstarpolygon(suppt, oldshlist[i], ptlist);
25737     // Find the edges of C_i(p). It DOES NOT form a closed polygon.
25738     for (j = 0; j < oldshlist[i]->len(); j++) {
25739       oldsh = * (face *)(* (oldshlist[i]))[j];
25740       cons = (point *) conlist->append(NULL);
25741       cons[0] = sorg(oldsh);
25742       cons[1] = sdest(oldsh);
25743     }
25744     // The C_i(p) isn't closed without ab. Add it to it.
25745     cons = (point *) conlist->append(NULL);
25746     cons[0] = pa;
25747     cons[1] = pb;
25748     // Re-triangulate C_i(p).
25749     shmark = shellmark(spinsh);
25750     triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25751     // Get new subs of C_i(p), remove protected segments.
25752     retrievenewsubs(newshlist[i], true);
25753     // Substitute old C_i(p) with the new C_i(p). !IT IS NOT COMPLETE!
25754     replacepolygonsubs(oldshlist[i], newshlist[i]);
25755     // Find the new subface s having edge ab.
25756     for (j = 0; j < newshlist[i]->len(); j++) {
25757       segsh1 = * (face *)(* (newshlist[i]))[j];
25758       for (k = 0; k < 3; k++) {
25759         if (((sorg(segsh1) == pa) && (sdest(segsh1) == pb)) ||
25760             ((sorg(segsh1) == pb) && (sdest(segsh1) == pa))) break;
25761         senextself(segsh1);
25762       }
25763       if (k < 3) break; // Found.
25764     }
25765     assert(j < newshlist[i]->len()); // ab must exist.
25766     // Bond s and ab together. The C_i(p) is completedly substituted.
25767     ssbond(segsh1, newseg);
25768     // Save s for forming the face ring of ab.
25769     newsegshlist->append(&segsh1);
25770     // Clear work lists.
25771     ptlist->clear();
25772     conlist->clear();
25773     flipque->clear();
25774     viri->restart();
25775   }
25776   // Form the face ring of ab.
25777   for (i = 0; i < newsegshlist->len(); i++) {
25778     segsh1 = * (face *)(* newsegshlist)[i];
25779     if ((i + 1) == newsegshlist->len()) {
25780       segsh2 = * (face *)(* newsegshlist)[0];
25781     } else {
25782       segsh2 = * (face *)(* newsegshlist)[i + 1];
25783     }
25784     sbond1(segsh1, segsh2);
25785   }
25786 
25787   // A work list for keeping subfaces from two facets.
25788   dnewshlist = new list(sizeof(face), NULL, 256);
25789   success = true; // Assume p is suppressable.
25790 
25791   // Suppress p in all B(p). B_i(p) is looped wrt the right-hand rule of ab.
25792   for (i = 0; i < spinshlist->len() && success; i++) {
25793     // Get an old  subface s (ap) of a facet.
25794     spinsh = * (face *)(* spinshlist)[i];
25795     // Let the edge direction of s be a->b. Hence all subfaces follow
25796     //   the right-hand rule of ab.
25797     if (sorg(spinsh) != pa) sesymself(spinsh);
25798     // Get a tet t of B_i(p).
25799     stpivot(spinsh, oldtet);
25800     // Is B_i(p) empty?
25801     if (oldtet.tet == dummytet) continue;
25802     // Allocate spaces for B_i(p).
25803     oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25804     newtetlist[i] = new list(sizeof(triface), NULL, 256);
25805     // Find all tets of old B_i(p).
25806     oldtetlist[i]->append(&oldtet);
25807     formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25808     // Infect tets of old B_i(p) (they're going to be deleted).
25809     for (j = 0; j < oldtetlist[i]->len(); j++) {
25810       oldtet = * (triface *)(* (oldtetlist[i]))[j];
25811       infect(oldtet);
25812     }
25813     // Collect new subfaces (of two facets) bounded B_i(p).
25814     for (k = 0; k < 2; k++) {
25815       if ((i + k) < spinshlist->len()) {
25816         pnewshlist = newshlist[i + k];
25817         segsh1 = * (face *)(* spinshlist)[i + k];
25818       } else {
25819         pnewshlist = newshlist[0];
25820         segsh1 = * (face *)(* spinshlist)[0];
25821       }
25822       // Adjust the orientation of segsh1 to face to the inside of C.
25823       if (k == 0) {
25824         if (sorg(segsh1) != pa) sesymself(segsh1);
25825         assert(sorg(segsh1) == pa);
25826       } else {
25827         if (sdest(segsh1) != pa) sesymself(segsh1);
25828         assert(sdest(segsh1) == pa);
25829       }
25830       // Preparation for re-tetrahedralzing old B_i(p).
25831       orientnewsubs(pnewshlist, &segsh1, pnorm[k]);
25832       for (j = 0; j < pnewshlist->len(); j++) {
25833         dnewshlist->append((face *)(* pnewshlist)[j]);
25834       }
25835     }
25836     // Tetrahedralize B_i(p).
25837     success = constrainedcavity(&oldtet, dnewshlist, oldtetlist[i], ptlist,
25838                 frontlist, misfrontlist, newtetlist[i], flipque);
25839     if (!success && !noreloc) {
25840       // C must be finished by re-locating the steiner point.
25841       makepoint(&(newpt[i]));
25842       for (j = 0; j < 3; j++) norm[j] = 0.5 * (pnorm[0][j] + pnorm[1][j]);
25843       success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25844                                   oldtetlist[i]);
25845       // for (j = 0; j < 3; j++) newpt[i][j] = suppt[j];
25846       // success = smoothvolpoint(newpt[i], frontlist, true);
25847       if (success) {
25848         // p is relocated by newpt[i]. Now insert it. Don't do flip since
25849         //   the new tets may get deleted again.
25850         relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25851         setpointtype(newpt[i], FREEVOLVERTEX);
25852         relverts++;
25853       } else {
25854         // Fail to relocate p. Clean fake tets and quit this option.
25855         deallocfaketets(frontlist);
25856         pointdealloc(newpt[i]);
25857         newpt[i] = (point) NULL;
25858         assert(newtetlist[i]->len() == 0);
25859       }
25860     }
25861     if (!success && noreloc) {
25862       // Failed and no point relocation. Clean fake tets.
25863       deallocfaketets(frontlist);
25864     }
25865     // Clear work lists.
25866     dnewshlist->clear();
25867     ptlist->clear();
25868     frontlist->clear();
25869     misfrontlist->clear();
25870     flipque->clear();
25871   }
25872 
25873   if (success) {
25874     // p has been suppressed. (Still in the pool).
25875     setpointtype(suppt, UNUSEDVERTEX);
25876     unuverts++;
25877     // Update the segmnet pointers saved in a and b.
25878     setpoint2sh(pa, sencode(newseg));
25879     setpoint2sh(pb, sencode(newseg));
25880     // Delete old segments ap, pb.
25881     shellfacedealloc(subsegs, supseg->sh);
25882     shellfacedealloc(subsegs, nsupseg.sh);
25883     // Delete subs of old C_i(p).
25884     for (i = 0; i < spinshlist->len(); i++) {
25885       for (j = 0; j < oldshlist[i]->len(); j++) {
25886         oldsh = * (face *)(* (oldshlist[i]))[j];
25887         if (j == 0) {
25888           // Update 'hullsize' if C_i(p) is on the hull.
25889           stpivot(oldsh, oldtet);
25890           if (oldtet.tet != dummytet) {
25891             sesymself(oldsh);
25892             stpivot(oldsh, oldtet);
25893           }
25894           if (oldtet.tet == dummytet) {
25895             // Update 'hullsize'.
25896             k = oldshlist[i]->len() - newshlist[i]->len();
25897             assert(k > 0);
25898             hullsize -= k;
25899           }
25900         }
25901         shellfacedealloc(subfaces, oldsh.sh);
25902       }
25903     }
25904     // Delete tets old B_i(p).
25905     for (i = 0; i < spinshlist->len(); i++) {
25906       // Delete them if it is not empty.
25907       if (oldtetlist[i] != (list *) NULL) {
25908         for (j = 0; j < oldtetlist[i]->len(); j++) {
25909           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25910           assert(!isdead(&oldtet));
25911           tetrahedrondealloc(oldtet.tet);
25912         }
25913       }
25914     }
25915     if (optflag) {
25916       for (i = 0; i < spinshlist->len(); i++) {
25917         // Check for new bad-quality tets.
25918         if (newtetlist[i] != (list *) NULL) {
25919           for (j = 0; j < newtetlist[i]->len(); j++) {
25920             newtet = * (triface *)(* (newtetlist[i]))[j];
25921             if (!isdead(&newtet)) checktet4opt(&newtet, true);
25922           }
25923         }
25924       }
25925     }
25926   } else {
25927     // p is not suppressed. Recover the original state.
25928     unsupverts++;
25929     // Restore old connection at a.
25930     senext2(*supseg, prevseg);
25931     spivotself(prevseg);
25932     if (prevseg.sh != dummysh) {
25933       prevseg.shver = 0;
25934       if (sdest(prevseg) != pa) sesymself(prevseg);
25935       assert(sdest(prevseg) == pa);
25936       senextself(prevseg);
25937       senext2self(*supseg);
25938       sbond(*supseg, prevseg);
25939       senextself(*supseg); // Restore original state.
25940       assert(supseg->shver < 2);
25941     }
25942     // Restore old connection at b.
25943     senext(nsupseg, nextseg);
25944     spivotself(nextseg);
25945     if (nextseg.sh != dummysh) {
25946       nextseg.shver = 0;
25947       if (sorg(nextseg) != pb) sesymself(nextseg);
25948       assert(sorg(nextseg) == pb);
25949       senext2self(nextseg);
25950       senextself(nsupseg);
25951       sbond(nsupseg, nextseg);
25952       // nsupseg.shver = 0;
25953       senext2self(nsupseg); // Restore original state
25954       assert(nsupseg.shver < 2);
25955     }
25956     // Delete the new segment ab.
25957     shellfacedealloc(subsegs, newseg.sh);
25958     // Restore old C_i(p).
25959     for (i = 0; i < spinshlist->len(); i++) {
25960       replacepolygonsubs(newshlist[i], oldshlist[i]);
25961       // Delete subs of the new C_i(p)
25962       for (j = 0; j < newshlist[i]->len(); j++) {
25963         newsh = * (face *)(* (newshlist[i]))[j];
25964         shellfacedealloc(subfaces, newsh.sh);
25965       }
25966     }
25967     // Restore old B_i(p).
25968     for (i = 0; i < spinshlist->len(); i++) {
25969       if (oldtetlist[i] != (list *) NULL) {
25970         // Uninfect tets of old B_i(p).
25971         for (j = 0; j < oldtetlist[i]->len(); j++) {
25972           oldtet = * (triface *)(* (oldtetlist[i]))[j];
25973           assert(infected(oldtet));
25974           uninfect(oldtet);
25975         }
25976         // Has it been re-meshed?
25977         if (newtetlist[i]->len() > 0) {
25978           // Restore the old B_i(p).
25979           restorepolyhedron(oldtetlist[i]);
25980           // Delete tets of the new B_i(p);
25981           for (j = 0; j < newtetlist[i]->len(); j++) {
25982             newtet = * (triface *)(* (newtetlist[i]))[j];
25983             // Some new tets may already be deleted (by carvecavity()).
25984             if (!isdead(&newtet)) {
25985               tetrahedrondealloc(newtet.tet);
25986             }
25987           }
25988         }
25989         // Dealloc newpt[i] if it exists.
25990         if (newpt[i] != (point) NULL) {
25991           pointdealloc(newpt[i]);
25992           relverts--;
25993         }
25994       }
25995     }
25996   }
25997 
25998   // Delete work lists.
25999   delete dnewshlist;
26000   for (i = 0; i < spinshlist->len(); i++) {
26001     delete oldshlist[i];
26002     delete newshlist[i];
26003   }
26004   delete [] oldshlist;
26005   delete [] newshlist;
26006   for (i = 0; i < spinshlist->len(); i++) {
26007     if (oldtetlist[i] != (list *) NULL) {
26008       delete oldtetlist[i];
26009       delete newtetlist[i];
26010     }
26011   }
26012   delete [] oldtetlist;
26013   delete [] newtetlist;
26014   // Clear work lists.
26015   newsegshlist->clear();
26016   spinshlist->clear();
26017 
26018   return success;
26019 }
26020 
26022 //                                                                           //
26023 // suppressvolpoint()    Suppress a point inside mesh.                       //
26024 //                                                                           //
26025 // The point p = org(suptet) is inside the mesh and will be suppressed from  //
26026 // the mesh. Note that p may not be suppressed.                              //
26027 //                                                                           //
26028 // 'optflag' is used for mesh optimization. If it is set, after removing p,  //
26029 // test the object function on each new tet, queue bad tets.                 //
26030 //                                                                           //
26032 
26033 bool tetgenmesh::suppressvolpoint(triface* suptet, list* frontlist,
26034   list* misfrontlist, list* ptlist, queue* flipque, bool optflag)
26035 {
26036   list *myfrontlist, *mymisfrontlist, *myptlist;
26037   list *oldtetlist, *newtetlist;
26038   list *newshlist; // a dummy list.
26039   queue *myflipque;
26040   triface oldtet, newtet;
26041   point suppt, conpt;
26042   bool success;
26043   int j;
26044 
26045   // Allocate spaces for storing (old and new) B(p).
26046   oldtetlist = new list(sizeof(triface), NULL, 256);
26047   newtetlist = new list(sizeof(triface), NULL, 256);
26048   newshlist = new list(sizeof(face), NULL, 256);
26049   // Allocate work lists if user doesn't supply them.
26050   myfrontlist = mymisfrontlist = myptlist = (list *) NULL;
26051   myflipque = (queue *) NULL;
26052   if (frontlist == (list *) NULL) {
26053     myfrontlist = new list(sizeof(triface), NULL, 256);
26054     frontlist = myfrontlist;
26055     mymisfrontlist = new list(sizeof(triface), NULL, 256);
26056     misfrontlist = mymisfrontlist;
26057     myptlist = new list(sizeof(point *), NULL, 256);
26058     ptlist = myptlist;
26059     myflipque = new queue(sizeof(badface));
26060     flipque = myflipque;
26061   }
26062 
26063   suppt = org(*suptet);
26064   oldtet = *suptet;
26065   success = true; // Assume p can be suppressed.
26066 
26067   if (b->verbose > 1) {
26068     printf("    Remove point %d in mesh.\n", pointmark(suppt));
26069   }
26070 
26071   // Form old B(p) in oldtetlist.
26072   oldtetlist->append(&oldtet);
26073   formstarpolyhedron(suppt, oldtetlist, ptlist, false);
26074   // Infect the tets in old B(p) (they're going to be delete).
26075   for (j = 0; j < oldtetlist->len(); j++) {
26076     oldtet = * (triface *)(* oldtetlist)[j];
26077     infect(oldtet);
26078   }
26079   // Tetrahedralize old B(p).
26080   success = constrainedcavity(&oldtet, newshlist, oldtetlist, ptlist,
26081               frontlist, misfrontlist, newtetlist, flipque);
26082   if (!success) {
26083     // Unable to suppress p.
26084     deallocfaketets(frontlist);
26085     // Try to collapse an edge at p.
26086     conpt = (point) NULL;
26087     assert(newtetlist->len() == 0);
26088     if (findcollapseedge(suppt, &conpt, oldtetlist, ptlist)) {
26089       // Collapse the edge suppt->conpt. Re-use newtetlist.
26090       collapseedge(suppt, conpt, oldtetlist, newtetlist);
26091       // The oldtetlist contains newtetlist.
26092       if (optflag) {
26093         assert(newtetlist->len() == 0);
26094         for (j = 0; j < oldtetlist->len(); j++) {
26095           newtet = * (triface *)(* oldtetlist)[j];
26096           newtetlist->append(&newtet);
26097         }
26098       }
26099       oldtetlist->clear(); // Do not delete them.
26100       collapverts++;
26101       success = true;
26102     }
26103   }
26104   if (success) {
26105     // p has been removed! (Still in the pool).
26106     setpointtype(suppt, UNUSEDVERTEX);
26107     unuverts++;
26108     suprelverts++;
26109     // Delete old B(p).
26110     for (j = 0; j < oldtetlist->len(); j++) {
26111       oldtet = * (triface *)(* oldtetlist)[j];
26112       assert(!isdead(&oldtet));
26113       tetrahedrondealloc(oldtet.tet);
26114     }
26115     if (optflag) {
26116       // Check for new bad tets.
26117       for (j = 0; j < newtetlist->len(); j++) {
26118         newtet = * (triface *)(* newtetlist)[j];
26119         if (!isdead(&newtet)) checktet4opt(&newtet, true);
26120       }
26121     }
26122   } else {
26123     // p is not suppressed. Recover the original state.
26124     // Uninfect tets of old B(p).
26125     for (j = 0; j < oldtetlist->len(); j++) {
26126       oldtet = * (triface *)(* oldtetlist)[j];
26127       assert(infected(oldtet));
26128       uninfect(oldtet);
26129     }
26130   }
26131 
26132   // Clear work lists.
26133   ptlist->clear();
26134   frontlist->clear();
26135   misfrontlist->clear();
26136   flipque->clear();
26137   // Deallocate work lists.
26138   if (myfrontlist != (list *) NULL) {
26139     delete myfrontlist;
26140     delete mymisfrontlist;
26141     delete myptlist;
26142     delete myflipque;
26143   }
26144   delete oldtetlist;
26145   delete newtetlist;
26146   delete newshlist;
26147 
26148   return success;
26149 }
26150 
26152 //                                                                           //
26153 // smoothpoint()    Smooth a volume/segment point.                           //
26154 //                                                                           //
26155 // 'smthpt' (p) is inside the polyhedron (C) bounded by faces in 'starlist'. //
26156 // This routine moves p inside C until an object function is maximized.      //
26157 //                                                                           //
26158 // Default, the CCW edge ring of the faces on C points to p. If 'invtori' is //
26159 // TRUE, the orientation is inversed.                                        //
26160 //                                                                           //
26161 // If 'key' != NULL, it contains an object value to be improved. Current it  //
26162 // means the cosine of the largest dihedral angle. In such case, the point   //
26163 // is smoothed only if the final configuration improves the object value, it //
26164 // is returned by the 'key'.                                                 //
26165 //                                                                           //
26167 
26168 bool tetgenmesh::smoothpoint(point smthpt, point e1, point e2, list *starlist,
26169   bool invtori, REAL *key)
26170 {
26171   triface starttet;
26172   point pa, pb, pc;
26173   REAL fcent[3], startpt[3], nextpt[3], bestpt[3];
26174   REAL iniTmax, oldTmax, newTmax;
26175   REAL ori, aspT, aspTmax, imprate;
26176   REAL cosd, maxcosd;
26177   bool segflag, randflag; //, subflag;
26178   int numdirs;
26179   int iter, i, j;
26180 
26181   // Is p a segment vertex?
26182   segflag = (e1 != (point) NULL);
26183   // Decide the number of moving directions.
26184   numdirs = segflag ? 2 : starlist->len();
26185   randflag = numdirs > 10;
26186   if (randflag) {
26187     numdirs = 10; // Maximum 10 directions.
26188   }
26189 
26190   aspTmax = 0.0;
26191   // Calculate the initial object value (the largest aspect ratio).
26192   for (i = 0; i < starlist->len(); i++) {
26193     starttet = * (triface *)(* starlist)[i];
26194     adjustedgering(starttet, !invtori ? CCW : CW);
26195     pa = org(starttet);
26196     pb = dest(starttet);
26197     pc = apex(starttet);
26198     aspT = tetaspectratio(pa, pb, pc, smthpt);
26199     if (i == 0) {
26200       aspTmax = aspT;
26201     } else {
26202       aspTmax = aspT > aspTmax ? aspT : aspTmax;
26203     }
26204   }
26205   iniTmax = aspTmax;
26206 
26207   if (b->verbose > 1) {
26208     printf("    Smooth %s point %d (%g, %g, %g).\n", segflag ? "seg" : "vol",
26209            pointmark(smthpt), smthpt[0], smthpt[1], smthpt[2]);
26210     printf("    Initial max L/h = %g.\n", iniTmax);
26211   }
26212   for (i = 0; i < 3; i++) {
26213     bestpt[i] = startpt[i] = smthpt[i];
26214   }
26215 
26216   // Do iteration until the new aspTmax does not decrease.
26217   newTmax = iniTmax;
26218   iter = 0;
26219   while (true) {
26220     // Find the best next location.
26221     oldTmax = newTmax;
26222     for (i = 0; i < numdirs; i++) {
26223       // Calculate the moved point (saved in 'nextpt').
26224       if (!segflag) {
26225         if (randflag) {
26226           // Randomly pick a direction.
26227           j = (int) randomnation(starlist->len());
26228         } else {
26229           j = i;
26230         }
26231         starttet = * (triface *)(* starlist)[j];
26232         adjustedgering(starttet, !invtori ? CCW : CW);
26233         pa = org(starttet);
26234         pb = dest(starttet);
26235         pc = apex(starttet);
26236         for (j = 0; j < 3; j++) {
26237           fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0;
26238         }
26239       } else {
26240         for (j = 0; j < 3; j++) {
26241           fcent[j] = (i == 0 ? e1[j] : e2[j]);
26242         }
26243       }
26244       for (j = 0; j < 3; j++) {
26245         nextpt[j] = startpt[j] + 0.01 * (fcent[j] - startpt[j]);
26246       }
26247       // Get the largest object value for the new location.
26248       for (j = 0; j < starlist->len(); j++) {
26249         starttet = * (triface *)(* starlist)[j];
26250         adjustedgering(starttet, !invtori ? CCW : CW);
26251         pa = org(starttet);
26252         pb = dest(starttet);
26253         pc = apex(starttet);
26254         ori = orient3d(pa, pb, pc, nextpt);
26255         if (ori < 0.0) {
26256           aspT = tetaspectratio(pa, pb, pc, nextpt);
26257           if (j == 0) {
26258             aspTmax = aspT;
26259           } else {
26260             aspTmax = aspT > aspTmax ? aspT : aspTmax;
26261           }
26262         } else {
26263           // An invalid new tet. Discard this point.
26264           aspTmax = newTmax;
26265         } // if (ori < 0.0)
26266         // Stop looping when the object value is bigger than before.
26267         if (aspTmax >= newTmax) break;
26268       } // for (j = 0; j < starlist->len(); j++)
26269       if (aspTmax < newTmax) {
26270         // Save the improved object value and the location.
26271         newTmax = aspTmax;
26272         for (j = 0; j < 3; j++) bestpt[j] = nextpt[j];
26273       }
26274     } // for (i = 0; i < starlist->len(); i++)
26275     // Does the object value improved much?
26276     imprate = fabs(oldTmax - newTmax) / oldTmax;
26277     if (imprate < 1e-3) break;
26278     // Yes, move p to the new location and continue.
26279     for (j = 0; j < 3; j++) startpt[j] = bestpt[j];
26280     iter++;
26281   } // while (true)
26282 
26283   if (iter > 0) {
26284     // The point is moved.
26285     if (key) {
26286       // Check if the quality is improved by the smoothed point.
26287       maxcosd = 0.0; // = cos(90).
26288       for (j = 0; j < starlist->len(); j++) {
26289         starttet = * (triface *)(* starlist)[j];
26290         adjustedgering(starttet, !invtori ? CCW : CW);
26291         pa = org(starttet);
26292         pb = dest(starttet);
26293         pc = apex(starttet);
26294         tetalldihedral(pa, pb, pc, startpt, NULL, &cosd, NULL);
26295         if (cosd < *key) {
26296           // This quality will not be improved. Stop.
26297           iter = 0; break;
26298         } else {
26299           // Remeber the worst quality value (of the new configuration).
26300           maxcosd = maxcosd < cosd ? maxcosd : cosd;
26301         }
26302       }
26303       if (iter > 0) *key = maxcosd;
26304     }
26305   }
26306 
26307   if (iter > 0) {
26308     segflag ? smoothsegverts++ : smoothvolverts++;
26309     for (i = 0; i < 3; i++) smthpt[i] = startpt[i];
26310     if (b->verbose > 1) {
26311       printf("    Move to new location (%g, %g, %g).\n", smthpt[0], smthpt[1],
26312              smthpt[2]);
26313       printf("    Final max L/h = %g. (%d iterations)\n", newTmax, iter);
26314       if (key) {
26315         printf("    Max. dihed = %g (degree).\n", acos(*key) / PI * 180.0);
26316       }
26317     }
26318     return true;
26319   } else {
26320     if (b->verbose > 1) {
26321       printf("    Not smoothed.\n");
26322     }
26323     return false;
26324   }
26325 }
26326 
26328 //                                                                           //
26329 // removesteiners()    Delete or relocate Steiner points on facets.          //
26330 //                                                                           //
26332 
26333 void tetgenmesh::removesteiners(bool coarseflag)
26334 {
26335   list *frontlist, *misfrontlist;
26336   list *spinshlist, *newsegshlist;
26337   list *ptlist, *conlist;
26338   memorypool *viri;
26339   queue *flipque;
26340   triface checktet;
26341   face shloop;
26342   face segloop, nextseg;
26343   point pa, neipt;
26344   REAL len;
26345   bool remflag;
26346   int *worklist;
26347   int oldnum, rmstein;
26348   int i, j;
26349 
26350   if (!b->quiet) {
26351     if (!coarseflag) {
26352       printf("Removing Steiner points.\n");
26353     } else {
26354       printf("Coarsening mesh.\n");
26355     }
26356   }
26357 
26358   // Initialize work lists.
26359   frontlist = new list(sizeof(triface), NULL);
26360   misfrontlist = new list(sizeof(triface), NULL);
26361   spinshlist = new list(sizeof(face), NULL);
26362   newsegshlist = new list(sizeof(face), NULL);
26363   ptlist = new list(sizeof(point *), NULL);
26364   conlist = new list(sizeof(point *) * 2, NULL);
26365   flipque = new queue(sizeof(badface));
26366   viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
26367   oldnum = unuverts;
26368   relverts = suprelverts = collapverts = unsupverts;
26369   smoothvolverts = 0;
26370   expcavcount = 0;
26371 
26372   // Suppress Steiner points inside facets.
26373   do {
26374     rmstein = unuverts;
26375     subfaces->traversalinit();
26376     shloop.sh = shellfacetraverse(subfaces);
26377     while (shloop.sh != (shellface *) NULL) {
26378       remflag = false;
26379       // Is s contains a Steiner point?
26380       shloop.shver = 0;
26381       for (i = 0; i < 3; i++) {
26382         pa = sapex(shloop);
26383         if (pointtype(pa) == FREESUBVERTEX) {
26384           if (!coarseflag) {
26385             // Remove it if it is not an input point.
26386             j = pointmark(pa) - in->firstnumber;
26387             if (j >= in->numberofpoints) {
26388               if (b->nobisect == 1) {
26389                 // '-Y'. Remove p if s is a hull face.
26390                 stpivot(shloop, checktet);
26391                 if (checktet.tet != dummytet) {
26392                   sesymself(shloop);
26393                   stpivot(shloop, checktet);
26394                 }
26395                 remflag = (checktet.tet == dummytet);
26396               } else {
26397                 // '-YY'. Remove p whatever s is a hull face or not.
26398                 remflag = true;
26399               }
26400             }
26401           } else {
26402             // Check if this vertex can be coarsed.
26403             if (b->nobisect == 0) {
26404               // Is a background mesh available?
26405               if (b->metric) {
26406                 // assert(pa[pointmtrindex] > 0.0);
26407                 // Form the star of pa.
26408                 spinshlist->append(&shloop);
26409                 formstarpolygon(pa, spinshlist, ptlist);
26410                 len = 0.0;
26411                 for (j = 0; j < ptlist->len(); j++) {
26412                   neipt = * (point *)(* ptlist)[j];
26413                   len += distance(pa, neipt);
26414                 }
26415                 len /= ptlist->len();
26416                 // Carse it if the average edge length is small.
26417                 remflag = len < pa[pointmtrindex];
26418                 spinshlist->clear();
26419                 ptlist->clear();
26420               } else {
26421                 // Coarse it if (1) it is an input point and its pointmarker
26422                 //   is zero, or (2) it is a Steiner point.
26423                 remflag = true;
26424                 j = pointmark(pa) - in->firstnumber;
26425                 if (j < in->numberofpoints) {
26426                   remflag = (in->pointmarkerlist[j] == 0);
26427                 }
26428               } // if (b->metric)
26429             } // if (b->nobisect == 0)
26430           } // if (!coarseflag)
26431           if (remflag) break;
26432         } // if (pointtype(pa) == FREESUBVERTEX)
26433         senextself(shloop);
26434       } // for (i = 0; i < 3; i++)
26435       if (remflag) {
26436         suppressfacetpoint(&shloop, frontlist, misfrontlist, ptlist, conlist,
26437                            viri, flipque, coarseflag, false);
26438       }
26439       shloop.sh = shellfacetraverse(subfaces);
26440     }
26441     // Continue if any Steiner point has been removed.
26442   } while (unuverts > rmstein);
26443 
26444   if (coarseflag) {
26445     shellface **segsperverlist;
26446     int *idx2seglist;
26447     face seg1, seg2;
26448     point e1, e2;
26449     // Connecting collinear segments. Hence the segment vertices may be
26450     //   removed. In fact, this should be done by reconstructmesh().
26451     makesegmentmap(idx2seglist, segsperverlist);
26452     subsegs->traversalinit();
26453     segloop.sh = shellfacetraverse(subsegs);
26454     while (segloop.sh != (shellface *) NULL) {
26455       for (i = 0; i < 2; i++) {
26456         segloop.shver = i;
26457         senext(segloop, nextseg);
26458         spivotself(nextseg);
26459         if ((nextseg.sh == dummysh) || (nextseg.sh > segloop.sh)) {
26460           // No neighbor segment connection or haven't been processed yet.
26461           pa = sdest(segloop);
26462           j = pointmark(pa) - in->firstnumber;
26463           if (idx2seglist[j + 1] - idx2seglist[j] == 2) {
26464             // pa is shared by only two segments. Get the other one.
26465             nextseg.sh = segsperverlist[idx2seglist[j]];
26466             if (nextseg.sh == segloop.sh) {
26467               nextseg.sh = segsperverlist[idx2seglist[j] + 1];
26468             }
26469             nextseg.shver = 0;
26470             if (sorg(nextseg) != pa) sesymself(nextseg);
26471             // Check if the two segments are collinear.
26472             e1 = sorg(segloop);
26473             e2 = sdest(nextseg);
26474             if (iscollinear(e1, pa, e2, b->epsilon)) {
26475               // Connect the two segments together.
26476               if (b->verbose > 1) {
26477                 printf("  Glue two insegs (%d, %d) at %d.\n", pointmark(e1),
26478                        pointmark(e2), pointmark(pa));
26479               }
26480               senext(segloop, seg1);
26481               senext2(nextseg, seg2);
26482               sbond(seg1, seg2);
26483             }
26484           }
26485         } // if (nextseg.sh == dummysh)
26486       } // for (i = 0;
26487       segloop.sh = shellfacetraverse(subsegs);
26488     }
26489     delete [] segsperverlist;
26490     delete [] idx2seglist;
26491   }
26492 
26493   // Suppress Steiner points on segments.
26494   do {
26495     rmstein = unuverts;
26496     subsegs->traversalinit();
26497     segloop.sh = shellfacetraverse(subsegs);
26498     while (segloop.sh != (shellface *) NULL) {
26499       remflag = false;
26500       // for (i = 0; i < 2; i++) {
26501         // Don't check the poinytype of pa, it may be a Steiner point but
26502         //   has type NACUTEVERTEX due to splitting a type-3 segment.
26503         segloop.shver = 0; // segloop.shver = i;
26504         senext(segloop, nextseg);
26505         spivotself(nextseg);
26506         if (nextseg.sh != dummysh) {
26507           pa = sdest(segloop); // p is going to be checked for removal.
26508           nextseg.shver = 0;
26509           if (sorg(nextseg) != pa) sesymself(nextseg);
26510           assert(sorg(nextseg) == pa);
26511           if (!coarseflag) {
26512             // try to remove it if it is not an input point.
26513             j = pointmark(pa) - in->firstnumber;
26514             if (j >= in->numberofpoints) {
26515               if (b->nobisect == 1) {
26516                 // '-Y'. Remove p if it is on the hull.
26517                 sstpivot(&segloop, &checktet);
26518                 assert(checktet.tet != dummytet);
26519                 pa = apex(checktet);
26520                 do {
26521                   if (!fnextself(checktet)) {
26522                     // Meet a boundary face - p is on the hull.
26523                     remflag = true; break;
26524                   }
26525                 } while (pa != apex(checktet));
26526               } else {
26527                 // '-YY'. Remove p whatever it is on the hull or not.
26528                 remflag = true;
26529               }
26530             }
26531           } else {
26532             // Check if this vertex can be coarsed.
26533             if (b->nobisect == 0) {
26534               if (b->metric) {
26535                 // assert(pa[pointmtrindex] > 0.0);
26536                 len = 0.0;
26537                 neipt = sorg(segloop);
26538                 for (j = 0; j < 2; j++) {
26539                   len += distance(pa, neipt);
26540                   /*// Is neipt inside the sparse ball of pa?
26541                   if (len < pa[pointmtrindex]) {
26542                     // Yes, the local of pa is too dense, corse it.
26543                     remflag = true; break;
26544                   } */
26545                   neipt = sdest(nextseg);
26546                 }
26547                 len /= 2.0;
26548                 // Carse it if the average edge lengh is small.
26549                 remflag = len < pa[pointmtrindex];
26550               } else {
26551                 // Coarse it if (1) it is an input point and its pointmarker
26552                 //   is zero, or (2) it is a Steiner point.
26553                 remflag = true;
26554                 j = pointmark(pa) - in->firstnumber;
26555                 if (j < in->numberofpoints) {
26556                   remflag = (in->pointmarkerlist[j] == 0);
26557                 }
26558               } // if (b->metric)
26559             } // if (b->nobisect == 0)
26560           } // if (!coarseflag)
26561         } // if (nextseg.sh != dummysh)
26562         // if (remflag) break;
26563       // } // for (i = 0; i < 2; i++)
26564       if (remflag) {
26565         suppresssegpoint(&segloop, spinshlist, newsegshlist, frontlist,
26566           misfrontlist, ptlist, conlist, viri, flipque, coarseflag, false);
26567       }
26568       segloop.sh = shellfacetraverse(subsegs);
26569     }
26570     // Continue if any Steiner point has been removed.
26571   } while (unuverts > rmstein);
26572 
26573   if ((relverts > 0) || coarseflag) {
26574     worklist = new int[points->items + 1];
26575     // Suppress relocated points & coarse free mesh points.
26576     do {
26577       // Initialize the work list. Each entry of the list counts how many
26578       //   times the point has been processed.
26579       for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26580       rmstein = unuverts;
26581       tetrahedrons->traversalinit();
26582       checktet.tet = tetrahedrontraverse();
26583       while (checktet.tet != (tetrahedron *) NULL) {
26584         remflag = false;
26585         for (i = 0; i < 4; i++) {
26586           pa = (point) checktet.tet[4 + i];
26587           if (pointtype(pa) == FREEVOLVERTEX) {
26588             // NOTE. Chenge the number 3 will change the number n of removed
26589             //   Steiner points. In my test, n is larger when it is 1. 3
26590             //   reduces n in a reasonable way (see example, mech_part,
26591             //   thepart), 5 results a larger n than 3 does. While the best
26592             //   result is no limit of this number, but it makes the code
26593             //   extremely slow.
26594             if (worklist[pointmark(pa)] < 3) {
26595               worklist[pointmark(pa)]++;
26596               if (!coarseflag) {
26597                 // Remove p if it is a Steiner point.
26598                 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26599                   remflag = true;
26600                 }
26601               } else {
26602                 if (b->metric) {
26603                   // assert(pa[pointmtrindex] > 0.0);
26604                   // Form the star of pa.
26605                   frontlist->append(&checktet);
26606                   formstarpolyhedron(pa, frontlist, ptlist, true);
26607                   len = 0.0;
26608                   for (j = 0; j < ptlist->len(); j++) {
26609                     neipt = * (point *)(* ptlist)[j];
26610                     len += distance(pa, neipt);
26611                   }
26612                   len /= ptlist->len();
26613                   // Carse it if the average edge length is small.
26614                   remflag = len < pa[pointmtrindex];
26615                   frontlist->clear();
26616                   ptlist->clear();
26617                 } else {
26618                   // Coarse it if (1) it is an input point and its pointmarker
26619                   //   is zero, or (2) it is a Steiner point.
26620                   remflag = true;
26621                   j = pointmark(pa) - in->firstnumber;
26622                   if (j < in->numberofpoints) {
26623                     remflag = (in->pointmarkerlist[j] == 0);
26624                   }
26625                 } // if (b->metric)
26626               } // if (!coarseflag)
26627               if (remflag) break;
26628             } // if (worklist[pointmark(pa)] == 0)
26629           } // if (pointtype(pa) == FREEVOLVERTEX)
26630         } // for (i = 0; i < 4; i++)
26631         if (remflag) {
26632           findorg(&checktet, pa);
26633           assert(org(checktet) == pa);
26634           suppressvolpoint(&checktet, frontlist, misfrontlist, ptlist, flipque,
26635                            false);
26636         }
26637         checktet.tet = tetrahedrontraverse();
26638       }
26639       // Continue if any relocated point has been suppressed.
26640     } while (unuverts > rmstein);
26641 
26642 
26643     // Smooth the unsuppressed points if it is not coarse mesh.
26644     if (!coarseflag && (relverts > suprelverts)) {
26645       if (b->verbose) {
26646         printf("  Smoothing relocated points.\n");
26647       }
26648       for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26649       tetrahedrons->traversalinit();
26650       checktet.tet = tetrahedrontraverse();
26651       while (checktet.tet != (tetrahedron *) NULL) {
26652         for (i = 0; i < 4; i++) {
26653           pa = (point) checktet.tet[4 + i];
26654           if (pointtype(pa) == FREEVOLVERTEX) {
26655             if (worklist[pointmark(pa)] == 0) {
26656               worklist[pointmark(pa)] = 1;
26657               if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26658                 // Smooth pa.
26659                 findorg(&checktet, pa);
26660                 frontlist->append(&checktet);
26661                 formstarpolyhedron(pa, frontlist, NULL, false);
26662                 smoothpoint(pa, NULL, NULL, frontlist, false, NULL);
26663                 frontlist->clear();
26664               }
26665             } // if (worklist[pointmark(pa)] == 0)
26666           } // if (pointtype(pa) == FREEVOLVERTEX)
26667         } // for (i = 0; i < 4; i++)
26668         checktet.tet = tetrahedrontraverse();
26669       }
26670     }
26671     delete [] worklist;
26672   }
26673 
26674   if (b->verbose > 0) {
26675     if (!coarseflag) {
26676       printf("  %d points removed from boundary", unuverts - oldnum);
26677       if (expcavcount > 0) {
26678         printf(" (%d cavity corrections)", expcavcount);
26679       }
26680       printf("\n");
26681       if (relverts > 0) {
26682         printf("  %d points relocated (%d suppressed, %d collapsed).\n",
26683                relverts, suprelverts - collapverts, collapverts);
26684         if (smoothvolverts > 0) {
26685           printf("  %d points are smoothed.\n", smoothvolverts);
26686         }
26687       }
26688       if (unsupverts > 0) {
26689         printf("  !! %d points are unsuppressed.\n", unsupverts);
26690       }
26691     } else {
26692       printf("  %d points are removed.\n", unuverts - oldnum);
26693     }
26694   }
26695 
26696   // Delete work lists.
26697   delete frontlist;
26698   delete misfrontlist;
26699   delete spinshlist;
26700   delete newsegshlist;
26701   delete ptlist;
26702   delete conlist;
26703   delete flipque;
26704   delete viri;
26705 }
26706 
26707 //
26708 // End of boundary Steiner points removing routines
26709 //
26710 
26712 //                                                                           //
26713 // reconstructmesh()    Reconstruct a tetrahedral mesh from a list of        //
26714 //                      tetrahedra and possibly a list of boundary faces.    //
26715 //                                                                           //
26716 // The list of tetrahedra is stored in 'in->tetrahedronlist',  the list of   //
26717 // boundary faces is stored in 'in->trifacelist'.  The tetrahedral mesh is   //
26718 // reconstructed in memorypool 'tetrahedrons', its boundary faces (subfaces) //
26719 // are reconstructed in 'subfaces', its boundary edges (subsegments) are     //
26720 // reconstructed in 'subsegs'. If the -a switch is used, this procedure will //
26721 // also read a list of REALs from 'in->tetrahedronvolumelist' and set a      //
26722 // maximum volume constraint on each tetrahedron.                            //
26723 //                                                                           //
26724 // If the user has provided the boundary faces in 'in->trifacelist', they    //
26725 // will be inserted the mesh. Otherwise subfaces will be identified from the //
26726 // mesh.  All hull faces (including faces of the internal holes) will be     //
26727 // recognized as subfaces, internal faces between two tetrahedra which have  //
26728 // different attributes will also be recognized as subfaces.                 //
26729 //                                                                           //
26730 // Subsegments will be identified after subfaces are reconstructed. Edges at //
26731 // the intersections of non-coplanar subfaces are recognized as subsegments. //
26732 // Edges between two coplanar subfaces with different boundary markers are   //
26733 // also recognized as subsegments.                                           //
26734 //                                                                           //
26735 // The facet index of each subface will be set automatically after we have   //
26736 // recovered subfaces and subsegments.  That is, the set of subfaces, which  //
26737 // are coplanar and have the same boundary marker will be recognized as a    //
26738 // facet and has a unique index, stored as the facet marker in each subface  //
26739 // of the set, the real boundary marker of each subface will be found in     //
26740 // 'in->facetmarkerlist' by the index.  Facet index will be used in Delaunay //
26741 // refinement for detecting two incident facets.                             //
26742 //                                                                           //
26743 // Points which are not corners of tetrahedra will be inserted into the mesh.//
26744 // Return the number of faces on the hull after the reconstruction.          //
26745 //                                                                           //
26747 
26748 long tetgenmesh::reconstructmesh()
26749 {
26750   tetrahedron **tetsperverlist;
26751   shellface **facesperverlist;
26752   triface tetloop, neightet, neineightet, spintet;
26753   face subloop, neighsh, neineighsh, subseg;
26754   face sface1, sface2;
26755   point *idx2verlist;
26756   point torg, tdest, tapex, toppo;
26757   point norg, ndest, napex;
26758   list *neighshlist, *markerlist;
26759   REAL sign, attrib, volume;
26760   REAL da1, da2;
26761   bool bondflag, insertsegflag;
26762   int *idx2tetlist;
26763   int *idx2facelist;
26764   int *worklist;
26765   int facetidx, marker;
26766   int iorg, idest, iapex, ioppo;
26767   int inorg, indest, inapex;
26768   int index, i, j;
26769 
26770   if (!b->quiet) {
26771     printf("Reconstructing mesh.\n");
26772   }
26773 
26774   // Create a map from index to points.
26775   makeindex2pointmap(idx2verlist);
26776 
26777   // Create the tetrahedra.
26778   for (i = 0; i < in->numberoftetrahedra; i++) {
26779     // Create a new tetrahedron and set its four corners, make sure that
26780     //   four corners form a positive orientation.
26781     maketetrahedron(&tetloop);
26782     index = i * in->numberofcorners;
26783     // Although there may be 10 nodes, we only read the first 4.
26784     iorg = in->tetrahedronlist[index] - in->firstnumber;
26785     idest = in->tetrahedronlist[index + 1] - in->firstnumber;
26786     iapex = in->tetrahedronlist[index + 2] - in->firstnumber;
26787     ioppo = in->tetrahedronlist[index + 3] - in->firstnumber;
26788     torg = idx2verlist[iorg];
26789     tdest = idx2verlist[idest];
26790     tapex = idx2verlist[iapex];
26791     toppo = idx2verlist[ioppo];
26792     sign = orient3d(torg, tdest, tapex, toppo);
26793     if (sign > 0.0) {
26794       norg = torg; torg = tdest; tdest = norg;
26795     } else if (sign == 0.0) {
26796       if (!b->quiet) {
26797         printf("Warning:  Tet %d is degenerate.\n", i + in->firstnumber);
26798       }
26799     }
26800     setorg(tetloop, torg);
26801     setdest(tetloop, tdest);
26802     setapex(tetloop, tapex);
26803     setoppo(tetloop, toppo);
26804     // Temporarily set the vertices be type FREEVOLVERTEX, to indicate that
26805     //   they belong to the mesh.  These types may be changed later.
26806     setpointtype(torg, FREEVOLVERTEX);
26807     setpointtype(tdest, FREEVOLVERTEX);
26808     setpointtype(tapex, FREEVOLVERTEX);
26809     setpointtype(toppo, FREEVOLVERTEX);
26810     // Set element attributes if they exist.
26811     for (j = 0; j < in->numberoftetrahedronattributes; j++) {
26812       index = i * in->numberoftetrahedronattributes;
26813       attrib = in->tetrahedronattributelist[index + j];
26814       setelemattribute(tetloop.tet, j, attrib);
26815     }
26816     // If -a switch is used (with no number follows) Set a volume
26817     //   constraint if it exists.
26818     if (b->varvolume) {
26819       if (in->tetrahedronvolumelist != (REAL *) NULL) {
26820         volume = in->tetrahedronvolumelist[i];
26821       } else {
26822         volume = -1.0;
26823       }
26824       setvolumebound(tetloop.tet, volume);
26825     }
26826   }
26827 
26828   // Set the connection between tetrahedra.
26829   hullsize = 0l;
26830   // Create a map from nodes to tetrahedra.
26831   maketetrahedronmap(idx2tetlist, tetsperverlist);
26832   // Initialize the worklist.
26833   worklist = new int[points->items];
26834   for (i = 0; i < points->items; i++) worklist[i] = 0;
26835 
26836   // Loop all tetrahedra, bond two tetrahedra if they share a common face.
26837   tetrahedrons->traversalinit();
26838   tetloop.tet = tetrahedrontraverse();
26839   while (tetloop.tet != (tetrahedron *) NULL) {
26840     // Loop the four sides of the tetrahedron.
26841     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26842       sym(tetloop, neightet);
26843       if (neightet.tet != dummytet) continue; // This side has finished.
26844       torg = org(tetloop);
26845       tdest = dest(tetloop);
26846       tapex = apex(tetloop);
26847       iorg = pointmark(torg) - in->firstnumber;
26848       idest = pointmark(tdest) - in->firstnumber;
26849       iapex = pointmark(tapex) - in->firstnumber;
26850       worklist[iorg] = 1;
26851       worklist[idest] = 1;
26852       worklist[iapex] = 1;
26853       bondflag = false;
26854       // Search its neighbor in the adjacent tets of torg.
26855       for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26856            j++) {
26857         if (tetsperverlist[j] == tetloop.tet) continue; // Skip myself.
26858         neightet.tet = tetsperverlist[j];
26859         for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26860           sym(neightet, neineightet);
26861           if (neineightet.tet == dummytet) {
26862             norg = org(neightet);
26863             ndest = dest(neightet);
26864             napex = apex(neightet);
26865             inorg = pointmark(norg) - in->firstnumber;
26866             indest = pointmark(ndest) - in->firstnumber;
26867             inapex = pointmark(napex) - in->firstnumber;
26868             if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26869               // Find! Bond them together and break the loop.
26870               bond(tetloop, neightet);
26871               bondflag = true;
26872               break;
26873             }
26874           }
26875         }
26876       }
26877       if (!bondflag) {
26878         hullsize++;  // It's a hull face.
26879         // Bond this side to outer space.
26880         dummytet[0] = encode(tetloop);
26881         if ((in->pointmarkerlist != (int *) NULL) && !b->coarse) {
26882           // Set its three corners's markers be boundary (hull) vertices.
26883           if (in->pointmarkerlist[iorg] == 0) {
26884             in->pointmarkerlist[iorg] = 1;
26885           }
26886           if (in->pointmarkerlist[idest] == 0) {
26887             in->pointmarkerlist[idest] = 1;
26888           }
26889           if (in->pointmarkerlist[iapex] == 0) {
26890             in->pointmarkerlist[iapex] = 1;
26891           }
26892         }
26893       }
26894       worklist[iorg] = 0;
26895       worklist[idest] = 0;
26896       worklist[iapex] = 0;
26897     }
26898     tetloop.tet = tetrahedrontraverse();
26899   }
26900 
26901   // Subfaces will be inserted into the mesh. It has two phases:
26902   //   (1) Insert subfaces provided by user (in->trifacelist);
26903   //   (2) Create subfaces for hull faces (if they're not subface yet) and
26904   //       interior faces which separate two different materials.
26905 
26906   // Phase (1). Is there a list of user-provided subfaces?
26907   if (in->trifacelist != (int *) NULL) {
26908     // Recover subfaces from 'in->trifacelist'.
26909     for (i = 0; i < in->numberoftrifaces; i++) {
26910       index = i * 3;
26911       iorg = in->trifacelist[index] - in->firstnumber;
26912       idest = in->trifacelist[index + 1] - in->firstnumber;
26913       iapex = in->trifacelist[index + 2] - in->firstnumber;
26914       // Look for the location of this subface.
26915       worklist[iorg] = 1;
26916       worklist[idest] = 1;
26917       worklist[iapex] = 1;
26918       bondflag = false;
26919       // Search its neighbor in the adjacent tets of torg.
26920       for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26921            j++) {
26922         neightet.tet = tetsperverlist[j];
26923         for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26924           norg = org(neightet);
26925           ndest = dest(neightet);
26926           napex = apex(neightet);
26927           inorg = pointmark(norg) - in->firstnumber;
26928           indest = pointmark(ndest) - in->firstnumber;
26929           inapex = pointmark(napex) - in->firstnumber;
26930           if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26931             bondflag = true;  // Find!
26932             break;
26933           }
26934         }
26935       }
26936       if (bondflag) {
26937         // Create a new subface and insert it into the mesh.
26938         makeshellface(subfaces, &subloop);
26939         torg = idx2verlist[iorg];
26940         tdest = idx2verlist[idest];
26941         tapex = idx2verlist[iapex];
26942         setsorg(subloop, torg);
26943         setsdest(subloop, tdest);
26944         setsapex(subloop, tapex);
26945         // Set the vertices be FREESUBVERTEX to indicate they belong to a
26946         //   facet of the domain.  They may be changed later.
26947         setpointtype(torg, FREESUBVERTEX);
26948         setpointtype(tdest, FREESUBVERTEX);
26949         setpointtype(tapex, FREESUBVERTEX);
26950         if (in->trifacemarkerlist != (int *) NULL) {
26951           setshellmark(subloop, in->trifacemarkerlist[i]);
26952         }
26953         adjustedgering(neightet, CCW);
26954         findedge(&subloop, org(neightet), dest(neightet));
26955         tsbond(neightet, subloop);
26956         sym(neightet, neineightet);
26957         if (neineightet.tet != dummytet) {
26958           sesymself(subloop);
26959           tsbond(neineightet, subloop);
26960         }
26961       } else {
26962         if (!b->quiet) {
26963           printf("Warning:  Subface %d is discarded.\n", i + in->firstnumber);
26964         }
26965       }
26966       worklist[iorg] = 0;
26967       worklist[idest] = 0;
26968       worklist[iapex] = 0;
26969     }
26970   }
26971 
26972   // Phase (2). Indentify subfaces from the mesh.
26973   tetrahedrons->traversalinit();
26974   tetloop.tet = tetrahedrontraverse();
26975   while (tetloop.tet != (tetrahedron *) NULL) {
26976     // Loop the four sides of the tetrahedron.
26977     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26978       tspivot(tetloop, subloop);
26979       if (subloop.sh != dummysh) continue;
26980       bondflag = false;
26981       sym(tetloop, neightet);
26982       if (neightet.tet == dummytet) {
26983         // It's a hull face. Insert a subface at here.
26984         bondflag = true;
26985       } else {
26986         // It's an interior face. Insert a subface if two tetrahedra have
26987         //   different attributes (i.e., they belong to two regions).
26988         if (in->numberoftetrahedronattributes > 0) {
26989           if (elemattribute(neightet.tet,
26990               in->numberoftetrahedronattributes - 1) !=
26991               elemattribute(tetloop.tet,
26992               in->numberoftetrahedronattributes - 1)) {
26993             bondflag = true;
26994           }
26995         }
26996       }
26997       if (bondflag) {
26998         adjustedgering(tetloop, CCW);
26999         makeshellface(subfaces, &subloop);
27000         torg = org(tetloop);
27001         tdest = dest(tetloop);
27002         tapex = apex(tetloop);
27003         setsorg(subloop, torg);
27004         setsdest(subloop, tdest);
27005         setsapex(subloop, tapex);
27006         // Set the vertices be FREESUBVERTEX to indicate they belong to a
27007         //   facet of the domain.  They may be changed later.
27008         setpointtype(torg, FREESUBVERTEX);
27009         setpointtype(tdest, FREESUBVERTEX);
27010         setpointtype(tapex, FREESUBVERTEX);
27011         tsbond(tetloop, subloop);
27012         if (neightet.tet != dummytet) {
27013           sesymself(subloop);
27014           tsbond(neightet, subloop);
27015         }
27016       }
27017     }
27018     tetloop.tet = tetrahedrontraverse();
27019   }
27020 
27021   // Set the connection between subfaces. A subsegment may have more than
27022   //   two subfaces sharing it, 'neighshlist' stores all subfaces sharing
27023   //   one edge.
27024   neighshlist = new list(sizeof(face), NULL);
27025   // Create a map from nodes to subfaces.
27026   makesubfacemap(idx2facelist, facesperverlist);
27027 
27028   // Loop over the set of subfaces, setup the connection between subfaces.
27029   subfaces->traversalinit();
27030   subloop.sh = shellfacetraverse(subfaces);
27031   while (subloop.sh != (shellface *) NULL) {
27032     for (i = 0; i < 3; i++) {
27033       spivot(subloop, neighsh);
27034       if (neighsh.sh == dummysh) {
27035         // This side is 'empty', operate on it.
27036         torg = sorg(subloop);
27037         tdest = sdest(subloop);
27038         tapex = sapex(subloop);
27039         neighshlist->append(&subloop);
27040         iorg = pointmark(torg) - in->firstnumber;
27041         // Search its neighbor in the adjacent list of torg.
27042         for (j = idx2facelist[iorg]; j < idx2facelist[iorg + 1]; j++) {
27043           neighsh.sh = facesperverlist[j];
27044           if (neighsh.sh == subloop.sh) continue;
27045           neighsh.shver = 0;
27046           if (isfacehasedge(&neighsh, torg, tdest)) {
27047             findedge(&neighsh, torg, tdest);
27048             // Insert 'neighsh' into 'neighshlist'.
27049             if (neighshlist->len() < 2) {
27050               neighshlist->append(&neighsh);
27051             } else {
27052               for (index = 0; index < neighshlist->len() - 1; index++) {
27053                 sface1 = * (face *)(* neighshlist)[index];
27054                 sface2 = * (face *)(* neighshlist)[index + 1];
27055                 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(neighsh));
27056                 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
27057                 if (da1 < da2) {
27058                   break;  // Insert it after index.
27059                 }
27060               }
27061               neighshlist->insert(index + 1, &neighsh);
27062             }
27063           }
27064         }
27065         // Bond the subfaces in 'neighshlist'.
27066         if (neighshlist->len() > 1) {
27067           neighsh = * (face *)(* neighshlist)[0];
27068           for (j = 1; j <= neighshlist->len(); j++) {
27069             if (j < neighshlist->len()) {
27070               neineighsh = * (face *)(* neighshlist)[j];
27071             } else {
27072               neineighsh = * (face *)(* neighshlist)[0];
27073             }
27074             sbond1(neighsh, neineighsh);
27075             neighsh = neineighsh;
27076           }
27077         } else {
27078           // No neighbor subface be found, bond 'subloop' to itself.
27079           sbond(subloop, subloop);
27080         }
27081         neighshlist->clear();
27082       }
27083       senextself(subloop);
27084     }
27085     subloop.sh = shellfacetraverse(subfaces);
27086   }
27087 
27088   // Segments will be introudced. Each segment has a unique marker (1-based).
27089   marker = 1;
27090   subfaces->traversalinit();
27091   subloop.sh = shellfacetraverse(subfaces);
27092   while (subloop.sh != (shellface *) NULL) {
27093     for (i = 0; i < 3; i++) {
27094       sspivot(subloop, subseg);
27095       if (subseg.sh == dummysh) {
27096         // This side has no subsegment bonded, check it.
27097         torg = sorg(subloop);
27098         tdest = sdest(subloop);
27099         tapex = sapex(subloop);
27100         spivot(subloop, neighsh);
27101         spivot(neighsh, neineighsh);
27102         insertsegflag = false;
27103         if (subloop.sh == neighsh.sh || subloop.sh != neineighsh.sh) {
27104           // This side is either self-bonded or more than two subfaces,
27105           //   insert a subsegment at this side.
27106           insertsegflag = true;
27107         } else {
27108           // Only two subfaces case.
27109 #ifdef SELF_CHECK
27110           assert(subloop.sh != neighsh.sh);
27111 #endif
27112           napex = sapex(neighsh);
27113           sign = orient3d(torg, tdest, tapex, napex);
27114           if (iscoplanar(torg, tdest, tapex, napex, sign, b->epsilon)) {
27115             // Although they are coplanar, we still need to check if they
27116             //   have the same boundary marker.
27117             insertsegflag = (shellmark(subloop) != shellmark(neighsh));
27118           } else {
27119             // Non-coplanar.
27120             insertsegflag = true;
27121           }
27122         }
27123         if (insertsegflag) {
27124           // Create a subsegment at this side.
27125           makeshellface(subsegs, &subseg);
27126           setsorg(subseg, torg);
27127           setsdest(subseg, tdest);
27128           // The two vertices have been marked as FREESUBVERTEX. Now mark
27129           //   them as NACUTEVERTEX.
27130           setpointtype(torg, NACUTEVERTEX);
27131           setpointtype(tdest, NACUTEVERTEX);
27132           setshellmark(subseg, marker);
27133           marker++;
27134           // Bond all subfaces to this subsegment.
27135           neighsh = subloop;
27136           do {
27137             ssbond(neighsh, subseg);
27138             spivotself(neighsh);
27139           } while (neighsh.sh != subloop.sh);
27140         }
27141       }
27142       senextself(subloop);
27143     }
27144     subloop.sh = shellfacetraverse(subfaces);
27145   }
27146   // Remember the number of input segments.
27147   insegments = subsegs->items;
27148   // Find the acute vertices and set them be type ACUTEVERTEX.
27149 
27150   // Indentify facets and set the facet marker (1-based) for subfaces.
27151   markerlist = new list((char*)"int");
27152 
27153   subfaces->traversalinit();
27154   subloop.sh = shellfacetraverse(subfaces);
27155   while (subloop.sh != (shellface *) NULL) {
27156     // Only operate on uninfected subface, after operating, infect it.
27157     if (!sinfected(subloop)) {
27158       // A new facet is found.
27159       marker = shellmark(subloop);
27160       markerlist->append(&marker);
27161       facetidx = markerlist->len(); // 'facetidx' starts from 1.
27162       setshellmark(subloop, facetidx);
27163       sinfect(subloop);
27164       neighshlist->append(&subloop);
27165       // Find out all subfaces of this facet (bounded by subsegments).
27166       for (i = 0; i < neighshlist->len(); i++) {
27167         neighsh = * (face *) (* neighshlist)[i];
27168         for (j = 0; j < 3; j++) {
27169           sspivot(neighsh, subseg);
27170           if (subseg.sh == dummysh) {
27171             spivot(neighsh, neineighsh);
27172             if (!sinfected(neineighsh)) {
27173               // 'neineighsh' is in the same facet as 'subloop'.
27174 #ifdef SELF_CHECK
27175               assert(shellmark(neineighsh) == marker);
27176 #endif
27177               setshellmark(neineighsh, facetidx);
27178               sinfect(neineighsh);
27179               neighshlist->append(&neineighsh);
27180             }
27181           }
27182           senextself(neighsh);
27183         }
27184       }
27185       neighshlist->clear();
27186     }
27187     subloop.sh = shellfacetraverse(subfaces);
27188   }
27189   // Uninfect all subfaces.
27190   subfaces->traversalinit();
27191   subloop.sh = shellfacetraverse(subfaces);
27192   while (subloop.sh != (shellface *) NULL) {
27193 #ifdef SELF_CHECK
27194     assert(sinfected(subloop));
27195 #endif
27196     suninfect(subloop);
27197     subloop.sh = shellfacetraverse(subfaces);
27198   }
27199   // Save the facet markers in 'in->facetmarkerlist'.
27200   in->numberoffacets = markerlist->len();
27201   in->facetmarkerlist = new int[in->numberoffacets];
27202   for (i = 0; i < in->numberoffacets; i++) {
27203     marker = * (int *) (* markerlist)[i];
27204     in->facetmarkerlist[i] = marker;
27205   }
27206   // Initialize the 'facetabovepointlist'.
27207   facetabovepointarray = new point[in->numberoffacets + 1];
27208   for (i = 0; i < in->numberoffacets + 1; i++) {
27209     facetabovepointarray[i] = (point) NULL;
27210   }
27211 
27212   // The mesh contains boundary now.
27213   checksubfaces = 1;
27214   // The mesh is nonconvex now.
27215   nonconvex = 1;
27216 
27217   // Is there periodic boundary confitions?
27218   if (checkpbcs) {
27219     tetgenio::pbcgroup *pg;
27220     pbcdata *pd;
27221     // Initialize the global array 'subpbcgrouptable'.
27222     createsubpbcgrouptable();
27223     // Loop for each pbcgroup i.
27224     for (i = 0; i < in->numberofpbcgroups; i++) {
27225       pg = &(in->pbcgrouplist[i]);
27226       pd = &(subpbcgrouptable[i]);
27227       // Find all subfaces of pd, set each subface's group id be i.
27228       for (j = 0; j < 2; j++) {
27229         subfaces->traversalinit();
27230         subloop.sh = shellfacetraverse(subfaces);
27231         while (subloop.sh != (shellface *) NULL) {
27232           facetidx = shellmark(subloop);
27233           marker = in->facetmarkerlist[facetidx - 1];
27234           if (marker == pd->fmark[j]) {
27235             setshellpbcgroup(subloop, i);
27236             pd->ss[j] = subloop;
27237           }
27238           subloop.sh = shellfacetraverse(subfaces);
27239         }
27240       }
27241       if (pg->pointpairlist != (int *) NULL) {
27242         // Set the connections between pbc point pairs.
27243         for (j = 0; j < pg->numberofpointpairs; j++) {
27244           iorg = pg->pointpairlist[j * 2] - in->firstnumber;
27245           idest = pg->pointpairlist[j * 2 + 1] - in->firstnumber;
27246           torg = idx2verlist[iorg];
27247           tdest = idx2verlist[idest];
27248           setpoint2pbcpt(torg, tdest);
27249           setpoint2pbcpt(tdest, torg);
27250         }
27251       }
27252     }
27253     // Create the global array 'segpbcgrouptable'.
27254     createsegpbcgrouptable();
27255   }
27256 
27257   delete markerlist;
27258   delete neighshlist;
27259   delete [] worklist;
27260   delete [] idx2tetlist;
27261   delete [] tetsperverlist;
27262   delete [] idx2facelist;
27263   delete [] facesperverlist;
27264   delete [] idx2verlist;
27265 
27266   return hullsize;
27267 }
27268 
27270 //                                                                           //
27271 // insertconstrainedpoints()    Insert a list of constrained points.         //
27272 //                                                                           //
27274 
27275 void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
27276 {
27277   queue *flipqueue;
27278   triface searchtet;
27279   face checksh, checkseg;
27280   point newpoint;
27281   enum locateresult loc;
27282   REAL *attr;
27283   bool insertflag;
27284   int covertices, outvertices;
27285   int index;
27286   int i, j;
27287 
27288   if (!b->quiet) {
27289     printf("Insert additional points into mesh.\n");
27290   }
27291   // Initialize 'flipqueue'.
27292   flipqueue = new queue(sizeof(badface));
27293   recenttet.tet = dummytet;
27294   covertices = outvertices = 0;
27295 
27296   index = 0;
27297   for (i = 0; i < addio->numberofpoints; i++) {
27298     // Create a newpoint.
27299     makepoint(&newpoint);
27300     newpoint[0] = addio->pointlist[index++];
27301     newpoint[1] = addio->pointlist[index++];
27302     newpoint[2] = addio->pointlist[index++];
27303     // Read the add point attributes if current points have attributes.
27304     if ((addio->numberofpointattributes > 0) &&
27305         (in->numberofpointattributes > 0)) {
27306       attr = addio->pointattributelist + addio->numberofpointattributes * i;
27307       for (j = 0; j < in->numberofpointattributes; j++) {
27308         if (j < addio->numberofpointattributes) {
27309           newpoint[3 + j] = attr[j];
27310         }
27311       }
27312     }
27313     // Find the location of the inserted point.
27314     searchtet = recenttet;
27315     loc = locate(newpoint, &searchtet);
27316     if (loc != ONVERTEX) {
27317       loc = adjustlocate(newpoint, &searchtet, loc, b->epsilon2);
27318     }
27319     if (loc == OUTSIDE) {
27320       loc = hullwalk(newpoint, &searchtet);
27321       if (loc == OUTSIDE) {
27322         // Perform a brute-force search.
27323         tetrahedrons->traversalinit();
27324         searchtet.tet = tetrahedrontraverse();
27325         while (searchtet.tet != (tetrahedron *) NULL) {
27326           loc = adjustlocate(newpoint, &searchtet, OUTSIDE, b->epsilon2);
27327           if (loc != OUTSIDE) break;
27328           searchtet.tet = tetrahedrontraverse();
27329         }
27330       }
27331     }
27332     // Insert the point if it not lies outside or on a vertex.
27333     insertflag = true;
27334     switch (loc) {
27335     case INTETRAHEDRON:
27336       setpointtype(newpoint, FREEVOLVERTEX);
27337       splittetrahedron(newpoint, &searchtet, flipqueue);
27338       break;
27339     case ONFACE:
27340       tspivot(searchtet, checksh);
27341       if (checksh.sh != dummysh) {
27342         // It is a boundary face. Don't insert it if -Y option is used.
27343         if (b->nobisect) {
27344           insertflag = false;
27345         } else {
27346           setpointtype(newpoint, FREESUBVERTEX);
27347         }
27348       } else {
27349         setpointtype(newpoint, FREEVOLVERTEX);
27350       }
27351       if (insertflag) {
27352         splittetface(newpoint, &searchtet, flipqueue);
27353       }
27354       break;
27355     case ONEDGE:
27356       tsspivot(&searchtet, &checkseg);
27357       if (checkseg.sh != dummysh) {
27358         if (b->nobisect) {
27359           insertflag = false;
27360         } else {
27361           setpointtype(newpoint, FREESEGVERTEX);
27362           setpoint2sh(newpoint, sencode(checkseg));
27363         }
27364       } else {
27365         tspivot(searchtet, checksh);
27366         if (checksh.sh != dummysh) {
27367           if (b->nobisect) {
27368             insertflag = false;
27369           } else {
27370             setpointtype(newpoint, FREESUBVERTEX);
27371           }
27372         } else {
27373           setpointtype(newpoint, FREEVOLVERTEX);
27374         }
27375       }
27376       if (insertflag) {
27377         splittetedge(newpoint, &searchtet, flipqueue);
27378       }
27379       break;
27380     case ONVERTEX:
27381       insertflag = false;
27382       covertices++;
27383       break;
27384     case OUTSIDE:
27385       insertflag = false;
27386       outvertices++;
27387       break;
27388     }
27389     // Remember the tetrahedron for next point searching.
27390     recenttet = searchtet;
27391     if (!insertflag) {
27392       pointdealloc(newpoint);
27393     } else {
27394       flip(flipqueue, NULL);
27395     }
27396   }
27397 
27398   if (b->verbose) {
27399     if (covertices > 0) {
27400       printf("  %d constrained points already exist.\n", covertices);
27401     }
27402     if (outvertices > 0) {
27403       printf("  %d constrained points lie outside the mesh.\n", outvertices);
27404     }
27405     printf("  %d constrained points have been inserted.\n",
27406            addio->numberofpoints - covertices - outvertices);
27407   }
27408 
27409   delete flipqueue;
27410 }
27411 
27413 //                                                                           //
27414 // p1interpolatebgm()    Set pt size by p^1 interpolation in background mesh.//
27415 //                                                                           //
27416 // On input, 'bgmtet' is a suggesting tet in background mesh for searching   //
27417 // 'pt'. It returns the tet containing 'pt'.                                 //
27418 //                                                                           //
27420 
27421 bool tetgenmesh::p1interpolatebgm(point pt, triface* bgmtet, long *scount)
27422 {
27423   point bgmpt[4];
27424   enum locateresult loc;
27425   REAL vol, volpt[4], weights[4];
27426   int i;
27427 
27428   loc = bgm->preciselocate(pt, bgmtet, bgm->tetrahedrons->items);
27429   if (loc == OUTSIDE) {
27430     loc = bgm->hullwalk(pt, bgmtet);
27431     if (loc == OUTSIDE) {
27432       // Perform a brute-force search.
27433       if (b->verbose) {
27434         printf("Warning:  Global point location.\n");
27435       }
27436       if (scount) (*scount)++;
27437       bgm->tetrahedrons->traversalinit(); // in bgm
27438       bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
27439       while (bgmtet->tet != (tetrahedron *) NULL) {
27440         loc = bgm->adjustlocate(pt, bgmtet, OUTSIDE, b->epsilon);
27441         if (loc != OUTSIDE) break;
27442         bgmtet->tet = bgm->tetrahedrontraverse(); // in bgm
27443       }
27444     }
27445   }
27446   if (loc != OUTSIDE) {
27447     // Let p remember t.
27448     setpoint2bgmtet(pt, encode(*bgmtet)); // in m
27449     // get the corners of t.
27450     for (i = 0; i < 4; i++) bgmpt[i] = (point) bgmtet->tet[4 + i];
27451     // Calculate the weighted coordinates of p in t.
27452     vol = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], bgmpt[3]);
27453     volpt[0] = orient3d(pt, bgmpt[1], bgmpt[2], bgmpt[3]);
27454     volpt[1] = orient3d(bgmpt[0], pt, bgmpt[2], bgmpt[3]);
27455     volpt[2] = orient3d(bgmpt[0], bgmpt[1], pt, bgmpt[3]);
27456     volpt[3] = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], pt);
27457     for (i = 0; i < 4; i++) weights[i] = fabs(volpt[i] / vol);
27458     // Interpolate the solution for p.
27459     for (i = 0; i < bgm->in->numberofpointmtrs; i++) {
27460       pt[pointmtrindex + i] = weights[0] * bgmpt[0][bgm->pointmtrindex + i]
27461                             + weights[1] * bgmpt[1][bgm->pointmtrindex + i]
27462                             + weights[2] * bgmpt[2][bgm->pointmtrindex + i]
27463                             + weights[3] * bgmpt[3][bgm->pointmtrindex + i];
27464     }
27465   } else {
27466     setpoint2bgmtet(pt, (tetrahedron) NULL);  // in m
27467   }
27468   return loc != OUTSIDE;
27469 }
27470 
27472 //                                                                           //
27473 // interpolatesizemap()    Interpolate the point sizes in the given size map.//
27474 //                                                                           //
27475 // The size map is specified on each node of the background mesh. The points //
27476 // of current mesh get their sizes by interpolating.                         //
27477 //                                                                           //
27478 // This function operation on two meshes simultaneously, the current mesh m, //
27479 // and the background mesh bgm. After this function, each point p in m will  //
27480 // have a pointer to a tet of bgm.                                           //
27481 //                                                                           //
27483 
27484 void tetgenmesh::interpolatesizemap()
27485 {
27486   list *adjtetlist;
27487   triface tetloop, neightet, bgmtet;
27488   point searchpt;
27489   long scount;
27490   int *worklist;
27491   int sepcount;
27492   int i;
27493 
27494   if (b->verbose) {
27495     printf("  Interpolating size map.\n");
27496   }
27497 
27498   worklist = new int[points->items + 1];
27499   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
27500   sepcount = 0;
27501   scount = 0l;
27502 
27503   tetrahedrons->traversalinit();
27504   tetloop.tet = tetrahedrontraverse();
27505   while (tetloop.tet != (tetrahedron *) NULL) {
27506     if (!infected(tetloop)) {
27507       // Find a new subdomain.
27508       adjtetlist = new list(sizeof(triface), NULL, 1024);
27509       infect(tetloop);
27510       // Search the four corners in background mesh.
27511       for (i = 0; i < 4; i++) {
27512         searchpt = (point) tetloop.tet[4 + i];
27513         // Mark the point for avoiding multiple searchings.
27514         // assert(worklist[pointmark(searchpt)] == 0);
27515         worklist[pointmark(searchpt)] = 1;
27516         // Does it contain a pointer to bgm tet?
27517         bgm->decode(point2bgmtet(searchpt), bgmtet);
27518         if (bgm->isdead(&bgmtet)) {
27519           bgmtet = bgm->recenttet;
27520         }
27521         if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27522           bgm->recenttet = bgmtet;
27523         }
27524       } // for (i = 0; i < 4; i++)
27525       // Collect all tets in this region.
27526       adjtetlist->append(&tetloop);
27527       // Collect the tets in the subdomain.
27528       for (i = 0; i < adjtetlist->len(); i++) {
27529         tetloop = * (triface *)(* adjtetlist)[i];
27530         for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27531           sym(tetloop, neightet);
27532           if ((neightet.tet != dummytet) && !infected(neightet)) {
27533             // Only need to search for the opposite point.
27534             searchpt = oppo(neightet);
27535             if (worklist[pointmark(searchpt)] == 0) {
27536               worklist[pointmark(searchpt)] = 1;
27537               decode(point2bgmtet(searchpt), bgmtet);
27538               if (bgm->isdead(&bgmtet)) {
27539                 bgmtet = bgm->recenttet;
27540               }
27541               if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27542                 bgm->recenttet = bgmtet;
27543               }
27544             }
27545             infect(neightet);
27546             adjtetlist->append(&neightet);
27547           }
27548         }
27549       }
27550       // Increase the number of separated domains.
27551       sepcount++;
27552       delete adjtetlist;
27553     } // if (!infect())
27554     tetloop.tet = tetrahedrontraverse();
27555   }
27556 
27557   // Unmark all tets.
27558   tetrahedrons->traversalinit();
27559   tetloop.tet = tetrahedrontraverse();
27560   while (tetloop.tet != (tetrahedron *) NULL) {
27561     assert(infected(tetloop));
27562     uninfect(tetloop);
27563     tetloop.tet = tetrahedrontraverse();
27564   }
27565   delete [] worklist;
27566 
27567 #ifdef SELF_CHECK
27568   if (b->verbose && scount > 0l) {
27569     printf("  %ld brute-force searches.\n", scount);
27570   }
27571   if (b->verbose && sepcount > 0) {
27572     printf("  %d separate domains.\n", sepcount);
27573   }
27574 #endif
27575 }
27576 
27578 //                                                                           //
27579 // duplicatebgmesh()    Duplicate current mesh to background mesh.           //
27580 //                                                                           //
27581 // Current mesh 'this' is copied into 'this->bgm'.Both meshes share the same //
27582 // input tetgenio object, 'this->in', same tetgenbehavior object 'this->b'.  //
27583 //                                                                           //
27585 
27586 void tetgenmesh::duplicatebgmesh()
27587 {
27588   triface tetloop, btetloop;
27589   triface symtet, bsymtet;
27590   face bhullsh, bneighsh;
27591   point *idx2bplist, *tetptbaklist;
27592   point ploop, bploop;
27593   int idx, i;
27594 
27595   if (!b->quiet) {
27596     printf("Duplicating background mesh.\n");
27597   }
27598 
27599   // The background mesh itself has no background mesh.
27600   // assert(bgm->bgm == (tetgenmesh *) NULL);
27601   // The space for metric tensor should be allocated.
27602   // assert(bgm->sizeoftensor > 0);
27603 
27604   // Copy point list.
27605   idx2bplist = new point[points->items + 1];
27606   idx = in->firstnumber;
27607   points->traversalinit();
27608   ploop = pointtraverse();
27609   while (ploop != (point) NULL) {
27610     bgm->makepoint(&bploop);
27611     // Copy coordinates, attributes.
27612     for (i = 0; i < 3 + in->numberofpointattributes; i++) {
27613       bploop[i] = ploop[i];
27614     }
27615     // Transfer the metric tensor.
27616     for (i = 0; i < bgm->sizeoftensor; i++) {
27617       bploop[bgm->pointmtrindex + i] = ploop[pointmtrindex + i];
27618       // Metric tensor should have a positive value.
27619       if (bploop[bgm->pointmtrindex + i] <= 0.0) {
27620         printf("Error:  Point %d has non-positive size %g (-m option).\n",
27621                bgm->pointmark(bploop), bploop[bgm->pointmtrindex + i]);
27622         terminatetetgen(1);
27623       }
27624     }
27625     // Remember the point for searching.
27626     idx2bplist[idx++] = bploop;
27627     ploop = pointtraverse();
27628   }
27629 
27630   // Copy tetrahedra list.
27631   tetptbaklist = new point[tetrahedrons->items + 1];
27632   idx = in->firstnumber;
27633   tetrahedrons->traversalinit();
27634   tetloop.tet = tetrahedrontraverse();
27635   while (tetloop.tet != (tetrahedron *) NULL) {
27636     bgm->maketetrahedron(&btetloop);
27637     // Set the four corners.
27638     for (i = 0; i < 4; i++) {
27639       ploop = (point) tetloop.tet[4 + i];
27640       bploop = idx2bplist[pointmark(ploop)];
27641       btetloop.tet[4 + i] = (tetrahedron) bploop;
27642     }
27643     // Remember the tet for setting neighbor connections.
27644     tetptbaklist[idx++] = (point) tetloop.tet[4];
27645     tetloop.tet[4] = (tetrahedron) btetloop.tet;
27646     tetloop.tet = tetrahedrontraverse();
27647   }
27648 
27649   // Set the connections between background tetrahedra. Create background
27650   //   hull subfaces. Create the map of point-to-bgmtet.
27651   idx = in->firstnumber;
27652   tetrahedrons->traversalinit();
27653   tetloop.tet = tetrahedrontraverse();
27654   while (tetloop.tet != (tetrahedron *) NULL) {
27655     // Get the corresponding background tet.
27656     btetloop.tet = (tetrahedron *) tetloop.tet[4];
27657     // Set the four neighbors.
27658     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27659       btetloop.loc = tetloop.loc;
27660       sym(tetloop, symtet);
27661       if ((symtet.tet != dummytet) && (symtet.tet > tetloop.tet)) {
27662         // Operate on the un-connected interior face.
27663         bsymtet.tet = (tetrahedron *) symtet.tet[4]; // The saved bgm tet.
27664         bsymtet.loc = symtet.loc;
27665         bgm->bond(btetloop, bsymtet);
27666       } else if (symtet.tet == dummytet) {
27667         // Create a subface in background mesh.
27668         bgm->makeshellface(bgm->subfaces, &bhullsh);
27669         bgm->adjustedgering(btetloop, CCW); // face to inside.
27670         bgm->setsorg(bhullsh, bgm->org(btetloop));
27671         bgm->setsdest(bhullsh, bgm->dest(btetloop));
27672         bgm->setsapex(bhullsh, bgm->apex(btetloop));
27673         bgm->tsbond(btetloop, bhullsh);
27674         // Remember a hull face for point location.
27675         bgm->dummytet[0] = bgm->encode(btetloop);
27676       }
27677     }
27678     // Restore the backup tet point.
27679     tetloop.tet[4] = (tetrahedron) tetptbaklist[idx++];
27680     // Make the point-to-bgmtet map for size interpolation.
27681     btetloop.loc = 0;
27682     for (i = 0; i < 4; i++) {
27683       ploop = (point) tetloop.tet[4 + i];
27684       setpoint2bgmtet(ploop, bgm->encode(btetloop));
27685     }
27686     // Go to the next tet, btet.
27687     tetloop.tet = tetrahedrontraverse();
27688   }
27689 
27690   // Connect bgm hull subfaces. Note: all hull subfaces form a 2-manifold.
27691   bgm->subfaces->traversalinit();
27692   bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27693   while (bhullsh.sh != (shellface *) NULL) {
27694     bhullsh.shver = 0;
27695     bgm->stpivot(bhullsh, btetloop);
27696     assert(btetloop.tet != bgm->dummytet);
27697     bgm->adjustedgering(btetloop, CCW);
27698     for (i = 0; i < 3; i++) {
27699       bgm->spivot(bhullsh, bneighsh);
27700       if (bneighsh.sh == bgm->dummysh) {
27701         // This side is open, operate on it.
27702         bsymtet = btetloop;
27703         while (bgm->fnextself(bsymtet));
27704         bgm->tspivot(bsymtet, bneighsh);
27705         bgm->findedge(&bneighsh, bgm->sdest(bhullsh), bgm->sorg(bhullsh));
27706         bgm->sbond(bhullsh, bneighsh);
27707       }
27708       bgm->enextself(btetloop);
27709       bgm->senextself(bhullsh);
27710     }
27711     bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27712   }
27713 
27714   delete [] tetptbaklist;
27715   delete [] idx2bplist;
27716 }
27717 
27718 //
27719 // Begin of Delaunay refinement routines
27720 //
27721 
27723 //                                                                           //
27724 // marksharpsegments()    Mark sharp segments.                               //
27725 //                                                                           //
27726 // A segment s is called sharp if it is in one of the two cases:             //
27727 //  (1) There is a segment s' intersecting with s.  The internal angle (*)   //
27728 //      between s and s' is acute.                                           //
27729 //  (2) There are two facets f1 and f2 intersecting at s.  The internal      //
27730 //      dihedral angle (*) between f1 and f2 is acute.                       //
27731 // This routine finds the sharp segments and marked them as type SHARP.      //
27732 // The minimum angle between segments (minfaceang) and the minimum dihedral  //
27733 // angle between facets (minfacetdihed) are calulcated.                      //
27734 //                                                                           //
27735 // (*) The internal angle (or dihedral) bewteen two features means the angle //
27736 // inside the mesh domain.                                                   //
27737 //                                                                           //
27739 
27740 void tetgenmesh::marksharpsegments(REAL sharpangle)
27741 {
27742   triface adjtet;
27743   face startsh, spinsh, neighsh;
27744   face segloop, prevseg, nextseg;
27745   point eorg, edest;
27746   REAL ang, smallang;
27747   bool issharp;
27748   int sharpsegcount;
27749 
27750   if (b->verbose > 0) {
27751     printf("  Marking sharp segments.\n");
27752   }
27753 
27754   smallang = sharpangle * PI / 180.;
27755   sharpsegcount = 0;
27756   eorg = edest = (point) NULL; // To avoid compiler warnings.
27757 
27758   // A segment s may have been split into many subsegments. Operate the one
27759   //   which contains the origin of s. Then mark the rest of subsegments.
27760   subsegs->traversalinit();
27761   segloop.sh = shellfacetraverse(subsegs);
27762   while (segloop.sh != (shellface *) NULL) {
27763     segloop.shver = 0;
27764     senext2(segloop, prevseg);
27765     spivotself(prevseg);
27766     if (prevseg.sh == dummysh) {
27767       // Operate on this seg s.
27768       assert(shelltype(segloop) != SHARP); // It should be unmarked.
27769       issharp = false;
27770       spivot(segloop, startsh);
27771       if (startsh.sh != dummysh) {
27772         // First check if two facets form an acute dihedral angle at s.
27773         eorg = sorg(segloop);
27774         edest = sdest(segloop);
27775         spinsh = startsh;
27776         do {
27777           if (sorg(spinsh) != eorg) {
27778             sesymself(spinsh);
27779           }
27780           // Only do test when the spinsh is faceing inward.
27781           stpivot(spinsh, adjtet);
27782           if (adjtet.tet != dummytet) {
27783             // Get the subface on the adjacent facet.
27784             spivot(spinsh, neighsh);
27785             // Do not calculate if it is self-bonded.
27786             if (neighsh.sh != spinsh.sh) {
27787               // Calculate the dihedral angle between the two subfaces.
27788               ang = facedihedral(eorg, edest, sapex(spinsh), sapex(neighsh));
27789               // Only do check if a sharp angle has not been found.
27790               if (!issharp) issharp = (ang < smallang);
27791               // Remember the smallest facet dihedral angle.
27792               minfacetdihed = minfacetdihed < ang ? minfacetdihed : ang;
27793             }
27794           }
27795           // Go to the next facet.
27796           spivotself(spinsh);
27797         } while (spinsh.sh != startsh.sh);
27798         // if (!issharp) {
27799           // Second check if s forms an acute angle with another seg.
27800           spinsh = startsh;
27801           do {
27802             if (sorg(spinsh) != eorg) {
27803               sesymself(spinsh);
27804             }
27805             // Calculate the angle between s and s' of this facet.
27806             neighsh = spinsh;
27807             // Rotate edges around 'eorg' until meeting another seg s'. Such
27808             //   seg (s') must exist since the facet is segment-bounded.
27809             //   The sum of the angles of faces at 'eorg' gives the internal
27810             //   angle between the two segments.
27811             ang = 0.0;
27812             do {
27813               ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27814               senext2self(neighsh);
27815               sspivot(neighsh, nextseg);
27816               if (nextseg.sh != dummysh) break;
27817               // Go to the next coplanar subface.
27818               spivotself(neighsh);
27819               assert(neighsh.sh != dummysh);
27820               if (sorg(neighsh) != eorg) {
27821                 sesymself(neighsh);
27822               }
27823             } while (true);
27824             // Only do check if a sharp angle has not been found.
27825             if (!issharp) issharp = (ang < smallang);
27826             // Remember the smallest input face angle.
27827             minfaceang = minfaceang < ang ? minfaceang : ang;
27828             // Go to the next facet.
27829             spivotself(spinsh);
27830           } while (spinsh.sh != startsh.sh);
27831         // }
27832       }
27833       if (issharp) {
27834         setshelltype(segloop, SHARP);
27835         // Set the type for all subsegments at forwards.
27836         senext(segloop, nextseg);
27837         spivotself(nextseg);
27838         while (nextseg.sh != dummysh) {
27839           nextseg.shver = 0;
27840           setshelltype(nextseg, SHARP);
27841           senextself(nextseg);
27842           spivotself(nextseg);
27843         }
27844         sharpsegcount++;
27845       }
27846     }
27847     segloop.sh = shellfacetraverse(subsegs);
27848   }
27849 
27850   // So far we have marked all segments which have an acute dihedral angle
27851   //   or whose ORIGINs have an acute angle. In the un-marked subsegments,
27852   //   there are possible ones whose DESTINATIONs have an acute angle.
27853   subsegs->traversalinit();
27854   segloop.sh = shellfacetraverse(subsegs);
27855   while (segloop.sh != (shellface *) NULL) {
27856     // Only operate if s is non-sharp and contains the dest.
27857     segloop.shver = 0;
27858     senext(segloop, nextseg);
27859     spivotself(nextseg);
27860     // if ((nextseg.sh == dummysh) && (shelltype(segloop) != SHARP)) {
27861     if (nextseg.sh == dummysh) {
27862       // issharp = false;
27863       issharp = (shelltype(segloop) == SHARP);
27864       spivot(segloop, startsh);
27865       if (startsh.sh != dummysh) {
27866         // Check if s forms an acute angle with another seg.
27867         eorg = sdest(segloop);
27868         spinsh = startsh;
27869         do {
27870           if (sorg(spinsh) != eorg) {
27871             sesymself(spinsh);
27872           }
27873           // Calculate the angle between s and s' of this facet.
27874           neighsh = spinsh;
27875           ang = 0.0;
27876           do {
27877             ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27878             senext2self(neighsh);
27879             sspivot(neighsh, nextseg);
27880             if (nextseg.sh != dummysh) break;
27881             // Go to the next coplanar subface.
27882             spivotself(neighsh);
27883             assert(neighsh.sh != dummysh);
27884             if (sorg(neighsh) != eorg) {
27885               sesymself(neighsh);
27886             }
27887           } while (true);
27888           // Only do check if a sharp angle has not been found.
27889           if (!issharp) issharp = (ang < smallang);
27890           // Remember the smallest input face angle.
27891           minfaceang = minfaceang < ang ? minfaceang : ang;
27892           // Go to the next facet.
27893           spivotself(spinsh);
27894         } while (spinsh.sh != startsh.sh);
27895       }
27896       if (issharp) {
27897         setshelltype(segloop, SHARP);
27898         // Set the type for all subsegments at backwards.
27899         senext2(segloop, prevseg);
27900         spivotself(prevseg);
27901         while (prevseg.sh != dummysh) {
27902           prevseg.shver = 0;
27903           setshelltype(prevseg, SHARP);
27904           senext2self(prevseg);
27905           spivotself(prevseg);
27906         }
27907         sharpsegcount++;
27908       }
27909     }
27910     segloop.sh = shellfacetraverse(subsegs);
27911   }
27912 
27913   if ((b->verbose > 0) && (sharpsegcount > 0)) {
27914     printf("  %d sharp segments.\n", sharpsegcount);
27915   }
27916 }
27917 
27919 //                                                                           //
27920 // decidefeaturepointsizes()    Decide the sizes for all feature points.     //
27921 //                                                                           //
27922 // A feature point is a point on a sharp segment. Every feature point p will //
27923 // be assigned a positive size which is the radius of the protecting ball.   //
27924 //                                                                           //
27925 // The size of a feature point may be specified by one of the following ways://
27926 //   (1) directly specifying on an input vertex (by using .mtr file);        //
27927 //   (2) imposing a fixed maximal volume constraint ('-a__' option);         //
27928 //   (3) imposing a maximal volume constraint in a region ('-a' option);     //
27929 //   (4) imposing a maximal area constraint on a facet (in .var file);       //
27930 //   (5) imposing a maximal length constraint on a segment (in .var file);   //
27931 //   (6) combining (1) - (5).                                                //
27932 //   (7) automatically deriving a size if none of (1) - (6) is available.    //
27933 // In case (7),the size of p is set to be the smallest edge length among all //
27934 // edges connecting at p.  The final size of p is the minimum of (1) - (7).  //
27935 //                                                                           //
27937 
27938 void tetgenmesh::decidefeaturepointsizes()
27939 {
27940   list *tetlist, *verlist;
27941   shellface **segsperverlist;
27942   triface starttet;
27943   face shloop;
27944   face checkseg, prevseg, nextseg, testseg;
27945   point ploop, adjpt, e1, e2;
27946   REAL lfs_0, len, vol, maxlen, varlen;
27947   bool isfeature;
27948   int *idx2seglist;
27949   int featurecount;
27950   int idx, i, j;
27951 
27952   maxlen = 0.0;
27953 
27954   if (b->verbose > 0) {
27955     printf("  Deciding feature-point sizes.\n");
27956   }
27957 
27958   // Constructing a map from vertices to segments.
27959   makesegmentmap(idx2seglist, segsperverlist);
27960   // Initialize working lists.
27961   tetlist = new list(sizeof(triface), NULL, 256);
27962   verlist = new list(sizeof(point *), NULL, 256);
27963 
27964   if (b->fixedvolume) {
27965     // A fixed volume constraint is imposed. This gives an upper bound of
27966     //   the maximal radius of the protect ball of a vertex.
27967     maxlen = pow(6.0 * b->maxvolume, 1.0/3.0);
27968   }
27969 
27970   if (!b->refine) {
27971     // Initially correct types for Steiner points.
27972     featurecount = 0;
27973     points->traversalinit();
27974     ploop = pointtraverse();
27975     while (ploop != (point) NULL) {
27976       if (pointtype(ploop) == NACUTEVERTEX) {
27977         if (point2sh(ploop) != (shellface) NULL) {
27978           setpointtype(ploop, FREESEGVERTEX);
27979           featurecount++;
27980         }
27981       }
27982       ploop = pointtraverse();
27983     }
27984 #ifdef SELF_CHECK
27985     if ((b->verbose > 0) && (featurecount > 0)) {
27986       printf("  %d Steiner points correction.\n", featurecount);
27987     }
27988 #endif
27989   }
27990 
27991   // First only assign a size of p if p is not a Steiner point. The size of
27992   //   a Steiner point will be interpolated later from the endpoints of the
27993   //   segment on which it lies.
27994   featurecount = 0;
27995   points->traversalinit();
27996   ploop = pointtraverse();
27997   while (ploop != (point) NULL) {
27998     if (pointtype(ploop) != FREESEGVERTEX) {
27999       // Is p a feature point?
28000       isfeature = false;
28001       idx = pointmark(ploop) - in->firstnumber;
28002       for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; i++) {
28003         checkseg.sh = segsperverlist[i];
28004         isfeature = (shelltype(checkseg) == SHARP);
28005       }
28006       // Decide the size of p if it is on a sharp segment.
28007       if (isfeature) {
28008         // Find a tet containing p (checkseg is a sharp seg which contains p).
28009         sstpivot(&checkseg, &starttet);
28010         // Form star(p).
28011         tetlist->append(&starttet);
28012         formstarpolyhedron(ploop, tetlist, verlist, true);
28013         // Decide the size for p if no input size is given on input.
28014         if (ploop[pointmtrindex] == 0.0) {
28015           // Calculate lfs_0(p).
28016           lfs_0 = longest;
28017           for (i = 0; i < verlist->len(); i++) {
28018             adjpt = * (point *)(* verlist)[i];
28019             if (pointtype(adjpt) == FREESEGVERTEX) {
28020               // A Steiner point q. Find the seg it lies on.
28021               sdecode(point2sh(adjpt), checkseg);
28022               assert(checkseg.sh != dummysh);
28023               checkseg.shver = 0;
28024               // Find the origin of this seg.
28025               prevseg = checkseg;
28026               do {
28027                 senext2(prevseg, testseg);
28028                 spivotself(testseg);
28029                 if (testseg.sh == dummysh) break;
28030                 prevseg = testseg; // Go to the previous subseg.
28031                 prevseg.shver = 0;
28032               } while (true);
28033               // Find the dest of this seg.
28034               nextseg = checkseg;
28035               do {
28036                 senext(nextseg, testseg);
28037                 spivotself(testseg);
28038                 if (testseg.sh == dummysh) break;
28039                 nextseg = testseg; // Go to the next subseg.
28040                 nextseg.shver = 0;
28041               } while (true);
28042               e1 = sorg(prevseg);
28043               e2 = sdest(nextseg);
28044               // Check if p is the origin or the dest of this seg.
28045               if (ploop == e1) {
28046                 // Set q to be the dest of this seg.
28047                 adjpt = e2;
28048               } else if (ploop == e2) {
28049                 // Set q to be the org of this seg.
28050                 adjpt = e1;
28051               }
28052             }
28053             len = distance(ploop, adjpt);
28054             if (lfs_0 > len) lfs_0 = len;
28055           }
28056           ploop[pointmtrindex] = lfs_0;
28057         }
28058         if (b->fixedvolume) {
28059           // A fixed volume constraint is imposed. Adjust H(p) <= maxlen.
28060           if (ploop[pointmtrindex] > maxlen) {
28061             ploop[pointmtrindex] = maxlen;
28062           }
28063         }
28064         if (b->varvolume) {
28065           // Variant volume constraints are imposed. Adjust H(p) <= varlen.
28066           for (i = 0; i < tetlist->len(); i++) {
28067             starttet = * (triface *)(* tetlist)[i];
28068             vol = volumebound(starttet.tet);
28069             if (vol > 0.0) {
28070               varlen = pow(6 * vol, 1.0/3.0);
28071               if (ploop[pointmtrindex] > varlen) {
28072                 ploop[pointmtrindex] = varlen;
28073               }
28074             }
28075           }
28076         }
28077         // Clear working lists.
28078         tetlist->clear();
28079         verlist->clear();
28080         featurecount++;
28081       } else {
28082         // NO feature point, set the size of p be zero.
28083         ploop[pointmtrindex] = 0.0;
28084       }
28085     } // if (pointtype(ploop) != FREESEGVERTEX) {
28086     ploop = pointtraverse();
28087   }
28088 
28089   if (b->verbose > 0) {
28090     printf("  %d feature points.\n", featurecount);
28091   }
28092 
28093   if (!b->refine) {
28094     // Second only assign sizes for all Steiner points. A Steiner point p
28095     //   inserted on a sharp segment s is assigned a size by interpolating
28096     //   the sizes of the original endpoints of s.
28097     featurecount = 0;
28098     points->traversalinit();
28099     ploop = pointtraverse();
28100     while (ploop != (point) NULL) {
28101       if (pointtype(ploop) == FREESEGVERTEX) {
28102         if (ploop[pointmtrindex] == 0.0) {
28103           sdecode(point2sh(ploop), checkseg);
28104           assert(checkseg.sh != dummysh);
28105           if (shelltype(checkseg) == SHARP) {
28106             checkseg.shver = 0;
28107             // Find the origin of this seg.
28108             prevseg = checkseg;
28109             do {
28110               senext2(prevseg, testseg);
28111               spivotself(testseg);
28112               if (testseg.sh == dummysh) break;
28113               prevseg = testseg; // Go the previous subseg.
28114               prevseg.shver = 0;
28115             } while (true);
28116             // Find the dest of this seg.
28117             nextseg = checkseg;
28118             do {
28119               senext(nextseg, testseg);
28120               spivotself(testseg);
28121               if (testseg.sh == dummysh) break;
28122               nextseg = testseg; // Go the next subseg.
28123               nextseg.shver = 0;
28124             } while (true);
28125             e1 = sorg(prevseg);
28126             e2 = sdest(nextseg);
28127             len = distance(e1, e2);
28128             lfs_0 = distance(e1, ploop);
28129             // The following assert() happens when -Y option is used.
28130             if (b->nobisect == 0) {
28131               assert(lfs_0 < len);
28132             }
28133             ploop[pointmtrindex] = e1[pointmtrindex]
28134               + (lfs_0 / len) * (e2[pointmtrindex] - e1[pointmtrindex]);
28135             featurecount++;
28136           } else {
28137             // NO feature point, set the size of p be zero.
28138             ploop[pointmtrindex] = 0.0;
28139           } // if (shelltype(checkseg) == SHARP)
28140         } // if (ploop[pointmtrindex] == 0.0)
28141       } // if (pointtype(ploop) != FREESEGVERTEX)
28142       ploop = pointtraverse();
28143     }
28144     if ((b->verbose > 0) && (featurecount > 0)) {
28145       printf("  %d Steiner feature points.\n", featurecount);
28146     }
28147   }
28148 
28149   if (varconstraint) {
28150     // A .var file exists. Adjust feature sizes.
28151     if (in->facetconstraintlist) {
28152       // Have facet area constrains.
28153       subfaces->traversalinit();
28154       shloop.sh = shellfacetraverse(subfaces);
28155       while (shloop.sh != (shellface *) NULL) {
28156         varlen = areabound(shloop);
28157         if (varlen > 0.0) {
28158           // Check if the three corners are feature points.
28159           varlen = sqrt(varlen);
28160           for (j = 0; j < 3; j++) {
28161             ploop = (point) shloop.sh[3 + j];
28162             isfeature = false;
28163             idx = pointmark(ploop) - in->firstnumber;
28164             for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28165                  i++) {
28166               checkseg.sh = segsperverlist[i];
28167               isfeature = (shelltype(checkseg) == SHARP);
28168             }
28169             if (isfeature) {
28170               assert(ploop[pointmtrindex] > 0.0);
28171               if (ploop[pointmtrindex] > varlen) {
28172                 ploop[pointmtrindex] = varlen;
28173               }
28174             }
28175           } // for (j = 0; j < 3; j++)
28176         }
28177         shloop.sh = shellfacetraverse(subfaces);
28178       }
28179     }
28180     if (in->segmentconstraintlist) {
28181       // Have facet area constrains.
28182       subsegs->traversalinit();
28183       shloop.sh = shellfacetraverse(subsegs);
28184       while (shloop.sh != (shellface *) NULL) {
28185         varlen = areabound(shloop);
28186         if (varlen > 0.0) {
28187           // Check if the two endpoints are feature points.
28188           for (j = 0; j < 2; j++) {
28189             ploop = (point) shloop.sh[3 + j];
28190             isfeature = false;
28191             idx = pointmark(ploop) - in->firstnumber;
28192             for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28193                  i++) {
28194               checkseg.sh = segsperverlist[i];
28195               isfeature = (shelltype(checkseg) == SHARP);
28196             }
28197             if (isfeature) {
28198               assert(ploop[pointmtrindex] > 0.0);
28199               if (ploop[pointmtrindex] > varlen) {
28200                 ploop[pointmtrindex] = varlen;
28201               }
28202             }
28203           } // for (j = 0; j < 2; j++)
28204         }
28205         shloop.sh = shellfacetraverse(subsegs);
28206       }
28207     }
28208   } // if (varconstraint)
28209 
28210   delete [] segsperverlist;
28211   delete [] idx2seglist;
28212   delete tetlist;
28213   delete verlist;
28214 }
28215 
28217 //                                                                           //
28218 // enqueueencsub()    Add an encroached subface into the queue.              //
28219 //                                                                           //
28221 
28222 void tetgenmesh::enqueueencsub(face* testsub, point encpt, int quenumber,
28223   REAL* cent)
28224 {
28225   badface *encsub;
28226   int i;
28227 
28228   encsub = (badface *) badsubfaces->alloc();
28229   encsub->ss = *testsub;
28230   encsub->forg = sorg(*testsub);
28231   encsub->fdest = sdest(*testsub);
28232   encsub->fapex = sapex(*testsub);
28233   encsub->foppo = (point) encpt;
28234   for (i = 0; i < 3; i++) encsub->cent[i] = cent[i];
28235   encsub->nextitem = (badface *) NULL;
28236   // Set the pointer of 'encsubseg' into 'testsub'.  It has two purposes:
28237   //   (1) We can regonize it is encroached; (2) It is uniquely queued.
28238   setshell2badface(encsub->ss, encsub);
28239   // Add the subface to the end of a queue (quenumber = 2, high priority).
28240   *subquetail[quenumber] = encsub;
28241   // Maintain a pointer to the NULL pointer at the end of the queue.
28242   subquetail[quenumber] = &encsub->nextitem;
28243   if (b->verbose > 2) {
28244     printf("    Queuing subface (%d, %d, %d) [%d].\n", pointmark(encsub->forg),
28245            pointmark(encsub->fdest), pointmark(encsub->fapex), quenumber);
28246   }
28247 }
28248 
28250 //                                                                           //
28251 // dequeueencsub()    Remove an enc-subface from the front of the queue.     //
28252 //                                                                           //
28254 
28255 tetgenmesh::badface* tetgenmesh::dequeueencsub(int* pquenumber)
28256 {
28257   badface *result;
28258   int quenumber;
28259 
28260   // Look for a nonempty queue.
28261   for (quenumber = 2; quenumber >= 0; quenumber--) {
28262     result = subquefront[quenumber];
28263     if (result != (badface *) NULL) {
28264       // Remove the badface from the queue.
28265       subquefront[quenumber] = result->nextitem;
28266       // Maintain a pointer to the NULL pointer at the end of the queue.
28267       if (subquefront[quenumber] == (badface *) NULL) {
28268         subquetail[quenumber] = &subquefront[quenumber];
28269       }
28270       *pquenumber = quenumber;
28271       return result;
28272     }
28273   }
28274   return (badface *) NULL;
28275 }
28276 
28278 //                                                                           //
28279 // enqueuebadtet()    Add a tetrahedron into the queue.                      //
28280 //                                                                           //
28282 
28283 void tetgenmesh::enqueuebadtet(triface* testtet, REAL ratio2, REAL* cent)
28284 {
28285   badface *newbadtet;
28286   int queuenumber;
28287   int i;
28288 
28289   // Allocate space for the bad tetrahedron.
28290   newbadtet = (badface *) badtetrahedrons->alloc();
28291   newbadtet->tt = *testtet;
28292   newbadtet->key = ratio2;
28293   if (cent != NULL) {
28294     for (i = 0; i < 3; i++) newbadtet->cent[i] = cent[i];
28295   } else {
28296     for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
28297   }
28298   newbadtet->forg = org(*testtet);
28299   newbadtet->fdest = dest(*testtet);
28300   newbadtet->fapex = apex(*testtet);
28301   newbadtet->foppo = oppo(*testtet);
28302   newbadtet->nextitem = (badface *) NULL;
28303   // Determine the appropriate queue to put the bad tetrahedron into.
28304   if (ratio2 > b->goodratio) {
28305     // queuenumber = (int) ((ratio2 - b->goodratio) / 0.5);
28306     queuenumber = (int) (64.0 - 64.0 / ratio2);
28307     // 'queuenumber' may overflow (negative) caused by a very large ratio.
28308     if ((queuenumber > 63) || (queuenumber < 0)) {
28309       queuenumber = 63;
28310     }
28311   } else {
28312     // It's not a bad ratio; put the tet in the lowest-priority queue.
28313     queuenumber = 0;
28314   }
28315 
28316   // Are we inserting into an empty queue?
28317   if (tetquefront[queuenumber] == (badface *) NULL) {
28318     // Yes. Will this become the highest-priority queue?
28319     if (queuenumber > firstnonemptyq) {
28320       // Yes, this is the highest-priority queue.
28321       nextnonemptyq[queuenumber] = firstnonemptyq;
28322       firstnonemptyq = queuenumber;
28323     } else {
28324       // No. Find the queue with next higher priority.
28325       i = queuenumber + 1;
28326       while (tetquefront[i] == (badface *) NULL) {
28327         i++;
28328       }
28329       // Mark the newly nonempty queue as following a higher-priority queue.
28330       nextnonemptyq[queuenumber] = nextnonemptyq[i];
28331       nextnonemptyq[i] = queuenumber;
28332     }
28333     // Put the bad tetrahedron at the beginning of the (empty) queue.
28334     tetquefront[queuenumber] = newbadtet;
28335   } else {
28336     // Add the bad tetrahedron to the end of an already nonempty queue.
28337     tetquetail[queuenumber]->nextitem = newbadtet;
28338   }
28339   // Maintain a pointer to the last tetrahedron of the queue.
28340   tetquetail[queuenumber] = newbadtet;
28341 
28342   if (b->verbose > 2) {
28343     printf("    Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
28344            pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
28345            pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
28346            sqrt(ratio2), queuenumber);
28347   }
28348 }
28349 
28351 //                                                                           //
28352 // dequeuebadtet()    Remove a tetrahedron from the front of the queue.      //
28353 //                                                                           //
28355 
28356 tetgenmesh::badface* tetgenmesh::topbadtetra()
28357 {
28358   // Keep a record of which queue was accessed in case dequeuebadtetra()
28359   //   is called later.
28360   recentq = firstnonemptyq;
28361   // If no queues are nonempty, return NULL.
28362   if (firstnonemptyq < 0) {
28363     return (badface *) NULL;
28364   } else {
28365     // Return the first tetrahedron of the highest-priority queue.
28366     return tetquefront[firstnonemptyq];
28367   }
28368 }
28369 
28370 void tetgenmesh::dequeuebadtet()
28371 {
28372   badface *deadbadtet;
28373   int i;
28374 
28375   // If queues were empty last time topbadtetra() was called, do nothing.
28376   if (recentq >= 0) {
28377     // Find the tetrahedron last returned by topbadtetra().
28378     deadbadtet = tetquefront[recentq];
28379     // Remove the tetrahedron from the queue.
28380     tetquefront[recentq] = deadbadtet->nextitem;
28381     // If this queue is now empty, update the list of nonempty queues.
28382     if (deadbadtet == tetquetail[recentq]) {
28383       // Was this the highest-priority queue?
28384       if (firstnonemptyq == recentq) {
28385         // Yes; find the queue with next lower priority.
28386         firstnonemptyq = nextnonemptyq[firstnonemptyq];
28387       } else {
28388         // No; find the queue with next higher priority.
28389         i = recentq + 1;
28390         while (tetquefront[i] == (badface *) NULL) {
28391           i++;
28392         }
28393         nextnonemptyq[i] = nextnonemptyq[recentq];
28394       }
28395     }
28396     // Return the bad tetrahedron to the pool.
28397     badfacedealloc(badtetrahedrons, deadbadtet);
28398   }
28399 }
28400 
28402 //                                                                           //
28403 // checkseg4encroach()    Check a subsegment to see if it is encroached.     //
28404 //                                                                           //
28405 // A segment s is encroached if there is a vertex lies inside or on its dia- //
28406 // metral circumsphere, i.e., s faces an angle theta >= 90 degrees.          //
28407 //                                                                           //
28408 // If 'testpt' (p) != NULL, only test if 'testseg' (s) is encroached by it,  //
28409 // else, check all apexes of faces around s. Return TRUE if s is encroached. //
28410 // If and 'enqflag' is TRUE, add it into 'badsubsegs' if s is encroached.    //
28411 //                                                                           //
28412 // If 'prefpt' != NULL, it returns the reference point (defined in my paper) //
28413 // if it exists.  This point is will be used to split s.                     //
28414 //                                                                           //
28416 
28417 bool tetgenmesh::checkseg4encroach(face* testseg, point testpt, point* prefpt,
28418   bool enqflag)
28419 {
28420   badface *encsubseg;
28421   triface starttet, spintet;
28422   point eorg, edest, eapex, encpt;
28423   REAL cent[3], radius, dist, diff;
28424   REAL maxradius;
28425   bool enq;
28426   int hitbdry;
28427 
28428   enq = false;
28429   eorg = sorg(*testseg);
28430   edest = sdest(*testseg);
28431   cent[0] = 0.5 * (eorg[0] + edest[0]);
28432   cent[1] = 0.5 * (eorg[1] + edest[1]);
28433   cent[2] = 0.5 * (eorg[2] + edest[2]);
28434   radius = distance(cent, eorg);
28435 
28436   if (varconstraint && (areabound(*testseg) > 0.0)) {
28437     enq = (2.0 * radius) > areabound(*testseg);
28438   }
28439 
28440   if (!enq) {
28441     maxradius = 0.0;
28442     if (testpt == (point) NULL) {
28443       // Check if it is encroached by traversing all faces containing it.
28444       sstpivot(testseg, &starttet);
28445       eapex = apex(starttet);
28446       spintet = starttet;
28447       hitbdry = 0;
28448       do {
28449         dist = distance(cent, apex(spintet));
28450         diff = dist - radius;
28451         if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28452         if (diff <= 0.0) {
28453           // s is encroached.
28454           enq = true;
28455           if (prefpt != (point *) NULL) {
28456             // Find the reference point.
28457             encpt = apex(spintet);
28458             circumsphere(eorg, edest, encpt, NULL, NULL, &dist);
28459             if (dist > maxradius) {
28460               // Rememebr this point.
28461               *prefpt = encpt;
28462               maxradius = dist;
28463             }
28464           } else {
28465             break;
28466           }
28467         }
28468         if (!fnextself(spintet)) {
28469           hitbdry++;
28470           if (hitbdry < 2) {
28471             esym(starttet, spintet);
28472             if (!fnextself(spintet)) {
28473               hitbdry++;
28474             }
28475           }
28476         }
28477       } while (apex(spintet) != eapex && (hitbdry < 2));
28478     } else {
28479       // Only check if 'testseg' is encroached by 'testpt'.
28480       dist = distance(cent, testpt);
28481       diff = dist - radius;
28482       if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28483       enq = (diff <= 0.0);
28484     }
28485   }
28486 
28487   if (enq && enqflag) {
28488     if (b->verbose > 2) {
28489       printf("    Queuing encroaching subsegment (%d, %d).\n",
28490              pointmark(eorg), pointmark(edest));
28491     }
28492     encsubseg = (badface *) badsubsegs->alloc();
28493     encsubseg->ss = *testseg;
28494     encsubseg->forg = eorg;
28495     encsubseg->fdest = edest;
28496     encsubseg->foppo = (point) NULL; // Not used.
28497     // Set the pointer of 'encsubseg' into 'testseg'.  It has two purposes:
28498     //   (1) We can regonize it is encroached; (2) It is uniquely queued.
28499     setshell2badface(encsubseg->ss, encsubseg);
28500   }
28501 
28502   return enq;
28503 }
28504 
28506 //                                                                           //
28507 // checksub4encroach()    Check a subface to see if it is encroached.        //
28508 //                                                                           //
28509 // A subface f is encroached if there is a vertex inside or on its diametral //
28510 // circumsphere.                                                             //
28511 //                                                                           //
28512 // If 'testpt (p) != NULL', test if 'testsub' (f) is encroached by it, else, //
28513 // test if f is encroached by one of the two opposites of the adjacent tets. //
28514 // Return TRUE if f is encroached and queue it if 'enqflag' is set.          //
28515 //                                                                           //
28517 
28518 bool tetgenmesh::checksub4encroach(face* testsub, point testpt, bool enqflag)
28519 {
28520   triface abuttet;
28521   point pa, pb, pc, encpt;
28522   REAL A[4][4], rhs[4], D;
28523   REAL cent[3], area;
28524   REAL radius, dist, diff;
28525   bool enq;
28526   int indx[4];
28527   int quenumber;
28528 
28529   enq = false;
28530   radius = 0.0;
28531   encpt = (point) NULL;
28532 
28533   pa = sorg(*testsub);
28534   pb = sdest(*testsub);
28535   pc = sapex(*testsub);
28536 
28537   // Compute the coefficient matrix A (3x3).
28538   A[0][0] = pb[0] - pa[0];
28539   A[0][1] = pb[1] - pa[1];
28540   A[0][2] = pb[2] - pa[2]; // vector V1 (pa->pb)
28541   A[1][0] = pc[0] - pa[0];
28542   A[1][1] = pc[1] - pa[1];
28543   A[1][2] = pc[2] - pa[2]; // vector V2 (pa->pc)
28544   cross(A[0], A[1], A[2]); // vector V3 (V1 X V2)
28545 
28546   if (varconstraint && (areabound(*testsub) > 0.0)) {
28547     // Check if the subface has too big area.
28548     area = 0.5 * sqrt(dot(A[2], A[2]));
28549     enq = area > areabound(*testsub);
28550     if (enq) {
28551       quenumber = 2; // A queue of subfaces having too big area.
28552     }
28553   }
28554 
28555   // Compute the right hand side vector b (3x1).
28556   rhs[0] = 0.5 * dot(A[0], A[0]);
28557   rhs[1] = 0.5 * dot(A[1], A[1]);
28558   rhs[2] = 0.0;
28559   // Solve the 3 by 3 equations use LU decomposition with partial pivoting
28560   //   and backward and forward substitute..
28561   if (lu_decmp(A, 3, indx, &D, 0)) {
28562     lu_solve(A, 3, indx, rhs, 0);
28563     cent[0] = pa[0] + rhs[0];
28564     cent[1] = pa[1] + rhs[1];
28565     cent[2] = pa[2] + rhs[2];
28566     radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
28567   }
28568 
28569   if (!enq) {
28570     // Check if the subface is encroached.
28571     if (testpt == (point) NULL) {
28572       stpivot(*testsub, abuttet);
28573       if (abuttet.tet != dummytet) {
28574         dist = distance(cent, oppo(abuttet));
28575         diff = dist - radius;
28576         if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28577         enq = (diff <= 0.0);
28578         if (enq) encpt = oppo(abuttet);
28579       }
28580       if (!enq) {
28581         sesymself(*testsub);
28582         stpivot(*testsub, abuttet);
28583         if (abuttet.tet != dummytet) {
28584           dist = distance(cent, oppo(abuttet));
28585           diff = dist - radius;
28586           if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28587           enq = (diff <= 0.0);
28588           if (enq) encpt = oppo(abuttet);
28589         }
28590       }
28591     } else {
28592       dist = distance(cent, testpt);
28593       diff = dist - radius;
28594       if (fabs(diff) / radius <= b->epsilon) diff = 0.0; // Rounding.
28595       enq = (diff <= 0.0);
28596     }
28597     if (enq) {
28598       quenumber = 0; // A queue of encroached subfaces.
28599     }
28600   }
28601 
28602   if (enq && enqflag) {
28603     enqueueencsub(testsub, encpt, quenumber, cent);
28604   }
28605 
28606   return enq;
28607 }
28608 
28610 //                                                                           //
28611 // checktet4badqual()    Test a tetrahedron for quality measures.            //
28612 //                                                                           //
28613 // Tests a tetrahedron to see if it satisfies the minimum ratio condition    //
28614 // and the maximum volume condition. Tetrahedra that aren't upto spec are    //
28615 // added to the bad tetrahedron queue.                                       //
28616 //                                                                           //
28618 
28619 bool tetgenmesh::checktet4badqual(triface* testtet, bool enqflag)
28620 {
28621   point pa, pb, pc, pd, pe1, pe2;
28622   REAL vda[3], vdb[3], vdc[3];
28623   REAL vab[3], vbc[3], vca[3];
28624   REAL N[4][3], A[4][4], rhs[4], D;
28625   REAL elen[6], circumcent[3];
28626   REAL bicent[3], offcent[3];
28627   REAL volume, L, cosd;
28628   REAL radius2, smlen2, ratio2;
28629   REAL dist, sdist, split;
28630   bool enq;
28631   int indx[4];
28632   int sidx, i, j;
28633 
28634   pa = (point) testtet->tet[4];
28635   pb = (point) testtet->tet[5];
28636   pc = (point) testtet->tet[6];
28637   pd = (point) testtet->tet[7];
28638 
28639   // Get the edge vectors vda: d->a, vdb: d->b, vdc: d->c.
28640   // Set the matrix A = [vda, vdb, vdc]^T.
28641   for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
28642   for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
28643   for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
28644   // Get the rest edge vectors
28645   for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
28646   for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i];
28647   for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i];
28648 
28649   // Lu-decompose the matrix A.
28650   lu_decmp(A, 3, indx, &D, 0);
28651   // Get the volume of abcd.
28652   volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
28653   if (volume < 0.0) volume = -volume;
28654   // Check the radiu-edge ratio of the tet.
28655   rhs[0] = 0.5 * dot(vda, vda);
28656   rhs[1] = 0.5 * dot(vdb, vdb);
28657   rhs[2] = 0.5 * dot(vdc, vdc);
28658   lu_solve(A, 3, indx, rhs, 0);
28659   // Get the circumcenter.
28660   for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
28661   // Get the square of the circumradius.
28662   radius2 = dot(rhs, rhs);
28663   // Find the square of the shortest edge length.
28664   elen[0] = dot(vda, vda);
28665   elen[1] = dot(vdb, vdb);
28666   elen[2] = dot(vdc, vdc);
28667   elen[3] = dot(vab, vab);
28668   elen[4] = dot(vbc, vbc);
28669   elen[5] = dot(vca, vca);
28670   smlen2 = elen[0]; sidx = 0;
28671   for (i = 1; i < 6; i++) {
28672     if (smlen2 > elen[i]) { smlen2 = elen[i]; sidx = i; }
28673   }
28674   // Calculate the square of radius-edge ratio.
28675   ratio2 = radius2 / smlen2;
28676   // Check whether the ratio is smaller than permitted.
28677   enq = ratio2 > b->goodratio;
28678   if (!enq) {
28679     // abcd has good ratio.
28680     // ratio2 = 0.0;
28681     // if (b->offcenter) {
28682       // Test if it is a sliver.
28683       // Compute the 4 face normals (N[0], ..., N[3]).
28684       for (j = 0; j < 3; j++) {
28685         for (i = 0; i < 3; i++) rhs[i] = 0.0;
28686         rhs[j] = 1.0;  // Positive means the inside direction
28687         lu_solve(A, 3, indx, rhs, 0);
28688         for (i = 0; i < 3; i++) N[j][i] = rhs[i];
28689       }
28690       // Get the fourth normal by summing up the first three.
28691       for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
28692       // Normalized the normals.
28693       for (i = 0; i < 4; i++) {
28694         L = sqrt(dot(N[i], N[i]));
28695         if (L > 0.0) {
28696           for (j = 0; j < 3; j++) N[i][j] /= L;
28697         }
28698       }
28699       // N[0] is the normal of face bcd. Test the dihedral angles at edge
28700       //   cd, bd, and bc to see if they are too small or too big.
28701       for (i = 1; i < 4 && !enq; i++) {
28702         cosd = -dot(N[0], N[i]); // Edge cd, bd, bc.
28703         enq = cosd > cosmindihed;
28704       }
28705       if (!enq) {
28706         for (i = 2; i < 4 && !enq; i++) {
28707           cosd = -dot(N[1], N[i]); // Edge ad, ac
28708           enq = cosd > cosmindihed;
28709         }
28710         if (!enq) {
28711           cosd = -dot(N[2], N[3]); // Edge ab
28712           enq = cosd > cosmindihed;
28713         }
28714       }
28715     // }
28716   } else if (b->offcenter) {
28717     // abcd has bad-quality. Use off-center instead of circumcenter.
28718     switch (sidx) {
28719     case 0: // edge da.
28720       pe1 = pd; pe2 = pa; break;
28721     case 1: // edge db.
28722       pe1 = pd; pe2 = pb; break;
28723     case 2: // edge dc.
28724       pe1 = pd; pe2 = pc; break;
28725     case 3: // edge ab.
28726       pe1 = pa; pe2 = pb; break;
28727     case 4: // edge bc.
28728       pe1 = pb; pe2 = pc; break;
28729     case 5: // edge ca.
28730       pe1 = pc; pe2 = pa; break;
28731     default:
28732       pe1 = pe2 = (point) NULL; // Avoid a compile warning.
28733     }
28734     // The shortest edge is e1->e2.
28735     for (i = 0; i < 3; i++) bicent[i] = 0.5 * (pe1[i] + pe2[i]);
28736     dist = distance(bicent, circumcent);
28737     // sdist = sqrt(smlen2) * sin(PI / 3.0); // A icoso-triangle.
28738     // The following formulae is from
28739     sdist = b->alpha3 * (b->minratio+sqrt(b->goodratio-0.25))* sqrt(smlen2);
28740     split = sdist / dist;
28741     if (split > 1.0) split = 1.0;
28742     // Get the off-center.
28743     for (i = 0; i < 3; i++) {
28744       offcent[i] = bicent[i] + split * (circumcent[i] - bicent[i]);
28745     }
28746   }
28747 
28748   if (!enq && (b->varvolume || b->fixedvolume)) {
28749     // Check if the tet has too big volume.
28750     enq = b->fixedvolume && (volume > b->maxvolume);
28751     if (!enq && b->varvolume) {
28752       enq = (volume > volumebound(testtet->tet)) &&
28753             (volumebound(testtet->tet) > 0.0);
28754     }
28755   }
28756 
28757   if (!enq) {
28758     // Check if the user-defined sizing function is satisfied.
28759     if (b->metric) {
28760       // assert(b->alpha1 > 0.0);
28761       sdist = sqrt(radius2) / b->alpha1;
28762       for (i = 0; i < 4; i++) {
28763         pa = (point) testtet->tet[4 + i];
28764         // Get the indicated size of p.
28765         dist = pa[pointmtrindex]; // dist = b->alpha1 * pa[pointmtrindex];
28766         enq = ((dist < sdist) && (dist > 0.0));
28767         if (enq) break; // It is bad wrt. a node constraint.
28768         // *** Experiment ! Stop test if c is inside H(a).
28769         // if ((dist > 0.0) && (dist > sdist)) break;
28770       }
28771       // *** Experiment !
28772       // enq = (i == 4); // Does c lies outside all sparse-ball?
28773     } // if (b->metric)
28774   }
28775 
28776   if (enq && enqflag) {
28777     if (b->offcenter && (ratio2 > b->goodratio)) {
28778       for (i = 0; i < 3; i++) circumcent[i] = offcent[i];
28779     }
28780     enqueuebadtet(testtet, ratio2, circumcent);
28781   }
28782 
28783   return enq;
28784 }
28785 
28787 //                                                                           //
28788 // acceptsegpt()    Check if a segment point can be inserted or not.         //
28789 //                                                                           //
28790 // Segment(ab) is indicated to be split by a point p (\in ab). This routine  //
28791 // decides whether p can be inserted or not.                                 //
28792 //                                                                           //
28793 // p can not be inserted either the '-Y' option is used and ab is a hull     //
28794 // segment or '-YY' option is used.                                          //
28795 //                                                                           //
28796 // p can be inserted if it is in one of the following cases:                 //
28797 //   (1) if L = |a - b| is too long wrt the edge constraint; or              //
28798 //   (2) if |x - p| > \alpha_2 H(x) for x = a, b; or                         //
28799 //   (3) if 'refpt' != NULL.                                                 //
28800 //                                                                           //
28802 
28803 bool tetgenmesh::acceptsegpt(point segpt, point refpt, face* splitseg)
28804 {
28805   point p[2];
28806   REAL L, lfs;
28807   int i, j;
28808 
28809   if (b->nobisect == 1) {
28810     // '-Y'. It can not be split if it is on the hull.
28811     triface spintet;
28812     point pc;
28813     sstpivot(splitseg, &spintet);
28814     assert(spintet.tet != dummytet);
28815     pc = apex(spintet);
28816     do {
28817       if (!fnextself(spintet)) {
28818         // Meet a boundary face - s is on the hull.
28819         return false;
28820       }
28821     } while (pc != apex(spintet));
28822   } else if (b->nobisect > 1) {
28823     // '-YY'. Do not split it.
28824     return false;
28825   }
28826 
28827   p[0] = sorg(*splitseg);
28828   p[1] = sdest(*splitseg);
28829   if (varconstraint && (areabound(*splitseg) > 0)) {
28830     lfs = areabound(*splitseg);
28831     L = distance(p[0], p[1]);
28832     if (L > lfs) {
28833       return true; // case (1)
28834     }
28835   }
28836 
28837   j = 0; // Use j to count the number of inside balls.
28838   for (i = 0; i < 2; i++) {
28839     // Check if p is inside the protect ball of q.
28840     if (p[i][pointmtrindex] > 0.0) {
28841       lfs = b->alpha2 * p[i][pointmtrindex];
28842       L = distance(p[i], segpt);
28843       if (L < lfs) j++; // p is inside ball.
28844     }
28845   }
28846   if (j == 0) return true; // case (3).
28847 
28848   // If 'refpt' != NULL, force p to be inserted.
28849   if (refpt != (point) NULL) {
28850     cdtenforcesegpts++;
28851     return true;
28852   }
28853 
28854   // Do not split it.
28855   rejsegpts++;
28856   return false;
28857 }
28858 
28860 //                                                                           //
28861 // acceptfacpt()    Check if a facet point can be inserted or not.           //
28862 //                                                                           //
28863 // 'subceillist' is CBC(p). 'verlist' (V) is empty on input, it returns the  //
28864 // set of vertices of CBC(p).                                                //
28865 //                                                                           //
28866 // p can not be inserted either the '-Y' option is used and the facet is on  //
28867 // the hull or '-YY' option is used.                                         //
28868 //                                                                           //
28869 // p can be inserted if |p - v| > \alpha_2 H(v), for all v \in V.            //
28870 //                                                                           //
28872 
28873 bool tetgenmesh::acceptfacpt(point facpt, list* subceillist, list* verlist)
28874 {
28875   face *testsh;
28876   point p[2], ploop;
28877   REAL L, lfs;
28878   int idx, i, j;
28879 
28880   if (b->nobisect == 1) {
28881     // '-Y'. p can not be inserted if CBC(p) is on the hull.
28882     triface testtet;
28883     testsh = (face *)(* subceillist)[0];
28884     stpivot(*testsh, testtet);
28885     if (testtet.tet != dummytet) {
28886       sesymself(*testsh);
28887       stpivot(*testsh, testtet);
28888     }
28889     if (testtet.tet == dummytet) return false;
28890   } else if (b->nobisect > 1) {
28891     // '-YY'. Do not split s.
28892     return false;
28893   }
28894 
28895   // Collect the vertices of CBC(p), save them in V.
28896   for (i = 0; i < subceillist->len(); i++) {
28897     testsh = (face *)(* subceillist)[i];
28898     p[0] = sorg(*testsh);
28899     p[1] = sdest(*testsh);
28900     for (j = 0; j < 2; j++) {
28901       idx = pointmark(p[j]);
28902       if (idx >= 0) {
28903         setpointmark(p[j], -idx - 1);
28904         verlist->append(&(p[j]));
28905       }
28906     }
28907   }
28908 
28909   j = 0; // Use j to count the number of inside balls.
28910   for (i = 0; i < verlist->len(); i++) {
28911     ploop = * (point *)(* verlist)[i];
28912     // Uninfect q.
28913     idx = pointmark(ploop);
28914     setpointmark(ploop, -(idx + 1));
28915     // Check if p is inside the protect ball of q.
28916     if (ploop[pointmtrindex] > 0.0) {
28917       lfs = b->alpha2 * ploop[pointmtrindex];
28918       L = distance(ploop, facpt);
28919       if (L < lfs) j++; // p is inside ball.
28920     }
28921   }
28922   verlist->clear();
28923 
28924   if (j == 0) return true; // case (3).
28925 
28926   rejsubpts++;
28927   return false;
28928 }
28929 
28931 //                                                                           //
28932 // acceptvolpt()    Check if a volume point can be inserted or not.          //
28933 //                                                                           //
28934 // 'ceillist' is B(p).  'verlist' (V) is empty on input, it returns the set  //
28935 // of vertices of B(p).                                                      //
28936 //                                                                           //
28937 // p can be split if |p - v| > \alpha_2 H(v), for all v \in V.               //
28938 //                                                                           //
28940 
28941 bool tetgenmesh::acceptvolpt(point volpt, list* ceillist, list* verlist)
28942 {
28943   triface* testtet;
28944   point p[3], ploop;
28945   REAL L, lfs;
28946   int idx, i, j;
28947 
28948   // Collect the vertices of CBC(p), save them in V.
28949   for (i = 0; i < ceillist->len(); i++) {
28950     testtet = (triface *)(* ceillist)[i];
28951     p[0] = org(*testtet);
28952     p[1] = dest(*testtet);
28953     p[2] = apex(*testtet);
28954     for (j = 0; j < 3; j++) {
28955       idx = pointmark(p[j]);
28956       if (idx >= 0) {
28957         setpointmark(p[j], -idx - 1);
28958         verlist->append(&(p[j]));
28959       }
28960     }
28961   }
28962 
28963   j = 0; // Use j to counte the number of inside balls.
28964   for (i = 0; i < verlist->len(); i++) {
28965     ploop = * (point *)(* verlist)[i];
28966     // Uninfect q.
28967     idx = pointmark(ploop);
28968     setpointmark(ploop, -(idx + 1));
28969     // Check if p is inside the protect ball of q.
28970     if (ploop[pointmtrindex] > 0.0) {
28971       lfs = b->alpha2 * ploop[pointmtrindex];
28972       L = distance(ploop, volpt);
28973       if (L < lfs) j++; // p is inside the protect ball.
28974     }
28975   }
28976   verlist->clear();
28977 
28978   if (j == 0) return true; // case (2).
28979 
28980   rejtetpts++;
28981   return false;
28982 }
28983 
28985 //                                                                           //
28986 // getsplitpoint()    Get the inserting point in a segment.                  //
28987 //                                                                           //
28989 
28990 void tetgenmesh::getsplitpoint(point e1, point e2, point refpt, point newpt)
28991 {
28992   point ei, ej;
28993   REAL split, L, d1, d2, ps, rs;
28994   bool acutea, acuteb;
28995   int i;
28996 
28997   if (refpt != (point) NULL) {
28998     // Use the CDT rules to split the segment.
28999     acutea = (pointtype(e1) == ACUTEVERTEX);
29000     acuteb = (pointtype(e2) == ACUTEVERTEX);
29001     if (acutea ^ acuteb) {
29002       // Only one endpoint is acute. Use rule-2 or rule-3.
29003       ei = acutea ? e1 : e2;
29004       ej = acutea ? e2 : e1;
29005       L = distance(ei, ej);
29006       // Apply rule-2.
29007       d1 = distance(ei, refpt);
29008       split = d1 / L;
29009       for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29010       // Check if rule-3 is needed.
29011       d2 = distance(refpt, newpt);
29012       if (d2 > (L - d1)) {
29013         // Apply rule-3.
29014         if ((d1 - d2) > (0.5 * d1)) {
29015           split = (d1 - d2) / L;
29016         } else {
29017           split = 0.5 * d1 / L;
29018         }
29019         for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29020         if (b->verbose > 1) {
29021           printf("    Found by rule-3:");
29022         }
29023         r3count++;
29024       } else {
29025         if (b->verbose > 1) {
29026           printf("    Found by rule-2:");
29027         }
29028         r2count++;
29029       }
29030       if (b->verbose > 1) {
29031         printf(" center %d, split = %.12g.\n", pointmark(ei), split);
29032       }
29033       // Add a random perturbation on newpt.
29034       d1 = distance(ei, newpt);
29035       d2 = distance(newpt, refpt);
29036       ps = randgenerator(d2 * b->epsilon2 * 1e+2);
29037       rs = ps / d1;
29038       // Perturb newpt away from ei.
29039       for (i = 0; i < 3; i++) newpt[i] = ei[i] + (1.0+rs) * (newpt[i] - ei[i]);
29040     } else {
29041       // Both endpoints are acute or not. Split it at the middle.
29042       for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29043       // Add a random perturbation on newpt.
29044       d1 = 0.5 * distance(e1, e2);
29045       ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29046       rs = ps / d1;
29047       for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29048     }
29049   } else {
29050     // Split the segment at its midpoint.
29051     for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29052     // Add a random perturbation on newpt.
29053     d1 = 0.5 * distance(e1, e2);
29054     ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29055     rs = ps / d1;
29056     for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29057   }
29058 }
29059 
29061 //                                                                           //
29062 // shepardinterpolation()    Interpolate the local size of a newpoint.       //
29063 //                                                                           //
29064 // The classical Shepard interoplation (inversed weighted distance) is used. //
29065 // (With the choice p = 2).                                                  //
29066 //                                                                           //
29067 // 'verlist' contains a list vertices neighboring to 'newpt'.                //
29068 //                                                                           //
29070 
29071 void tetgenmesh::shepardinterpolate(point newpt, list *verlist)
29072 {
29073   point neipt;
29074   REAL *weights, sumweight;
29075   REAL vec[3];
29076   int i, j;
29077 
29078   weights = new REAL[verlist->len()];
29079   sumweight = 0.0;
29080 
29081   // Calculate the weight of each point.
29082   for (i = 0; i < verlist->len(); i++) {
29083     neipt = * (point *)(* verlist)[i];
29084     for (j = 0; j < 3; j++) vec[j] = neipt[j] - newpt[j];
29085     weights[i] = 1.0 / dot(vec, vec);
29086     sumweight += weights[i];
29087   }
29088   // Interpolate.
29089   newpt[pointmtrindex] = 0.0;
29090   for (i = 0; i < verlist->len(); i++) {
29091     neipt = * (point *)(* verlist)[i];
29092     newpt[pointmtrindex] += (weights[i] * neipt[pointmtrindex]) / sumweight;
29093   }
29094 
29095   delete [] weights;
29096 }
29097 
29099 //                                                                           //
29100 // setnewpointsize()    Set the size for a new point.                        //
29101 //                                                                           //
29102 // The size of the new point p is interpolated either from a background mesh //
29103 // (b->bgmesh) or from the two input endpoints.                              //
29104 //                                                                           //
29106 
29107 void tetgenmesh::setnewpointsize(point newpt, point e1, point e2)
29108 {
29109   if (b->metric) {
29110     // Interpolate the point size in a background mesh.
29111     triface bgmtet;
29112     // Get a tet in background mesh for locating p.
29113     decode(point2bgmtet(e1), bgmtet);
29114     p1interpolatebgm(newpt, &bgmtet, NULL);
29115   } else {
29116     if (e2 != (point) NULL) {
29117       // Interpolate the size between the two endpoints.
29118       REAL split, l, d;
29119       l = distance(e1, e2);
29120       d = distance(e1, newpt);
29121       split = d / l;
29122 #ifdef SELF_CHECK
29123       // Check if e1 and e2 are endpoints of a sharp segment.
29124       assert(e1[pointmtrindex] > 0.0);
29125       assert(e2[pointmtrindex] > 0.0);
29126 #endif
29127       newpt[pointmtrindex] = (1.0 - split) * e1[pointmtrindex]
29128                            + split * e2[pointmtrindex];
29129     }
29130   }
29131 }
29132 
29134 //                                                                           //
29135 // splitencseg()    Split an enc-seg and recover the Delaunayness by flips.  //
29136 //                                                                           //
29138 
29139 void tetgenmesh::splitencseg(point newpt, face* splitseg, list* tetlist,
29140   list* sublist, list* verlist, queue* flipque, bool chkencsub, bool chkbadtet,
29141   bool optflag)
29142 {
29143   list *mytetlist;
29144   queue *myflipque;
29145   triface starttet;
29146   face startsh, spinsh, checksh;
29147   int i;
29148 
29149   mytetlist = NULL;
29150   myflipque = NULL;
29151 
29152   if (optflag) {
29153     mytetlist = new list(sizeof(triface), NULL, 1024);
29154     myflipque = new queue(sizeof(badface));
29155     tetlist = mytetlist;
29156     flipque = myflipque;
29157   }
29158 
29159   // Use the base orientation (important in this routine).
29160   splitseg->shver = 0;
29161   // Insert p, this should always success.
29162   sstpivot(splitseg, &starttet);
29163   splittetedge(newpt, &starttet, flipque);
29164   // Remove locally non-Delaunay faces by flipping.
29165   flip(flipque, NULL); // lawson(NULL, flipque);
29166 
29167   if (!optflag) {
29168     // Check the two new subsegs to see if they're encroached (not by p).
29169     for (i = 0; i < 2; i++) {
29170       if (!shell2badface(*splitseg)) {
29171         checkseg4encroach(splitseg, NULL, NULL, true);
29172       }
29173       if (i == 1) break; // Two new segs have been checked.
29174       senextself(*splitseg);
29175       spivotself(*splitseg);
29176 #ifdef SELF_CHECK
29177       assert(splitseg->sh != (shellface *) NULL);
29178 #endif
29179       splitseg->shver = 0;
29180     }
29181     // Check the new subfaces to see if they're encroached (not by p).
29182     if (chkencsub) {
29183       spivot(*splitseg, startsh);
29184       spinsh = startsh;
29185       do {
29186         sublist->append(&spinsh);
29187         formstarpolygon(newpt, sublist, verlist);
29188         for (i = 0; i < sublist->len(); i++) {
29189           checksh = * (face *)(* sublist)[i];
29190           if (!shell2badface(checksh)) {
29191             checksub4encroach(&checksh, NULL, true);
29192           }
29193         }
29194         sublist->clear();
29195         if (verlist) verlist->clear();
29196         spivotself(spinsh);
29197       } while (spinsh.sh != startsh.sh);
29198     }
29199   } // if (!optflag)
29200 
29201   // Collect the new tets connecting at p.
29202   sstpivot(splitseg, &starttet);
29203   tetlist->append(&starttet);
29204   formstarpolyhedron(newpt, tetlist, verlist, true);
29205 
29206   if (!optflag) {
29207     // Check if p encroaches adjacent segments.
29208     tallencsegs(newpt, 1, &tetlist);
29209     if (chkencsub) {
29210       // Check if p encroaches adjacent subfaces.
29211       tallencsubs(newpt, 1, &tetlist);
29212     }
29213     if (chkbadtet) {
29214       // Check if there are new bad quality tets at p.
29215       for (i = 0; i < tetlist->len(); i++) {
29216         starttet = * (triface *)(* tetlist)[i];
29217         checktet4badqual(&starttet, true);
29218       }
29219     }
29220     tetlist->clear();
29221   } else {
29222     // Check if new tets are non-optimal.
29223     for (i = 0; i < tetlist->len(); i++) {
29224       starttet = * (triface *)(* tetlist)[i];
29225       checktet4opt(&starttet, true);
29226     }
29227     delete mytetlist;
29228     delete myflipque;
29229   }
29230 }
29231 
29233 //                                                                           //
29234 // tallencsegs()    Check for encroached segments and save them in list.     //
29235 //                                                                           //
29236 // If 'testpt' (p) != NULL, only check if segments are encroached by p, else,//
29237 // check all the nearby mesh vertices.                                       //
29238 //                                                                           //
29239 // If 'ceillists' (B_i(p)) != NULL, there are 'n' B_i(p)s, only check the    //
29240 // segments which are on B_i(p)s, else, check the entire list of segments    //
29241 // (in the pool 'this->subsegs').                                            //
29242 //                                                                           //
29244 
29245 bool tetgenmesh::tallencsegs(point testpt, int n, list **ceillists)
29246 {
29247   list *ceillist;
29248   triface ceiltet;
29249   face checkseg;
29250   long oldencnum;
29251   int i, j, k;
29252 
29253   // Remember the current number of encroached segments.
29254   oldencnum = badsubsegs->items;
29255 
29256   if (ceillists != (list **) NULL) {
29257     for (k = 0; k < n; k++) {
29258       ceillist = ceillists[k];
29259       // Check the segments on B_i(p).
29260       for (i = 0; i < ceillist->len(); i++) {
29261         ceiltet = * (triface *)(* ceillist)[i];
29262         ceiltet.ver = 0;
29263         for (j = 0; j < 3; j++) {
29264           tsspivot(&ceiltet, &checkseg);
29265           if (checkseg.sh != dummysh) {
29266             // Found a segment. Test it if it isn't in enc-list.
29267             if (!shell2badface(checkseg)) {
29268               checkseg4encroach(&checkseg, testpt, NULL, true);
29269             }
29270           }
29271           enextself(ceiltet);
29272         }
29273       }
29274     }
29275   } else {
29276     // Check the entire list of segments.
29277     subsegs->traversalinit();
29278     checkseg.sh = shellfacetraverse(subsegs);
29279     while (checkseg.sh != (shellface *) NULL) {
29280       // Test it if it isn't in enc-list.
29281       if (!shell2badface(checkseg)) {
29282         checkseg4encroach(&checkseg, testpt, NULL, true);
29283       }
29284       checkseg.sh = shellfacetraverse(subsegs);
29285     }
29286   }
29287 
29288   return (badsubsegs->items > oldencnum);
29289 }
29290 
29292 //                                                                           //
29293 // tallencsubs()    Find all encroached subfaces and save them in list.      //
29294 //                                                                           //
29295 // If 'testpt' (p) != NULL, only check if subfaces are encroached by p, else,//
29296 // check the adjacent vertices of subfaces.                                  //
29297 //                                                                           //
29298 // If 'ceillists' (B_i(p)) != NULL, there are 'n' B_i(p)s, only check the    //
29299 // subfaces which are on B_i(p)s, else, check the entire list of subfaces    //
29300 // (in the pool 'this->subfaces').                                           //
29301 //                                                                           //
29303 
29304 bool tetgenmesh::tallencsubs(point testpt, int n, list** ceillists)
29305 {
29306   list *ceillist;
29307   triface ceiltet;
29308   face checksh;
29309   long oldencnum;
29310   int i, k;
29311 
29312   // Remember the current number of encroached segments.
29313   oldencnum = badsubfaces->items;
29314 
29315   if (ceillists != (list **) NULL) {
29316     for (k = 0; k < n; k++) {
29317       ceillist = ceillists[k];
29318       // Check the subfaces on B_i(p).
29319       for (i = 0; i < ceillist->len(); i++) {
29320         ceiltet = * (triface *)(* ceillist)[i];
29321         tspivot(ceiltet, checksh);
29322         if (checksh.sh != dummysh) {
29323           // Found a subface. Test it if it isn't in enc-list.
29324           if (!shell2badface(checksh)) {
29325             checksub4encroach(&checksh, testpt, true);
29326           }
29327         }
29328       }
29329     }
29330   } else {
29331     // Check the entire list of subfaces.
29332     subfaces->traversalinit();
29333     checksh.sh = shellfacetraverse(subfaces);
29334     while (checksh.sh != (shellface *) NULL) {
29335       // Test it if it isn't in enc-list.
29336       if (!shell2badface(checksh)) {
29337         checksub4encroach(&checksh, testpt, true);
29338       }
29339       checksh.sh = shellfacetraverse(subfaces);
29340     }
29341   }
29342 
29343   return (badsubfaces->items > oldencnum);
29344 }
29345 
29347 //                                                                           //
29348 // tallbadtetrahedrons()    Queue all the bad-quality tetrahedra in the mesh.//
29349 //                                                                           //
29351 
29352 void tetgenmesh::tallbadtetrahedrons()
29353 {
29354   triface tetloop;
29355 
29356   tetrahedrons->traversalinit();
29357   tetloop.tet = tetrahedrontraverse();
29358   while (tetloop.tet != (tetrahedron *) NULL) {
29359     checktet4badqual(&tetloop, true);
29360     tetloop.tet = tetrahedrontraverse();
29361   }
29362 }
29363 
29365 //                                                                           //
29366 // repairencsegs()    Repair (split) all the encroached segments.            //
29367 //                                                                           //
29368 // Each encroached segment is repaired by splitting it - inserting a vertex  //
29369 // at or near its midpoint.  Newly inserted vertices may encroach upon other //
29370 // subsegments, these are also repaired.                                     //
29371 //                                                                           //
29372 // 'chkencsub' and 'chkbadtet' are two flags that specify whether one should //
29373 // take note of new encroaced subfaces and bad quality tets that result from //
29374 // inserting vertices to repair encroached subsegments.                      //
29375 //                                                                           //
29377 
29378 void tetgenmesh::repairencsegs(bool chkencsub, bool chkbadtet)
29379 {
29380   list **tetlists, **ceillists;
29381   list **sublists, **subceillists;
29382   list *tetlist, *sublist;
29383   queue *flipque;
29384   badface *encloop;
29385   face splitseg, symsplitseg;
29386   point newpt, sympt, refpt;
29387   point e1, e2;
29388   enum locateresult symloc;
29389   int nmax, n, i, j;
29390 
29391   ceillists = NULL;
29392   flipque = NULL;
29393   subceillists = NULL;
29394   sublist = NULL;
29395   sublists = NULL;
29396   tetlist = NULL;
29397   tetlists = NULL;
29398 
29399   n = 0;
29400   nmax = 128;
29401   if (!b->fliprepair) {
29402     tetlists = new list*[nmax];
29403     ceillists = new list*[nmax];
29404     sublists = new list*[nmax];
29405     subceillists = new list*[nmax];
29406   } else {
29407     tetlist = new list(sizeof(triface), NULL, 1024);
29408     sublist = new list(sizeof(face), NULL, 256);
29409     flipque = new queue(sizeof(badface));
29410   }
29411 
29412   // Loop until the pool 'badsubsegs' is empty. Note that steinerleft == -1
29413   //   if an unlimited number of Steiner points is allowed.
29414   while ((badsubsegs->items > 0) && (steinerleft != 0)) {
29415     badsubsegs->traversalinit();
29416     encloop = badfacetraverse(badsubsegs);
29417     while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
29418       // Get an encroached subsegment s.
29419       splitseg = encloop->ss;
29420       // Clear the in-queue flag in s.
29421       setshell2badface(splitseg, NULL);
29422       if ((sorg(splitseg) == encloop->forg) &&
29423           (sdest(splitseg) == encloop->fdest)) {
29424         if (b->verbose > 1) {
29425           printf("  Get an enc-seg (%d, %d)\n", pointmark(encloop->forg),
29426                  pointmark(encloop->fdest));
29427         }
29428         refpt = (point) NULL;
29429         if (b->conformdel) {
29430           // Look for a reference point.
29431           checkseg4encroach(&splitseg, NULL, &refpt, false);
29432         }
29433         // Create the new point p (at the middle of s).
29434         makepoint(&newpt);
29435         getsplitpoint(encloop->forg, encloop->fdest, refpt, newpt);
29436         setpointtype(newpt, FREESEGVERTEX);
29437         setpoint2sh(newpt, sencode(splitseg));
29438         // Decide whether p can be inserted or not.
29439         if (acceptsegpt(newpt, refpt, &splitseg)) {
29440           // Is there periodic boundary condition?
29441           if (checkpbcs) {
29442             // Insert points on other segments of incident pbcgroups.
29443             i = shellmark(splitseg) - 1;
29444             for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
29445               makepoint(&sympt);
29446               symloc = getsegpbcsympoint(newpt, &splitseg, sympt, &symsplitseg,
29447                                          segpglist[j]);
29448               if (symloc == ONEDGE) {
29449                 if (symsplitseg.sh != splitseg.sh) {
29450                   // Insert sympt.
29451                   setpointtype(sympt, FREESEGVERTEX);
29452                   setpoint2sh(sympt, sencode(symsplitseg));
29453                   // Save the endpoints of the seg for size interpolation.
29454                   e1 = sorg(symsplitseg);
29455                   if (shelltype(symsplitseg) == SHARP) {
29456                     e2 = sdest(symsplitseg);
29457                   } else {
29458                     e2 = (point) NULL; // No need to do size interpolation.
29459                   }
29460                   if (!b->fliprepair) {
29461                     // Form BC(symp), B(symp), CBC(symp)s, C(symp)s.
29462                     formbowatcavity(sympt, &symsplitseg, NULL, &n, &nmax,
29463                       sublists, subceillists, tetlists, ceillists);
29464                     // Validate BC(symp), B(symp), CBC(symp)s, C(symp)s.
29465                     if (trimbowatcavity(sympt, &symsplitseg, n, sublists,
29466                           subceillists, tetlists, ceillists, -1.0)) {
29467                       bowatinsertsite(sympt, &symsplitseg, n, sublists,
29468                         subceillists, tetlists, ceillists, NULL, flipque,
29469                         true, chkencsub, chkbadtet);
29470                       setnewpointsize(sympt, e1, e2);
29471                       if (steinerleft > 0) steinerleft--;
29472                     } else {
29473                       // p did not insert for invalid BC(symp).
29474                       pointdealloc(sympt);
29475                     }
29476                     // Free the memory allocated in formbowatcavity().
29477                     releasebowatcavity(&symsplitseg, n, sublists, subceillists,
29478                                        tetlists, ceillists);
29479                   } else {
29480                     splitencseg(sympt, &symsplitseg, tetlist, sublist, NULL,
29481                                 flipque, chkencsub, chkbadtet, false);
29482                     setnewpointsize(sympt, e1, e2);
29483                     if (steinerleft > 0) steinerleft--;
29484                   }
29485                 } else {
29486                   // The sympt are on the same segment. It is possible when
29487                   //   splitseg is the symmetric rotating axes.
29488                   pointdealloc(sympt);
29489                 }
29490               } else if (symloc == ONVERTEX) {
29491                 // The sympt already exists. It is possible when two pbc
29492                 //   groups are exactly the same. Omit this point.
29493                 pointdealloc(sympt);
29494               } else {
29495                 // Do not isnert symp for unknown cases: ONFACE, OUTSIDE.
29496                 // assert(0);
29497                 pointdealloc(sympt);
29498               }
29499             } // for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++)
29500           } // if (checkpbcs)
29501           // Save the endpoints of the seg for size interpolation.
29502           e1 = sorg(splitseg);
29503           if (shelltype(splitseg) == SHARP) {
29504             e2 = sdest(splitseg);
29505           } else {
29506             e2 = (point) NULL; // No need to do size interoplation.
29507           }
29508           if (!b->fliprepair) {
29509             // Form BC(p), B(p), CBC(p)s, and C(p)s.
29510             formbowatcavity(newpt, &splitseg, NULL, &n, &nmax, sublists,
29511                             subceillists, tetlists, ceillists);
29512             // Validate/update BC(p), B(p), CBC(p)s, and C(p)s.
29513             if (trimbowatcavity(newpt, &splitseg, n, sublists, subceillists,
29514                                 tetlists, ceillists, -1.0)) {
29515               bowatinsertsite(newpt, &splitseg, n, sublists, subceillists,
29516                               tetlists, ceillists, NULL, flipque, true,
29517                               chkencsub, chkbadtet);
29518               setnewpointsize(newpt, e1, e2);
29519               if (steinerleft > 0) steinerleft--;
29520             } else {
29521               // p did not insert for invalid B(p).
29522               pointdealloc(newpt);
29523             }
29524             // Free the memory allocated in formbowatcavity().
29525             releasebowatcavity(&splitseg, n, sublists, subceillists, tetlists,
29526                                ceillists);
29527           } else {
29528             splitencseg(newpt, &splitseg, tetlist, sublist, NULL, flipque,
29529                         chkencsub, chkbadtet, false);
29530             setnewpointsize(newpt, e1, e2);
29531             if (steinerleft > 0) steinerleft--;
29532           }
29533         } else {
29534           // p did not accept for insertion.
29535           pointdealloc(newpt);
29536         } // if (checkseg4splitting(newpt, &splitseg))
29537       } // if ((encloop->forg == pa) && (encloop->fdest == pb))
29538       badfacedealloc(badsubsegs, encloop); // Remove this entry from list.
29539       encloop = badfacetraverse(badsubsegs); // Get the next enc-segment.
29540     } // while ((encloop != (badface *) NULL) && (steinerleft != 0))
29541   } // while ((badsubsegs->items > 0) && (steinerleft != 0))
29542 
29543   if (!b->fliprepair) {
29544     delete [] tetlists;
29545     delete [] ceillists;
29546     delete [] sublists;
29547     delete [] subceillists;
29548   } else {
29549     delete tetlist;
29550     delete sublist;
29551     delete flipque;
29552   }
29553 }
29554 
29556 //                                                                           //
29557 // repairencsubs()    Repair (split) all the encroached subfaces.            //
29558 //                                                                           //
29559 // Each encroached subface is repaired by splitting it - inserting a vertex  //
29560 // at or near its circumcenter.  Newly inserted vertices may encroach upon   //
29561 // other subfaces, these are also repaired.                                  //
29562 //                                                                           //
29563 // 'chkbadtet' is a flag that specifies whether one should take note of new  //
29564 // bad quality tets that result from inserted vertices.                      //
29565 //                                                                           //
29567 
29568 void tetgenmesh::repairencsubs(bool chkbadtet)
29569 {
29570   list *tetlists[2], *ceillists[2];
29571   list *sublist, *subceillist;
29572   list *verlist;
29573   badface *encloop;
29574   face splitsub, symsplitsub;
29575   point newpt, sympt, e1;
29576   enum locateresult loc, symloc;
29577   bool reject;
29578   long oldptnum;
29579   int quenumber, n, i;
29580 
29581   quenumber = 0;
29582   n = 0;
29583   sublist = (list *) NULL;
29584   subceillist = (list *) NULL;
29585   verlist = new list(sizeof(point *), NULL, 256);
29586 
29587   // Loop until the pool 'badsubfaces' is empty. Note that steinerleft == -1
29588   //   if an unlimited number of Steiner points is allowed.
29589   while ((badsubfaces->items > 0) && (steinerleft != 0)) {
29590     // Get an encroached subface f.
29591     encloop = dequeueencsub(&quenumber);
29592     splitsub = encloop->ss;
29593     // Clear the in-queue flag of f.
29594     setshell2badface(splitsub, NULL);
29595     // f may not be the same one when it was determined to be encroached.
29596     if (!isdead(&splitsub)
29597         && (sorg(splitsub) == encloop->forg)
29598         && (sdest(splitsub) == encloop->fdest)
29599         && (sapex(splitsub) == encloop->fapex)) {
29600       if (b->verbose > 1) {
29601         printf("    Dequeuing ensub (%d, %d, %d) [%d].\n",
29602                pointmark(encloop->forg), pointmark(encloop->fdest),
29603                pointmark(encloop->fapex), quenumber);
29604       }
29605       // Create a new point p at the circumcenter of f.
29606       makepoint(&newpt);
29607       for (i = 0; i < 3; i++) newpt[i] = encloop->cent[i];
29608       setpointtype(newpt, FREESUBVERTEX);
29609       setpoint2sh(newpt, sencode(splitsub));
29610       // Set the abovepoint of f for point location.
29611       abovepoint = facetabovepointarray[shellmark(splitsub)];
29612       if (abovepoint == (point) NULL) {
29613         getfacetabovepoint(&splitsub);
29614       }
29615       // Locate p, start from f, stop at segment (1), use a tolerance to
29616       //   detect ONVERTEX or OUTSIDE case. Update f on return.
29617       loc = locatesub(newpt, &splitsub, 1, b->epsilon * 1e+2);
29618       if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29619         // Form BC(p), B(p), CBC(p) and C(p).
29620         formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29621                         &subceillist, tetlists, ceillists);
29622         // Check for encroached subsegments (on B(p)).
29623         reject = tallencsegs(newpt, 2, ceillists);
29624         // Execute point accept rule if p does not encroach upon any segment.
29625         if (!reject) {
29626           reject = !acceptfacpt(newpt, subceillist, verlist);
29627         }
29628         if (!reject) {
29629           // Validate/update cavity.
29630           reject = !trimbowatcavity(newpt, NULL, n, &sublist, &subceillist,
29631                                     tetlists, ceillists, -1.0);
29632         }
29633         if (!reject) {
29634           // CBC(p) should include s, so that s can be removed after CBC(p)
29635           //   is remeshed. However, if there are locally non-Delaunay faces
29636           //   and encroached subsegments, s may not be collected in CBC(p).
29637           //   p should not be inserted in such case.
29638           reject = !sinfected(encloop->ss);
29639         }
29640         if (!reject) {
29641           if (checkpbcs) {
29642             if (shellpbcgroup(splitsub) >= 0) {
29643               // Check for splitting of the symmetric subface of f.
29644               makepoint(&sympt);
29645               symloc = getsubpbcsympoint(newpt,&splitsub,sympt,&symsplitsub);
29646               if (symloc != ONVERTEX) {
29647                 // Release CBC(p) and BC(p) and free the memory..
29648                 releasebowatcavity(NULL, 2, &sublist, &subceillist, tetlists,
29649                                    ceillists);
29650                 // Form CBC(symp), C(symp), BC(sympt) and B(sympt).
29651                 formbowatcavity(sympt, NULL, &symsplitsub, &n, NULL, &sublist,
29652                                 &subceillist, tetlists, ceillists);
29653                 reject = tallencsegs(sympt, 2, ceillists);
29654                 if (!reject) {
29655                   reject = !acceptfacpt(sympt, subceillist, verlist);
29656                 }
29657                 if (!reject) {
29658                   reject = !trimbowatcavity(sympt,NULL,n,&sublist,&subceillist,
29659                                             tetlists, ceillists, -1.0);
29660                 }
29661                 if (!reject) {
29662                   // Insert sympt.
29663                   setpoint2pbcpt(newpt, sympt);
29664                   setpoint2pbcpt(sympt, newpt);
29665                   setpointtype(sympt, FREESUBVERTEX);
29666                   setpoint2sh(sympt, sencode(symsplitsub));
29667                   // Save a point for size interpolation.
29668                   e1 = sorg(symsplitsub);
29669                   bowatinsertsite(sympt, NULL, n, &sublist, &subceillist,
29670                      tetlists,ceillists,NULL,NULL,false,true,chkbadtet);
29671                   setnewpointsize(sympt, e1, NULL);
29672                   if (steinerleft > 0) steinerleft--;
29673                   // Release CBC(symp) and BC(symp) and free the memory..
29674                   releasebowatcavity(NULL, n, &sublist, &subceillist, tetlists,
29675                                      ceillists);
29676                 } else {
29677                   // symp is rejected for one of the following reasons:
29678                   //   (1) BC(symp) is not valid; or
29679                   //   (2) symp encroaches upon some subsegments (queued); or
29680                   //   (3) symp is rejected by point accepting rule.
29681                   pointdealloc(sympt);
29682                   // Cavity will be released by the following code.
29683                 }
29684               } else {
29685                 // Do not insert sympt for invalid PBC data.
29686                 pointdealloc(sympt);
29687                 // p is rejected due to symp.
29688                 reject = true;
29689               }
29690             }
29691           } // if (checkpbcs)
29692         }
29693         if (!reject) {
29694           // Insert p.
29695           if (checkpbcs) {
29696             if (shellpbcgroup(splitsub) >= 0) {
29697               // Form CBC(p), C(p), BC(p) and B(p).
29698               formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29699                               &subceillist, tetlists, ceillists);
29700               trimbowatcavity(newpt, NULL, n, &sublist, &subceillist, tetlists,
29701                               ceillists, -1.0);
29702             }
29703           }
29704           // Save a point for size interpolation.
29705           e1 = sorg(splitsub);
29706           bowatinsertsite(newpt, NULL, n, &sublist, &subceillist, tetlists,
29707                           ceillists, NULL, NULL, true, true, chkbadtet);
29708           setnewpointsize(newpt, e1, NULL);
29709           if (steinerleft > 0) steinerleft--;
29710         } else {
29711           // p is rejected for the one of the following reasons:
29712           //   (1) BC(p) is not valid.
29713           //   (2) s does not in CBC(p).
29714           //   (3) p encroaches upon some segments (queued); or
29715           //   (4) p is rejected by point accepting rule, or
29716           //   (5) due to the rejection of symp (the PBC).
29717           pointdealloc(newpt);
29718         } // if (!reject)
29719         // Release the cavity and free the memory.
29720         releasebowatcavity(NULL,n,&sublist,&subceillist,tetlists,ceillists);
29721         if (reject) {
29722           // Are there queued encroached subsegments.
29723           if (badsubsegs->items > 0) {
29724             // Repair enc-subsegments.
29725             oldptnum = points->items;
29726             repairencsegs(true, chkbadtet);
29727             if (points->items > oldptnum) {
29728               // Some enc-subsegments got split. Try to repair f later.
29729               splitsub = encloop->ss;
29730               if (!isdead(&splitsub)) {
29731                 if (!shell2badface(splitsub)) {
29732                   checksub4encroach(&splitsub, NULL, true);
29733                 }
29734               }
29735             }
29736           }
29737         }
29738       } else {
29739         // Don't insert p for one of the following reasons:
29740         //   (1) Locate on an existing vertex; or
29741         //   (2) locate outside the domain.
29742         // Case (1) should not be possible. If such vertex v exists, it is
29743         //   the circumcenter of f, ie., f is non-Delaunay. Either f was got
29744         //   split before by v, but survived after v was inserted, or the
29745         //   same for a f' which is nearly co-circular with f.  Whatsoever,
29746         //   there are encroached segs by v, but the routine tallencsegs()
29747         //   did not find them out.
29748         if (loc == ONVERTEX) {
29749           printf("Internal error in repairencsubs():\n");
29750           printf("  During repairing encroached subface (%d, %d, %d)\n",
29751                  pointmark(encloop->forg), pointmark(encloop->fdest),
29752                  pointmark(encloop->fapex));
29753           printf("  New point %d is coincident with an existing vertex %d\n",
29754                  pointmark(newpt), pointmark(sorg(splitsub)));
29755           internalerror();
29756         }
29757         // Case (2) can happen when thers is a segment s which is close to f
29758         //   and is non-conforming Delaunay. The circumcenter of f encroaches
29759         //   upon s, but the circumcenter of s is rejected for insertion.
29760         pointdealloc(newpt);
29761       } // if ((loc != ONVERTEX) && (loc != OUTSIDE))
29762     } else {
29763       if (!isdead(&splitsub)) {
29764         // The subface has been changed, re-check it.
29765         checksub4encroach(&splitsub, NULL, true);
29766       }
29767     } // if (!isdead(&splitsub) && (sorg(splitsub) == encloop->forg) &&
29768     // Remove this entry from list.
29769     badfacedealloc(badsubfaces, encloop);
29770   } // while ((badsubfaces->items > 0) && (steinerleft != 0))
29771 
29772   delete verlist;
29773 }
29774 
29776 //                                                                           //
29777 // repairbadtets()    Repair all bad-quality tetrahedra.                     //
29778 //                                                                           //
29779 // All bad-quality tets are stored in pool 'badtetrahedrons'.  Each bad tet  //
29780 // is repaired by inserting a point at or near its circumcenter. However, if //
29781 // this point encroaches any subsegment or subface, it is not inserted. Ins- //
29782 // tead the encroached segment and subface are split.  Newly inserted points //
29783 // may create other bad-quality tets, these are also repaired.               //
29784 //                                                                           //
29786 
29787 void tetgenmesh::repairbadtets()
29788 {
29789   list *tetlist, *ceillist;
29790   list *verlist;
29791   badface *badtet;
29792   triface starttet;
29793   point newpt, e1;
29794   enum locateresult loc;
29795   bool reject;
29796   long oldptnum;
29797   int i;
29798 
29799   tetlist = new list(sizeof(triface), NULL, 1024);
29800   ceillist = new list(sizeof(triface), NULL, 1024);
29801   verlist = new list(sizeof(point *), NULL, 256);
29802 
29803   // Loop until pool 'badtetrahedrons' is empty. Note that steinerleft == -1
29804   //   if an unlimited number of Steiner points is allowed.
29805   while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
29806     // Get a bad-quality tet t.
29807     badtet = topbadtetra();
29808     // Make sure that the tet is still the same one when it was tested.
29809     //   Subsequent transformations may have made it a different tet.
29810     if ((badtet != (badface *) NULL) && !isdead(&badtet->tt)
29811          && org(badtet->tt) == badtet->forg
29812          && dest(badtet->tt) == badtet->fdest
29813          && apex(badtet->tt) == badtet->fapex
29814          && oppo(badtet->tt) == badtet->foppo) {
29815       if (b->verbose > 1) {
29816         printf("    Dequeuing btet (%d, %d, %d, %d).\n",
29817                pointmark(badtet->forg), pointmark(badtet->fdest),
29818                pointmark(badtet->fapex), pointmark(badtet->foppo));
29819       }
29820       // Create the new point p (at the circumcenter of t).
29821       makepoint(&newpt);
29822       for (i = 0; i < 3; i++) newpt[i] = badtet->cent[i];
29823       setpointtype(newpt, FREEVOLVERTEX);
29824       // Locate p.
29825       starttet = badtet->tt;
29826       loc = preciselocate(newpt, &starttet, tetrahedrons->items);
29827       if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29828         // For BC(p) and B(p).
29829         infect(starttet);
29830         tetlist->append(&starttet);
29831         formbowatcavityquad(newpt, tetlist, ceillist);
29832         // Check for encroached subsegments.
29833         reject = tallencsegs(newpt, 1, &ceillist);
29834         if (!reject) {
29835           // Check for encroached subfaces.
29836           reject = tallencsubs(newpt, 1, &ceillist);
29837         }
29838         // Execute point accepting rule if p does not encroach upon any
29839         //   subsegment and subface.
29840         if (!reject) {
29841           reject = !acceptvolpt(newpt, ceillist, verlist);
29842         }
29843         if (!reject) {
29844           reject = !trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist,
29845                                     &ceillist, -1.0);
29846         }
29847         if (!reject) {
29848           // BC(p) should include t, so that t can be removed after BC(p) is
29849           //   remeshed. However, if there are locally non-Delaunay faces
29850           //   and encroached subsegments/subfaces, t may not be collected
29851           //   in BC(p). p should not be inserted in such case.
29852           reject = !infected(badtet->tt);
29853           if (reject) outbowatcircumcount++;
29854         }
29855         if (!reject) {
29856           // Save a point for size interpolation.
29857           e1 = org(starttet);
29858           // Insert p.
29859           bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist,
29860                           NULL, NULL, false, false, true);
29861           setnewpointsize(newpt, e1, NULL);
29862           if (steinerleft > 0) steinerleft--;
29863         } else {
29864           // p is rejected for one of the following reasons:
29865           //   (1) BC(p) is not valid.
29866           //   (2) t does not in BC(p).
29867           //   (3) p encroaches upon some segments;
29868           //   (4) p encroaches upon some subfaces;
29869           //   (5) p is rejected by the point accepting rule.
29870           pointdealloc(newpt);
29871           // Uninfect tets of BC(p).
29872           for (i = 0; i < tetlist->len(); i++) {
29873             starttet = * (triface *)(* tetlist)[i];
29874             uninfect(starttet);
29875           }
29876         }
29877         tetlist->clear();
29878         ceillist->clear();
29879         // Split encroached subsegments/subfaces if there are.
29880         if (reject) {
29881           oldptnum = points->items;
29882           if (badsubsegs->items > 0) {
29883             repairencsegs(true, true);
29884           }
29885           if (badsubfaces->items > 0) {
29886             repairencsubs(true);
29887           }
29888           if (points->items > oldptnum) {
29889             // Some encroaching subsegments/subfaces got split. Re-queue the
29890             //   tet if it is still alive.
29891             starttet = badtet->tt;
29892             if (!isdead(&starttet)) {
29893               checktet4badqual(&starttet, true);
29894             }
29895           }
29896         }
29897       } else {
29898         // Do not insert p. The reason may be one of:
29899         //   (1) p is coincident (ONVERTEX) with an existing vertex; or
29900         //   (2) p is outside (OUTSIDE) the mesh.
29901         // Case (1) should not be possible. If such vertex v exists, it is
29902         //   the circumcenter of t, ie., t is non-Delaunay. Either t was got
29903         //   split before by v, but survived after v was inserted, or the
29904         //   same for a t' which is nearly co-spherical with t.  Whatsoever,
29905         //   there are encroached segments or subfaces by v but the routines
29906         //   tallencsegs() or tallencsubs() did not find them out.
29907         if (loc == ONVERTEX) {
29908           printf("Internal error in repairbadtets():\n");
29909           printf("  During repairing bad tet (%d, %d, %d, %d)\n",
29910                  pointmark(badtet->forg), pointmark(badtet->fdest),
29911                  pointmark(badtet->fapex), pointmark(badtet->foppo));
29912           printf("  New point %d is coincident with an existing vertex %d\n",
29913                  pointmark(newpt), pointmark(org(starttet)));
29914           internalerror();
29915         }
29916         // Case (2) can happen when there is a segment s (or subface f) which
29917         //   is close to f and is non-conforming Delaunay.  The circumcenter
29918         //   of t encroaches upon s (or f), but the circumcenter of s (or f)
29919         //   is rejected for insertion.
29920         pointdealloc(newpt);
29921       } // if ((loc != ONVERTEX) && (loc != OUTSIDE))
29922     } // if (!isdead(&badtet->tt) && org(badtet->tt) == badtet->forg &&
29923     // Remove the tet from the queue.
29924     dequeuebadtet();
29925   } // while ((badtetrahedrons->items > 0) && (steinerleft != 0))
29926 
29927   delete tetlist;
29928   delete ceillist;
29929   delete verlist;
29930 }
29931 
29933 //                                                                           //
29934 // enforcequality()    Refine the mesh.                                      //
29935 //                                                                           //
29937 
29938 void tetgenmesh::enforcequality()
29939 {
29940   long total, vertcount;
29941   int i;
29942 
29943   if (!b->quiet) {
29944     printf("Adding Steiner points to enforce quality.\n");
29945   }
29946 
29947   total = vertcount = 0l;
29948   if (b->conformdel) {
29949     r2count = r3count = 0l;
29950   }
29951 
29952   // If both '-D' and '-r' options are used.
29953   if (b->conformdel && b->refine) {
29954     markacutevertices(65.0);
29955   }
29956   // If '-m' is not used.
29957   if (!b->metric) {
29958     // Find and mark all sharp segments.
29959     marksharpsegments(65.0);
29960     // Decide the sizes for feature points.
29961     decidefeaturepointsizes();
29962   }
29963 
29964   // Initialize the pool of encroached subsegments.
29965   badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29966   // Looking for encroached subsegments.
29967   tallencsegs(NULL, 0, NULL);
29968   if (b->verbose && badsubsegs->items > 0) {
29969     printf("  Splitting encroached subsegments.\n");
29970   }
29971   vertcount = points->items;
29972   // Fix encroached segments without noting any enc subfaces.
29973   repairencsegs(false, false);
29974   if (b->verbose > 0) {
29975     printf("  %ld split points.\n", points->items - vertcount);
29976   }
29977   total += points->items - vertcount;
29978 
29979   // Initialize the pool of encroached subfaces.
29980   badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29981   // Initialize the priority queues of badfaces.
29982   for (i = 0; i < 3; i++) subquefront[i] = (badface *) NULL;
29983   for (i = 0; i < 3; i++) subquetail[i] = &subquefront[i];
29984   // Looking for encroached subfaces.
29985   tallencsubs(NULL, 0, NULL);
29986   if (b->verbose && badsubfaces->items > 0) {
29987     printf("  Splitting encroached subfaces.\n");
29988   }
29989   vertcount = points->items;
29990   // Fix encroached subfaces without noting bad tetrahedra.
29991   repairencsubs(false);
29992   if (b->verbose > 0) {
29993     printf("  %ld split points.\n", points->items - vertcount);
29994   }
29995   total += points->items - vertcount;
29996   // At this point, the mesh should be conforming Delaunay if no input
29997   //   angle is smaller than 90 degree.
29998 
29999   // Next, fix bad quality tetrahedra.
30000   if ((b->minratio > 0.0) || b->varvolume || b->fixedvolume) {
30001     // Initialize the pool of bad tets
30002     badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30003     // Initialize the priority queues of bad tets.
30004     for (i = 0; i < 64; i++) tetquefront[i] = (badface *) NULL;
30005     firstnonemptyq = -1;
30006     recentq = -1;
30007     // Looking for bad quality tets.
30008     cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30009     cosmindihed = cos(b->mindihedral * PI / 180.0);
30010     tallbadtetrahedrons();
30011     if (b->verbose && badtetrahedrons->items > 0) {
30012       printf("  Splitting bad tetrahedra.\n");
30013     }
30014     vertcount = points->items;
30015     repairbadtets();
30016     if (b->verbose > 0) {
30017       printf("  %ld refinement points.\n", points->items - vertcount);
30018     }
30019     total += points->items - vertcount;
30020     delete badtetrahedrons;
30021   }
30022 
30023   if (b->verbose > 0) {
30024     printf("  Totally added %ld points.\n", total);
30025   }
30026 
30027   delete badsubfaces;
30028   delete badsubsegs;
30029 }
30030 
30031 //
30032 // End of Delaunay refinement routines
30033 //
30034 
30035 //
30036 // Begin of mesh optimization routines
30037 //
30038 
30039 void tetgenmesh::dumpbadtets()
30040 {
30041   FILE *fout;
30042   badface *remtet;
30043 
30044   // Write out a file of remaining bad tets.
30045   printf("  Writing bad tets to file bad-dump.lua.\n");
30046   fout = fopen("bad-dump.lua", "w");
30047   fprintf(fout, "-- %ld remaining bad tets (> %g degree).\n",
30048           badtetrahedrons->items, b->maxdihedral);
30049   badtetrahedrons->traversalinit();
30050   remtet = badfacetraverse(badtetrahedrons);
30051   while (remtet != (badface *) NULL) {
30052     if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30053         dest(remtet->tt) == remtet->fdest &&
30054         apex(remtet->tt) == remtet->fapex &&
30055         oppo(remtet->tt) == remtet->foppo) {
30056       fprintf(fout, "p:draw_tet(%d, %d, %d, %d) -- %g\n",
30057               pointmark(remtet->forg), pointmark(remtet->fdest),
30058               pointmark(remtet->fapex), pointmark(remtet->foppo),
30059               acos(remtet->key) * 180.0 / PI);
30060     }
30061     remtet = badfacetraverse(badtetrahedrons);
30062   }
30063   fclose(fout);
30064 }
30065 
30067 //                                                                           //
30068 // checktet4ill()    Check a tet to see if it is illegal.                    //
30069 //                                                                           //
30070 // A tet is "illegal" if it spans on one input facet.  Save the tet in queue //
30071 // if it is illegal and the flag 'enqflag' is set.                           //
30072 //                                                                           //
30073 // Note: Such case can happen when the input facet has non-coplanar vertices //
30074 // and the Delaunay tetrahedralization of the vertices may creat such tets.  //
30075 //                                                                           //
30077 
30078 bool tetgenmesh::checktet4ill(triface* testtet, bool enqflag)
30079 {
30080   badface *newbadtet;
30081   triface checktet;
30082   face checksh1, checksh2;
30083   face checkseg;
30084   bool illflag;
30085   int i;
30086 
30087   illflag = false;
30088   for (testtet->loc = 0; testtet->loc < 4; testtet->loc++) {
30089     tspivot(*testtet, checksh1);
30090     if (checksh1.sh != dummysh) {
30091       testtet->ver = 0;
30092       findedge(&checksh1, org(*testtet), dest(*testtet));
30093       for (i = 0; i < 3; i++) {
30094         fnext(*testtet, checktet);
30095         tspivot(checktet, checksh2);
30096         if (checksh2.sh != dummysh) {
30097           // Two subfaces share this edge.
30098           sspivot(checksh1, checkseg);
30099           if (checkseg.sh == dummysh) {
30100             // The four corners of the tet are on one facet. Illegal! Try to
30101             //   flip the opposite edge of the current one.
30102             enextfnextself(*testtet);
30103             enextself(*testtet);
30104             illflag = true;
30105             break;
30106           }
30107         }
30108         enextself(*testtet);
30109         senextself(checksh1);
30110       }
30111     }
30112     if (illflag) break;
30113   }
30114 
30115   if (illflag && enqflag) {
30116     // Allocate space for the bad tetrahedron.
30117     newbadtet = (badface *) badtetrahedrons->alloc();
30118     newbadtet->tt = *testtet;
30119     newbadtet->key = -1.0; // = 180 degree.
30120     for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
30121     newbadtet->forg = org(*testtet);
30122     newbadtet->fdest = dest(*testtet);
30123     newbadtet->fapex = apex(*testtet);
30124     newbadtet->foppo = oppo(*testtet);
30125     newbadtet->nextitem = (badface *) NULL;
30126     if (b->verbose > 2) {
30127       printf("    Queueing illtet: (%d, %d, %d, %d).\n",
30128              pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30129              pointmark(newbadtet->fapex), pointmark(newbadtet->foppo));
30130     }
30131   }
30132 
30133   return illflag;
30134 }
30135 
30137 //                                                                           //
30138 // checktet4opt()    Check a tet to see if it needs to be optimized.         //
30139 //                                                                           //
30140 // A tet t needs to be optimized if it fails to certain quality measures.    //
30141 // The only quality measure currently used is the maximal dihedral angle at  //
30142 // edges. The desired maximal dihedral angle is b->maxdihed (set by the '-s' //
30143 // option.                                                                   //
30144 //                                                                           //
30145 // A tet may have one, two, or three big dihedral angles. Examples: Let the  //
30146 // tet t = abcd, and its four corners are nearly co-planar. Then t has one   //
30147 // big dihedral angle if d is very close to the edge ab; t has three big     //
30148 // dihedral angles if d's projection on the face abc is also inside abc, i.e.//
30149 // the shape of t likes a hat; finally, t has two big dihedral angles if d's //
30150 // projection onto abc is outside abc.                                       //
30151 //                                                                           //
30153 
30154 bool tetgenmesh::checktet4opt(triface* testtet, bool enqflag)
30155 {
30156   badface *newbadtet;
30157   point pa, pb, pc, pd;
30158   REAL N[4][3], len;
30159   REAL cosd;
30160   bool enq;
30161   int i, j;
30162 
30163   cosd = 0.0;
30164   enq = false;
30165   pa = (point) testtet->tet[4];
30166   pb = (point) testtet->tet[5];
30167   pc = (point) testtet->tet[6];
30168   pd = (point) testtet->tet[7];
30169   // Compute the 4 face normals: N[0] cbd, N[1] acd, N[2] bad, N[3] abc.
30170   tetallnormal(pa, pb, pc, pd, N, NULL);
30171   // Normalize the normals.
30172   for (i = 0; i < 4; i++) {
30173     len = sqrt(dot(N[i], N[i]));
30174     if (len != 0.0) {
30175       for (j = 0; j < 3; j++) N[i][j] /= len;
30176     }
30177   }
30178   // Find all large dihedral angles.
30179   for (i = 0; i < 6; i++) {
30180     // Locate the edge i and calculate the dihedral angle at the edge.
30181     testtet->loc = 0;
30182     testtet->ver = 0;
30183     switch (i) {
30184     case 0: // edge ab
30185       cosd = -dot(N[2], N[3]);
30186       break;
30187     case 1: // edge cd
30188       enextfnextself(*testtet);
30189       enextself(*testtet);
30190       cosd = -dot(N[0], N[1]);
30191       break;
30192     case 2: // edge bd
30193       enextfnextself(*testtet);
30194       enext2self(*testtet);
30195       cosd = -dot(N[0], N[2]);
30196       break;
30197     case 3: // edge bc
30198       enextself(*testtet);
30199       cosd = -dot(N[0], N[3]);
30200       break;
30201     case 4: // edge ad
30202       enext2fnextself(*testtet);
30203       enextself(*testtet);
30204       cosd = -dot(N[1], N[2]);
30205       break;
30206     case 5: // edge ac
30207       enext2self(*testtet);
30208       cosd = -dot(N[1], N[3]);
30209       break;
30210     }
30211     if (cosd < cosmaxdihed) {
30212       // A bigger dihedral angle.
30213       if (enqflag) {
30214         // Allocate space for the bad tetrahedron.
30215         newbadtet = (badface *) badtetrahedrons->alloc();
30216         newbadtet->tt = *testtet;
30217         newbadtet->key = cosd;
30218         for (j = 0; j < 3; j++) newbadtet->cent[j] = 0.0;
30219         newbadtet->forg = org(*testtet);
30220         newbadtet->fdest = dest(*testtet);
30221         newbadtet->fapex = apex(*testtet);
30222         newbadtet->foppo = oppo(*testtet);
30223         newbadtet->nextitem = (badface *) NULL;
30224         if (b->verbose > 2) {
30225           printf("    Queueing tet: (%d, %d, %d, %d), dihed %g (degree).\n",
30226                  pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30227                  pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
30228                  acos(cosd) * 180.0 / PI);
30229         }
30230       }
30231       enq = true;
30232     }
30233   }
30234 
30235   return enq;
30236 }
30237 
30239 //                                                                           //
30240 // removeedge()    Remove an edge                                            //
30241 //                                                                           //
30242 // 'remedge' is a tet (abcd) having the edge ab wanted to be removed.  Local //
30243 // reconnecting operations are used to remove edge ab.  The following opera- //
30244 // tion will be tryed.                                                       //
30245 //                                                                           //
30246 // If ab is on the hull, and abc and abd are both hull faces. Then ab can be //
30247 // removed by stripping abcd from the mesh. However, if ab is a segemnt, do  //
30248 // the operation only if 'b->optlevel' > 1 and 'b->nobisect == 0'.           //
30249 //                                                                           //
30250 // If ab is an internal edge, there are n tets contains it.  Then ab can be  //
30251 // removed if there exists another m tets which can replace the n tets with- //
30252 // out changing the boundary of the n tets.                                  //
30253 //                                                                           //
30254 // If 'optflag' is set.  The value 'remedge->key' means cos(theta), where    //
30255 // 'theta' is the maximal dishedral angle at ab. In this case, even if the   //
30256 // n-to-m flip exists, it will not be performed if the maximum dihedral of   //
30257 // the new tets is larger than 'theta'.                                      //
30258 //                                                                           //
30260 
30261 bool tetgenmesh::removeedge(badface* remedge, bool optflag)
30262 {
30263   triface abcd, badc;  // Tet configuration at edge ab.
30264   triface baccasing, abdcasing;
30265   triface abtetlist[11];  // Old configuration at ab, save maximum 10 tets.
30266   triface bftetlist[11];  // Old configuration at bf, save maximum 10 tets.
30267   triface newtetlist[33]; // New configuration after removing ab.
30268   face checksh;
30269   enum fliptype fty;
30270   REAL key;
30271   bool remflag, subflag;
30272   int n, n1, m, i, j;
30273 
30274   // First try to strip abcd from the mesh. This needs to check either ab
30275   //   or cd is on the hull. Try to strip it whichever is true.
30276   abcd = remedge->tt;
30277   adjustedgering(abcd, CCW);
30278   i = 0;
30279   do {
30280     sym(abcd, baccasing);
30281     // Is the tet on the hull?
30282     if (baccasing.tet == dummytet) {
30283       fnext(abcd, badc);
30284       sym(badc, abdcasing);
30285       if (abdcasing.tet == dummytet) {
30286         // Strip the tet from the mesh -> ab is removed as well.
30287         if (removetetbypeeloff(&abcd)) {
30288           if (b->verbose > 1) {
30289             printf("    Stripped tet from the mesh.\n");
30290           }
30291           optcount[0]++;
30292           return true;
30293         }
30294       }
30295     }
30296     // Check if the oppsite edge cd is on the hull.
30297     enext2fnextself(abcd);
30298     enext2self(abcd);
30299     esymself(abcd); // --> cdab
30300     i++;
30301   } while (i < 2);
30302 
30303   // Get the tets configuration at ab. Collect maximum 10 tets.
30304   subflag = false;
30305   abcd = remedge->tt;
30306   adjustedgering(abcd, CW);
30307   n = 0;
30308   abtetlist[n] = abcd;
30309   do {
30310     // Is the list full?
30311     if (n == 10) break;
30312     // Stop if a subface appears.
30313     tspivot(abtetlist[n], checksh);
30314     if (checksh.sh != dummysh) {
30315       // ab is either a segment or a facet edge. The latter case is not
30316       //   handled yet! An edge flip is needed.
30317       subflag = true; break; // return false;
30318     }
30319     // Get the next tet at ab.
30320     fnext(abtetlist[n], abtetlist[n + 1]);
30321     n++;
30322   } while (apex(abtetlist[n]) != apex(abcd));
30323 
30324   remflag = false;
30325   key = remedge->key;
30326 
30327   if (subflag && optflag) {
30328     abcd = remedge->tt;
30329     adjustedgering(abcd, CCW);
30330     // Try to flip face cda or cdb to improve quality.
30331     for (j = 0; j < 2; j++) {
30332       if (j == 0) {
30333         enext2fnext(abcd, abtetlist[0]); // Goto cda.
30334       } else {
30335         enextfnext(abcd, abtetlist[0]); // Goto cdb.
30336       }
30337       fty = categorizeface(abtetlist[0]);
30338       if (fty == T23) {
30339         // A 2-to-3 flip is possible.
30340         sym(abtetlist[0], abtetlist[1]);
30341         assert(abtetlist[1].tet != dummytet);
30342         n = 2;
30343         m = 3;
30344         remflag = removefacebyflip23(&key, abtetlist, newtetlist, NULL);
30345       } else if (fty == T22) {
30346         // A 2-to-2 or 4-to-4 flip is possible.
30347         n = 2;
30348         newtetlist[0] = abtetlist[0];
30349         adjustedgering(newtetlist[0], CW);
30350         fnext(newtetlist[0], newtetlist[1]);
30351         assert(newtetlist[1].tet != dummytet);
30352         // May it is 4-to-4 flip.
30353         if (fnext(newtetlist[1], newtetlist[2])) {
30354           fnext(newtetlist[2], newtetlist[3]);
30355           assert(newtetlist[3].tet != dummytet);
30356           n = 4;
30357         }
30358         m = n;
30359         remflag = removeedgebyflip22(&key, n, newtetlist, NULL);
30360       }
30361       // Has quality been improved?
30362       if (remflag) {
30363         if (b->verbose > 1) {
30364           printf("  Done flip %d-to-%d. Qual: %g -> %g.\n", n, m,
30365                  acos(remedge->key) / PI * 180.0, acos(key) / PI * 180.0);
30366         }
30367         // Delete the old tets. Note, flip22() does not create new tets.
30368         if (m == 3) {
30369           for (i = 0; i < n; i++) {
30370             tetrahedrondealloc(abtetlist[i].tet);
30371           }
30372         }
30373         for (i = 0; i < m; i++) {
30374           checktet4opt(&(newtetlist[i]), true);
30375         }
30376         optcount[1]++;
30377         return true;
30378       }
30379     } // if (j = 0; j < 2; j++)
30380     // Faces are not flipable. Return.
30381     return false;
30382   }
30383 
30384   // 2 <= n <= 10.
30385   if (n == 3) {
30386     // There are three tets at ab. Try to do a flip32 at ab.
30387     remflag = removeedgebyflip32(&key, abtetlist, newtetlist, NULL);
30388   } else if ((n == 4) || (n == 5) || (n == 6)) {
30389     // Four tets case. Try to do edge transformation.
30390     remflag = removeedgebytranNM(&key,n,abtetlist,newtetlist,NULL,NULL,NULL);
30391   } else {
30392     if (b->verbose > 1) {
30393       printf("  !! Unhandled case: n = %d.\n", n);
30394     }
30395   }
30396   if (remflag) {
30397     optcount[n]++;
30398     // Delete the old tets.
30399     for (i = 0; i < n; i++) {
30400       tetrahedrondealloc(abtetlist[i].tet);
30401     }
30402     m = (n - 2) * 2; // The numebr of new tets.
30403     if (b->verbose > 1) {
30404       printf("  Done flip %d-to-%d. ", n, m);
30405       if (optflag) {
30406         printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30407                acos(key) / PI * 180.0);
30408       }
30409       printf("\n");
30410     }
30411   }
30412 
30413   if (!remflag && (key == remedge->key) && (n < 7)) {
30414     // Try to do a combination of flips.
30415     n1 = 0;
30416     remflag = removeedgebycombNM(&key, n, abtetlist, &n1, bftetlist,
30417       newtetlist, NULL);
30418     if (remflag) {
30419       optcount[9]++;
30420       // Delete the old tets.
30421       for (i = 0; i < n; i++) {
30422         tetrahedrondealloc(abtetlist[i].tet);
30423       }
30424       for (i = 0; i < n1; i++) {
30425         if (!isdead(&(bftetlist[i]))) {
30426           tetrahedrondealloc(bftetlist[i].tet);
30427         }
30428       }
30429       m = ((n1 - 2) * 2 - 1) + (n - 3) * 2; // The number of new tets.
30430       if (b->verbose > 1) {
30431         printf("  Done flip %d-to-%d (n-1=%d, n1=%d). ", n+n1-2, m, n-1,n1);
30432         if (optflag) {
30433           printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30434                acos(key) / PI * 180.0);
30435         }
30436         printf("\n");
30437       }
30438     }
30439   }
30440 
30441   if (remflag) {
30442     // edge is removed. Test new tets for further optimization.
30443     for (i = 0; i < m; i++) {
30444       if (optflag) {
30445         checktet4opt(&(newtetlist[i]), true);
30446       } else {
30447         checktet4ill(&(newtetlist[i]), true);
30448       }
30449     }
30450   }
30451 
30452   return remflag;
30453 }
30454 
30456 //                                                                           //
30457 // smoothsliver()    Remove a sliver by smoothing a vertex of it.            //
30458 //                                                                           //
30459 // The 'slivtet' represents a sliver abcd, and ab is the current edge which  //
30460 // has a large dihedral angle (close to 180 degree).                         //
30461 //                                                                           //
30463 
30464 bool tetgenmesh::smoothsliver(badface* remedge, list *starlist)
30465 {
30466   triface checktet;
30467   point smthpt;
30468   bool smthed;
30469   int idx, i, j;
30470 
30471   // Find a Steiner volume point and smooth it.
30472   smthed = false;
30473   for (i = 0; i < 4 && !smthed; i++) {
30474     smthpt = (point) remedge->tt.tet[4 + i];
30475     // Is it a volume point?
30476     if (pointtype(smthpt) == FREEVOLVERTEX) {
30477       // Is it a Steiner point?
30478       idx = pointmark(smthpt) - in->firstnumber;
30479       if (!(idx < in->numberofpoints)) {
30480         // Smooth a Steiner volume point.
30481         starlist->append(&(remedge->tt.tet));
30482         formstarpolyhedron(smthpt, starlist, NULL, false);
30483         smthed = smoothpoint(smthpt,NULL,NULL,starlist,false,&remedge->key);
30484         // If it is smoothed. Queue new bad tets.
30485         if (smthed) {
30486           for (j = 0; j < starlist->len(); j++) {
30487             checktet = * (triface *)(* starlist)[j];
30488             checktet4opt(&checktet, true);
30489           }
30490         }
30491         starlist->clear();
30492       }
30493     }
30494   }
30495 
30496   /* Omit to smooth segment points. This may cause infinite loop.
30497   if (smthed) {
30498     return true;
30499   }
30500   face abseg, nextseg, prevseg;
30501   point pt[2];
30502   // Check if ab is a segment.
30503   tsspivot(slivtet, &abseg);
30504   if (abseg.sh == dummysh) {
30505     // ab is not a segment. Check if a or b is a Steiner segment point.
30506     for (i = 0; i < 2 && !smthed; i++) {
30507       smthpt = (i == 0 ? org(*slivtet) : dest(*slivtet));
30508       if (pointtype(smthpt) == FREESEGVERTEX) {
30509         // Is it a Steiner point?
30510         idx = pointmark(smthpt) - in->firstnumber;
30511         if (!(idx < in->numberofpoints)) {
30512           // Smooth a Steiner segment point. Get the segment.
30513           sdecode(point2sh(smthpt), nextseg);
30514           locateseg(smthpt, &nextseg);
30515           assert(sorg(nextseg) == smthpt);
30516           pt[0] = sdest(nextseg);
30517           senext2(nextseg, prevseg);
30518           spivotself(prevseg);
30519           prevseg.shver = 0;
30520           if (sorg(prevseg) == smthpt) sesymself(prevseg);
30521           assert(sdest(prevseg) == smthpt);
30522           pt[1] = sorg(prevseg);
30523           starlist->append(slivtet);
30524           formstarpolyhedron(smthpt, starlist, NULL, true);
30525           smthed = smoothpoint(smthpt, pt[0], pt[1], starlist, false);
30526           // If it is smoothed. Check if the tet is still a sliver.
30527           if (smthed) checktet4opt(slivtet, true);
30528           starlist->clear();
30529         }
30530       }
30531     }
30532   }
30533   */
30534 
30535   return smthed;
30536 }
30537 
30539 //                                                                           //
30540 // splitsliver()    Remove a sliver by inserting a point.                    //
30541 //                                                                           //
30542 // The 'remedge->tt' represents a sliver abcd, ab is the current edge which  //
30543 // has a large dihedral angle (close to 180 degree).                         //
30544 //                                                                           //
30546 
30547 bool tetgenmesh::splitsliver(badface *remedge, list *tetlist, list *ceillist)
30548 {
30549   triface starttet;
30550   face checkseg;
30551   point newpt, pt[4];
30552   bool remflag;
30553   int i;
30554 
30555   starttet = remedge->tt;
30556 
30557   // Check if cd is a segment.
30558   adjustedgering(starttet, CCW);
30559   enextfnextself(starttet);
30560   enextself(starttet);
30561   tsspivot(&starttet, &checkseg);
30562   if (b->nobisect == 0) {
30563     if (checkseg.sh != dummysh) {
30564       // cd is a segment. The seg will be split. BUT do not flip! Due to the
30565       //   exact predicates, lot of slivers ay be rsulted and hard to remove.
30566       checkseg.shver = 0;
30567       pt[0] = sorg(checkseg);
30568       pt[1] = sdest(checkseg);
30569       makepoint(&newpt);
30570       getsplitpoint(pt[0], pt[1], NULL, newpt);
30571       setpointtype(newpt, FREESEGVERTEX);
30572       setpoint2sh(newpt, sencode(checkseg));
30573       // Insert p, this should always success.
30574       sstpivot(&checkseg, &starttet);
30575       splittetedge(newpt, &starttet, NULL);
30576       // Collect the new tets connecting at p.
30577       sstpivot(&checkseg, &starttet);
30578       ceillist->append(&starttet);
30579       formstarpolyhedron(newpt, ceillist, NULL, true);
30580       setnewpointsize(newpt, pt[0], NULL);
30581       if (steinerleft > 0) steinerleft--;
30582       // Smooth p.
30583       smoothpoint(newpt, pt[0], pt[1], ceillist, false, NULL);
30584       // Queue new slivers.
30585       for (i = 0; i < ceillist->len(); i++) {
30586         starttet = * (triface *)(* ceillist)[i];
30587         checktet4opt(&starttet, true);
30588       }
30589       ceillist->clear();
30590       return true;
30591     }
30592   }
30593 
30594   // Get the four corners.
30595   for (i = 0; i < 4; i++) {
30596     pt[i] = (point) starttet.tet[4 + i];
30597   }
30598   // Create the new point p (at the circumcenter of t).
30599   makepoint(&newpt);
30600   for (i = 0; i < 3; i++) {
30601     newpt[i] = 0.25 * (pt[0][i] + pt[1][i] + pt[2][i] + pt[3][i]);
30602   }
30603   setpointtype(newpt, FREEVOLVERTEX);
30604 
30605   // Form the Bowyer-Watson cavity of p.
30606   remflag = false;
30607   infect(starttet);
30608   tetlist->append(&starttet);
30609   formbowatcavityquad(newpt, tetlist, ceillist);
30610   if (trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, -1.0)) {
30611     // Smooth p.
30612     if (smoothpoint( newpt, NULL, NULL, ceillist, false, &remedge->key)) {
30613       // Insert p.
30614       bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, NULL,
30615                       NULL, false, false, false);
30616       setnewpointsize(newpt, pt[0], NULL);
30617       if (steinerleft > 0) steinerleft--;
30618       // Queue new slivers.
30619       for (i = 0; i < ceillist->len(); i++) {
30620         starttet = * (triface *)(* ceillist)[i];
30621         checktet4opt(&starttet, true);
30622       }
30623       remflag = true;
30624     } // if (smoothpoint)
30625   } // if (trimbowatcavity)
30626 
30627   if (!remflag) {
30628     // p is rejected for BC(p) is not valid.
30629     pointdealloc(newpt);
30630     // Uninfect tets of BC(p).
30631     for (i = 0; i < tetlist->len(); i++) {
30632       starttet = * (triface *)(* tetlist)[i];
30633       uninfect(starttet);
30634     }
30635   }
30636   tetlist->clear();
30637   ceillist->clear();
30638 
30639   return remflag;
30640 }
30641 
30643 //                                                                           //
30644 // tallslivers()    Queue all the slivers in the mesh.                       //
30645 //                                                                           //
30647 
30648 void tetgenmesh::tallslivers(bool optflag)
30649 {
30650   triface tetloop;
30651 
30652   tetrahedrons->traversalinit();
30653   tetloop.tet = tetrahedrontraverse();
30654   while (tetloop.tet != (tetrahedron *) NULL) {
30655     if (optflag) {
30656       checktet4opt(&tetloop, true);
30657     } else {
30658       checktet4ill(&tetloop, true);
30659     }
30660     tetloop.tet = tetrahedrontraverse();
30661   }
30662 }
30663 
30665 //                                                                           //
30666 // optimizemesh()    Improve mesh quality by mesh optimizations.             //
30667 //                                                                           //
30668 // Available mesh optimizing operations are: (1) multiple edge flips (3-to-2,//
30669 // 4-to-4, 5-to-6, etc), (2) free vertex deletion, (3) new vertex insertion. //
30670 // (1) is mandatory, while (2) and (3) are optionally.                       //
30671 //                                                                           //
30672 // The variable 'b->optlevel' (set after '-s') determines the use of these   //
30673 // operations. If it is: 0, do no optimization; 1, only do (1) operation; 2, //
30674 // do (1) and (2) operations; 3, do all operations. Deault, b->optlvel = 2.  //
30675 //                                                                           //
30677 
30678 void tetgenmesh::optimizemesh(bool optflag)
30679 {
30680   list *splittetlist, *tetlist, *ceillist;
30681   badface *remtet, *lastentry;
30682   //REAL maxdihed, objdihed, curdihed; // maxdihead commented out to get gcc 4.6 working
30683   REAL objdihed, curdihed;
30684   long oldnum;
30685   int iter, i;
30686 
30687   objdihed = 0.0;
30688 
30689   if (!b->quiet) {
30690     if (optflag) {
30691       printf("Optimizing mesh.\n");
30692     } else {
30693       printf("Repairing mesh.\n");
30694     }
30695   }
30696 
30697 #ifdef SELF_CHECK
30698   if (optflag && (b->verbose)) {
30699     printf("  level = %d.\n", b->optlevel);
30700   }
30701 #endif
30702 
30703   // Initialize the pool of bad tets.
30704   badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30705   if (optflag) {
30706     cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30707     cosmindihed = cos(b->mindihedral * PI / 180.0);
30708     // The radian of the maximum dihedral angle.
30709     //maxdihed = b->maxdihedral / 180.0 * PI; // maxdihead commented out to get gcc 4.6 working
30710     // A sliver has an angle large than 'objdihed' will be split.
30711     objdihed = b->maxdihedral + 5.0;
30712     if (objdihed < 170.0) objdihed = 170.0;
30713     objdihed = objdihed / 180.0 * PI;
30714   }
30715   // Looking for non-optimal tets.
30716   tallslivers(optflag);
30717 
30718   optcount[0] = 0l;  // tet strip count.
30719   optcount[1] = 0l;  // face (2-3) and edge (2-2) flip count.
30720   optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l; // edge flips.
30721   optcount[9] = 0l;  // combined flip count.
30722 
30723   // Perform edge flip to improve quality.
30724   lastentry = (badface *) NULL;
30725   // Loop until pool 'badtetrahedrons' is empty.
30726   while (badtetrahedrons->items > 0) {
30727     badtetrahedrons->traversalinit();
30728     remtet = badfacetraverse(badtetrahedrons);
30729     while (remtet != (badface *) NULL) {
30730       // Make sure that the tet is still the same one when it was tested.
30731       //   Subsequent transformations may have made it a different tet.
30732       if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30733           dest(remtet->tt) == remtet->fdest &&
30734           apex(remtet->tt) == remtet->fapex &&
30735           oppo(remtet->tt) == remtet->foppo) {
30736         if (b->verbose > 1) {
30737           printf("    Repair tet (%d, %d, %d, %d) %g (degree).\n",
30738                  pointmark(remtet->forg), pointmark(remtet->fdest),
30739                  pointmark(remtet->fapex), pointmark(remtet->foppo),
30740                  acos(remtet->key) / PI * 180.0);
30741         }
30742         if (!removeedge(remtet, optflag)) {
30743           // An unremoveable tet. Check if it forms a loop.
30744           if (lastentry != (badface *) NULL) {
30745             if (remtet == lastentry) break;
30746           } else {
30747             // Remember this tet as a breakpoint.
30748             lastentry = remtet;
30749           }
30750         } else {
30751           // Clear the breakpoint.
30752           lastentry = (badface *) NULL;
30753           // Remove the entry from the queue.
30754           badfacedealloc(badtetrahedrons, remtet);
30755         }
30756       } else {
30757         // Remove the entry from the queue.
30758         badfacedealloc(badtetrahedrons, remtet);
30759       }
30760       remtet = badfacetraverse(badtetrahedrons);
30761     }
30762     // Stop if the above loop was out by force.
30763     if (remtet != (badface *) NULL) break;
30764   }
30765 
30766   if (b->verbose) {
30767     if (optcount[0] > 0l) {
30768       printf("  %ld tets are peeled off.\n", optcount[0]);
30769     }
30770     if (optcount[1] > 0l) {
30771       printf("  %ld faces are flipped.\n", optcount[1]);
30772     }
30773     if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30774         optcount[9] > 0l) {
30775       printf("  %ld edges are flipped.\n", optcount[3] + optcount[4] +
30776              optcount[5] + optcount[6] + optcount[9]);
30777     }
30778     // if (badtetrahedrons->items > 0l) {
30779     //   printf("  %ld edges remain.\n", badtetrahedrons->items);
30780     // }
30781   }
30782 
30783   if ((badtetrahedrons->items > 0l) && optflag  && (b->optlevel > 2)) {
30784     splittetlist = new list(sizeof(badface), NULL, 256);
30785     tetlist = new list(sizeof(triface), NULL, 256);
30786     ceillist = new list(sizeof(triface), NULL, 256);
30787     oldnum = points->items;
30788     smoothsegverts = smoothvolverts = 0;
30789     optcount[1] = 0l;
30790     optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l; // edge flips.
30791     optcount[9] = 0l;  // combined flip count.
30792     iter = 0;
30793 
30794     do {
30795       // Form a list of slivers to be split and clean the pool.
30796       badtetrahedrons->traversalinit();
30797       remtet = badfacetraverse(badtetrahedrons);
30798       while (remtet != (badface *) NULL) {
30799         splittetlist->append(remtet);
30800         // Remove the entry from the queue.
30801         badfacedealloc(badtetrahedrons, remtet);
30802         remtet = badfacetraverse(badtetrahedrons);
30803       }
30804       for (i = 0; i < splittetlist->len(); i++) {
30805         remtet = (badface *)(* splittetlist)[i];
30806         // Make sure that the tet is still the same one when it was tested.
30807         //   Subsequent transformations may have made it a different tet.
30808         if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30809             dest(remtet->tt) == remtet->fdest &&
30810             apex(remtet->tt) == remtet->fapex &&
30811             oppo(remtet->tt) == remtet->foppo) {
30812           // The sliver may get smoothed due to a neighboring tet.
30813           curdihed = facedihedral(remtet->forg, remtet->fdest, remtet->fapex,
30814                                   remtet->foppo);
30815           // The dihedral angle of a tet must less than PI, correct it.
30816           if (curdihed > PI) curdihed = 2 * PI - curdihed;
30817           // Is it a large angle?
30818           if (curdihed > objdihed) {
30819             remtet->key = cos(curdihed);
30820             if (b->verbose > 1) {
30821               printf("    Get sliver (%d, %d, %d, %d) %g (degree).\n",
30822                      pointmark(remtet->forg), pointmark(remtet->fdest),
30823                      pointmark(remtet->fapex), pointmark(remtet->foppo),
30824                      acos(remtet->key) / PI * 180.0);
30825             }
30826             if (!removeedge(remtet, optflag)) {
30827               if (!smoothsliver(remtet, tetlist)) {
30828                 splitsliver(remtet, tetlist, ceillist);
30829               }
30830             }
30831           }
30832         }
30833       }
30834       iter++;
30835     } while ((badtetrahedrons->items > 0l) && (iter < b->optpasses));
30836 
30837     if (b->verbose) {
30838       printf("  %d passes.\n", iter);
30839       if ((points->items - oldnum) > 0l) {
30840         printf("  %ld points are inserted (%d on segment).\n",
30841                points->items - oldnum, smoothsegverts);
30842       }
30843       if (optcount[1] > 0l) {
30844         printf("  %ld faces are flipped.\n", optcount[1]);
30845       }
30846       if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30847           optcount[9] > 0l) {
30848         printf("  %ld edges are flipped.\n", optcount[3] + optcount[4] +
30849                optcount[5] + optcount[6] + optcount[9]);
30850       }
30851       // if (badtetrahedrons->items > 0l) {
30852       //   printf("  %ld edges remain.\n", badtetrahedrons->items);
30853       // }
30854     }
30855     delete tetlist;
30856     delete ceillist;
30857     delete splittetlist;
30858   }
30859 
30860   delete badtetrahedrons;
30861   badtetrahedrons = (memorypool *) NULL;
30862 }
30863 
30864 //
30865 // End of mesh optimization routines
30866 //
30867 
30868 //
30869 // Begin of I/O rouitnes
30870 //
30871 
30873 //                                                                           //
30874 // transfernodes()    Transfer nodes from 'io->pointlist' to 'this->points'. //
30875 //                                                                           //
30876 // Initializing 'this->points'.  Transferring all points from 'in->pointlist'//
30877 // into it. All points are indexed (start from in->firstnumber).  Each point //
30878 // is initialized be UNUSEDVERTEX.  The bounding box (xmin, xmax, ymin, ymax,//
30879 // zmin, zmax) and the diameter (longest) of the point set are calculated.   //
30880 //                                                                           //
30882 
30883 void tetgenmesh::transfernodes()
30884 {
30885   point pointloop;
30886   REAL x, y, z;
30887   int coordindex;
30888   int attribindex;
30889   int mtrindex;
30890   int i, j;
30891 
30892   // Read the points.
30893   coordindex = 0;
30894   attribindex = 0;
30895   mtrindex = 0;
30896   for (i = 0; i < in->numberofpoints; i++) {
30897     makepoint(&pointloop);
30898     // Read the point coordinates.
30899     x = pointloop[0] = in->pointlist[coordindex++];
30900     y = pointloop[1] = in->pointlist[coordindex++];
30901     z = pointloop[2] = in->pointlist[coordindex++];
30902     // Read the point attributes.
30903     for (j = 0; j < in->numberofpointattributes; j++) {
30904       pointloop[3 + j] = in->pointattributelist[attribindex++];
30905     }
30906     // Read the point metric tensor.
30907     for (j = 0; j < in->numberofpointmtrs; j++) {
30908       pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
30909     }
30910     // Determine the smallest and largests x, y and z coordinates.
30911     if (i == 0) {
30912       xmin = xmax = x;
30913       ymin = ymax = y;
30914       zmin = zmax = z;
30915     } else {
30916       xmin = (x < xmin) ? x : xmin;
30917       xmax = (x > xmax) ? x : xmax;
30918       ymin = (y < ymin) ? y : ymin;
30919       ymax = (y > ymax) ? y : ymax;
30920       zmin = (z < zmin) ? z : zmin;
30921       zmax = (z > zmax) ? z : zmax;
30922     }
30923   }
30924   // 'longest' is the largest possible edge length formed by input vertices.
30925   x = xmax - xmin;
30926   y = ymax - ymin;
30927   z = zmax - zmin;
30928   longest = sqrt(x * x + y * y + z * z);
30929   if (longest == 0.0) {
30930     printf("Error:  The point set is trivial.\n");
30931     terminatetetgen(1);
30932   }
30933   // Two identical points are distinguished by 'lengthlimit'.
30934   lengthlimit = longest * b->epsilon * 1e+2;
30935 }
30936 
30938 //                                                                           //
30939 // jettisonnodes()    Jettison unused or duplicated vertices.                //
30940 //                                                                           //
30941 // Unused points are those input points which are outside the mesh domain or //
30942 // have no connection (isolated) to the mesh.  Duplicated points exist for   //
30943 // example if the input PLC is read from a .stl mesh file (marked during the //
30944 // Delaunay tetrahedralization step. This routine remove these points from   //
30945 // points list. All existing points are reindexed.                           //
30946 //                                                                           //
30948 
30949 void tetgenmesh::jettisonnodes()
30950 {
30951   point pointloop;
30952   bool jetflag;
30953   int oldidx, newidx;
30954   int remcount;
30955 
30956   if (!b->quiet) {
30957     printf("Jettisoning redundants points.\n");
30958   }
30959 
30960   points->traversalinit();
30961   pointloop = pointtraverse();
30962   oldidx = newidx = 0; // in->firstnumber;
30963   remcount = 0;
30964   while (pointloop != (point) NULL) {
30965     jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) ||
30966       (pointtype(pointloop) == UNUSEDVERTEX);
30967     if (jetflag) {
30968       // It is a duplicated point, delete it.
30969       pointdealloc(pointloop);
30970       remcount++;
30971     } else {
30972       // Re-index it.
30973       setpointmark(pointloop, newidx + in->firstnumber);
30974       if (in->pointmarkerlist != (int *) NULL) {
30975         if (oldidx < in->numberofpoints) {
30976           // Re-index the point marker as well.
30977           in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
30978         }
30979       }
30980       newidx++;
30981     }
30982     oldidx++;
30983     if (oldidx == in->numberofpoints) {
30984       // Update the numbe of input points (Because some were removed).
30985       in->numberofpoints -= remcount;
30986       // Remember this number for output original input nodes.
30987       jettisoninverts = remcount;
30988     }
30989     pointloop = pointtraverse();
30990   }
30991   if (b->verbose) {
30992     printf("  %d duplicated vertices have been removed.\n", dupverts);
30993     printf("  %d unused vertices have been removed.\n", unuverts);
30994   }
30995   dupverts = 0;
30996   unuverts = 0;
30997 
30998   // The following line ensures that dead items in the pool of nodes cannot
30999   //   be allocated for the new created nodes. This ensures that the input
31000   //   nodes will occur earlier in the output files, and have lower indices.
31001   points->deaditemstack = (void *) NULL;
31002 }
31003 
31005 //                                                                           //
31006 // highorder()   Create extra nodes for quadratic subparametric elements.    //
31007 //                                                                           //
31008 // 'highordertable' is an array (size = numberoftetrahedra * 6) for storing  //
31009 // high-order nodes of each tetrahedron.  This routine is used only when -o2 //
31010 // switch is used.                                                           //
31011 //                                                                           //
31013 
31014 void tetgenmesh::highorder()
31015 {
31016   triface tetloop, worktet;
31017   triface spintet, adjtet;
31018   point torg, tdest, tapex;
31019   point *extralist, *adjextralist;
31020   point newpoint;
31021   int hitbdry, ptmark;
31022   int i, j;
31023 
31024   if (!b->quiet) {
31025     printf("Adding vertices for second-order tetrahedra.\n");
31026   }
31027 
31028   // Initialize the 'highordertable'.
31029   highordertable = new point[tetrahedrons->items * 6];
31030   if (highordertable == (point *) NULL) {
31031     printf("Error:  Out of memory.\n");
31032     terminatetetgen(1);
31033   }
31034 
31035   // The following line ensures that dead items in the pool of nodes cannot
31036   //   be allocated for the extra nodes associated with high order elements.
31037   //   This ensures that the primary nodes (at the corners of elements) will
31038   //   occur earlier in the output files, and have lower indices, than the
31039   //   extra nodes.
31040   points->deaditemstack = (void *) NULL;
31041 
31042   // Assign an entry for each tetrahedron to find its extra nodes. At the
31043   //   mean while, initialize all extra nodes be NULL.
31044   i = 0;
31045   tetrahedrons->traversalinit();
31046   tetloop.tet = tetrahedrontraverse();
31047   while (tetloop.tet != (tetrahedron *) NULL) {
31048     tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
31049     for (j = 0; j < 6; j++) {
31050       highordertable[i + j] = (point) NULL;
31051     }
31052     i += 6;
31053     tetloop.tet = tetrahedrontraverse();
31054   }
31055 
31056   // To create a unique node on each edge. Loop over all tetrahedra, and
31057   //   look at the six edges of each tetrahedron.  If the extra node in
31058   //   the tetrahedron corresponding to this edge is NULL, create a node
31059   //   for this edge, at the same time, set the new node into the extra
31060   //   node lists of all other tetrahedra sharing this edge.
31061   tetrahedrons->traversalinit();
31062   tetloop.tet = tetrahedrontraverse();
31063   while (tetloop.tet != (tetrahedron *) NULL) {
31064     // Get the list of extra nodes.
31065     extralist = (point *) tetloop.tet[highorderindex];
31066     worktet.tet = tetloop.tet;
31067     for (i = 0; i < 6; i++) {
31068       if (extralist[i] == (point) NULL) {
31069         // Operate on this edge.
31070         worktet.loc = edge2locver[i][0];
31071         worktet.ver = edge2locver[i][1];
31072         // Create a new node on this edge.
31073         torg = org(worktet);
31074         tdest = dest(worktet);
31075         // Create a new node in the middle of the edge.
31076         newpoint = (point) points->alloc();
31077         // Interpolate its attributes.
31078         for (j = 0; j < 3 + in->numberofpointattributes; j++) {
31079           newpoint[j] = 0.5 * (torg[j] + tdest[j]);
31080         }
31081         ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
31082         setpointmark(newpoint, ptmark);
31083         // Add this node to its extra node list.
31084         extralist[i] = newpoint;
31085         // Set 'newpoint' into extra node lists of other tetrahedra
31086         //   sharing this edge.
31087         tapex = apex(worktet);
31088         spintet = worktet;
31089         hitbdry = 0;
31090         while (hitbdry < 2) {
31091           if (fnextself(spintet)) {
31092             // Get the extra node list of 'spintet'.
31093             adjextralist = (point *) spintet.tet[highorderindex];
31094             // Find the index of its extra node list.
31095             j = locver2edge[spintet.loc][spintet.ver];
31096             // Only set 'newpoint' into 'adjextralist' if it is a NULL.
31097             //   Because two faces can belong to the same tetrahedron.
31098             if (adjextralist[j] == (point) NULL) {
31099               adjextralist[j] = newpoint;
31100             }
31101             if (apex(spintet) == tapex) {
31102               break;
31103             }
31104           } else {
31105             hitbdry++;
31106             if (hitbdry < 2) {
31107               esym(worktet, spintet);
31108         }
31109           }
31110         }
31111       }
31112     }
31113     tetloop.tet = tetrahedrontraverse();
31114   }
31115 }
31116 
31118 //                                                                           //
31119 // outnodes()    Output the points to a .node file or a tetgenio structure.  //
31120 //                                                                           //
31121 // Note: each point has already been numbered on input (the first index is   //
31122 // 'in->firstnumber').                                                       //
31123 //                                                                           //
31125 
31126 void tetgenmesh::outnodes(tetgenio* out)
31127 {
31128   FILE *outfile;
31129   char outnodefilename[FILENAMESIZE];
31130   shellface subptr;
31131   triface adjtet;
31132   face subloop;
31133   point pointloop;
31134   point *extralist, ep[3];
31135   int nextras, bmark, shmark, marker;
31136   int coordindex, attribindex;
31137   int pointnumber, firstindex;
31138   int index, i;
31139 
31140   if (out == (tetgenio *) NULL) {
31141     strcpy(outnodefilename, b->outfilename);
31142     strcat(outnodefilename, ".node");
31143   }
31144 
31145   if (!b->quiet) {
31146     if (out == (tetgenio *) NULL) {
31147       printf("Writing %s.\n", outnodefilename);
31148     } else {
31149       printf("Writing nodes.\n");
31150     }
31151   }
31152 
31153   nextras = in->numberofpointattributes;
31154   bmark = !b->nobound && in->pointmarkerlist;
31155 
31156   // Avoid compile warnings.
31157   outfile = (FILE *) NULL;
31158   marker = coordindex = 0;
31159 
31160   if (out == (tetgenio *) NULL) {
31161     outfile = fopen(outnodefilename, "w");
31162     if (outfile == (FILE *) NULL) {
31163       printf("File I/O Error:  Cannot create file %s.\n", outnodefilename);
31164       terminatetetgen(1);
31165     }
31166     // Number of points, number of dimensions, number of point attributes,
31167     //   and number of boundary markers (zero or one).
31168     fprintf(outfile, "%ld  %d  %d  %d\n", points->items, 3, nextras, bmark);
31169   } else {
31170     // Allocate space for 'pointlist';
31171     out->pointlist = new REAL[points->items * 3];
31172     if (out->pointlist == (REAL *) NULL) {
31173       printf("Error:  Out of memory.\n");
31174       terminatetetgen(1);
31175     }
31176     // Allocate space for 'pointattributelist' if necessary;
31177     if (nextras > 0) {
31178       out->pointattributelist = new REAL[points->items * nextras];
31179       if (out->pointattributelist == (REAL *) NULL) {
31180         printf("Error:  Out of memory.\n");
31181         terminatetetgen(1);
31182       }
31183     }
31184     // Allocate space for 'pointmarkerlist' if necessary;
31185     if (bmark) {
31186       out->pointmarkerlist = new int[points->items];
31187       if (out->pointmarkerlist == (int *) NULL) {
31188         printf("Error:  Out of memory.\n");
31189         terminatetetgen(1);
31190       }
31191     }
31192     out->numberofpoints = points->items;
31193     out->numberofpointattributes = nextras;
31194     coordindex = 0;
31195     attribindex = 0;
31196   }
31197 
31198   if (bmark && (b->plc || b->refine)) {
31199     // Initialize the point2tet field of each point.
31200     points->traversalinit();
31201     pointloop = pointtraverse();
31202     while (pointloop != (point) NULL) {
31203       setpoint2tet(pointloop, (tetrahedron) NULL);
31204       pointloop = pointtraverse();
31205     }
31206     // Make a map point-to-subface. Hence a boundary point will get the
31207     //   facet marker from that facet where it lies on.
31208     subfaces->traversalinit();
31209     subloop.sh = shellfacetraverse(subfaces);
31210     while (subloop.sh != (shellface *) NULL) {
31211       subloop.shver = 0;
31212       // Check all three points of the subface.
31213       for (i = 0; i < 3; i++) {
31214         pointloop = (point) subloop.sh[3 + i];
31215         setpoint2tet(pointloop, (tetrahedron) sencode(subloop));
31216       }
31217       if (b->order == 2) {
31218         // '-o2' switch. Set markers for quadratic nodes of this subface.
31219         stpivot(subloop, adjtet);
31220         if (adjtet.tet == dummytet) {
31221           sesymself(subloop);
31222           stpivot(subloop, adjtet);
31223         }
31224         assert(adjtet.tet != dummytet);
31225         extralist = (point *) adjtet.tet[highorderindex];
31226         switch (adjtet.loc) {
31227         case 0:
31228           ep[0] = extralist[0];
31229           ep[1] = extralist[1];
31230           ep[2] = extralist[2];
31231           break;
31232         case 1:
31233           ep[0] = extralist[0];
31234           ep[1] = extralist[4];
31235           ep[2] = extralist[3];
31236           break;
31237         case 2:
31238           ep[0] = extralist[1];
31239           ep[1] = extralist[5];
31240           ep[2] = extralist[4];
31241           break;
31242         case 3:
31243           ep[0] = extralist[2];
31244           ep[1] = extralist[3];
31245           ep[2] = extralist[5];
31246           break;
31247         default: break;
31248         }
31249         for (i = 0; i < 3; i++) {
31250           setpoint2tet(ep[i], (tetrahedron) sencode(subloop));
31251         }
31252       }
31253       subloop.sh = shellfacetraverse(subfaces);
31254     }
31255   }
31256 
31257   // Determine the first index (0 or 1).
31258   firstindex = b->zeroindex ? 0 : in->firstnumber;
31259 
31260   points->traversalinit();
31261   pointloop = pointtraverse();
31262   pointnumber = firstindex; // in->firstnumber;
31263   index = 0;
31264   while (pointloop != (point) NULL) {
31265     if (bmark) {
31266       // Default the vertex has a zero marker.
31267       marker = 0;
31268       // Is it an input vertex?
31269       if (index < in->numberofpoints) {
31270         // Input point's marker is directly copied to output.
31271         marker = in->pointmarkerlist[index];
31272       }
31273       // Is it a boundary vertex has marker zero?
31274       if ((marker == 0) && (b->plc || b->refine)) {
31275         subptr = (shellface) point2tet(pointloop);
31276         if (subptr != (shellface) NULL) {
31277           // Default a boundary vertex has marker 1.
31278           marker = 1;
31279           if (in->facetmarkerlist != (int *) NULL) {
31280             // The vertex gets the marker from the facet it lies on.
31281             sdecode(subptr, subloop);
31282             shmark = shellmark(subloop);
31283             marker = in->facetmarkerlist[shmark - 1];
31284           }
31285         }
31286       }
31287     }
31288     if (out == (tetgenio *) NULL) {
31289       // Point number, x, y and z coordinates.
31290       fprintf(outfile, "%4d    %.17g  %.17g  %.17g", pointnumber,
31291               pointloop[0], pointloop[1], pointloop[2]);
31292       for (i = 0; i < nextras; i++) {
31293         // Write an attribute.
31294         fprintf(outfile, "  %.17g", pointloop[3 + i]);
31295       }
31296       if (bmark) {
31297         // Write the boundary marker.
31298         fprintf(outfile, "    %d", marker);
31299       }
31300       fprintf(outfile, "\n");
31301     } else {
31302       // X, y, and z coordinates.
31303       out->pointlist[coordindex++] = pointloop[0];
31304       out->pointlist[coordindex++] = pointloop[1];
31305       out->pointlist[coordindex++] = pointloop[2];
31306       // Point attributes.
31307       for (i = 0; i < nextras; i++) {
31308         // Output an attribute.
31309         out->pointattributelist[attribindex++] = pointloop[3 + i];
31310       }
31311       if (bmark) {
31312         // Output the boundary marker.
31313         out->pointmarkerlist[index] = marker;
31314       }
31315     }
31316     pointloop = pointtraverse();
31317     pointnumber++;
31318     index++;
31319   }
31320 
31321   if (out == (tetgenio *) NULL) {
31322     fprintf(outfile, "# Generated by %s\n", b->commandline);
31323     fclose(outfile);
31324   }
31325 }
31326 
31328 //                                                                           //
31329 // outmetrics()    Output the metric to a file (*.mtr) or a tetgenio obj.    //
31330 //                                                                           //
31332 
31333 void tetgenmesh::outmetrics(tetgenio* out)
31334 {
31335   FILE *outfile;
31336   char outmtrfilename[FILENAMESIZE];
31337   list *tetlist, *ptlist;
31338   triface tetloop;
31339   point ptloop, neipt;
31340   REAL lave, len; // lmin, lmax,
31341   int mtrindex;
31342   int i;
31343 
31344   lave = 0.0;
31345 
31346   if (out == (tetgenio *) NULL) {
31347     strcpy(outmtrfilename, b->outfilename);
31348     strcat(outmtrfilename, ".mtr");
31349   }
31350 
31351   if (!b->quiet) {
31352     if (out == (tetgenio *) NULL) {
31353       printf("Writing %s.\n", outmtrfilename);
31354     } else {
31355       printf("Writing metrics.\n");
31356     }
31357   }
31358 
31359   // Avoid compile warnings.
31360   outfile = (FILE *) NULL;
31361   mtrindex = 0;
31362 
31363   if (out == (tetgenio *) NULL) {
31364     outfile = fopen(outmtrfilename, "w");
31365     if (outfile == (FILE *) NULL) {
31366       printf("File I/O Error:  Cannot create file %s.\n", outmtrfilename);
31367       terminatetetgen(1);
31368     }
31369     // Number of points, number of point metrices,
31370     // fprintf(outfile, "%ld  %d\n", points->items, sizeoftensor + 3);
31371     fprintf(outfile, "%ld  %d\n", points->items, 1);
31372   } else {
31373     // Allocate space for 'pointmtrlist' if necessary;
31374     // out->pointmtrlist = new REAL[points->items * (sizeoftensor + 3)];
31375     out->pointmtrlist = new REAL[points->items];
31376     if (out->pointmtrlist == (REAL *) NULL) {
31377       printf("Error:  Out of memory.\n");
31378       terminatetetgen(1);
31379     }
31380     out->numberofpointmtrs = 1; // (sizeoftensor + 3);
31381     mtrindex = 0;
31382   }
31383 
31384   // Initialize the point2tet field of each point.
31385   points->traversalinit();
31386   ptloop = pointtraverse();
31387   while (ptloop != (point) NULL) {
31388     setpoint2tet(ptloop, (tetrahedron) NULL);
31389     ptloop = pointtraverse();
31390   }
31391   // Create the point-to-tet map.
31392   tetrahedrons->traversalinit();
31393   tetloop.tet = tetrahedrontraverse();
31394   while (tetloop.tet != (tetrahedron *) NULL) {
31395     for (i = 0; i < 4; i++) {
31396       ptloop = (point) tetloop.tet[4 + i];
31397       setpoint2tet(ptloop, encode(tetloop));
31398     }
31399     tetloop.tet = tetrahedrontraverse();
31400   }
31401 
31402   tetlist = new list(sizeof(triface), NULL, 256);
31403   ptlist = new list(sizeof(point *), NULL, 256);
31404 
31405   points->traversalinit();
31406   ptloop = pointtraverse();
31407   while (ptloop != (point) NULL) {
31408     decode(point2tet(ptloop), tetloop);
31409     if (!isdead(&tetloop)) {
31410       // Form the star of p.
31411       tetlist->append(&tetloop);
31412       formstarpolyhedron(ptloop, tetlist, ptlist, true);
31413       // lmin = longest;
31414       // lmax = 0.0;
31415       lave = 0.0;
31416       for (i = 0; i < ptlist->len(); i++) {
31417         neipt = * (point *)(* ptlist)[i];
31418         len = distance(ptloop, neipt);
31419         // lmin = lmin < len ? lmin : len;
31420         // lmax = lmax > len ? lmax : len;
31421         lave += len;
31422       }
31423       lave /= ptlist->len();
31424     }
31425     if (out == (tetgenio *) NULL) {
31426       // for (i = 0; i < sizeoftensor; i++) {
31427       //   fprintf(outfile, "%-16.8e ", ptloop[pointmtrindex + i]);
31428       // }
31429       if (ptlist->len() > 0) {
31430         // fprintf(outfile, "%-16.8e %-16.8e %-16.8e", lmin, lmax, lave);
31431         fprintf(outfile, "%-16.8e ", lave);
31432       } else {
31433         fprintf(outfile, "0.0 "); // fprintf(outfile, "0.0  0.0  0.0");
31434       }
31435       fprintf(outfile, "\n");
31436     } else {
31437       // for (i = 0; i < sizeoftensor; i++) {
31438       //   out->pointmtrlist[mtrindex++] = ptloop[pointmtrindex + i];
31439       // }
31440       if (ptlist->len() > 0) {
31441         // out->pointmtrlist[mtrindex++] = lmin;
31442         // out->pointmtrlist[mtrindex++] = lmax;
31443         out->pointmtrlist[mtrindex++] = lave;
31444       } else {
31445         // out->pointmtrlist[mtrindex++] = 0.0;
31446         // out->pointmtrlist[mtrindex++] = 0.0;
31447         out->pointmtrlist[mtrindex++] = 0.0;
31448       }
31449     }
31450     tetlist->clear();
31451     ptlist->clear();
31452     ptloop = pointtraverse();
31453   }
31454 
31455   delete tetlist;
31456   delete ptlist;
31457 
31458   if (out == (tetgenio *) NULL) {
31459     fprintf(outfile, "# Generated by %s\n", b->commandline);
31460     fclose(outfile);
31461   }
31462 }
31463 
31465 //                                                                           //
31466 // outelements()    Output the tetrahedra to an .ele file or a tetgenio      //
31467 //                  structure.                                               //
31468 //                                                                           //
31470 
31471 void tetgenmesh::outelements(tetgenio* out)
31472 {
31473   FILE *outfile;
31474   char outelefilename[FILENAMESIZE];
31475   tetrahedron* tptr;
31476   int *tlist;
31477   REAL *talist;
31478   int firstindex, shift;
31479   int pointindex;
31480   int attribindex;
31481   point p1, p2, p3, p4;
31482   point *extralist;
31483   int elementnumber;
31484   int eextras;
31485   int i;
31486 
31487   if (out == (tetgenio *) NULL) {
31488     strcpy(outelefilename, b->outfilename);
31489     strcat(outelefilename, ".ele");
31490   }
31491 
31492   if (!b->quiet) {
31493     if (out == (tetgenio *) NULL) {
31494       printf("Writing %s.\n", outelefilename);
31495     } else {
31496       printf("Writing elements.\n");
31497     }
31498   }
31499 
31500   // Avoid compile warnings.
31501   outfile = (FILE *) NULL;
31502   tlist = (int *) NULL;
31503   talist = (double *) NULL;
31504   pointindex = attribindex = 0;
31505 
31506   eextras = in->numberoftetrahedronattributes;
31507   if (out == (tetgenio *) NULL) {
31508     outfile = fopen(outelefilename, "w");
31509     if (outfile == (FILE *) NULL) {
31510       printf("File I/O Error:  Cannot create file %s.\n", outelefilename);
31511       terminatetetgen(1);
31512     }
31513     // Number of tetras, points per tetra, attributes per tetra.
31514     fprintf(outfile, "%ld  %d  %d\n", tetrahedrons->items,
31515             b->order == 1 ? 4 : 10, eextras);
31516   } else {
31517     // Allocate memory for output tetrahedra.
31518     out->tetrahedronlist = new int[tetrahedrons->items *
31519                                    (b->order == 1 ? 4 : 10)];
31520     if (out->tetrahedronlist == (int *) NULL) {
31521       printf("Error:  Out of memory.\n");
31522       terminatetetgen(1);
31523     }
31524     // Allocate memory for output tetrahedron attributes if necessary.
31525     if (eextras > 0) {
31526       out->tetrahedronattributelist = new REAL[tetrahedrons->items * eextras];
31527       if (out->tetrahedronattributelist == (REAL *) NULL) {
31528         printf("Error:  Out of memory.\n");
31529         terminatetetgen(1);
31530       }
31531     }
31532     out->numberoftetrahedra = tetrahedrons->items;
31533     out->numberofcorners = b->order == 1 ? 4 : 10;
31534     out->numberoftetrahedronattributes = eextras;
31535     tlist = out->tetrahedronlist;
31536     talist = out->tetrahedronattributelist;
31537     pointindex = 0;
31538     attribindex = 0;
31539   }
31540 
31541   // Determine the first index (0 or 1).
31542   firstindex = b->zeroindex ? 0 : in->firstnumber;
31543   shift = 0; // Default no shiftment.
31544   if ((in->firstnumber == 1) && (firstindex == 0)) {
31545     shift = 1; // Shift the output indices by 1.
31546   }
31547 
31548   tetrahedrons->traversalinit();
31549   tptr = tetrahedrontraverse();
31550   elementnumber = firstindex; // in->firstnumber;
31551   while (tptr != (tetrahedron *) NULL) {
31552     p1 = (point) tptr[4];
31553     p2 = (point) tptr[5];
31554     p3 = (point) tptr[6];
31555     p4 = (point) tptr[7];
31556     if (out == (tetgenio *) NULL) {
31557       // Tetrahedron number, indices for four points.
31558       fprintf(outfile, "%5d   %5d %5d %5d %5d", elementnumber,
31559               pointmark(p1) - shift, pointmark(p2) - shift,
31560               pointmark(p3) - shift, pointmark(p4) - shift);
31561       if (b->order == 2) {
31562         extralist = (point *) tptr[highorderindex];
31563         // Tetrahedron number, indices for four points plus six extra points.
31564         fprintf(outfile, "  %5d %5d %5d %5d %5d %5d",
31565           pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
31566           pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
31567           pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
31568       }
31569       for (i = 0; i < eextras; i++) {
31570         fprintf(outfile, "    %.17g", elemattribute(tptr, i));
31571       }
31572       fprintf(outfile, "\n");
31573     } else {
31574       tlist[pointindex++] = pointmark(p1) - shift;
31575       tlist[pointindex++] = pointmark(p2) - shift;
31576       tlist[pointindex++] = pointmark(p3) - shift;
31577       tlist[pointindex++] = pointmark(p4) - shift;
31578       if (b->order == 2) {
31579         extralist = (point *) tptr[highorderindex];
31580         tlist[pointindex++] = pointmark(extralist[0]) - shift;
31581         tlist[pointindex++] = pointmark(extralist[1]) - shift;
31582         tlist[pointindex++] = pointmark(extralist[2]) - shift;
31583         tlist[pointindex++] = pointmark(extralist[3]) - shift;
31584         tlist[pointindex++] = pointmark(extralist[4]) - shift;
31585         tlist[pointindex++] = pointmark(extralist[5]) - shift;
31586       }
31587       for (i = 0; i < eextras; i++) {
31588         talist[attribindex++] = elemattribute(tptr, i);
31589       }
31590     }
31591     if (b->neighout) {
31592       // Remember the index of this element.
31593       * (int *) (tptr + elemmarkerindex) = elementnumber;
31594     }
31595     tptr = tetrahedrontraverse();
31596     elementnumber++;
31597   }
31598   if (b->neighout) {
31599     // Set the outside element marker.
31600     * (int *) (dummytet + elemmarkerindex) = -1;
31601   }
31602 
31603   if (out == (tetgenio *) NULL) {
31604     fprintf(outfile, "# Generated by %s\n", b->commandline);
31605     fclose(outfile);
31606   }
31607 }
31608 
31610 //                                                                           //
31611 // outfaces()    Output all faces to a .face file or a tetgenio structure.   //
31612 //                                                                           //
31613 // This routines outputs all triangular faces (including outer boundary      //
31614 // faces and inner faces) of this mesh.                                      //
31615 //                                                                           //
31617 
31618 void tetgenmesh::outfaces(tetgenio* out)
31619 {
31620   FILE *outfile;
31621   char facefilename[FILENAMESIZE];
31622   int *elist;
31623   int *emlist;
31624   int neigh1, neigh2;
31625   int index;
31626   triface tface, tsymface;
31627   face checkmark;
31628   point torg, tdest, tapex;
31629   long faces;
31630   int bmark, faceid, marker;
31631   int firstindex, shift;
31632   int facenumber;
31633 
31634   neigh1 = 0;
31635   neigh2 = 0;
31636 
31637   if (out == (tetgenio *) NULL) {
31638     strcpy(facefilename, b->outfilename);
31639     strcat(facefilename, ".face");
31640   }
31641 
31642   if (!b->quiet) {
31643     if (out == (tetgenio *) NULL) {
31644       printf("Writing %s.\n", facefilename);
31645     } else {
31646       printf("Writing faces.\n");
31647     }
31648   }
31649 
31650   // Avoid compile warnings.
31651   outfile = (FILE *) NULL;
31652   elist = (int *) NULL;
31653   emlist = (int *) NULL;
31654   index =  marker = 0;
31655 
31656   faces = (4l * tetrahedrons->items + hullsize) / 2l;
31657   bmark = !b->nobound && in->facetmarkerlist;
31658 
31659   if (out == (tetgenio *) NULL) {
31660     outfile = fopen(facefilename, "w");
31661     if (outfile == (FILE *) NULL) {
31662       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31663       terminatetetgen(1);
31664     }
31665     fprintf(outfile, "%ld  %d\n", faces, bmark);
31666   } else {
31667     // Allocate memory for 'trifacelist'.
31668     out->trifacelist = new int[faces * 3];
31669     if (out->trifacelist == (int *) NULL) {
31670       printf("Error:  Out of memory.\n");
31671       terminatetetgen(1);
31672     }
31673     // Allocate memory for 'trifacemarkerlist' if necessary.
31674     if (bmark) {
31675       out->trifacemarkerlist = new int[faces];
31676       if (out->trifacemarkerlist == (int *) NULL) {
31677         printf("Error:  Out of memory.\n");
31678         terminatetetgen(1);
31679       }
31680     }
31681     if (b->neighout > 1) {
31682       // '-nn' switch.
31683       out->adjtetlist = new int[subfaces->items * 2];
31684       if (out->adjtetlist == (int *) NULL) {
31685         printf("Error:  Out of memory.\n");
31686         terminatetetgen(1);
31687       }
31688     }
31689     out->numberoftrifaces = faces;
31690     elist = out->trifacelist;
31691     emlist = out->trifacemarkerlist;
31692     index = 0;
31693   }
31694 
31695   // Determine the first index (0 or 1).
31696   firstindex = b->zeroindex ? 0 : in->firstnumber;
31697   shift = 0; // Default no shiftment.
31698   if ((in->firstnumber == 1) && (firstindex == 0)) {
31699     shift = 1; // Shift the output indices by 1.
31700   }
31701 
31702   tetrahedrons->traversalinit();
31703   tface.tet = tetrahedrontraverse();
31704   facenumber = firstindex; // in->firstnumber;
31705   // To loop over the set of faces, loop over all tetrahedra, and look at
31706   //   the four faces of each one. If there isn't another tetrahedron
31707   //   adjacent to this face, operate on the face.  If there is another
31708   //   adjacent tetrahedron, operate on the face only if the current
31709   //   tetrahedron has a smaller pointer than its neighbor.  This way, each
31710   //   face is considered only once.
31711   while (tface.tet != (tetrahedron *) NULL) {
31712     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31713       sym(tface, tsymface);
31714       if ((tsymface.tet == dummytet) || (tface.tet < tsymface.tet)) {
31715         torg = org(tface);
31716         tdest = dest(tface);
31717         tapex = apex(tface);
31718         if (bmark) {
31719           // Get the boundary marker of this face. If it is an inner face,
31720           //   it has no boundary marker, set it be zero.
31721           if (b->useshelles) {
31722             // Shell face is used.
31723             tspivot(tface, checkmark);
31724             if (checkmark.sh == dummysh) {
31725               marker = 0;  // It is an inner face.
31726             } else {
31727               faceid = shellmark(checkmark) - 1;
31728               marker = in->facetmarkerlist[faceid];
31729             }
31730           } else {
31731             // Shell face is not used, only distinguish outer and inner face.
31732             marker = tsymface.tet != dummytet ? 1 : 0;
31733           }
31734         }
31735         if (b->neighout > 1) {
31736           // '-nn' switch. Output adjacent tets indices.
31737           neigh1 = * (int *)(tface.tet + elemmarkerindex);
31738           if (tsymface.tet != dummytet) {
31739             neigh2 = * (int *)(tsymface.tet + elemmarkerindex);
31740           } else {
31741             neigh2 = -1;
31742           }
31743         }
31744         if (out == (tetgenio *) NULL) {
31745           // Face number, indices of three vertices.
31746           fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
31747                   pointmark(torg) - shift, pointmark(tdest) - shift,
31748                   pointmark(tapex) - shift);
31749           if (bmark) {
31750             // Output a boundary marker.
31751             fprintf(outfile, "  %d", marker);
31752           }
31753           if (b->neighout > 1) {
31754             fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
31755           }
31756           fprintf(outfile, "\n");
31757         } else {
31758           // Output indices of three vertices.
31759           elist[index++] = pointmark(torg) - shift;
31760           elist[index++] = pointmark(tdest) - shift;
31761           elist[index++] = pointmark(tapex) - shift;
31762           if (bmark) {
31763             emlist[facenumber - in->firstnumber] = marker;
31764           }
31765           if (b->neighout > 1) {
31766             out->adjtetlist[(facenumber - in->firstnumber) * 2]     = neigh1;
31767             out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
31768           }
31769         }
31770         facenumber++;
31771       }
31772     }
31773     tface.tet = tetrahedrontraverse();
31774   }
31775 
31776   if (out == (tetgenio *) NULL) {
31777     fprintf(outfile, "# Generated by %s\n", b->commandline);
31778     fclose(outfile);
31779   }
31780 }
31781 
31783 //                                                                           //
31784 // outhullfaces()    Output outer boundary faces to a .face file or a        //
31785 //                   tetgenio structure.                                     //
31786 //                                                                           //
31787 // The normal of each face is arranged to point inside of the domain (use    //
31788 // right-hand rule).  This routines will outputs convex hull faces if the    //
31789 // mesh is a Delaunay tetrahedralization.                                    //
31790 //                                                                           //
31792 
31793 void tetgenmesh::outhullfaces(tetgenio* out)
31794 {
31795   FILE *outfile;
31796   char facefilename[FILENAMESIZE];
31797   int *elist;
31798   int index;
31799   triface tface, tsymface;
31800   face checkmark;
31801   point torg, tdest, tapex;
31802   int firstindex, shift;
31803   int facenumber;
31804 
31805   if (out == (tetgenio *) NULL) {
31806     strcpy(facefilename, b->outfilename);
31807     strcat(facefilename, ".face");
31808   }
31809 
31810   if (!b->quiet) {
31811     if (out == (tetgenio *) NULL) {
31812       printf("Writing %s.\n", facefilename);
31813     } else {
31814       printf("Writing faces.\n");
31815     }
31816   }
31817 
31818   // Avoid compile warnings.
31819   outfile = (FILE *) NULL;
31820   elist = (int *) NULL;
31821   index = 0;
31822 
31823   if (out == (tetgenio *) NULL) {
31824     outfile = fopen(facefilename, "w");
31825     if (outfile == (FILE *) NULL) {
31826       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31827       terminatetetgen(1);
31828     }
31829     fprintf(outfile, "%ld  0\n", hullsize);
31830   } else {
31831     // Allocate memory for 'trifacelist'.
31832     out->trifacelist = new int[hullsize * 3];
31833     if (out->trifacelist == (int *) NULL) {
31834       printf("Error:  Out of memory.\n");
31835       terminatetetgen(1);
31836     }
31837     out->numberoftrifaces = hullsize;
31838     elist = out->trifacelist;
31839     index = 0;
31840   }
31841 
31842   // Determine the first index (0 or 1).
31843   firstindex = b->zeroindex ? 0 : in->firstnumber;
31844   shift = 0; // Default no shiftment.
31845   if ((in->firstnumber == 1) && (firstindex == 0)) {
31846     shift = 1; // Shift the output indices by 1.
31847   }
31848 
31849   tetrahedrons->traversalinit();
31850   tface.tet = tetrahedrontraverse();
31851   facenumber = firstindex; // in->firstnumber;
31852   // To loop over the set of hull faces, loop over all tetrahedra, and look
31853   //   at the four faces of each one. If there isn't another tetrahedron
31854   //   adjacent to this face, operate on the face.
31855   while (tface.tet != (tetrahedron *) NULL) {
31856     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31857       sym(tface, tsymface);
31858       if (tsymface.tet == dummytet) {
31859         torg = org(tface);
31860         tdest = dest(tface);
31861         tapex = apex(tface);
31862         if (out == (tetgenio *) NULL) {
31863           // Face number, indices of three vertices.
31864           fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
31865                   pointmark(torg) - shift, pointmark(tdest) - shift,
31866                   pointmark(tapex) - shift);
31867           fprintf(outfile, "\n");
31868         } else {
31869           // Output indices of three vertices.
31870           elist[index++] = pointmark(torg) - shift;
31871           elist[index++] = pointmark(tdest) - shift;
31872           elist[index++] = pointmark(tapex) - shift;
31873         }
31874         facenumber++;
31875       }
31876     }
31877     tface.tet = tetrahedrontraverse();
31878   }
31879 
31880   if (out == (tetgenio *) NULL) {
31881     fprintf(outfile, "# Generated by %s\n", b->commandline);
31882     fclose(outfile);
31883   }
31884 }
31885 
31887 //                                                                           //
31888 // outsubfaces()    Output subfaces (i.e. boundary faces) to a .face file or //
31889 //                  a tetgenio structure.                                    //
31890 //                                                                           //
31891 // The boundary faces are exist in 'subfaces'. For listing triangle vertices //
31892 // in the same sense for all triangles in the mesh, the direction determined //
31893 // by right-hand rule is pointer to the inside of the volume.                //
31894 //                                                                           //
31896 
31897 void tetgenmesh::outsubfaces(tetgenio* out)
31898 {
31899   FILE *outfile;
31900   char facefilename[FILENAMESIZE];
31901   int *elist;
31902   int *emlist;
31903   int index, index1, index2;
31904   triface abuttingtet;
31905   face faceloop;
31906   point torg, tdest, tapex;
31907   int bmark, faceid, marker;
31908   int firstindex, shift;
31909   int neigh1, neigh2;
31910   int facenumber;
31911 
31912   if (out == (tetgenio *) NULL) {
31913     strcpy(facefilename, b->outfilename);
31914     strcat(facefilename, ".face");
31915   }
31916 
31917   if (!b->quiet) {
31918     if (out == (tetgenio *) NULL) {
31919       printf("Writing %s.\n", facefilename);
31920     } else {
31921       printf("Writing faces.\n");
31922     }
31923   }
31924 
31925   // Avoid compile warnings.
31926   outfile = (FILE *) NULL;
31927   elist = (int *) NULL;
31928   emlist = (int *) NULL;
31929   index = index1 = index2 = 0;
31930   faceid = marker = 0;
31931   neigh1 = neigh2 = 0;
31932 
31933   bmark = !b->nobound && in->facetmarkerlist;
31934 
31935   if (out == (tetgenio *) NULL) {
31936     outfile = fopen(facefilename, "w");
31937     if (outfile == (FILE *) NULL) {
31938       printf("File I/O Error:  Cannot create file %s.\n", facefilename);
31939       terminatetetgen(1);
31940     }
31941     // Number of subfaces.
31942     fprintf(outfile, "%ld  %d\n", subfaces->items, bmark);
31943   } else {
31944     // Allocate memory for 'trifacelist'.
31945     out->trifacelist = new int[subfaces->items * 3];
31946     if (out->trifacelist == (int *) NULL) {
31947       printf("Error:  Out of memory.\n");
31948       terminatetetgen(1);
31949     }
31950     if (bmark) {
31951       // Allocate memory for 'trifacemarkerlist'.
31952       out->trifacemarkerlist = new int[subfaces->items];
31953       if (out->trifacemarkerlist == (int *) NULL) {
31954         printf("Error:  Out of memory.\n");
31955         terminatetetgen(1);
31956       }
31957     }
31958     if (b->neighout > 1) {
31959       // '-nn' switch.
31960       out->adjtetlist = new int[subfaces->items * 2];
31961       if (out->adjtetlist == (int *) NULL) {
31962         printf("Error:  Out of memory.\n");
31963         terminatetetgen(1);
31964       }
31965     }
31966     out->numberoftrifaces = subfaces->items;
31967     elist = out->trifacelist;
31968     emlist = out->trifacemarkerlist;
31969   }
31970 
31971   // Determine the first index (0 or 1).
31972   firstindex = b->zeroindex ? 0 : in->firstnumber;
31973   shift = 0; // Default no shiftment.
31974   if ((in->firstnumber == 1) && (firstindex == 0)) {
31975     shift = 1; // Shift the output indices by 1.
31976   }
31977 
31978   subfaces->traversalinit();
31979   faceloop.sh = shellfacetraverse(subfaces);
31980   facenumber = firstindex; // in->firstnumber;
31981   while (faceloop.sh != (shellface *) NULL) {
31982     stpivot(faceloop, abuttingtet);
31983     if (abuttingtet.tet == dummytet) {
31984       sesymself(faceloop);
31985       stpivot(faceloop, abuttingtet);
31986     }
31987     if (abuttingtet.tet != dummytet) {
31988       // If there is a tetrahedron containing this subface, orient it so
31989       //   that the normal of this face points to inside of the volume by
31990       //   right-hand rule.
31991       adjustedgering(abuttingtet, CCW);
31992       torg = org(abuttingtet);
31993       tdest = dest(abuttingtet);
31994       tapex = apex(abuttingtet);
31995     } else {
31996       // This may happen when only a surface mesh be generated.
31997       torg = sorg(faceloop);
31998       tdest = sdest(faceloop);
31999       tapex = sapex(faceloop);
32000     }
32001     if (bmark) {
32002       faceid = shellmark(faceloop) - 1;
32003       marker = in->facetmarkerlist[faceid];
32004     }
32005     if (b->neighout > 1) {
32006       // '-nn' switch. Output adjacent tets indices.
32007       neigh1 = -1;
32008       stpivot(faceloop, abuttingtet);
32009       if (abuttingtet.tet != dummytet) {
32010         neigh1 = * (int *)(abuttingtet.tet + elemmarkerindex);
32011       }
32012       neigh2 = -1;
32013       sesymself(faceloop);
32014       stpivot(faceloop, abuttingtet);
32015       if (abuttingtet.tet != dummytet) {
32016         neigh2 = * (int *)(abuttingtet.tet + elemmarkerindex);
32017       }
32018     }
32019     if (out == (tetgenio *) NULL) {
32020       fprintf(outfile, "%5d   %4d  %4d  %4d", facenumber,
32021               pointmark(torg) - shift, pointmark(tdest) - shift,
32022               pointmark(tapex) - shift);
32023       if (bmark) {
32024         fprintf(outfile, "    %d", marker);
32025       }
32026       if (b->neighout > 1) {
32027         fprintf(outfile, "    %5d  %5d", neigh1, neigh2);
32028       }
32029       fprintf(outfile, "\n");
32030     } else {
32031       // Output three vertices of this face;
32032       elist[index++] = pointmark(torg) - shift;
32033       elist[index++] = pointmark(tdest) - shift;
32034       elist[index++] = pointmark(tapex) - shift;
32035       if (bmark) {
32036         emlist[index1++] = marker;
32037       }
32038       if (b->neighout > 1) {
32039         out->adjtetlist[index2++] = neigh1;
32040         out->adjtetlist[index2++] = neigh2;
32041       }
32042     }
32043     facenumber++;
32044     faceloop.sh = shellfacetraverse(subfaces);
32045   }
32046 
32047   if (out == (tetgenio *) NULL) {
32048     fprintf(outfile, "# Generated by %s\n", b->commandline);
32049     fclose(outfile);
32050   }
32051 }
32052 
32054 //                                                                           //
32055 // outedges()    Output all edges to a .edge file or a structure.            //
32056 //                                                                           //
32058 
32059 void tetgenmesh::outedges(tetgenio* out)
32060 {
32061   FILE *outfile;
32062   char edgefilename[FILENAMESIZE];
32063   int *elist, *emlist;
32064   int index, index1;
32065   triface tetloop, worktet, spintet;
32066   face checksh;
32067   point torg, tdest;
32068   long faces, edges;
32069   int firstindex, shift;
32070   int edgenumber, faceid, marker;
32071   int hitbdry, i;
32072 
32073   if (out == (tetgenio *) NULL) {
32074     strcpy(edgefilename, b->outfilename);
32075     strcat(edgefilename, ".edge");
32076   }
32077 
32078   if (!b->quiet) {
32079     if (out == (tetgenio *) NULL) {
32080       printf("Writing %s.\n", edgefilename);
32081     } else {
32082       printf("Writing edges.\n");
32083     }
32084   }
32085 
32086   // Avoid compile warnings.
32087   outfile = (FILE *) NULL;
32088   elist = (int *) NULL;
32089   emlist = (int *) NULL;
32090   index = index1 = 0;
32091   faceid = marker = 0;
32092 
32093   // Using the Euler formula (V-E+F-T=1) to get the total number of edges.
32094   faces = (4l * tetrahedrons->items + hullsize) / 2l;
32095   edges = points->items + faces - tetrahedrons->items - 1l;
32096 
32097   if (out == (tetgenio *) NULL) {
32098     outfile = fopen(edgefilename, "w");
32099     if (outfile == (FILE *) NULL) {
32100       printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
32101       terminatetetgen(1);
32102     }
32103     // Write the number of edges, boundary markers (0 or 1).
32104     fprintf(outfile, "%ld  %d\n", edges, !b->nobound);
32105   } else {
32106     // Allocate memory for 'edgelist'.
32107     out->edgelist = new int[edges * 2];
32108     if (out->edgelist == (int *) NULL) {
32109       printf("Error:  Out of memory.\n");
32110       terminatetetgen(1);
32111     }
32112     if (!b->nobound) {
32113       out->edgemarkerlist = new int[edges];
32114     }
32115     out->numberofedges = edges;
32116     elist = out->edgelist;
32117     emlist = out->edgemarkerlist;
32118   }
32119 
32120   // Determine the first index (0 or 1).
32121   firstindex = b->zeroindex ? 0 : in->firstnumber;
32122   shift = 0; // Default no shiftment.
32123   if ((in->firstnumber == 1) && (firstindex == 0)) {
32124     shift = 1; // Shift (reduce) the output indices by 1.
32125   }
32126 
32127   tetrahedrons->traversalinit();
32128   tetloop.tet = tetrahedrontraverse();
32129   edgenumber = firstindex; // in->firstnumber;
32130   while (tetloop.tet != (tetrahedron *) NULL) {
32131     // Count the number of Voronoi faces. Look at the six edges of each
32132     //   tetrahedron. Count the edge only if the tetrahedron's pointer is
32133     //   smaller than those of all other tetrahedra that share the edge.
32134     worktet.tet = tetloop.tet;
32135     for (i = 0; i < 6; i++) {
32136       worktet.loc = edge2locver[i][0];
32137       worktet.ver = edge2locver[i][1];
32138       adjustedgering(worktet, CW);
32139       spintet = worktet;
32140       hitbdry = 0;
32141       while (hitbdry < 2) {
32142         if (fnextself(spintet)) {
32143           if (apex(spintet) == apex(worktet)) break;
32144           if (spintet.tet < worktet.tet) break;
32145         } else {
32146           hitbdry++;
32147           if (hitbdry < 2) {
32148             esym(worktet, spintet);
32149             fnextself(spintet); // In the same tet.
32150       }
32151         }
32152       }
32153       // Count this edge if no adjacent tets are smaller than this tet.
32154       if (spintet.tet >= worktet.tet) {
32155         torg = org(worktet);
32156         tdest = dest(worktet);
32157         if (out == (tetgenio *) NULL) {
32158           fprintf(outfile, "%5d   %4d  %4d", edgenumber,
32159                   pointmark(torg) - shift, pointmark(tdest) - shift);
32160         } else {
32161           // Output three vertices of this face;
32162           elist[index++] = pointmark(torg) - shift;
32163           elist[index++] = pointmark(tdest) - shift;
32164         }
32165         if (!b->nobound) {
32166           if (hitbdry > 0) {
32167             // It is a boundary edge. Get the boundary marker of the facet
32168             //   containing this edge. Note there may have more than one
32169             //   facet, choose one arbitrarily.
32170             if ((b->plc || b->refine) && in->facetmarkerlist) {
32171               tspivot(spintet, checksh);
32172               faceid = shellmark(checksh) - 1;
32173               marker = in->facetmarkerlist[faceid];
32174             } else {
32175               marker = 1;  // Indicate it's a boundary edge.
32176             }
32177           } else {
32178             marker = 0;
32179           }
32180           if (out == (tetgenio *) NULL) {
32181             fprintf(outfile, "  %d", marker);
32182           } else {
32183             emlist[index1++] = marker;
32184           }
32185         }
32186         if (out == (tetgenio *) NULL) {
32187           fprintf(outfile, "\n");
32188         }
32189         edgenumber++;
32190       }
32191     }
32192     tetloop.tet = tetrahedrontraverse();
32193   }
32194 
32195   if (out == (tetgenio *) NULL) {
32196     fprintf(outfile, "# Generated by %s\n", b->commandline);
32197     fclose(outfile);
32198   }
32199 }
32200 
32202 //                                                                           //
32203 // outsubsegments()    Output segments to a .edge file or a structure.       //
32204 //                                                                           //
32206 
32207 void tetgenmesh::outsubsegments(tetgenio* out)
32208 {
32209   FILE *outfile;
32210   char edgefilename[FILENAMESIZE];
32211   int *elist;
32212   int index;
32213   face edgeloop;
32214   point torg, tdest;
32215   int firstindex, shift;
32216   int edgenumber;
32217 
32218   if (out == (tetgenio *) NULL) {
32219     strcpy(edgefilename, b->outfilename);
32220     strcat(edgefilename, ".edge");
32221   }
32222 
32223   if (!b->quiet) {
32224     if (out == (tetgenio *) NULL) {
32225       printf("Writing %s.\n", edgefilename);
32226     } else {
32227       printf("Writing edges.\n");
32228     }
32229   }
32230 
32231   // Avoid compile warnings.
32232   outfile = (FILE *) NULL;
32233   elist = (int *) NULL;
32234   index = 0;
32235 
32236   if (out == (tetgenio *) NULL) {
32237     outfile = fopen(edgefilename, "w");
32238     if (outfile == (FILE *) NULL) {
32239       printf("File I/O Error:  Cannot create file %s.\n", edgefilename);
32240       terminatetetgen(1);
32241     }
32242     // Number of subsegments.
32243     fprintf(outfile, "%ld\n", subsegs->items);
32244   } else {
32245     // Allocate memory for 'edgelist'.
32246     out->edgelist = new int[subsegs->items * 2];
32247     if (out->edgelist == (int *) NULL) {
32248       printf("Error:  Out of memory.\n");
32249       terminatetetgen(1);
32250     }
32251     out->numberofedges = subsegs->items;
32252     elist = out->edgelist;
32253   }
32254 
32255   // Determine the first index (0 or 1).
32256   firstindex = b->zeroindex ? 0 : in->firstnumber;
32257   shift = 0; // Default no shiftment.
32258   if ((in->firstnumber == 1) && (firstindex == 0)) {
32259     shift = 1; // Shift the output indices by 1.
32260   }
32261 
32262   subsegs->traversalinit();
32263   edgeloop.sh = shellfacetraverse(subsegs);
32264   edgenumber = firstindex; // in->firstnumber;
32265   while (edgeloop.sh != (shellface *) NULL) {
32266     torg = sorg(edgeloop);
32267     tdest = sdest(edgeloop);
32268     if (out == (tetgenio *) NULL) {
32269       fprintf(outfile, "%5d   %4d  %4d\n", edgenumber,
32270               pointmark(torg) - shift, pointmark(tdest) - shift);
32271     } else {
32272       // Output three vertices of this face;
32273       elist[index++] = pointmark(torg) - shift;
32274       elist[index++] = pointmark(tdest) - shift;
32275     }
32276     edgenumber++;
32277     edgeloop.sh = shellfacetraverse(subsegs);
32278   }
32279 
32280   if (out == (tetgenio *) NULL) {
32281     fprintf(outfile, "# Generated by %s\n", b->commandline);
32282     fclose(outfile);
32283   }
32284 }
32285 
32287 //                                                                           //
32288 // outneighbors()    Output tet neighbors to a .neigh file or a structure.   //
32289 //                                                                           //
32291 
32292 void tetgenmesh::outneighbors(tetgenio* out)
32293 {
32294   FILE *outfile;
32295   char neighborfilename[FILENAMESIZE];
32296   int *nlist;
32297   int index;
32298   triface tetloop, tetsym;
32299   int neighbor1, neighbor2, neighbor3, neighbor4;
32300   int firstindex;
32301   int elementnumber;
32302 
32303   if (out == (tetgenio *) NULL) {
32304     strcpy(neighborfilename, b->outfilename);
32305     strcat(neighborfilename, ".neigh");
32306   }
32307 
32308   if (!b->quiet) {
32309     if (out == (tetgenio *) NULL) {
32310       printf("Writing %s.\n", neighborfilename);
32311     } else {
32312       printf("Writing neighbors.\n");
32313     }
32314   }
32315 
32316   // Avoid compile warnings.
32317   outfile = (FILE *) NULL;
32318   nlist = (int *) NULL;
32319   index = 0;
32320 
32321   if (out == (tetgenio *) NULL) {
32322     outfile = fopen(neighborfilename, "w");
32323     if (outfile == (FILE *) NULL) {
32324       printf("File I/O Error:  Cannot create file %s.\n", neighborfilename);
32325       terminatetetgen(1);
32326     }
32327     // Number of tetrahedra, four faces per tetrahedron.
32328     fprintf(outfile, "%ld  %d\n", tetrahedrons->items, 4);
32329   } else {
32330     // Allocate memory for 'neighborlist'.
32331     out->neighborlist = new int[tetrahedrons->items * 4];
32332     if (out->neighborlist == (int *) NULL) {
32333       printf("Error:  Out of memory.\n");
32334       terminatetetgen(1);
32335     }
32336     nlist = out->neighborlist;
32337   }
32338 
32339   // Determine the first index (0 or 1).
32340   firstindex = b->zeroindex ? 0 : in->firstnumber;
32341 
32342   tetrahedrons->traversalinit();
32343   tetloop.tet = tetrahedrontraverse();
32344   elementnumber = firstindex; // in->firstnumber;
32345   while (tetloop.tet != (tetrahedron *) NULL) {
32346     tetloop.loc = 2;
32347     sym(tetloop, tetsym);
32348     neighbor1 = * (int *) (tetsym.tet + elemmarkerindex);
32349     tetloop.loc = 3;
32350     sym(tetloop, tetsym);
32351     neighbor2 = * (int *) (tetsym.tet + elemmarkerindex);
32352     tetloop.loc = 1;
32353     sym(tetloop, tetsym);
32354     neighbor3 = * (int *) (tetsym.tet + elemmarkerindex);
32355     tetloop.loc = 0;
32356     sym(tetloop, tetsym);
32357     neighbor4 = * (int *) (tetsym.tet + elemmarkerindex);
32358     if (out == (tetgenio *) NULL) {
32359       // Tetrahedra number, neighboring tetrahedron numbers.
32360       fprintf(outfile, "%4d    %4d  %4d  %4d  %4d\n", elementnumber,
32361               neighbor1, neighbor2, neighbor3, neighbor4);
32362     } else {
32363       nlist[index++] = neighbor1;
32364       nlist[index++] = neighbor2;
32365       nlist[index++] = neighbor3;
32366       nlist[index++] = neighbor4;
32367     }
32368     tetloop.tet = tetrahedrontraverse();
32369     elementnumber++;
32370   }
32371 
32372   if (out == (tetgenio *) NULL) {
32373     fprintf(outfile, "# Generated by %s\n", b->commandline);
32374     fclose(outfile);
32375   }
32376 }
32377 
32379 //                                                                           //
32380 // outvoronoi()    Output the Voronoi diagram to .v.node, .v.edge, v.face,   //
32381 //                 and .v.cell.                                              //
32382 //                                                                           //
32383 // The Voronoi diagram is the geometric dual of the Delaunay triangulation.  //
32384 // The Voronoi vertices are the circumcenters of Delaunay tetrahedra.  Each  //
32385 // Voronoi edge connects two Voronoi vertices at two sides of a common Dela- //
32386 // unay face. At a face of convex hull, it becomes a ray (goto the infinity).//
32387 // A Voronoi face is the convex hull of all Voronoi vertices around a common //
32388 // Delaunay edge. It is a closed polygon for any interal Delaunay edge. At a //
32389 // ridge, it is unbounded.  Each Voronoi cell is the convex hull of all Vor- //
32390 // onoi vertices around a common Delaunay vertex. It is a polytope for any   //
32391 // internal Delaunay vertex. It is an unbounded polyhedron for a Delaunay    //
32392 // vertex belonging to the convex hull.                                      //
32393 //                                                                           //
32395 
32396 void tetgenmesh::outvoronoi(tetgenio* out)
32397 {
32398   FILE *outfile;
32399   char outfilename[FILENAMESIZE];
32400   tetgenio::voroedge *vedge;
32401   tetgenio::vorofacet *vfacet;
32402   list *tetlist, *ptlist;
32403   triface tetloop, worktet, spintet;
32404   point pt[4], ptloop, neipt;
32405   REAL ccent[3], infvec[3], vec1[3], vec2[3], L;
32406   long faces, edges;
32407   int *tetfaceindexarray, *tetedgeindexarray;
32408   int arraysize, *vertarray;
32409   int vpointcount, vedgecount, vfacecount, tcount;
32410   int index, shift;
32411   int end1, end2;
32412   int hitbdry, i, j, k;
32413 
32414   vedge = NULL;
32415   vertarray = NULL;
32416   vfacet = NULL;
32417   k = 0;
32418 
32419   // Output Voronoi vertices to .v.node file.
32420   if (out == (tetgenio *) NULL) {
32421     strcpy(outfilename, b->outfilename);
32422     strcat(outfilename, ".v.node");
32423   }
32424 
32425   if (!b->quiet) {
32426     if (out == (tetgenio *) NULL) {
32427       printf("Writing %s.\n", outfilename);
32428     } else {
32429       printf("Writing Voronoi vertices.\n");
32430     }
32431   }
32432 
32433   // Determine the first index (0 or 1).
32434   shift = (b->zeroindex ? 0 : in->firstnumber);
32435   // The number of Delaunay faces (= the number of Voronoi edges).
32436   faces = (4l * tetrahedrons->items + hullsize) / 2l;
32437   // The number of Delaunay edges (= the number of Voronoi faces).
32438   edges = points->items + faces - tetrahedrons->items - 1;
32439   outfile = (FILE *) NULL; // Avoid compile warnings.
32440 
32441   if (out == (tetgenio *) NULL) {
32442     outfile = fopen(outfilename, "w");
32443     if (outfile == (FILE *) NULL) {
32444       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32445       terminatetetgen(1);
32446     }
32447     // Number of voronoi points, 3 dim, no attributes, no marker.
32448     fprintf(outfile, "%ld  3  0  0\n", tetrahedrons->items);
32449   } else {
32450     // Allocate space for 'vpointlist'.
32451     out->numberofvpoints = (int) tetrahedrons->items;
32452     out->vpointlist = new REAL[out->numberofvpoints * 3];
32453     if (out->vpointlist == (REAL *) NULL) {
32454       printf("Error:  Out of memory.\n");
32455       terminatetetgen(1);
32456     }
32457   }
32458 
32459   // Loop the tetrahedronlist once, do the following:
32460   //   (1) Output Voronoi vertices (the circumcenter of the tetrahedron).
32461   //   (2) Make a map from points-to-tetrahedra (for Voronoi cells).
32462   tetrahedrons->traversalinit();
32463   tetloop.tet = tetrahedrontraverse();
32464   vpointcount = 0;
32465   index = 0;
32466   while (tetloop.tet != (tetrahedron *) NULL) {
32467     // Calculate the circumcenter.
32468     for (i = 0; i < 4; i++) {
32469       pt[i] = (point) tetloop.tet[4 + i];
32470       setpoint2tet(pt[i], encode(tetloop));
32471     }
32472     circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
32473     if (out == (tetgenio *) NULL) {
32474       fprintf(outfile, "%4d  %16.8e %16.8e %16.8e\n", vpointcount + shift,
32475               ccent[0], ccent[1], ccent[2]);
32476     } else {
32477       out->vpointlist[index++] = ccent[0];
32478       out->vpointlist[index++] = ccent[1];
32479       out->vpointlist[index++] = ccent[2];
32480     }
32481     // Remember the index of this element.
32482     * (int *) (tetloop.tet + elemmarkerindex) = vpointcount;
32483     vpointcount++;
32484     tetloop.tet = tetrahedrontraverse();
32485   }
32486   // Set the outside element marker.
32487   * (int *) (dummytet + elemmarkerindex) = -1;
32488 
32489   if (out == (tetgenio *) NULL) {
32490     fprintf(outfile, "# Generated by %s\n", b->commandline);
32491     fclose(outfile);
32492   }
32493 
32494   // Output Voronoi edges to .v.edge file.
32495   if (out == (tetgenio *) NULL) {
32496     strcpy(outfilename, b->outfilename);
32497     strcat(outfilename, ".v.edge");
32498   }
32499 
32500   if (!b->quiet) {
32501     if (out == (tetgenio *) NULL) {
32502       printf("Writing %s.\n", outfilename);
32503     } else {
32504       printf("Writing Voronoi edges.\n");
32505     }
32506   }
32507 
32508   if (out == (tetgenio *) NULL) {
32509     outfile = fopen(outfilename, "w");
32510     if (outfile == (FILE *) NULL) {
32511       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32512       terminatetetgen(1);
32513     }
32514     // Number of Voronoi edges, no marker.
32515     fprintf(outfile, "%ld  0\n", faces);
32516   } else {
32517     // Allocate space for 'vpointlist'.
32518     out->numberofedges = (int) faces;
32519     out->vedgelist = new tetgenio::voroedge[out->numberofvedges];
32520   }
32521 
32522   // Loop the tetrahedronlist once, output the Voronoi edges. The index of
32523   //   each Voronoi edge corresponding to the index of the Delaunay face.
32524   //   The four faces' indices of each tetrahedron are saved in the list
32525   //   'tetfaceindexarray', in the entry of i,  where i (0-based) is the
32526   //   index of this tetrahedron (= vpointcount).
32527   tetfaceindexarray = new int[tetrahedrons->items * 4];
32528   tetrahedrons->traversalinit();
32529   tetloop.tet = tetrahedrontraverse();
32530   vedgecount = 0;
32531   index = 0;
32532   while (tetloop.tet != (tetrahedron *) NULL) {
32533     // Count the number of Voronoi edges. Look at the four faces of each
32534     //   tetrahedron. Count the face if the tetrahedron's pointer is
32535     //   smaller than its neighbor's or the neighbor is outside.
32536     end1 = * (int *) (tetloop.tet + elemmarkerindex);
32537     for (i = 0; i < 4; i++) {
32538       decode(tetloop.tet[i], worktet);
32539       if ((worktet.tet == dummytet) || (tetloop.tet < worktet.tet)) {
32540         if (out == (tetgenio *) NULL) {
32541           fprintf(outfile, "%4d  %4d", vedgecount + shift, end1 + shift);
32542         } else {
32543           vedge = &(out->vedgelist[index++]);
32544           vedge->v1 = end1 + shift;
32545         }
32546         end2 = * (int *) (worktet.tet + elemmarkerindex);
32547         // Note that end2 may be -1 (worktet.tet is outside).
32548         if (end2 == -1) {
32549           // Calculate the out normal of this hull face.
32550           worktet.tet = tetloop.tet;
32551           worktet.loc = i;
32552           worktet.ver = 1; // The CW edge ring.
32553           pt[0] = org(worktet);
32554           pt[1] = dest(worktet);
32555           pt[2] = apex(worktet);
32556           for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j];
32557           for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j];
32558           cross(vec1, vec2, infvec);
32559           // Normalize it.
32560           L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1]
32561                    + infvec[2] * infvec[2]);
32562           if (L > 0) for (j = 0; j < 3; j++) infvec[j] /= L;
32563           if (out == (tetgenio *) NULL) {
32564             fprintf(outfile, " -1");
32565             fprintf(outfile, " %g %g %g\n", infvec[0], infvec[1], infvec[2]);
32566           } else {
32567             vedge->v2 = -1;
32568             vedge->vnormal[0] = infvec[0];
32569             vedge->vnormal[1] = infvec[1];
32570             vedge->vnormal[2] = infvec[2];
32571           }
32572         } else {
32573           if (out == (tetgenio *) NULL) {
32574             fprintf(outfile, " %4d\n", end2 + shift);
32575           } else {
32576             vedge->v2 = end2 + shift;
32577             vedge->vnormal[0] = 0.0;
32578             vedge->vnormal[1] = 0.0;
32579             vedge->vnormal[2] = 0.0;
32580           }
32581         }
32582         // Save the face index in this tet and its neighbor if exists.
32583         tetfaceindexarray[end1 * 4 + i] = vedgecount;
32584         if (end2 != -1) {
32585           tetfaceindexarray[end2 * 4 + worktet.loc] = vedgecount;
32586         }
32587         vedgecount++;
32588       }
32589     }
32590     tetloop.tet = tetrahedrontraverse();
32591   }
32592 
32593   if (out == (tetgenio *) NULL) {
32594     fprintf(outfile, "# Generated by %s\n", b->commandline);
32595     fclose(outfile);
32596   }
32597 
32598   // Output Voronoi faces to .v.face file.
32599   if (out == (tetgenio *) NULL) {
32600     strcpy(outfilename, b->outfilename);
32601     strcat(outfilename, ".v.face");
32602   }
32603 
32604   if (!b->quiet) {
32605     if (out == (tetgenio *) NULL) {
32606       printf("Writing %s.\n", outfilename);
32607     } else {
32608       printf("Writing Voronoi faces.\n");
32609     }
32610   }
32611 
32612   if (out == (tetgenio *) NULL) {
32613     outfile = fopen(outfilename, "w");
32614     if (outfile == (FILE *) NULL) {
32615       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32616       terminatetetgen(1);
32617     }
32618     // Number of Voronoi faces.
32619     fprintf(outfile, "%ld  0\n", edges);
32620   } else {
32621     out->numberofvfacets = edges;
32622     out->vfacetlist = new tetgenio::vorofacet[out->numberofvfacets];
32623     if (out->vfacetlist == (tetgenio::vorofacet *) NULL) {
32624       printf("Error:  Out of memory.\n");
32625       terminatetetgen(1);
32626     }
32627   }
32628 
32629   // Loop the tetrahedronlist once, Output Voronoi facets. The index of each
32630   //   Voronoi facet corresponding to the index of the Delaunay edge.  The
32631   //   six edges' indices of each tetrahedron are saved in the list 'tetedge-
32632   //   indexarray', in the entry of i,  where i (0-based) is the index of
32633   //   this tetrahedron (= vpointcount).
32634   tetedgeindexarray = new int[tetrahedrons->items * 6];
32635   tetrahedrons->traversalinit();
32636   tetloop.tet = tetrahedrontraverse();
32637   vfacecount = 0;
32638   while (tetloop.tet != (tetrahedron *) NULL) {
32639     // Count the number of Voronoi faces. Look at the six edges of each
32640     //   tetrahedron. Count the edge only if the tetrahedron's pointer is
32641     //   smaller than those of all other tetrahedra that share the edge.
32642     worktet = tetloop;
32643     for (i = 0; i < 6; i++) {
32644       worktet.loc = edge2locver[i][0];
32645       worktet.ver = edge2locver[i][1];
32646       // Now count the number of tets surrounding this edge.
32647       tcount = 1;
32648       adjustedgering(worktet, CW);
32649       spintet = worktet;
32650       hitbdry = 0;
32651       while (hitbdry < 2) {
32652         if (fnextself(spintet)) {
32653           if (apex(spintet) == apex(worktet)) break;
32654           if (spintet.tet < worktet.tet) break;
32655           tcount++;
32656         } else {
32657           hitbdry++;
32658           if (hitbdry < 2) {
32659             esym(worktet, spintet);
32660             fnextself(spintet); // In the same tet.
32661       }
32662         }
32663       }
32664       // Count this edge if no adjacent tets are smaller than this tet.
32665       if (spintet.tet >= worktet.tet) {
32666         // Get the two endpoints of this edge.
32667         pt[0] = org(worktet);
32668         pt[1] = dest(worktet);
32669         end1 = pointmark(pt[0]) - in->firstnumber;
32670         end2 = pointmark(pt[1]) - in->firstnumber;
32671         if (out == (tetgenio *) NULL) {
32672           fprintf(outfile, "%4d  %4d %4d  %-2d ", vfacecount + shift,
32673                   end1 + shift, end2 + shift, tcount + (hitbdry > 0));
32674         } else {
32675           vfacet = &(out->vfacetlist[vfacecount]);
32676           vfacet->c1 = end1 + shift;
32677           vfacet->c2 = end2 + shift;
32678           vfacet->elist = new int[tcount + (hitbdry > 0) + 1];
32679           vfacet->elist[0] = tcount + (hitbdry > 0);
32680           index = 1;
32681         }
32682         // If hitbdry > 0, then spintet is a hull face.
32683         if (hitbdry > 0) {
32684           // The edge list starts with a ray.
32685           vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32686           vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32687           if (out == (tetgenio *) NULL) {
32688             fprintf(outfile, " %d", vedgecount + shift);
32689           } else {
32690             vfacet->elist[index++] = vedgecount + shift;
32691           }
32692           // Save this facet number in tet.
32693           tetedgeindexarray[vpointcount * 6 +
32694             locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32695           esymself(spintet);
32696           fnextself(spintet); // In the same tet.
32697         }
32698         // Output internal Voronoi edges.
32699         for (j = 0; j < tcount; j++) {
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           fnextself(spintet);
32711         }
32712         if (out == (tetgenio *) NULL) {
32713           fprintf(outfile, "\n");
32714         }
32715         vfacecount++;
32716       }
32717     } // if (i = 0; i < 6; i++)
32718     tetloop.tet = tetrahedrontraverse();
32719   }
32720 
32721   if (out == (tetgenio *) NULL) {
32722     fprintf(outfile, "# Generated by %s\n", b->commandline);
32723     fclose(outfile);
32724   }
32725 
32726   // Output Voronoi cells to .v.cell file.
32727   if (out == (tetgenio *) NULL) {
32728     strcpy(outfilename, b->outfilename);
32729     strcat(outfilename, ".v.cell");
32730   }
32731 
32732   if (!b->quiet) {
32733     if (out == (tetgenio *) NULL) {
32734       printf("Writing %s.\n", outfilename);
32735     } else {
32736       printf("Writing Voronoi cells.\n");
32737     }
32738   }
32739 
32740   if (out == (tetgenio *) NULL) {
32741     outfile = fopen(outfilename, "w");
32742     if (outfile == (FILE *) NULL) {
32743       printf("File I/O Error:  Cannot create file %s.\n", outfilename);
32744       terminatetetgen(1);
32745     }
32746     // Number of Voronoi cells.
32747     fprintf(outfile, "%ld\n", points->items);
32748   } else {
32749     out->numberofvcells = points->items;
32750     out->vcelllist = new int*[out->numberofvcells];
32751     if (out->vcelllist == (int **) NULL) {
32752       printf("Error:  Out of memory.\n");
32753       terminatetetgen(1);
32754     }
32755   }
32756 
32757   // Loop through point list, for each point, output a Voronoi cell.
32758   tetlist = new list(sizeof(triface), NULL, 256);
32759   ptlist = new list(sizeof(point *), NULL, 256);
32760   points->traversalinit();
32761   ptloop = pointtraverse();
32762   vpointcount = 0;
32763   while (ptloop != (point) NULL) {
32764     decode(point2tet(ptloop), tetloop);
32765     // assert(!isdead(&tetloop));
32766     if (!isdead(&tetloop)) {
32767       // Form the star of p.
32768       tetlist->append(&tetloop);
32769       formstarpolyhedron(ptloop, tetlist, ptlist, true);
32770       tcount = ptlist->len();
32771       if (out == (tetgenio *) NULL) {
32772         fprintf(outfile, "%4d  %-2d ", vpointcount + shift, tcount);
32773       } else {
32774         arraysize = tcount;
32775         vertarray = out->vcelllist[vpointcount];
32776         vertarray = new int[arraysize + 1];
32777         vertarray[0] = arraysize;
32778         index = 1;
32779       }
32780       // List Voronoi facets bounding this cell.
32781       for (i = 0; i < ptlist->len(); i++) {
32782         neipt =  * (point *)(* ptlist)[i];
32783         // Find a tet in tetlist having edge (ptloop, neipt) -- Very Slow.
32784         for (j = 0; j < tetlist->len(); j++) {
32785           tetloop = * (triface *)(* tetlist)[j];
32786           for (k = 0; k < 6; k++) {
32787             tetloop.loc = edge2locver[k][0];
32788             tetloop.ver = edge2locver[k][1];
32789             if (org(tetloop) == ptloop) {
32790               if (dest(tetloop) == neipt) break;
32791             } else if (org(tetloop) == neipt) {
32792               if (dest(tetloop) == ptloop) break;
32793             }
32794           }
32795           if (k < 6) break; // Found this edge.
32796         }
32797         assert(j < tetlist->len());
32798         // k is the right edge number.
32799         end1 = * (int *) (tetloop.tet + elemmarkerindex);
32800         vfacecount = tetedgeindexarray[end1 * 6 + k];
32801         if (out == (tetgenio *) NULL) {
32802           fprintf(outfile, " %d", vfacecount + shift);
32803         } else {
32804           vertarray[index++] = vfacecount + shift;
32805         }
32806       } // for (i = 0; i < ptlist->len(); i++) {
32807       if (out == (tetgenio *) NULL) {
32808         fprintf(outfile, "\n");
32809       }
32810       vpointcount++;
32811     }
32812     tetlist->clear();
32813     ptlist->clear();
32814     ptloop = pointtraverse();
32815   }
32816   delete tetlist;
32817   delete ptlist;
32818   delete [] tetfaceindexarray;
32819   delete [] tetedgeindexarray;
32820 
32821   if (out == (tetgenio *) NULL) {
32822     fprintf(outfile, "# Generated by %s\n", b->commandline);
32823     fclose(outfile);
32824   }
32825 }
32826 
32828 //                                                                           //
32829 // outpbcnodes()    Output pbc node pairs to a .pbc file or a structure.     //
32830 //                                                                           //
32832 
32833 void tetgenmesh::outpbcnodes(tetgenio* out)
32834 {
32835   FILE *outfile;
32836   char pbcfilename[FILENAMESIZE];
32837   list *ptpairlist;
32838   tetgenio::pbcgroup *pgi, *pgo;
32839   pbcdata *pd;
32840   face faceloop;
32841   face checkseg, symseg;
32842   point *ptpair, pa, pb;
32843   enum locateresult loc;
32844   REAL sympt[3], d1, d2;
32845   int *worklist;
32846   int firstindex, shift;
32847   int index, idx;
32848   int i, j, k, l;
32849 
32850   if (out == (tetgenio *) NULL) {
32851     strcpy(pbcfilename, b->outfilename);
32852     strcat(pbcfilename, ".pbc");
32853   }
32854 
32855   if (!b->quiet) {
32856     if (out == (tetgenio *) NULL) {
32857       printf("Writing %s.\n", pbcfilename);
32858     } else {
32859       printf("Writing pbc nodes.\n");
32860     }
32861   }
32862 
32863   // Avoid compilation warnings.
32864   outfile = (FILE *) NULL;
32865   pgo = (tetgenio::pbcgroup *) NULL;
32866   index = 0;
32867 
32868   if (out == (tetgenio *) NULL) {
32869     outfile = fopen(pbcfilename, "w");
32870     if (outfile == (FILE *) NULL) {
32871       printf("File I/O Error:  Cannot create file %s.\n", pbcfilename);
32872       terminatetetgen(1);
32873     }
32874     // Number of pbc groups.
32875     fprintf(outfile, "# number of PBCs.\n");
32876     fprintf(outfile, "%d\n\n", in->numberofpbcgroups);
32877   } else {
32878     out->numberofpbcgroups = in->numberofpbcgroups;
32879     // Allocate memory for 'out->pbcgrouplist'.
32880     out->pbcgrouplist = new tetgenio::pbcgroup[in->numberofpbcgroups];
32881     // (Next line was a bug, reported by Murry Nigel).
32882     if (out->pbcgrouplist == (tetgenio::pbcgroup *) NULL) {
32883       printf("Error:  Out of memory.\n");
32884       terminatetetgen(1);
32885     }
32886   }
32887 
32888   ptpairlist = new list(2 * sizeof(point *), NULL, 256);
32889   worklist = new int[points->items + 1];
32890   for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
32891 
32892   // Determine the first index (0 or 1).
32893   firstindex = b->zeroindex ? 0 : in->firstnumber;
32894   shift = 0; // Default no shiftment.
32895   if ((in->firstnumber == 1) && (firstindex == 0)) {
32896     shift = 1; // Shift the output indices by 1.
32897   }
32898 
32899   for (i = 0; i < in->numberofpbcgroups; i++) {
32900     // Group i.
32901     pgi = &(in->pbcgrouplist[i]);
32902     if (out == (tetgenio *) NULL) {
32903       fprintf(outfile, "# PBC %d\n", in->firstnumber + i);
32904       // Output facet markers.
32905       fprintf(outfile, "%d  %d\n", pgi->fmark1, pgi->fmark2);
32906       // Output transformation matrix.
32907       fprintf(outfile, "[\n");
32908       for (j = 0; j < 4; j++) {
32909         fprintf(outfile, "  %.12g %.12g %.12g %.12g\n", pgi->transmat[j][0],
32910                 pgi->transmat[j][1], pgi->transmat[j][2], pgi->transmat[j][3]);
32911       }
32912       fprintf(outfile, "]\n");
32913     } else {
32914       pgo = &(out->pbcgrouplist[i]);
32915       // Copy data from pgi to pgo.
32916       pgo->fmark1 = pgi->fmark1;
32917       pgo->fmark2 = pgi->fmark2;
32918       for (j = 0; j < 4; j++) {
32919         for (k = 0; k < 4; k++) pgo->transmat[j][k] = pgi->transmat[j][k];
32920       }
32921     }
32922 
32923     // Find the point pairs of group i.
32924     subfaces->traversalinit();
32925     faceloop.sh = shellfacetraverse(subfaces);
32926     while (faceloop.sh != (shellface *) NULL) {
32927       if (shellpbcgroup(faceloop) == i) {
32928         // It is in group i. Operate on it if it has pgi->fmark1.
32929         idx = shellmark(faceloop) - 1;
32930         if (in->facetmarkerlist[idx] == pgi->fmark1) {
32931           // Loop three edges of the subface.
32932           for (j = 0; j < 3; j++) {
32933             sspivot(faceloop, checkseg);
32934             // Loop two vertices of the edge.
32935             for (k = 0; k < 2; k++) {
32936               if (k == 0) pa = sorg(faceloop);
32937               else pa = sdest(faceloop);
32938               if (worklist[pointmark(pa)] == 0) {
32939                 pb = (point) NULL;
32940                 if (checkseg.sh != dummysh) {
32941                   // pa is on a segment. Find pb.
32942                   // Find the incident pbcgroup of checkseg.
32943                   idx = shellmark(checkseg) - 1;
32944                   for (l = idx2segpglist[idx]; l < idx2segpglist[idx + 1];
32945                        l++) {
32946                     pd = (pbcdata *)(* segpbcgrouptable)[segpglist[l]];
32947                     if (((pd->fmark[0] == pgi->fmark1) &&
32948                          (pd->fmark[1] == pgi->fmark2)) ||
32949                         ((pd->fmark[0] == pgi->fmark2) &&
32950                          (pd->fmark[1] == pgi->fmark1))) break;
32951                   }
32952 #ifdef SELF_CHECK
32953                   assert(l < idx2segpglist[idx + 1]);
32954 #endif
32955                   loc = getsegpbcsympoint(pa, &checkseg, sympt, &symseg,
32956                                           segpglist[l]);
32957                   if (loc != ONVERTEX) {
32958                     // Not found a match point! It may be caused by the
32959                     //   pair of input vertices don't have enough digits.
32960                     //   Choose a near vertex.
32961                     d1 = distance(sympt, sorg(symseg));
32962                     d2 = distance(sympt, sdest(symseg));
32963                     if (d1 > d2) sesymself(symseg);
32964                   }
32965                   pb = sorg(symseg);
32966                 } else {
32967                   // Operate on pa if it is inside the facet.
32968                   if (pointtype(pa) == FREESUBVERTEX) {
32969                     pb = point2pbcpt(pa);
32970                   }
32971                 }
32972                 if (pb != (point) NULL) {
32973                   // Add the pair (pa, pb) into list.
32974                   ptpair = (point *) ptpairlist->append(NULL);
32975                   ptpair[0] = pa;
32976                   ptpair[1] = pb;
32977                   // Mark pa (avoid to operate on it later).
32978                   worklist[pointmark(pa)] = 1;
32979                 }
32980               }
32981             }
32982             // Get the next edge.
32983             senextself(faceloop);
32984           }
32985         }
32986       }
32987       faceloop.sh = shellfacetraverse(subfaces);
32988     }
32989 
32990     // Output the list of pbc points.
32991     if (out == (tetgenio *) NULL) {
32992       fprintf(outfile, "%d\n", ptpairlist->len());
32993     } else {
32994       pgo->numberofpointpairs = ptpairlist->len();
32995       pgo->pointpairlist = new int[pgo->numberofpointpairs * 2];
32996       index = 0;
32997     }
32998     for (j = 0; j < ptpairlist->len(); j++) {
32999       ptpair = (point *)(* ptpairlist)[j];
33000       pa = ptpair[0];
33001       pb = ptpair[1];
33002       if (out == (tetgenio *) NULL) {
33003         fprintf(outfile, "  %4d %4d\n", pointmark(pa) - shift,
33004                 pointmark(pb) - shift);
33005       } else {
33006         pgo->pointpairlist[index++] = pointmark(pa) - shift;
33007         pgo->pointpairlist[index++] = pointmark(pb) - shift;
33008       }
33009       // Unmark pa.
33010       worklist[pointmark(pa)] = 0;
33011     }
33012     if (out == (tetgenio *) NULL) {
33013       fprintf(outfile, "\n");
33014     }
33015     ptpairlist->clear();
33016   }
33017 
33018   delete [] worklist;
33019   delete ptpairlist;
33020 
33021   if (out == (tetgenio *) NULL) {
33022     fprintf(outfile, "# Generated by %s\n", b->commandline);
33023     fclose(outfile);
33024   }
33025 }
33026 
33028 //                                                                           //
33029 // outsmesh()    Write surface mesh to a .smesh file, which can be read and  //
33030 //               tetrahedralized by TetGen.                                  //
33031 //                                                                           //
33032 // You can specify a filename (without suffix) in 'smfilename'. If you don't //
33033 // supply a filename (let smfilename be NULL), the default name stored in    //
33034 // 'tetgenbehavior' will be used.                                            //
33035 //                                                                           //
33037 
33038 void tetgenmesh::outsmesh(char* smfilename)
33039 {
33040   FILE *outfile;
33041   char nodfilename[FILENAMESIZE];
33042   char smefilename[FILENAMESIZE];
33043   face faceloop;
33044   point p1, p2, p3;
33045   int firstindex, shift;
33046   int bmark;
33047   int faceid, marker;
33048   int i;
33049 
33050   if (smfilename != (char *) NULL && smfilename[0] != '\0') {
33051     strcpy(smefilename, smfilename);
33052   } else if (b->outfilename[0] != '\0') {
33053     strcpy(smefilename, b->outfilename);
33054   } else {
33055     strcpy(smefilename, "unnamed");
33056   }
33057   strcpy(nodfilename, smefilename);
33058   strcat(smefilename, ".smesh");
33059   strcat(nodfilename, ".node");
33060 
33061   if (!b->quiet) {
33062     printf("Writing %s.\n", smefilename);
33063   }
33064   outfile = fopen(smefilename, "w");
33065   if (outfile == (FILE *) NULL) {
33066     printf("File I/O Error:  Cannot create file %s.\n", smefilename);
33067     return;
33068   }
33069 
33070   // Determine the first index (0 or 1).
33071   firstindex = b->zeroindex ? 0 : in->firstnumber;
33072   shift = 0; // Default no shiftment.
33073   if ((in->firstnumber == 1) && (firstindex == 0)) {
33074     shift = 1; // Shift the output indices by 1.
33075   }
33076 
33077   fprintf(outfile, "# %s.  TetGen's input file.\n", smefilename);
33078   fprintf(outfile, "\n# part 1: node list.\n");
33079   fprintf(outfile, "0  3  0  0  # nodes are found in %s.\n", nodfilename);
33080 
33081   marker = 0; // avoid compile warning.
33082   bmark = !b->nobound && in->facetmarkerlist;
33083 
33084   fprintf(outfile, "\n# part 2: facet list.\n");
33085   // Number of facets, boundary marker.
33086   fprintf(outfile, "%ld  %d\n", subfaces->items, bmark);
33087 
33088   subfaces->traversalinit();
33089   faceloop.sh = shellfacetraverse(subfaces);
33090   while (faceloop.sh != (shellface *) NULL) {
33091     p1 = sorg(faceloop);
33092     p2 = sdest(faceloop);
33093     p3 = sapex(faceloop);
33094     if (bmark) {
33095       faceid = shellmark(faceloop) - 1;
33096       if (faceid >= 0) {
33097         marker = in->facetmarkerlist[faceid];
33098       } else {
33099         marker = 0; // This subface must be added manually later.
33100       }
33101     }
33102     fprintf(outfile, "3    %4d  %4d  %4d", pointmark(p1) - shift,
33103             pointmark(p2) - shift, pointmark(p3) - shift);
33104     if (bmark) {
33105       fprintf(outfile, "    %d", marker);
33106     }
33107     fprintf(outfile, "\n");
33108     faceloop.sh = shellfacetraverse(subfaces);
33109   }
33110 
33111   // Copy input holelist.
33112   fprintf(outfile, "\n# part 3: hole list.\n");
33113   fprintf(outfile, "%d\n", in->numberofholes);
33114   for (i = 0; i < in->numberofholes; i++) {
33115     fprintf(outfile, "%d  %g  %g  %g\n", i + in->firstnumber,
33116             in->holelist[i * 3], in->holelist[i * 3 + 1],
33117             in->holelist[i * 3 + 2]);
33118   }
33119 
33120   // Copy input regionlist.
33121   fprintf(outfile, "\n# part 4: region list.\n");
33122   fprintf(outfile, "%d\n", in->numberofregions);
33123   for (i = 0; i < in->numberofregions; i++) {
33124     fprintf(outfile, "%d  %g  %g  %g  %d  %g\n", i + in->firstnumber,
33125             in->regionlist[i * 5], in->regionlist[i * 5 + 1],
33126             in->regionlist[i * 5 + 2], (int) in->regionlist[i * 5 + 3],
33127             in->regionlist[i * 5 + 4]);
33128   }
33129 
33130   fprintf(outfile, "# Generated by %s\n", b->commandline);
33131   fclose(outfile);
33132 }
33133 
33135 //                                                                           //
33136 // outmesh2medit()    Write mesh to a .mesh file, which can be read and      //
33137 //                    rendered by Medit (a free mesh viewer from INRIA).     //
33138 //                                                                           //
33139 // You can specify a filename (without suffix) in 'mfilename'.  If you don't //
33140 // supply a filename (let mfilename be NULL), the default name stored in     //
33141 // 'tetgenbehavior' will be used. The output file will have the suffix .mesh.//
33142 //                                                                           //
33144 
33145 void tetgenmesh::outmesh2medit(char* mfilename)
33146 {
33147   FILE *outfile;
33148   char mefilename[FILENAMESIZE];
33149   tetrahedron* tetptr;
33150   triface tface, tsymface;
33151   face segloop, checkmark;
33152   point ptloop, p1, p2, p3, p4;
33153   long faces;
33154   int pointnumber;
33155   int i;
33156 
33157   if (mfilename != (char *) NULL && mfilename[0] != '\0') {
33158     strcpy(mefilename, mfilename);
33159   } else if (b->outfilename[0] != '\0') {
33160     strcpy(mefilename, b->outfilename);
33161   } else {
33162     strcpy(mefilename, "unnamed");
33163   }
33164   strcat(mefilename, ".mesh");
33165 
33166   if (!b->quiet) {
33167     printf("Writing %s.\n", mefilename);
33168   }
33169   outfile = fopen(mefilename, "w");
33170   if (outfile == (FILE *) NULL) {
33171     printf("File I/O Error:  Cannot create file %s.\n", mefilename);
33172     return;
33173   }
33174 
33175   fprintf(outfile, "MeshVersionFormatted 1\n");
33176   fprintf(outfile, "\n");
33177   fprintf(outfile, "Dimension\n");
33178   fprintf(outfile, "3\n");
33179   fprintf(outfile, "\n");
33180 
33181   fprintf(outfile, "\n# Set of mesh vertices\n");
33182   fprintf(outfile, "Vertices\n");
33183   fprintf(outfile, "%ld\n", points->items);
33184 
33185   points->traversalinit();
33186   ptloop = pointtraverse();
33187   pointnumber = 1;                        // Medit need start number form 1.
33188   while (ptloop != (point) NULL) {
33189     // Point coordinates.
33190     fprintf(outfile, "%.17g  %.17g  %.17g", ptloop[0], ptloop[1], ptloop[2]);
33191     if (in->numberofpointattributes > 0) {
33192       // Write an attribute, ignore others if more than one.
33193       fprintf(outfile, "  %.17g\n", ptloop[3]);
33194     } else {
33195       fprintf(outfile, "    0\n");
33196     }
33197     setpointmark(ptloop, pointnumber);
33198     ptloop = pointtraverse();
33199     pointnumber++;
33200   }
33201 
33202   // Compute the number of edges.
33203   faces = (4l * tetrahedrons->items + hullsize) / 2l;
33204 
33205   fprintf(outfile, "\n# Set of Triangles\n");
33206   fprintf(outfile, "Triangles\n");
33207   fprintf(outfile, "%ld\n", faces);
33208 
33209   tetrahedrons->traversalinit();
33210   tface.tet = tetrahedrontraverse();
33211   // To loop over the set of faces, loop over all tetrahedra, and look at
33212   //   the four faces of each tetrahedron. If there isn't another tetrahedron
33213   //   adjacent to the face, operate on the face.  If there is another adj-
33214   //   acent tetrahedron, operate on the face only if the current tetrahedron
33215   //   has a smaller pointer than its neighbor.  This way, each face is
33216   //   considered only once.
33217   while (tface.tet != (tetrahedron *) NULL) {
33218     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33219       sym(tface, tsymface);
33220       if (tface.tet < tsymface.tet || tsymface.tet == dummytet) {
33221         p1 = org (tface);
33222         p2 = dest(tface);
33223         p3 = apex(tface);
33224         fprintf(outfile, "%5d  %5d  %5d",
33225                 pointmark(p1), pointmark(p2), pointmark(p3));
33226         fprintf(outfile, "    0\n");
33227       }
33228     }
33229     tface.tet = tetrahedrontraverse();
33230   }
33231 
33232   fprintf(outfile, "\n# Set of Tetrahedra\n");
33233   fprintf(outfile, "Tetrahedra\n");
33234   fprintf(outfile, "%ld\n", tetrahedrons->items);
33235 
33236   tetrahedrons->traversalinit();
33237   tetptr = tetrahedrontraverse();
33238   while (tetptr != (tetrahedron *) NULL) {
33239     p1 = (point) tetptr[4];
33240     p2 = (point) tetptr[5];
33241     p3 = (point) tetptr[6];
33242     p4 = (point) tetptr[7];
33243     fprintf(outfile, "%5d  %5d  %5d  %5d",
33244             pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33245     if (in->numberoftetrahedronattributes > 0) {
33246       fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
33247     } else {
33248       fprintf(outfile, "  0");
33249     }
33250     fprintf(outfile, "\n");
33251     tetptr = tetrahedrontraverse();
33252   }
33253 
33254   fprintf(outfile, "\nCorners\n");
33255   fprintf(outfile, "%d\n", in->numberofpoints);
33256 
33257   for (i = 0; i < in->numberofpoints; i++) {
33258     fprintf(outfile, "%4d\n", i + 1);
33259   }
33260 
33261   if (b->useshelles) {
33262     fprintf(outfile, "\nEdges\n");
33263     fprintf(outfile, "%ld\n", subsegs->items);
33264 
33265     subsegs->traversalinit();
33266     segloop.sh = shellfacetraverse(subsegs);
33267     while (segloop.sh != (shellface *) NULL) {
33268       p1 = sorg(segloop);
33269       p2 = sdest(segloop);
33270       fprintf(outfile, "%5d  %5d", pointmark(p1), pointmark(p2));
33271       fprintf(outfile, "    0\n");
33272       segloop.sh = shellfacetraverse(subsegs);
33273     }
33274   }
33275 
33276   fprintf(outfile, "\nEnd\n");
33277   fclose(outfile);
33278 }
33279 
33281 //                                                                           //
33282 // outmesh2gid()    Write mesh to a .ele.msh file and a .face.msh file,      //
33283 //                  which can be imported and rendered by Gid.               //
33284 //                                                                           //
33285 // You can specify a filename (without suffix) in 'gfilename'.  If you don't //
33286 // supply a filename (let gfilename be NULL), the default name stored in     //
33287 // 'tetgenbehavior' will be used. The suffixes (.ele.msh and .face.msh) will //
33288 // be automatically added.                                                   //
33289 //                                                                           //
33291 
33292 void tetgenmesh::outmesh2gid(char* gfilename)
33293 {
33294   FILE *outfile;
33295   char gidfilename[FILENAMESIZE];
33296   tetrahedron* tetptr;
33297   triface tface, tsymface;
33298   face sface;
33299   point ptloop, p1, p2, p3, p4;
33300   int pointnumber;
33301   int elementnumber;
33302 
33303   if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33304     strcpy(gidfilename, gfilename);
33305   } else if (b->outfilename[0] != '\0') {
33306     strcpy(gidfilename, b->outfilename);
33307   } else {
33308     strcpy(gidfilename, "unnamed");
33309   }
33310   strcat(gidfilename, ".ele.msh");
33311 
33312   if (!b->quiet) {
33313     printf("Writing %s.\n", gidfilename);
33314   }
33315   outfile = fopen(gidfilename, "w");
33316   if (outfile == (FILE *) NULL) {
33317     printf("File I/O Error:  Cannot create file %s.\n", gidfilename);
33318     return;
33319   }
33320 
33321   fprintf(outfile, "mesh dimension = 3 elemtype tetrahedron nnode = 4\n");
33322   fprintf(outfile, "coordinates\n");
33323 
33324   points->traversalinit();
33325   ptloop = pointtraverse();
33326   pointnumber = 1;                        // Gid need start number form 1.
33327   while (ptloop != (point) NULL) {
33328     // Point coordinates.
33329     fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
33330             ptloop[0], ptloop[1], ptloop[2]);
33331     if (in->numberofpointattributes > 0) {
33332       // Write an attribute, ignore others if more than one.
33333       fprintf(outfile, "  %.17g", ptloop[3]);
33334     }
33335     fprintf(outfile, "\n");
33336     setpointmark(ptloop, pointnumber);
33337     ptloop = pointtraverse();
33338     pointnumber++;
33339   }
33340 
33341   fprintf(outfile, "end coordinates\n");
33342   fprintf(outfile, "elements\n");
33343 
33344   tetrahedrons->traversalinit();
33345   tetptr = tetrahedrontraverse();
33346   elementnumber = 1;
33347   while (tetptr != (tetrahedron *) NULL) {
33348     p1 = (point) tetptr[4];
33349     p2 = (point) tetptr[5];
33350     p3 = (point) tetptr[6];
33351     p4 = (point) tetptr[7];
33352     fprintf(outfile, "%5d  %5d %5d %5d %5d", elementnumber,
33353             pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33354     if (in->numberoftetrahedronattributes > 0) {
33355       fprintf(outfile, "  %.17g", elemattribute(tetptr, 0));
33356     }
33357     fprintf(outfile, "\n");
33358     tetptr = tetrahedrontraverse();
33359     elementnumber++;
33360   }
33361 
33362   fprintf(outfile, "end elements\n");
33363   fclose(outfile);
33364 
33365   if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33366     strcpy(gidfilename, gfilename);
33367   } else if (b->outfilename[0] != '\0') {
33368     strcpy(gidfilename, b->outfilename);
33369   } else {
33370     strcpy(gidfilename, "unnamed");
33371   }
33372   strcat(gidfilename, ".face.msh");
33373 
33374   if (!b->quiet) {
33375     printf("Writing %s.\n", gidfilename);
33376   }
33377   outfile = fopen(gidfilename, "w");
33378   if (outfile == (FILE *) NULL) {
33379     printf("File I/O Error:  Cannot create file %s.\n", gidfilename);
33380     return;
33381   }
33382 
33383   fprintf(outfile, "mesh dimension = 3 elemtype triangle nnode = 3\n");
33384   fprintf(outfile, "coordinates\n");
33385 
33386   points->traversalinit();
33387   ptloop = pointtraverse();
33388   pointnumber = 1;                        // Gid need start number form 1.
33389   while (ptloop != (point) NULL) {
33390     // Point coordinates.
33391     fprintf(outfile, "%4d  %.17g %.17g %.17g", pointnumber,
33392             ptloop[0], ptloop[1], ptloop[2]);
33393     if (in->numberofpointattributes > 0) {
33394       // Write an attribute, ignore others if more than one.
33395       fprintf(outfile, "  %.17g", ptloop[3]);
33396     }
33397     fprintf(outfile, "\n");
33398     setpointmark(ptloop, pointnumber);
33399     ptloop = pointtraverse();
33400     pointnumber++;
33401   }
33402 
33403   fprintf(outfile, "end coordinates\n");
33404   fprintf(outfile, "elements\n");
33405 
33406   tetrahedrons->traversalinit();
33407   tface.tet = tetrahedrontraverse();
33408   elementnumber = 1;
33409   while (tface.tet != (tetrahedron *) NULL) {
33410     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33411       sym(tface, tsymface);
33412       if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33413         p1 = org(tface);
33414         p2 = dest(tface);
33415         p3 = apex(tface);
33416         if (tsymface.tet == dummytet) {
33417           // It's a hull face, output it.
33418           fprintf(outfile, "%5d   %d  %d  %d\n", elementnumber,
33419                   pointmark(p1), pointmark(p2), pointmark(p3));
33420           elementnumber++;
33421         } else if (b->useshelles) {
33422           // Only output it if it's a subface.
33423           tspivot(tface, sface);
33424           if (sface.sh != dummysh) {
33425             fprintf(outfile, "%5d   %d  %d  %d\n", elementnumber,
33426                     pointmark(p1), pointmark(p2), pointmark(p3));
33427             elementnumber++;
33428           }
33429         }
33430       }
33431     }
33432     tface.tet = tetrahedrontraverse();
33433   }
33434 
33435   fprintf(outfile, "end elements\n");
33436   fclose(outfile);
33437 }
33438 
33440 //                                                                           //
33441 // outmesh2off()    Write the mesh to an .off file.                          //
33442 //                                                                           //
33443 // .off, the Object File Format, is one of the popular file formats from the //
33444 // Geometry Center's Geomview package (http://www.geomview.org).             //
33445 //                                                                           //
33447 
33448 void tetgenmesh::outmesh2off(char* ofilename)
33449 {
33450   FILE *outfile;
33451   char offfilename[FILENAMESIZE];
33452   triface tface, tsymface;
33453   point ptloop, p1, p2, p3;
33454   long faces;
33455   int shift;
33456 
33457   if (ofilename != (char *) NULL && ofilename[0] != '\0') {
33458     strcpy(offfilename, ofilename);
33459   } else if (b->outfilename[0] != '\0') {
33460     strcpy(offfilename, b->outfilename);
33461   } else {
33462     strcpy(offfilename, "unnamed");
33463   }
33464   strcat(offfilename, ".off");
33465 
33466   if (!b->quiet) {
33467     printf("Writing %s.\n", offfilename);
33468   }
33469   outfile = fopen(offfilename, "w");
33470   if (outfile == (FILE *) NULL) {
33471     printf("File I/O Error:  Cannot create file %s.\n", offfilename);
33472     return;
33473   }
33474 
33475   // Calculate the number of triangular faces in the tetrahedral mesh.
33476   faces = (4l * tetrahedrons->items + hullsize) / 2l;
33477 
33478   // Number of points, faces, and edges(not used, here show hullsize).
33479   fprintf(outfile, "OFF\n%ld  %ld  %ld\n", points->items, faces, hullsize);
33480 
33481   // Write the points.
33482   points->traversalinit();
33483   ptloop = pointtraverse();
33484   while (ptloop != (point) NULL) {
33485     fprintf(outfile, " %.17g  %.17g  %.17g\n",ptloop[0], ptloop[1], ptloop[2]);
33486     ptloop = pointtraverse();
33487   }
33488 
33489   // OFF always use zero as the first index.
33490   shift = in->firstnumber == 1 ? 1 : 0;
33491 
33492   tetrahedrons->traversalinit();
33493   tface.tet = tetrahedrontraverse();
33494   // To loop over the set of faces, loop over all tetrahedra, and look at
33495   //   the four faces of each tetrahedron. If there isn't another tetrahedron
33496   //   adjacent to the face, operate on the face.  If there is another adj-
33497   //   acent tetrahedron, operate on the face only if the current tetrahedron
33498   //   has a smaller pointer than its neighbor.  This way, each face is
33499   //   considered only once.
33500   while (tface.tet != (tetrahedron *) NULL) {
33501     for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33502       sym(tface, tsymface);
33503       if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33504         p1 = org(tface);
33505         p2 = dest(tface);
33506         p3 = apex(tface);
33507         // Face number, indices of three vertexs.
33508         fprintf(outfile, "3   %4d  %4d  %4d\n", pointmark(p1) - shift,
33509                 pointmark(p2) - shift, pointmark(p3) - shift);
33510       }
33511     }
33512     tface.tet = tetrahedrontraverse();
33513   }
33514 
33515   fprintf(outfile, "# Generated by %s\n", b->commandline);
33516   fclose(outfile);
33517 }
33518 
33519 //
33520 // End of I/O rouitnes
33521 //
33522 
33523 //
33524 // Begin of user interaction routines
33525 //
33526 
33528 //                                                                           //
33529 // internalerror()    Ask the user to send me the defective product.  Exit.  //
33530 //                                                                           //
33532 
33533 void tetgenmesh::internalerror()
33534 {
33535   printf("  Please report this bug to sihang@mail.berlios.de. Include the\n");
33536   printf("    message above, your input data set, and the exact command\n");
33537   printf("    line you used to run this program, thank you.\n");
33538   terminatetetgen(2);
33539 }
33540 
33542 //                                                                           //
33543 // checkmesh()    Test the mesh for topological consistency.                 //
33544 //                                                                           //
33546 
33547 void tetgenmesh::checkmesh()
33548 {
33549   triface tetraloop;
33550   triface oppotet, oppooppotet;
33551   point tetorg, tetdest, tetapex, tetoppo;
33552   REAL oritest;
33553   int horrors;
33554 
33555   if (!b->quiet) {
33556     printf("  Checking consistency of mesh...\n");
33557   }
33558 
33559   horrors = 0;
33560   // Run through the list of tetrahedra, checking each one.
33561   tetrahedrons->traversalinit();
33562   tetraloop.tet = tetrahedrontraverse();
33563   while (tetraloop.tet != (tetrahedron *) NULL) {
33564     // Check all four faces of the tetrahedron.
33565     for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33566       tetorg = org(tetraloop);
33567       tetdest = dest(tetraloop);
33568       tetapex = apex(tetraloop);
33569       tetoppo = oppo(tetraloop);
33570       if (tetraloop.loc == 0) {             // Only test for inversion once.
33571         oritest = orient3d(tetorg, tetdest, tetapex, tetoppo);
33572         if (oritest >= 0.0) {
33573           printf("  !! !! %s ", oritest > 0.0 ? "Inverted" : "Degenerated");
33574           printtet(&tetraloop);
33575           printf("  orient3d = %.17g.\n", oritest);
33576           horrors++;
33577         }
33578       }
33579       // Find the neighboring tetrahedron on this face.
33580       sym(tetraloop, oppotet);
33581       if (oppotet.tet != dummytet) {
33582         // Check that the tetrahedron's neighbor knows it's a neighbor.
33583         sym(oppotet, oppooppotet);
33584         if ((tetraloop.tet != oppooppotet.tet)
33585             || (tetraloop.loc != oppooppotet.loc)) {
33586           printf("  !! !! Asymmetric tetra-tetra bond:\n");
33587           if (tetraloop.tet == oppooppotet.tet) {
33588             printf("   (Right tetrahedron, wrong orientation)\n");
33589           }
33590           printf("    First ");
33591           printtet(&tetraloop);
33592           printf("    Second (nonreciprocating) ");
33593           printtet(&oppotet);
33594           horrors++;
33595         }
33596       }
33597     }
33598     tetraloop.tet = tetrahedrontraverse();
33599   }
33600   if (horrors == 0) {
33601     if (!b->quiet) {
33602       printf("  In my studied opinion, the mesh appears to be consistent.\n");
33603     }
33604   } else if (horrors == 1) {
33605     printf("  !! !! !! !! Precisely one festering wound discovered.\n");
33606   } else {
33607     printf("  !! !! !! !! %d abominations witnessed.\n", horrors);
33608   }
33609 }
33610 
33612 //                                                                           //
33613 // checkshells()       Test the boundary mesh for topological consistency.   //
33614 //                                                                           //
33616 
33617 void tetgenmesh::checkshells()
33618 {
33619   triface oppotet, oppooppotet, testtet;
33620   face shloop, segloop, spin;
33621   face testsh, testseg, testshsh;
33622   point shorg, shdest, segorg, segdest;
33623   REAL checksign;
33624   bool same;
33625   int horrors;
33626   int i;
33627 
33628   if (!b->quiet) {
33629     printf("  Checking consistency of the mesh boundary...\n");
33630   }
33631   horrors = 0;
33632 
33633   // Run through the list of subfaces, checking each one.
33634   subfaces->traversalinit();
33635   shloop.sh = shellfacetraverse(subfaces);
33636   while (shloop.sh != (shellface *) NULL) {
33637     // Check two connected tetrahedra if they exist.
33638     shloop.shver = 0;
33639     stpivot(shloop, oppotet);
33640     if (oppotet.tet != dummytet) {
33641       tspivot(oppotet, testsh);
33642       if (testsh.sh != shloop.sh) {
33643         printf("  !! !! Wrong tetra-subface connection.\n");
33644         printf("    Tetra: ");
33645         printtet(&oppotet);
33646         printf("    Subface: ");
33647         printsh(&shloop);
33648         horrors++;
33649       }
33650       if (oppo(oppotet) != (point) NULL) {
33651         adjustedgering(oppotet, CCW);
33652         checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33653                              oppo(oppotet));
33654         if (checksign >= 0.0) {
33655           printf("  !! !! Wrong subface orientation.\n");
33656           printf("    Subface: ");
33657           printsh(&shloop);
33658           horrors++;
33659         }
33660       }
33661     }
33662     sesymself(shloop);
33663     stpivot(shloop, oppooppotet);
33664     if (oppooppotet.tet != dummytet) {
33665       tspivot(oppooppotet, testsh);
33666       if (testsh.sh != shloop.sh) {
33667         printf("  !! !! Wrong tetra-subface connection.\n");
33668         printf("    Tetra: ");
33669         printtet(&oppooppotet);
33670         printf("    Subface: ");
33671         printsh(&shloop);
33672         horrors++;
33673       }
33674       if (oppotet.tet != dummytet) {
33675         sym(oppotet, testtet);
33676         if (testtet.tet != oppooppotet.tet) {
33677           printf("  !! !! Wrong tetra-subface-tetra connection.\n");
33678           printf("    Tetra 1: ");
33679           printtet(&oppotet);
33680           printf("    Subface: ");
33681           printsh(&shloop);
33682           printf("    Tetra 2: ");
33683           printtet(&oppooppotet);
33684           horrors++;
33685         }
33686       }
33687       if (oppo(oppooppotet) != (point) NULL) {
33688         adjustedgering(oppooppotet, CCW);
33689         checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33690                              oppo(oppooppotet));
33691         if (checksign >= 0.0) {
33692           printf("  !! !! Wrong subface orientation.\n");
33693           printf("    Subface: ");
33694           printsh(&shloop);
33695           horrors++;
33696         }
33697       }
33698     }
33699     // Check connection between subfaces.
33700     shloop.shver = 0;
33701     for (i = 0; i < 3; i++) {
33702       shorg = sorg(shloop);
33703       shdest = sdest(shloop);
33704       sspivot(shloop, testseg);
33705       if (testseg.sh != dummysh) {
33706         segorg = sorg(testseg);
33707         segdest = sdest(testseg);
33708         same = ((shorg == segorg) && (shdest == segdest))
33709         || ((shorg == segdest) && (shdest == segorg));
33710         if (!same) {
33711           printf("  !! !! Wrong subface-subsegment connection.\n");
33712           printf("    Subface: ");
33713           printsh(&shloop);
33714           printf("    Subsegment: ");
33715           printsh(&testseg);
33716           horrors++;
33717         }
33718       }
33719       spivot(shloop, testsh);
33720       if (testsh.sh != dummysh) {
33721         segorg = sorg(testsh);
33722         segdest = sdest(testsh);
33723         same = ((shorg == segorg) && (shdest == segdest))
33724         || ((shorg == segdest) && (shdest == segorg));
33725         if (!same) {
33726           printf("  !! !! Wrong subface-subface connection.\n");
33727           printf("    Subface 1: ");
33728           printsh(&shloop);
33729           printf("    Subface 2: ");
33730           printsh(&testsh);
33731           horrors++;
33732         }
33733         spivot(testsh, testshsh);
33734         shorg = sorg(testshsh);
33735         shdest = sdest(testshsh);
33736         same = ((shorg == segorg) && (shdest == segdest))
33737         || ((shorg == segdest) && (shdest == segorg));
33738         if (!same) {
33739           printf("  !! !! Wrong subface-subface connection.\n");
33740           printf("    Subface 1: ");
33741           printsh(&testsh);
33742           printf("    Subface 2: ");
33743           printsh(&testshsh);
33744           horrors++;
33745         }
33746         if (testseg.sh == dummysh) {
33747           if (testshsh.sh != shloop.sh) {
33748             printf("  !! !! Wrong subface-subface connection.\n");
33749             printf("    Subface 1: ");
33750             printsh(&shloop);
33751             printf("    Subface 2: ");
33752             printsh(&testsh);
33753             horrors++;
33754           }
33755         }
33756       }
33757       senextself(shloop);
33758     }
33759     shloop.sh = shellfacetraverse(subfaces);
33760   }
33761 
33762   // Run through the list of subsegs, checking each one.
33763   subsegs->traversalinit();
33764   segloop.sh = shellfacetraverse(subsegs);
33765   while (segloop.sh != (shellface *) NULL) {
33766     segorg = sorg(segloop);
33767     segdest = sdest(segloop);
33768     spivot(segloop, testsh);
33769     if (testsh.sh == dummysh) {
33770       printf("  !! !! Wrong subsegment-subface connection.\n");
33771       printf("    Subsegment: ");
33772       printsh(&segloop);
33773       horrors++;
33774       segloop.sh = shellfacetraverse(subsegs);
33775       continue;
33776     }
33777     shorg = sorg(testsh);
33778     shdest = sdest(testsh);
33779     same = ((shorg == segorg) && (shdest == segdest))
33780         || ((shorg == segdest) && (shdest == segorg));
33781     if (!same) {
33782       printf("  !! !! Wrong subsegment-subface connection.\n");
33783       printf("    Subsegment : ");
33784       printsh(&segloop);
33785       printf("    Subface : ");
33786       printsh(&testsh);
33787       horrors++;
33788       segloop.sh = shellfacetraverse(subsegs);
33789       continue;
33790     }
33791     // Check the connection of face loop around this subsegment.
33792     spin = testsh;
33793     i = 0;
33794     do {
33795       spivotself(spin);
33796       shorg = sorg(spin);
33797       shdest = sdest(spin);
33798       same = ((shorg == segorg) && (shdest == segdest))
33799           || ((shorg == segdest) && (shdest == segorg));
33800       if (!same) {
33801         printf("  !! !! Wrong subsegment-subface connection.\n");
33802         printf("    Subsegment : ");
33803         printsh(&segloop);
33804         printf("    Subface : ");
33805         printsh(&testsh);
33806         horrors++;
33807         break;
33808       }
33809       i++;
33810     } while (spin.sh != testsh.sh && i < 1000);
33811     if (i >= 1000) {
33812       printf("  !! !! Wrong subsegment-subface connection.\n");
33813       printf("    Subsegment : ");
33814       printsh(&segloop);
33815       horrors++;
33816     }
33817     segloop.sh = shellfacetraverse(subsegs);
33818   }
33819   if (horrors == 0) {
33820     if (!b->quiet) {
33821       printf("  Mesh boundaries connected correctly.\n");
33822     }
33823   } else {
33824     printf("  !! !! !! !! %d boundary connection viewed with horror.\n",
33825            horrors);
33826     return;
33827   }
33828 }
33829 
33831 //                                                                           //
33832 // checkdelaunay()    Ensure that the mesh is constrained Delaunay.          //
33833 //                                                                           //
33834 // If 'flipqueue' is not NULL, non-locally Delaunay faces are saved in it.   //
33835 //                                                                           //
33837 
33838 void tetgenmesh::checkdelaunay(REAL eps, queue* flipqueue)
33839 {
33840   triface tetraloop;
33841   triface oppotet;
33842   face opposhelle;
33843   point tetorg, tetdest, tetapex, tetoppo;
33844   point oppooppo;
33845   enum fliptype fc;
33846   REAL sign;
33847   int shouldbedelaunay;
33848   int horrors;
33849 
33850   if (!b->quiet) {
33851     printf("  Checking Delaunay property of the mesh...\n");
33852   }
33853   horrors = 0;
33854   // Run through the list of triangles, checking each one.
33855   tetrahedrons->traversalinit();
33856   tetraloop.tet = tetrahedrontraverse();
33857   while (tetraloop.tet != (tetrahedron *) NULL) {
33858     // Check all four faces of the tetrahedron.
33859     for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33860       tetorg = org(tetraloop);
33861       tetdest = dest(tetraloop);
33862       tetapex = apex(tetraloop);
33863       tetoppo = oppo(tetraloop);
33864       sym(tetraloop, oppotet);
33865       oppooppo = oppo(oppotet);
33866       // Only do testif there is an adjoining tetrahedron whose pointer is
33867       //   larger (to ensure that each pair isn't tested twice).
33868       shouldbedelaunay = (oppotet.tet != dummytet)
33869                           && (tetoppo != (point) NULL)
33870                           && (oppooppo != (point) NULL)
33871                           && (tetraloop.tet < oppotet.tet);
33872       if (checksubfaces && shouldbedelaunay) {
33873         // If a shell face separates the tetrahedra, then the face is
33874         //   constrained, so no local Delaunay test should be done.
33875         tspivot(tetraloop, opposhelle);
33876         if (opposhelle.sh != dummysh){
33877           shouldbedelaunay = 0;
33878         }
33879       }
33880       if (shouldbedelaunay) {
33881         sign = insphere(tetdest, tetorg, tetapex, tetoppo, oppooppo);
33882         if ((sign > 0.0) && (eps > 0.0)) {
33883           if (iscospheric(tetdest, tetorg, tetapex, tetoppo, oppooppo, sign,
33884                           eps)) sign = 0.0;
33885         }
33886         if (sign > 0.0) {
33887           if (flipqueue) {
33888             enqueueflipface(tetraloop, flipqueue);
33889           } else {
33890             printf("  !! Non-locally Delaunay face (%d, %d, %d) ",
33891                    pointmark(tetorg), pointmark(tetdest), pointmark(tetapex));
33892             fc = categorizeface(tetraloop);
33893             switch (fc) {
33894             case T23: printf("\"T23\""); break;
33895             case T32: printf("\"T32\""); break;
33896             case T22: printf("\"T22\""); break;
33897             case T44: printf("\"T44\""); break;
33898             case N32: printf("\"N32\""); break;
33899             case N40: printf("\"N40\""); break;
33900             case FORBIDDENFACE:printf("\"FORBIDDENFACE\""); break;
33901             case FORBIDDENEDGE:printf("\"FORBIDDENEDGE\""); break;
33902             }
33903             printf("\n");
33904           }
33905           horrors++;
33906         }
33907       }
33908     }
33909     tetraloop.tet = tetrahedrontraverse();
33910   }
33911   if (flipqueue == (queue *) NULL) {
33912     if (horrors == 0) {
33913       if (!b->quiet) {
33914         printf("  The mesh is %s.\n",
33915                checksubfaces ? "constrained Delaunay" : "Delaunay");
33916       }
33917     } else {
33918       printf("  !! !! !! !! %d obscenities viewed with horror.\n", horrors);
33919     }
33920   }
33921 }
33922 
33924 //                                                                           //
33925 // checkconforming()    Ensure that the mesh is conforming Delaunay.         //
33926 //                                                                           //
33928 
33929 void tetgenmesh::checkconforming()
33930 {
33931   face segloop, shloop;
33932   int encsubsegs, encsubfaces;
33933 
33934   if (!b->quiet) {
33935     printf("  Checking conforming Delaunay property of mesh...\n");
33936   }
33937   encsubsegs = encsubfaces = 0;
33938   // Run through the list of subsegments, check each one.
33939   subsegs->traversalinit();
33940   segloop.sh = shellfacetraverse(subsegs);
33941   while (segloop.sh != (shellface *) NULL) {
33942     if (checkseg4encroach(&segloop, NULL, NULL, false)) {
33943       printf("  !! !! Non-conforming subsegment: (%d, %d)\n",
33944              pointmark(sorg(segloop)), pointmark(sdest(segloop)));
33945       encsubsegs++;
33946     }
33947     segloop.sh = shellfacetraverse(subsegs);
33948   }
33949   // Run through the list of subfaces, check each one.
33950   subfaces->traversalinit();
33951   shloop.sh = shellfacetraverse(subfaces);
33952   while (shloop.sh != (shellface *) NULL) {
33953     if (checksub4encroach(&shloop, NULL, false)) {
33954       printf("  !! !! Non-conforming subface: (%d, %d, %d)\n",
33955              pointmark(sorg(shloop)), pointmark(sdest(shloop)),
33956              pointmark(sapex(shloop)));
33957       encsubfaces++;
33958     }
33959     shloop.sh = shellfacetraverse(subfaces);
33960   }
33961   if (encsubsegs == 0 && encsubfaces == 0) {
33962     if (!b->quiet) {
33963       printf("  The mesh is conforming Delaunay.\n");
33964     }
33965   } else {
33966     if (encsubsegs > 0) {
33967       printf("  !! !! %d subsegments are non-conforming.\n", encsubsegs);
33968     }
33969     if (encsubfaces > 0) {
33970       printf("  !! !! %d subfaces are non-conforming.\n", encsubfaces);
33971     }
33972   }
33973 }
33974 
33976 //                                                                           //
33977 // algorithmicstatistics()    Print statistics about the mesh algorithms.    //
33978 //                                                                           //
33980 
33981 #ifdef SELF_CHECK
33982 
33983 void tetgenmesh::algorithmicstatistics()
33984 {
33985   /*
33986   printf("Algorithmic statistics:\n\n");
33987   printf("  Point location millisecond:  %g\n", (REAL) tloctime * 1e+3);
33988   printf("  Flip millisecond:  %g\n", (REAL) tfliptime * 1e+3);
33989   if (b->plc || b->refine) {
33990     printf("  Number of facet above points calculations: %ld\n", abovecount);
33991   }
33992   if (b->plc) {
33993     printf("  Segment split rules: R1 %ld, R2 %ld, R3 %ld\n", r1count, r2count,
33994            r3count);
33995   }
33996   if (b->quality) {
33997     printf("  Bowyer-Watson insertions: seg %ld, sub %ld, vol %ld.\n",
33998            bowatsegcount, bowatsubcount, bowatvolcount);
33999     printf("  Bowyer-Watson corrections: seg %ld, sub %ld, vol %ld\n",
34000            updsegcount, updsubcount, updvolcount);
34001     printf("  Bowyer-Watson failures: seg %ld, sub %ld, vol %ld\n",
34002            failsegcount, failsubcount, failvolcount);
34003     printf("  Number of repair flips: %ld.\n", repairflipcount);
34004     printf("  Number of circumcenters outside Bowat-cav.: %ld.\n",
34005            outbowatcircumcount);
34006     if (b->conformdel) {
34007       printf("  Segment split rules: R2 %ld, R3 %ld\n", r2count, r3count);
34008       printf("  Number of CDT enforcement points: %ld.\n", cdtenforcesegpts);
34009     }
34010     printf("  Number of Rejections: seg %ld, sub %ld, tet %ld.\n", rejsegpts,
34011            rejsubpts, rejtetpts);
34012     if (b->optlevel) {
34013       printf(
34014       "  Optimization flips: f32 %ld, f44 %ld, f56 %ld, f68 %ld, fnm %ld.\n",
34015              optcount[3], optcount[4], optcount[5], optcount[6], optcount[9]);
34016       printf("  Optimization segment deletions: %ld.\n", optcount[1]);
34017     }
34018   }
34019   printf("\n");
34020   */
34021 }
34022 
34023 #endif // #ifdef SELF_CHECK
34024 
34026 //                                                                           //
34027 // qualitystatistics()    Print statistics about the quality of the mesh.    //
34028 //                                                                           //
34030 
34031 void tetgenmesh::qualitystatistics()
34032 {
34033   triface tetloop, neightet;
34034   point p[4];
34035   char sbuf[128];
34036   REAL radiusratiotable[12];
34037   REAL aspectratiotable[12];
34038   REAL A[4][4], rhs[4], D;
34039   REAL V[6][3], N[4][3], H[4]; // edge-vectors, face-normals, face-heights.
34040   REAL edgelength[6], alldihed[6], faceangle[3];
34041   REAL shortest, longest;
34042   REAL smallestvolume, biggestvolume;
34043   REAL smallestdiangle, biggestdiangle;
34044   REAL smallestfaangle, biggestfaangle;
34045   REAL tetvol, minaltitude;
34046   REAL cirradius, minheightinv; // insradius;
34047   REAL shortlen, longlen;
34048   REAL tetaspect, tetradius;
34049   REAL smalldiangle, bigdiangle;
34050   REAL smallfaangle, bigfaangle;
34051   int radiustable[12];
34052   int aspecttable[16];
34053   int dihedangletable[18];
34054   int faceangletable[18];
34055   int indx[4];
34056   int radiusindex;
34057   int aspectindex;
34058   int tendegree;
34059   int i, j;
34060 
34061   smallfaangle = 0.0;
34062   bigfaangle = 0.0;
34063 
34064   printf("Mesh quality statistics:\n\n");
34065 
34066   // Avoid compile warnings.
34067   shortlen = longlen = 0.0;
34068   smalldiangle = bigdiangle = 0.0;
34069 
34070   radiusratiotable[0]  =    0.707;    radiusratiotable[1]  =     1.0;
34071   radiusratiotable[2]  =      1.1;    radiusratiotable[3]  =     1.2;
34072   radiusratiotable[4]  =      1.4;    radiusratiotable[5]  =     1.6;
34073   radiusratiotable[6]  =      1.8;    radiusratiotable[7]  =     2.0;
34074   radiusratiotable[8]  =      2.5;    radiusratiotable[9]  =     3.0;
34075   radiusratiotable[10] =     10.0;    radiusratiotable[11] =     0.0;
34076 
34077   aspectratiotable[0]  =      1.5;    aspectratiotable[1]  =     2.0;
34078   aspectratiotable[2]  =      2.5;    aspectratiotable[3]  =     3.0;
34079   aspectratiotable[4]  =      4.0;    aspectratiotable[5]  =     6.0;
34080   aspectratiotable[6]  =     10.0;    aspectratiotable[7]  =    15.0;
34081   aspectratiotable[8]  =     25.0;    aspectratiotable[9]  =    50.0;
34082   aspectratiotable[10] =    100.0;    aspectratiotable[11] =     0.0;
34083 
34084   for (i = 0; i < 12; i++) radiustable[i] = 0;
34085   for (i = 0; i < 12; i++) aspecttable[i] = 0;
34086   for (i = 0; i < 18; i++) dihedangletable[i] = 0;
34087   for (i = 0; i < 18; i++) faceangletable[i] = 0;
34088 
34089   minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
34090   minaltitude = minaltitude * minaltitude;
34091   shortest = minaltitude;
34092   longest = 0.0;
34093   smallestvolume = minaltitude;
34094   biggestvolume = 0.0;
34095   smallestdiangle = smallestfaangle = 180.0;
34096   biggestdiangle = biggestfaangle = 0.0;
34097 
34098   // Loop all elements, calculate quality parameters for each element.
34099   tetrahedrons->traversalinit();
34100   tetloop.tet = tetrahedrontraverse();
34101   while (tetloop.tet != (tetrahedron *) NULL) {
34102 
34103     // Get four vertices: p0, p1, p2, p3.
34104     for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i];
34105     // Set the edge vectors: V[0], ..., V[5]
34106     for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i]; // V[0]: p3->p0.
34107     for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i]; // V[1]: p3->p1.
34108     for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i]; // V[2]: p3->p2.
34109     for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i]; // V[3]: p0->p1.
34110     for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i]; // V[4]: p1->p2.
34111     for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i]; // V[5]: p2->p0.
34112     // Set the matrix A = [V[0], V[1], V[2]]^T.
34113     for (j = 0; j < 3; j++) {
34114       for (i = 0; i < 3; i++) A[j][i] = V[j][i];
34115     }
34116     // Decompose A just once.
34117     lu_decmp(A, 3, indx, &D, 0);
34118     // Get the tet volume.
34119     tetvol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
34120     // Get the three faces normals.
34121     for (j = 0; j < 3; j++) {
34122       for (i = 0; i < 3; i++) rhs[i] = 0.0;
34123       rhs[j] = 1.0;  // Positive means the inside direction
34124       lu_solve(A, 3, indx, rhs, 0);
34125       for (i = 0; i < 3; i++) N[j][i] = rhs[i];
34126     }
34127     // Get the fourth face normal by summing up the first three.
34128     for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
34129     // Get the radius of the circumsphere.
34130     for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]);
34131     lu_solve(A, 3, indx, rhs, 0);
34132     cirradius = sqrt(dot(rhs, rhs));
34133     // Normalize the face normals.
34134     for (i = 0; i < 4; i++) {
34135       // H[i] is the inverse of height of its corresponding face.
34136       H[i] = sqrt(dot(N[i], N[i]));
34137       for (j = 0; j < 3; j++) N[i][j] /= H[i];
34138     }
34139     // Get the radius of the inscribed sphere.
34140     // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]);
34141     // Get the biggest H[i] (corresponding to the smallest height).
34142     minheightinv = H[0];
34143     for (i = 1; i < 3; i++) {
34144       if (H[i] > minheightinv) minheightinv = H[i];
34145     }
34146     // Get the squares of the edge lengthes.
34147     for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
34148     // Get the dihedrals (in degree) at each edges.
34149     j = 0;
34150     for (i = 1; i < 4; i++) {
34151       alldihed[j] = -dot(N[0], N[i]); // Edge cd, bd, bc.
34152       if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34153       else if (alldihed[j] > 1.0) alldihed[j] = 1;
34154       alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34155       j++;
34156     }
34157     for (i = 2; i < 4; i++) {
34158       alldihed[j] = -dot(N[1], N[i]); // Edge ad, ac.
34159       if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34160       else if (alldihed[j] > 1.0) alldihed[j] = 1;
34161       alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34162       j++;
34163     }
34164     alldihed[j] = -dot(N[2], N[3]); // Edge ab.
34165     if (alldihed[j] < -1.0) alldihed[j] = -1; // Rounding.
34166     else if (alldihed[j] > 1.0) alldihed[j] = 1;
34167     alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34168 
34169     // Calculate the longest and shortest edge length.
34170     for (i = 0; i < 6; i++) {
34171       if (i == 0) {
34172         shortlen = longlen = edgelength[i];
34173       } else {
34174         shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen;
34175         longlen  = edgelength[i] > longlen  ? edgelength[i] : longlen;
34176       }
34177       if (edgelength[i] > longest) {
34178         longest = edgelength[i];
34179       }
34180       if (edgelength[i] < shortest) {
34181         shortest = edgelength[i];
34182       }
34183     }
34184 
34185     // Calculate the largest and smallest volume.
34186     if (tetvol < smallestvolume) {
34187       smallestvolume = tetvol;
34188     }
34189     if (tetvol > biggestvolume) {
34190       biggestvolume = tetvol;
34191     }
34192 
34193     // Calculate the largest and smallest dihedral angles.
34194     for (i = 0; i < 6; i++) {
34195       if (i == 0) {
34196         smalldiangle = bigdiangle = alldihed[i];
34197       } else {
34198         smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle;
34199         bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle;
34200       }
34201       if (alldihed[i] < smallestdiangle) {
34202         smallestdiangle = alldihed[i];
34203       }
34204       if (alldihed[i] > biggestdiangle) {
34205         biggestdiangle = alldihed[i];
34206       }
34207     }
34208     // Accumulate the corresponding number in the dihedral angle histogram.
34209     if (smalldiangle < 5.0) {
34210       tendegree = 0;
34211     } else if (smalldiangle >= 5.0 && smalldiangle < 10.0) {
34212       tendegree = 1;
34213     } else if (smalldiangle >= 80.0 && smalldiangle < 110.0) {
34214       tendegree = 9; // Angles between 80 to 110 degree are in one entry.
34215     } else {
34216       tendegree = (int) (smalldiangle / 10.);
34217       if (smalldiangle < 80.0) {
34218         tendegree++;  // In the left column.
34219       } else {
34220         tendegree--;  // In the right column.
34221       }
34222     }
34223     dihedangletable[tendegree]++;
34224     if (bigdiangle >= 80.0 && bigdiangle < 110.0) {
34225       tendegree = 9; // Angles between 80 to 110 degree are in one entry.
34226     } else if (bigdiangle >= 170.0 && bigdiangle < 175.0) {
34227       tendegree = 16;
34228     } else if (bigdiangle >= 175.0) {
34229       tendegree = 17;
34230     } else {
34231       tendegree = (int) (bigdiangle / 10.);
34232       if (bigdiangle < 80.0) {
34233         tendegree++;  // In the left column.
34234       } else {
34235         tendegree--;  // In the right column.
34236       }
34237     }
34238     dihedangletable[tendegree]++;
34239 
34240     // Calulate the largest and smallest face angles.
34241     tetloop.ver = 0;
34242     for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
34243       sym(tetloop, neightet);
34244       // Only do the calulation once for a face.
34245       if ((neightet.tet == dummytet) || (tetloop.tet < neightet.tet)) {
34246         p[0] = org(tetloop);
34247         p[1] = dest(tetloop);
34248         p[2] = apex(tetloop);
34249         faceangle[0] = interiorangle(p[0], p[1], p[2], NULL);
34250         faceangle[1] = interiorangle(p[1], p[2], p[0], NULL);
34251         faceangle[2] = PI - (faceangle[0] + faceangle[1]);
34252         // Translate angles into degrees.
34253         for (i = 0; i < 3; i++) {
34254           faceangle[i] = (faceangle[i] * 180.0) / PI;
34255         }
34256         // Calculate the largest and smallest face angles.
34257         for (i = 0; i < 3; i++) {
34258           if (i == 0) {
34259             smallfaangle = bigfaangle = faceangle[i];
34260           } else {
34261             smallfaangle = faceangle[i] < smallfaangle ?
34262               faceangle[i] : smallfaangle;
34263             bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle;
34264           }
34265           if (faceangle[i] < smallestfaangle) {
34266             smallestfaangle = faceangle[i];
34267           }
34268           if (faceangle[i] > biggestfaangle) {
34269             biggestfaangle = faceangle[i];
34270           }
34271         }
34272         tendegree = (int) (smallfaangle / 10.);
34273         faceangletable[tendegree]++;
34274         tendegree = (int) (bigfaangle / 10.);
34275         faceangletable[tendegree]++;
34276       }
34277     }
34278 
34279     // Calculate aspect ratio and radius-edge ratio for this element.
34280     tetradius = cirradius / sqrt(shortlen);
34281     // tetaspect = sqrt(longlen) / (2.0 * insradius);
34282     tetaspect = sqrt(longlen) * minheightinv;
34283     aspectindex = 0;
34284     while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) {
34285       aspectindex++;
34286     }
34287     aspecttable[aspectindex]++;
34288     radiusindex = 0;
34289     while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) {
34290       radiusindex++;
34291     }
34292     radiustable[radiusindex]++;
34293 
34294     tetloop.tet = tetrahedrontraverse();
34295   }
34296 
34297   shortest = sqrt(shortest);
34298   longest = sqrt(longest);
34299   minaltitude = sqrt(minaltitude);
34300 
34301   printf("  Smallest volume: %16.5g   |  Largest volume: %16.5g\n",
34302          smallestvolume, biggestvolume);
34303   printf("  Shortest edge:   %16.5g   |  Longest edge:   %16.5g\n",
34304          shortest, longest);
34305   sprintf(sbuf, "%.17g", biggestfaangle);
34306   if (strlen(sbuf) > 8) {
34307     sbuf[8] = '\0';
34308   }
34309   printf("  Smallest facangle: %14.5g   |  Largest facangle:       %s\n",
34310          smallestfaangle, sbuf);
34311   sprintf(sbuf, "%.17g", biggestdiangle);
34312   if (strlen(sbuf) > 8) {
34313     sbuf[8] = '\0';
34314   }
34315   printf("  Smallest dihedral: %14.5g   |  Largest dihedral:       %s\n\n",
34316          smallestdiangle, sbuf);
34317 
34318   /*
34319   printf("  Radius-edge ratio histogram:\n");
34320   printf("         < %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34321          radiusratiotable[0], radiustable[0], radiusratiotable[5],
34322          radiusratiotable[6], radiustable[6]);
34323   for (i = 1; i < 5; i++) {
34324     printf("  %6.6g - %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34325            radiusratiotable[i - 1], radiusratiotable[i], radiustable[i],
34326            radiusratiotable[i + 5], radiusratiotable[i + 6],
34327            radiustable[i + 6]);
34328   }
34329   printf("  %6.6g - %-6.6g    :  %8d      | %6.6g -            :  %8d\n",
34330          radiusratiotable[4], radiusratiotable[5], radiustable[5],
34331          radiusratiotable[10], radiustable[11]);
34332   printf("  (A tetrahedron's radius-edge ratio is its radius of ");
34333   printf("circumsphere divided\n");
34334   printf("    by its shortest edge length)\n\n");
34335   */
34336 
34337   printf("  Aspect ratio histogram:\n");
34338   printf("         < %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34339          aspectratiotable[0], aspecttable[0], aspectratiotable[5],
34340          aspectratiotable[6], aspecttable[6]);
34341   for (i = 1; i < 5; i++) {
34342     printf("  %6.6g - %-6.6g    :  %8d      | %6.6g - %-6.6g     :  %8d\n",
34343            aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i],
34344            aspectratiotable[i + 5], aspectratiotable[i + 6],
34345            aspecttable[i + 6]);
34346   }
34347   printf("  %6.6g - %-6.6g    :  %8d      | %6.6g -            :  %8d\n",
34348          aspectratiotable[4], aspectratiotable[5], aspecttable[5],
34349          aspectratiotable[10], aspecttable[11]);
34350   printf("  (A tetrahedron's aspect ratio is its longest edge length");
34351   printf(" divided by its\n");
34352   printf("    smallest side height)\n\n");
34353 
34354   printf("  Face angle histogram:\n");
34355   for (i = 0; i < 9; i++) {
34356     printf("    %3d - %3d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34357            i * 10, i * 10 + 10, faceangletable[i],
34358            i * 10 + 90, i * 10 + 100, faceangletable[i + 9]);
34359   }
34360   if (minfaceang != PI) {
34361     printf("  Minimum input face angle is %g (degree).\n",
34362            minfaceang / PI * 180.0);
34363   }
34364   printf("\n");
34365 
34366   printf("  Dihedral angle histogram:\n");
34367   // Print the three two rows:
34368   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34369          0, 5, dihedangletable[0], 80, 110, dihedangletable[9]);
34370   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34371          5, 10, dihedangletable[1], 110, 120, dihedangletable[10]);
34372   // Print the third to seventh rows.
34373   for (i = 2; i < 7; i++) {
34374     printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34375            (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i],
34376            (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]);
34377   }
34378   // Print the last two rows.
34379   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34380          60, 70, dihedangletable[7], 170, 175, dihedangletable[16]);
34381   printf("     %3d - %2d degrees:  %8d      |    %3d - %3d degrees:  %8d\n",
34382          70, 80, dihedangletable[8], 175, 180, dihedangletable[17]);
34383   if (minfacetdihed != PI) {
34384     printf("  Minimum input facet dihedral angle is %g (degree).\n",
34385            minfacetdihed / PI * 180.0);
34386   }
34387   printf("\n");
34388 }
34389 
34391 //                                                                           //
34392 // statistics()    Print all sorts of cool facts.                            //
34393 //                                                                           //
34395 
34396 void tetgenmesh::statistics()
34397 {
34398   printf("\nStatistics:\n\n");
34399   printf("  Input points: %d\n", in->numberofpoints + jettisoninverts);
34400   if (b->refine) {
34401     printf("  Input tetrahedra: %d\n", in->numberoftetrahedra);
34402   }
34403   if (b->plc) {
34404     printf("  Input facets: %d\n", in->numberoffacets);
34405     printf("  Input segments: %ld\n", insegments);
34406     printf("  Input holes: %d\n", in->numberofholes);
34407     printf("  Input regions: %d\n", in->numberofregions);
34408   }
34409 
34410   printf("\n  Mesh points: %ld\n", points->items);
34411   printf("  Mesh tetrahedra: %ld\n", tetrahedrons->items);
34412   if (b->plc || b->refine) {
34413     printf("  Mesh triangles: %ld\n", (4l*tetrahedrons->items+hullsize)/2l);
34414   }
34415   if (b->plc || b->refine) {
34416     printf("  Mesh subfaces: %ld\n", subfaces->items);
34417     printf("  Mesh subsegments: %ld\n\n", subsegs->items);
34418   } else {
34419     printf("  Convex hull triangles: %ld\n\n", hullsize);
34420   }
34421   if (b->verbose > 0) {
34422     qualitystatistics();
34423     unsigned long totalmeshbytes;
34424     printf("Memory allocation statistics:\n\n");
34425     printf("  Maximum number of vertices: %ld\n", points->maxitems);
34426     totalmeshbytes = points->maxitems * points->itembytes;
34427     printf("  Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems);
34428     totalmeshbytes += tetrahedrons->maxitems * tetrahedrons->itembytes;
34429     if (subfaces != (memorypool *) NULL) {
34430       printf("  Maximum number of subfaces: %ld\n", subfaces->maxitems);
34431       totalmeshbytes += subfaces->maxitems * subfaces->itembytes;
34432     }
34433     if (subsegs != (memorypool *) NULL) {
34434       printf("  Maximum number of segments: %ld\n", subsegs->maxitems);
34435       totalmeshbytes += subsegs->maxitems * subsegs->itembytes;
34436     }
34437     printf("  Approximate heap memory used by the mesh (K bytes): %g\n\n",
34438            (double) totalmeshbytes / 1024.0);
34439 #ifdef SELF_CHECK
34440     algorithmicstatistics();
34441 #endif
34442   }
34443 }
34444 
34445 //
34446 // End of user interaction routines
34447 //
34448 
34449 //
34450 // Begin of constructor and destructor of tetgenmesh
34451 //
34452 
34454 //                                                                           //
34455 // ~tetgenmesh()    Deallocte memory occupied by a tetgenmesh object.        //
34456 //                                                                           //
34458 
34459 tetgenmesh::~tetgenmesh()
34460 {
34461   bgm = (tetgenmesh *) NULL;
34462   in = (tetgenio *) NULL;
34463   b = (tetgenbehavior *) NULL;
34464 
34465   if (tetrahedrons != (memorypool *) NULL) {
34466     delete tetrahedrons;
34467   }
34468   if (subfaces != (memorypool *) NULL) {
34469     delete subfaces;
34470   }
34471   if (subsegs != (memorypool *) NULL) {
34472     delete subsegs;
34473   }
34474   if (points != (memorypool *) NULL) {
34475     delete points;
34476   }
34477   if (dummytetbase != (tetrahedron *) NULL) {
34478     delete [] dummytetbase;
34479   }
34480   if (dummyshbase != (shellface *) NULL) {
34481     delete [] dummyshbase;
34482   }
34483   if (facetabovepointarray != (point *) NULL) {
34484     delete [] facetabovepointarray;
34485   }
34486   if (highordertable != (point *) NULL) {
34487     delete [] highordertable;
34488   }
34489   if (subpbcgrouptable != (pbcdata *) NULL) {
34490     delete [] subpbcgrouptable;
34491   }
34492   if (segpbcgrouptable != (list *) NULL) {
34493     delete segpbcgrouptable;
34494     delete [] idx2segpglist;
34495     delete [] segpglist;
34496   }
34497 }
34498 
34500 //                                                                           //
34501 // tetgenmesh()    Initialize a tetgenmesh object.                           //
34502 //                                                                           //
34504 
34505 tetgenmesh::tetgenmesh()
34506 {
34507   bgm = (tetgenmesh *) NULL;
34508   in = (tetgenio *) NULL;
34509   b = (tetgenbehavior *) NULL;
34510 
34511   tetrahedrons = (memorypool *) NULL;
34512   subfaces = (memorypool *) NULL;
34513   subsegs = (memorypool *) NULL;
34514   points = (memorypool *) NULL;
34515   badsubsegs = (memorypool *) NULL;
34516   badsubfaces = (memorypool *) NULL;
34517   badtetrahedrons = (memorypool *) NULL;
34518   flipstackers = (memorypool *) NULL;
34519 
34520   dummytet = (tetrahedron *) NULL;
34521   dummytetbase = (tetrahedron *) NULL;
34522   dummysh = (shellface *) NULL;
34523   dummyshbase = (shellface *) NULL;
34524 
34525   facetabovepointarray = (point *) NULL;
34526   abovepoint = (point) NULL;
34527   highordertable = (point *) NULL;
34528   subpbcgrouptable = (pbcdata *) NULL;
34529   segpbcgrouptable = (list *) NULL;
34530   idx2segpglist = (int *) NULL;
34531   segpglist = (int *) NULL;
34532 
34533   xmax = xmin = ymax = ymin = zmax = zmin = 0.0;
34534   longest = 0.0;
34535   hullsize = 0l;
34536   insegments = 0l;
34537   pointmtrindex = 0;
34538   pointmarkindex = 0;
34539   point2simindex = 0;
34540   point2pbcptindex = 0;
34541   highorderindex = 0;
34542   elemattribindex = 0;
34543   volumeboundindex = 0;
34544   shmarkindex = 0;
34545   areaboundindex = 0;
34546   checksubfaces = 0;
34547   checksubsegs = 0;
34548   checkpbcs = 0;
34549   varconstraint = 0;
34550   nonconvex = 0;
34551   dupverts = 0;
34552   unuverts = 0;
34553   relverts = 0;
34554   suprelverts = 0;
34555   collapverts = 0;
34556   unsupverts = 0;
34557   jettisoninverts = 0;
34558   symbolic = 1;
34559   samples = 0l;
34560   randomseed = 1l;
34561   macheps = 0.0;
34562   minfaceang = minfacetdihed = PI;
34563   maxcavfaces = maxcavverts = 0;
34564   expcavcount = 0;
34565   abovecount = 0l;
34566   bowatvolcount = bowatsubcount = bowatsegcount = 0l;
34567   updvolcount = updsubcount = updsegcount = 0l;
34568   repairflipcount = 0l;
34569   outbowatcircumcount = 0l;
34570   failvolcount = failsubcount = failsegcount = 0l;
34571   r1count = r2count = r3count = 0l;
34572   cdtenforcesegpts = 0l;
34573   rejsegpts = rejsubpts = rejtetpts = 0l;
34574   flip23s = flip32s = flip22s = flip44s = 0l;
34575   tloctime = tfliptime = 0.0;
34576 }
34577 
34578 //
34579 // End of constructor and destructor of tetgenmesh
34580 //
34581 
34582 //
34583 // End of class 'tetgenmesh' implementation.
34584 //
34585 
34587 //                                                                           //
34588 // tetrahedralize()    The interface for users using TetGen library to       //
34589 //                     generate tetrahedral meshes with all features.        //
34590 //                                                                           //
34591 // The sequence is roughly as follows.  Many of these steps can be skipped,  //
34592 // depending on the command line switches.                                   //
34593 //                                                                           //
34594 // - Initialize constants and parse the command line.                        //
34595 // - Read the vertices from a file and either                                //
34596 //   - tetrahedralize them (no -r), or                                       //
34597 //   - read an old mesh from files and reconstruct it (-r).                  //
34598 // - Insert the PLC segments and facets (-p).                                //
34599 // - Read the holes (-p), regional attributes (-pA), and regional volume     //
34600 //   constraints (-pa).  Carve the holes and concavities, and spread the     //
34601 //   regional attributes and volume constraints.                             //
34602 // - Enforce the constraints on minimum quality bound (-q) and maximum       //
34603 //   volume (-a). Also enforce the conforming Delaunay property (-q and -a). //
34604 // - Promote the mesh's linear tetrahedra to higher order elements (-o).     //
34605 // - Write the output files and print the statistics.                        //
34606 // - Check the consistency and Delaunay property of the mesh (-C).           //
34607 //                                                                           //
34609 
34610 void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
34611   tetgenio *addin, tetgenio *bgmin)
34612 {
34613   tetgenmesh m;
34614   // Variables for timing the performance of TetGen (defined in time.h).
34615   clock_t tv[14];
34616 
34617   tv[0] = clock();
34618 
34619   m.b = b;
34620   m.in = in;
34621   m.macheps = exactinit();
34622   m.steinerleft = b->steiner;
34623   if (b->metric) {
34624     m.bgm = new tetgenmesh();
34625     m.bgm->b = b;
34626     m.bgm->in = bgmin;
34627     m.bgm->macheps = exactinit();
34628   }
34629   m.initializepools();
34630   m.transfernodes();
34631 
34632   tv[1] = clock();
34633 
34634   if (b->refine) {
34635     m.reconstructmesh();
34636   } else {
34637     m.delaunizevertices();
34638   }
34639 
34640   tv[2] = clock();
34641 
34642   if (!b->quiet) {
34643     if (b->refine) {
34644       printf("Mesh reconstruction seconds:");
34645     } else {
34646       printf("Delaunay seconds:");
34647     }
34648     printf("  %g\n", (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
34649   }
34650 
34651   if (b->metric) {
34652     if (bgmin != (tetgenio *) NULL) {
34653       m.bgm->initializepools();
34654       m.bgm->transfernodes();
34655       m.bgm->reconstructmesh();
34656     } else {
34657       m.bgm->in = in;
34658       m.bgm->initializepools();
34659       m.duplicatebgmesh();
34660     }
34661   }
34662 
34663   tv[3] = clock();
34664 
34665   if (!b->quiet) {
34666     if (b->metric) {
34667       printf("Background mesh reconstruct seconds:  %g\n",
34668              (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
34669     }
34670   }
34671 
34672   if (b->useshelles && !b->refine) {
34673     m.meshsurface();
34674     if (b->diagnose != 1) {
34675       m.markacutevertices(89.0);
34676       m.incrperturbvertices(b->epsilon);
34677       m.delaunizesegments();
34678       if (m.checkpbcs) {
34679         long oldnum;
34680         do {
34681           oldnum = m.points->items;
34682           m.incrperturbvertices(b->epsilon);
34683           if (m.points->items > oldnum) {
34684             oldnum = m.points->items;
34685             m.delaunizesegments();
34686           }
34687         } while (oldnum < m.points->items);
34688       }
34689       m.constrainedfacets();
34690     } else {
34691       m.detectinterfaces();
34692     }
34693   }
34694 
34695   tv[4] = clock();
34696 
34697   if (!b->quiet) {
34698     if (b->useshelles && !b->refine) {
34699       if (b->diagnose != 1) {
34700         printf("Segment and facet ");
34701       } else {
34702         printf("Intersection ");
34703       }
34704       printf("seconds:  %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
34705     }
34706   }
34707 
34708   if (b->plc && !(b->diagnose == 1)) {
34709     m.carveholes();
34710   }
34711 
34712   tv[5] = clock();
34713 
34714   if (!b->quiet) {
34715     if (b->plc && !(b->diagnose == 1)) {
34716       printf("Hole seconds:  %g\n", (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
34717     }
34718   }
34719 
34720   if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34721     m.optimizemesh(false);
34722   }
34723 
34724   tv[6] = clock();
34725 
34726   if (!b->quiet) {
34727     if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34728       printf("Repair seconds:  %g\n", (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
34729     }
34730   }
34731 
34732   if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34733     m.removesteiners(false);
34734   }
34735 
34736   tv[7] = clock();
34737 
34738   if (!b->quiet) {
34739     if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34740       printf("Steiner removal seconds:  %g\n",
34741              (tv[7] - tv[6]) / (REAL) CLOCKS_PER_SEC);
34742     }
34743   }
34744 
34745   if (b->insertaddpoints && (addin != (tetgenio *) NULL)) {
34746     if (addin->numberofpoints > 0) {
34747       m.insertconstrainedpoints(addin);
34748     }
34749   }
34750 
34751   tv[8] = clock();
34752 
34753   if (!b->quiet) {
34754     if ((b->plc || b->refine) && (b->insertaddpoints)) {
34755       printf("Constrained points seconds:  %g\n",
34756              (tv[8] - tv[7]) / (REAL) CLOCKS_PER_SEC);
34757     }
34758   }
34759 
34760   if (b->metric) {
34761     m.interpolatesizemap();
34762   }
34763 
34764   tv[9] = clock();
34765 
34766   if (!b->quiet) {
34767     if (b->metric) {
34768       printf("Size interpolating seconds:  %g\n",
34769              (tv[9] - tv[8]) / (REAL) CLOCKS_PER_SEC);
34770     }
34771   }
34772 
34773   if (b->coarse) {
34774     m.removesteiners(true);
34775   }
34776 
34777   tv[10] = clock();
34778 
34779   if (!b->quiet) {
34780     if (b->coarse) {
34781       printf("Mesh coarsening seconds:  %g\n",
34782              (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
34783     }
34784   }
34785 
34786   if (b->quality) {
34787     m.enforcequality();
34788   }
34789 
34790   tv[11] = clock();
34791 
34792   if (!b->quiet) {
34793     if (b->quality) {
34794       printf("Quality seconds:  %g\n",
34795              (tv[11] - tv[10]) / (REAL) CLOCKS_PER_SEC);
34796     }
34797   }
34798 
34799   if (b->quality && (b->optlevel > 0)) {
34800     m.optimizemesh(true);
34801   }
34802 
34803   tv[12] = clock();
34804 
34805   if (!b->quiet) {
34806     if (b->quality && (b->optlevel > 0)) {
34807       printf("Optimize seconds:  %g\n",
34808              (tv[12] - tv[11]) / (REAL) CLOCKS_PER_SEC);
34809     }
34810   }
34811 
34812   if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0)
34813       || (b->refine && (in->numberofcorners == 10)))) {
34814     m.jettisonnodes();
34815   }
34816 
34817   if (b->order > 1) {
34818     m.highorder();
34819   }
34820 
34821   if (!b->quiet) {
34822     printf("\n");
34823   }
34824 
34825   if (out != (tetgenio *) NULL) {
34826     out->firstnumber = in->firstnumber;
34827     out->mesh_dim = in->mesh_dim;
34828   }
34829 
34830   if (b->nonodewritten || b->noiterationnum) {
34831     if (!b->quiet) {
34832       printf("NOT writing a .node file.\n");
34833     }
34834   } else {
34835     if (b->diagnose == 1) {
34836       if (m.subfaces->items > 0l) {
34837         m.outnodes(out);  // Only output when self-intersecting faces exist.
34838       }
34839     } else {
34840       m.outnodes(out);
34841       if (b->quality || b->metric) {
34842         // m.outmetrics(out);
34843       }
34844     }
34845   }
34846 
34847   if (b->noelewritten) {
34848     if (!b->quiet) {
34849       printf("NOT writing an .ele file.\n");
34850     }
34851   } else {
34852     if (!(b->diagnose == 1)) {
34853       if (m.tetrahedrons->items > 0l) {
34854         m.outelements(out);
34855       }
34856     }
34857   }
34858 
34859   if (b->nofacewritten) {
34860     if (!b->quiet) {
34861       printf("NOT writing an .face file.\n");
34862     }
34863   } else {
34864     if (b->facesout) {
34865       if (m.tetrahedrons->items > 0l) {
34866         m.outfaces(out);  // Output all faces.
34867       }
34868     } else {
34869       if (b->diagnose == 1) {
34870         if (m.subfaces->items > 0l) {
34871           m.outsubfaces(out); // Only output self-intersecting faces.
34872         }
34873       } else if (b->plc || b->refine) {
34874         if (m.subfaces->items > 0l) {
34875           m.outsubfaces(out); // Output boundary faces.
34876         }
34877       } else {
34878         if (m.tetrahedrons->items > 0l) {
34879           m.outhullfaces(out); // Output convex hull faces.
34880         }
34881       }
34882     }
34883   }
34884 
34885   if (m.checkpbcs) {
34886     m.outpbcnodes(out);
34887   }
34888 
34889   if (b->edgesout) {
34890     if (b->edgesout > 1) {
34891       m.outedges(out); // -ee, output all mesh edges.
34892     } else {
34893       m.outsubsegments(out); // -e, only output subsegments.
34894     }
34895   }
34896 
34897   if (!out && b->plc &&
34898       ((b->object == tetgenbehavior::OFF) ||
34899        (b->object == tetgenbehavior::PLY) ||
34900        (b->object == tetgenbehavior::STL))) {
34901     m.outsmesh(b->outfilename);
34902   }
34903 
34904   if (!out && b->meditview) {
34905     m.outmesh2medit(b->outfilename);
34906   }
34907 
34908   if (!out && b->gidview) {
34909     m.outmesh2gid(b->outfilename);
34910   }
34911 
34912   if (!out && b->geomview) {
34913     m.outmesh2off(b->outfilename);
34914   }
34915 
34916   if (b->neighout) {
34917     m.outneighbors(out);
34918   }
34919 
34920   if (b->voroout) {
34921     m.outvoronoi(out);
34922   }
34923 
34924   tv[13] = clock();
34925 
34926   if (!b->quiet) {
34927     printf("\nOutput seconds:  %g\n",
34928            (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
34929     printf("Total running seconds:  %g\n",
34930            (tv[13] - tv[0]) / (REAL) CLOCKS_PER_SEC);
34931   }
34932 
34933   if (b->docheck) {
34934     m.checkmesh();
34935     if (m.checksubfaces) {
34936       m.checkshells();
34937     }
34938     if (b->docheck > 1) {
34939       m.checkdelaunay(0.0, NULL);
34940       if (b->docheck > 2) {
34941         if (b->quality || b->refine) {
34942           m.checkconforming();
34943         }
34944       }
34945     }
34946   }
34947 
34948   if (!b->quiet) {
34949     m.statistics();
34950   }
34951 
34952   if (b->metric) {
34953     delete m.bgm;
34954   }
34955 }
34956 
34957 #ifndef TETLIBRARY
34958 
34960 //                                                                           //
34961 // main()    The entrance for running TetGen from command line.              //
34962 //                                                                           //
34964 
34965 int main(int argc, char *argv[])
34966 
34967 #else // with TETLIBRARY
34968 
34970 //                                                                           //
34971 // tetrahedralize()    The entrance for calling TetGen from another program. //
34972 //                                                                           //
34974 
34975 void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
34976   tetgenio *addin, tetgenio *bgmin)
34977 
34978 #endif // not TETLIBRARY
34979 
34980 {
34981   tetgenbehavior b;
34982 
34983 #ifndef TETLIBRARY
34984 
34985   tetgenio in, addin, bgmin;
34986 
34987   if (!b.parse_commandline(argc, argv)) {
34988     terminatetetgen(1);
34989   }
34990   if (b.refine) {
34991     if (!in.load_tetmesh(b.infilename)) {
34992       terminatetetgen(1);
34993     }
34994   } else {
34995     if (!in.load_plc(b.infilename, (int) b.object)) {
34996       terminatetetgen(1);
34997     }
34998   }
34999   if (b.insertaddpoints) {
35000     if (!addin.load_node(b.addinfilename)) {
35001       addin.numberofpoints = 0l;
35002     }
35003   }
35004   if (b.metric) {
35005     if (!bgmin.load_tetmesh(b.bgmeshfilename)) {
35006       bgmin.numberoftetrahedra = 0l;
35007     }
35008   }
35009 
35010   if (bgmin.numberoftetrahedra > 0l) {
35011     tetrahedralize(&b, &in, NULL, &addin, &bgmin);
35012   } else {
35013     tetrahedralize(&b, &in, NULL, &addin, NULL);
35014   }
35015 
35016   return 0;
35017 
35018 #else // with TETLIBRARY
35019 
35020   if (!b.parse_commandline(switches)) {
35021     terminatetetgen(1);
35022   }
35023   tetrahedralize(&b, in, out, addin, bgmin);
35024 
35025 #endif // not TETLIBRARY
35026 }
35027 
35028 } //Added namespace to avoid clash with triangle
35029 
35030 #ifndef TETLIBRARY
35031 // Shim for entry point to main inside the namespace.  This is just in case we want to compile up a binary from this
35032 // source code.
35033 int main(int argc, char *argv[])
35034 {
35035     tetgen::main(argc, argv);
35036 }
35037 #endif // not TETLIBRARY
Generated on Thu Dec 22 13:00:15 2011 for Chaste by  doxygen 1.6.3