Chaste Release::3.1
tetgen.cpp
Go to the documentation of this file.
00001 
00008 // This include is here so that the chaste_libs=0 build correctly links predicates.o.
00009 #include "predicates.hpp"
00010 
00012 //                                                                           //
00013 // TetGen                                                                    //
00014 //                                                                           //
00015 // A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator         //
00016 //                                                                           //
00017 // Version 1.4                                                               //
00018 // April 16, 2007                                                            //
00019 //                                                                           //
00020 // Copyright (C) 2002--2007                                                  //
00021 // Hang Si                                                                   //
00022 // Research Group Numerical Mathematics and Scientific Computing             //
00023 // Weierstrass Institute for Applied Analysis and Stochastics                //
00024 // Mohrenstr. 39, 10117 Berlin, Germany                                      //
00025 // si@wias-berlin.de                                                         //
00026 //                                                                           //
00027 // TetGen is freely available through the website: http://tetgen.berlios.de. //
00028 //   It may be copied, modified, and redistributed for non-commercial use.   //
00029 //   Please consult the file LICENSE for the detailed copyright notices.     //
00030 //                                                                           //
00032 
00034 //                                                                           //
00035 // tetgen.cxx                                                                //
00036 //                                                                           //
00037 // The TetGen library and program.                                           //
00038 //                                                                           //
00040 
00041 #include "tetgen.h"
00042 namespace tetgen
00043 { //Added namespace to avoid clash with triangle
00044 
00046 //                                                                           //
00047 // terminatetetgen()    Terminate TetGen with a given exit code.             //
00048 //                                                                           //
00050 
00051 void terminatetetgen(int x)
00052 {
00053 #ifdef TETLIBRARY
00054   throw x;
00055 #else
00056   exit(x);
00057 #endif // #ifdef TETLIBRARY
00058 }
00059 
00060 //
00061 // Begin of class 'tetgenio' implementation
00062 //
00063 
00065 //                                                                           //
00066 // initialize()    Initialize all variables of 'tetgenio'.                   //
00067 //                                                                           //
00068 // It is called by the only class constructor 'tetgenio()' implicitly. Thus, //
00069 // all variables are guaranteed to be initialized. Each array is initialized //
00070 // to be a 'NULL' pointer, and its length is equal zero. Some variables have //
00071 // their default value, 'firstnumber' equals zero, 'mesh_dim' equals 3,  and //
00072 // 'numberofcorners' equals 4.  Another possible use of this routine is to   //
00073 // call it before to re-use an object.                                       //
00074 //                                                                           //
00076 
00077 void tetgenio::initialize()
00078 {
00079   firstnumber = 0;              // Default item index is numbered from Zero.
00080   mesh_dim = 3;                              // Default mesh dimension is 3.
00081   useindex = true;
00082 
00083   pointlist = (REAL *) NULL;
00084   pointattributelist = (REAL *) NULL;
00085   pointmtrlist = (REAL *) NULL;
00086   pointmarkerlist = (int *) NULL;
00087   numberofpoints = 0;
00088   numberofpointattributes = 0;
00089   numberofpointmtrs = 0;
00090 
00091   tetrahedronlist = (int *) NULL;
00092   tetrahedronattributelist = (REAL *) NULL;
00093   tetrahedronvolumelist = (REAL *) NULL;
00094   neighborlist = (int *) NULL;
00095   numberoftetrahedra = 0;
00096   numberofcorners = 4;                   // Default is 4 nodes per element.
00097   numberoftetrahedronattributes = 0;
00098 
00099   trifacelist = (int *) NULL;
00100   adjtetlist = (int *) NULL;
00101   trifacemarkerlist = (int *) NULL;
00102   numberoftrifaces = 0;
00103 
00104   facetlist = (facet *) NULL;
00105   facetmarkerlist = (int *) NULL;
00106   numberoffacets = 0;
00107 
00108   edgelist = (int *) NULL;
00109   edgemarkerlist = (int *) NULL;
00110   numberofedges = 0;
00111 
00112   holelist = (REAL *) NULL;
00113   numberofholes = 0;
00114 
00115   regionlist = (REAL *) NULL;
00116   numberofregions = 0;
00117 
00118   facetconstraintlist = (REAL *) NULL;
00119   numberoffacetconstraints = 0;
00120   segmentconstraintlist = (REAL *) NULL;
00121   numberofsegmentconstraints = 0;
00122 
00123   pbcgrouplist = (pbcgroup *) NULL;
00124   numberofpbcgroups = 0;
00125 
00126   vpointlist = (REAL *) NULL;
00127   vedgelist = (voroedge *) NULL;
00128   vfacetlist = (vorofacet *) NULL;
00129   vcelllist = (int **) NULL;
00130   numberofvpoints = 0;
00131   numberofvedges = 0;
00132   numberofvfacets = 0;
00133   numberofvcells = 0;
00134 }
00135 
00137 //                                                                           //
00138 // deinitialize()    Free the memory allocated in 'tetgenio'.                //
00139 //                                                                           //
00140 // It is called by the class destructor '~tetgenio()' implicitly. Hence, the //
00141 // occupied memory by arrays of an object will be automatically released on  //
00142 // the deletion of the object. However, this routine assumes that the memory //
00143 // is allocated by C++ memory allocation operator 'new', thus it is freed by //
00144 // the C++ array deletor 'delete []'. If one uses the C/C++ library function //
00145 // 'malloc()' to allocate memory for arrays, one has to free them with the   //
00146 // 'free()' function, and call routine 'initialize()' once to disable this   //
00147 // routine on deletion of the object.                                        //
00148 //                                                                           //
00150 
00151 void tetgenio::deinitialize()
00152 {
00153   facet *f;
00154   polygon *p;
00155   pbcgroup *pg;
00156   int i, j;
00157 
00158   if (pointlist != (REAL *) NULL) {
00159     delete [] pointlist;
00160   }
00161   if (pointattributelist != (REAL *) NULL) {
00162     delete [] pointattributelist;
00163   }
00164   if (pointmtrlist != (REAL *) NULL) {
00165     delete [] pointmtrlist;
00166   }
00167   if (pointmarkerlist != (int *) NULL) {
00168     delete [] pointmarkerlist;
00169   }
00170 
00171   if (tetrahedronlist != (int *) NULL) {
00172     delete [] tetrahedronlist;
00173   }
00174   if (tetrahedronattributelist != (REAL *) NULL) {
00175     delete [] tetrahedronattributelist;
00176   }
00177   if (tetrahedronvolumelist != (REAL *) NULL) {
00178     delete [] tetrahedronvolumelist;
00179   }
00180   if (neighborlist != (int *) NULL) {
00181     delete [] neighborlist;
00182   }
00183 
00184   if (trifacelist != (int *) NULL) {
00185     delete [] trifacelist;
00186   }
00187   if (adjtetlist != (int *) NULL) {
00188     delete [] adjtetlist;
00189   }
00190   if (trifacemarkerlist != (int *) NULL) {
00191     delete [] trifacemarkerlist;
00192   }
00193 
00194   if (edgelist != (int *) NULL) {
00195     delete [] edgelist;
00196   }
00197   if (edgemarkerlist != (int *) NULL) {
00198     delete [] edgemarkerlist;
00199   }
00200 
00201   if (facetlist != (facet *) NULL) {
00202     for (i = 0; i < numberoffacets; i++) {
00203       f = &facetlist[i];
00204       for (j = 0; j < f->numberofpolygons; j++) {
00205         p = &f->polygonlist[j];
00206         delete [] p->vertexlist;
00207       }
00208       delete [] f->polygonlist;
00209       if (f->holelist != (REAL *) NULL) {
00210         delete [] f->holelist;
00211       }
00212     }
00213     delete [] facetlist;
00214   }
00215   if (facetmarkerlist != (int *) NULL) {
00216     delete [] facetmarkerlist;
00217   }
00218 
00219   if (holelist != (REAL *) NULL) {
00220     delete [] holelist;
00221   }
00222   if (regionlist != (REAL *) NULL) {
00223     delete [] regionlist;
00224   }
00225   if (facetconstraintlist != (REAL *) NULL) {
00226     delete [] facetconstraintlist;
00227   }
00228   if (segmentconstraintlist != (REAL *) NULL) {
00229     delete [] segmentconstraintlist;
00230   }
00231   if (pbcgrouplist != (pbcgroup *) NULL) {
00232     for (i = 0; i < numberofpbcgroups; i++) {
00233       pg = &(pbcgrouplist[i]);
00234       if (pg->pointpairlist != (int *) NULL) {
00235         delete [] pg->pointpairlist;
00236       }
00237     }
00238     delete [] pbcgrouplist;
00239   }
00240   if (vpointlist != (REAL *) NULL) {
00241     delete [] vpointlist;
00242   }
00243   if (vedgelist != (voroedge *) NULL) {
00244     delete [] vedgelist;
00245   }
00246   if (vfacetlist != (vorofacet *) NULL) {
00247     for (i = 0; i < numberofvfacets; i++) {
00248       delete [] vfacetlist[i].elist;
00249     }
00250     delete [] vfacetlist;
00251   }
00252   if (vcelllist != (int **) NULL) {
00253     for (i = 0; i < numberofvcells; i++) {
00254       delete [] vcelllist[i];
00255     }
00256     delete [] vcelllist;
00257   }
00258 }
00259 
00261 //                                                                           //
00262 // load_node_call()    Load a list of nodes.                                 //
00263 //                                                                           //
00264 // It is a support routine for routines: 'load_nodes()', 'load_poly()', and  //
00265 // 'load_tetmesh()'.  'infile' is the file handle contains the node list. It //
00266 // may point to a .node, or .poly or .smesh file.  'markers' indicates each  //
00267 // node contains an additional marker (integer) or not. 'infilename' is the  //
00268 // name of the file being read,  it is only appeared in error message.       //
00269 //                                                                           //
00270 // The 'firstnumber' (0 or 1) is automatically determined by the number of   //
00271 // the first index of the first point.                                       //
00272 //                                                                           //
00274 
00275 bool tetgenio::load_node_call(FILE* infile, int markers, char* infilename)
00276 {
00277   char inputline[INPUTLINESIZE];
00278   char *stringptr;
00279   REAL x, y, z, attrib;
00280   int firstnode, currentmarker;
00281   int index, attribindex;
00282   int i, j;
00283 
00284   // Initialize 'pointlist', 'pointattributelist', and 'pointmarkerlist'.
00285   pointlist = new REAL[numberofpoints * 3];
00286   if (pointlist == (REAL *) NULL) {
00287     printf("Error:  Out of memory.\n");
00288     terminatetetgen(1);
00289   }
00290   if (numberofpointattributes > 0) {
00291     pointattributelist = new REAL[numberofpoints * numberofpointattributes];
00292     if (pointattributelist == (REAL *) NULL) {
00293       printf("Error:  Out of memory.\n");
00294       terminatetetgen(1);
00295     }
00296   }
00297   if (markers) {
00298     pointmarkerlist = new int[numberofpoints];
00299     if (pointmarkerlist == (int *) NULL) {
00300       printf("Error:  Out of memory.\n");
00301       terminatetetgen(1);
00302     }
00303   }
00304 
00305   // Read the point section.
00306   index = 0;
00307   attribindex = 0;
00308   for (i = 0; i < numberofpoints; i++) {
00309     stringptr = readnumberline(inputline, infile, infilename);
00310     if (useindex) {
00311       if (i == 0) {
00312         firstnode = (int) strtol (stringptr, &stringptr, 0);
00313         if ((firstnode == 0) || (firstnode == 1)) {
00314           firstnumber = firstnode;
00315         }
00316       }
00317       stringptr = findnextnumber(stringptr);
00318     } // if (useindex)
00319     if (*stringptr == '\0') {
00320       printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
00321       break;
00322     }
00323     x = (REAL) strtod(stringptr, &stringptr);
00324     stringptr = findnextnumber(stringptr);
00325     if (*stringptr == '\0') {
00326       printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
00327       break;
00328     }
00329     y = (REAL) strtod(stringptr, &stringptr);
00330     if (mesh_dim == 3) {
00331       stringptr = findnextnumber(stringptr);
00332       if (*stringptr == '\0') {
00333         printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
00334         break;
00335       }
00336       z = (REAL) strtod(stringptr, &stringptr);
00337     } else {
00338       z = 0.0; // mesh_dim == 2;
00339     }
00340     pointlist[index++] = x;
00341     pointlist[index++] = y;
00342     pointlist[index++] = z;
00343     // Read the point attributes.
00344     for (j = 0; j < numberofpointattributes; j++) {
00345       stringptr = findnextnumber(stringptr);
00346       if (*stringptr == '\0') {
00347         attrib = 0.0;
00348       } else {
00349         attrib = (REAL) strtod(stringptr, &stringptr);
00350       }
00351       pointattributelist[attribindex++] = attrib;
00352     }
00353     if (markers) {
00354       // Read a point marker.
00355       stringptr = findnextnumber(stringptr);
00356       if (*stringptr == '\0') {
00357         currentmarker = 0;
00358       } else {
00359         currentmarker = (int) strtol (stringptr, &stringptr, 0);
00360       }
00361       pointmarkerlist[i] = currentmarker;
00362     }
00363   }
00364   if (i < numberofpoints) {
00365     // Failed to read points due to some error.
00366     delete [] pointlist;
00367     pointlist = (REAL *) NULL;
00368     if (markers) {
00369       delete [] pointmarkerlist;
00370       pointmarkerlist = (int *) NULL;
00371     }
00372     if (numberofpointattributes > 0) {
00373       delete [] pointattributelist;
00374       pointattributelist = (REAL *) NULL;
00375     }
00376     numberofpoints = 0;
00377     return false;
00378   }
00379   return true;
00380 }
00381 
00383 //                                                                           //
00384 // load_node()    Load a list of nodes from a .node file.                    //
00385 //                                                                           //
00386 // 'filename' is the inputfile without suffix. The node list is in 'filename.//
00387 // node'. On completion, the node list is returned in 'pointlist'.           //
00388 //                                                                           //
00390 
00391 bool tetgenio::load_node(char* filename)
00392 {
00393   FILE *infile;
00394   char innodefilename[FILENAMESIZE];
00395   char inputline[INPUTLINESIZE];
00396   char *stringptr;
00397   int markers;
00398 
00399   markers = 0;
00400   // Assembling the actual file names we want to open.
00401   strcpy(innodefilename, filename);
00402   strcat(innodefilename, ".node");
00403 
00404   // Try to open a .node file.
00405   infile = fopen(innodefilename, "r");
00406   if (infile == (FILE *) NULL) {
00407     printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
00408     return false;
00409   }
00410   printf("Opening %s.\n", innodefilename);
00411   // Read the first line of the file.
00412   stringptr = readnumberline(inputline, infile, innodefilename);
00413   // Is this list of points generated from rbox?
00414   stringptr = strstr(inputline, "rbox");
00415   if (stringptr == NULL) {
00416     // Read number of points, number of dimensions, number of point
00417     //   attributes, and number of boundary markers.
00418     stringptr = inputline;
00419     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00420     stringptr = findnextnumber(stringptr);
00421     if (*stringptr == '\0') {
00422       mesh_dim = 3;
00423     } else {
00424       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00425     }
00426     stringptr = findnextnumber(stringptr);
00427     if (*stringptr == '\0') {
00428       numberofpointattributes = 0;
00429     } else {
00430       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00431     }
00432     stringptr = findnextnumber(stringptr);
00433     if (*stringptr == '\0') {
00434       markers = 0;
00435     } else {
00436       markers = (int) strtol (stringptr, &stringptr, 0);
00437     }
00438   } else {
00439     // It is a rbox (qhull) input file.
00440     stringptr = inputline;
00441     // Get the dimension.
00442     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00443     // Get the number of points.
00444     stringptr = readnumberline(inputline, infile, innodefilename);
00445     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00446     // There is no index column.
00447     useindex = 0;
00448   }
00449 
00450   // if ((mesh_dim != 3) && (mesh_dim != 2)) {
00451   //   printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
00452   //   fclose(infile);
00453   //   return false;
00454   // }
00455   if (numberofpoints < (mesh_dim + 1)) {
00456     printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
00457     fclose(infile);
00458     return false;
00459   }
00460 
00461   // Load the list of nodes.
00462   if (!load_node_call(infile, markers, innodefilename)) {
00463     fclose(infile);
00464     return false;
00465   }
00466   fclose(infile);
00467   return true;
00468 }
00469 
00471 //                                                                           //
00472 // load_pbc()    Load a list of pbc groups into 'pbcgrouplist'.              //
00473 //                                                                           //
00474 // 'filename' is the filename of the original inputfile without suffix. The  //
00475 // pbc groups are found in file 'filename.pbc'.                              //
00476 //                                                                           //
00477 // This routine will be called both in load_poly() and load_tetmesh().       //
00478 //                                                                           //
00480 
00481 bool tetgenio::load_pbc(char* filename)
00482 {
00483   FILE *infile;
00484   char pbcfilename[FILENAMESIZE];
00485   char inputline[INPUTLINESIZE];
00486   char *stringptr;
00487   pbcgroup *pg;
00488   int index, p1, p2;
00489   int i, j, k;
00490 
00491   // Pbc groups are saved in file "filename.pbc".
00492   strcpy(pbcfilename, filename);
00493   strcat(pbcfilename, ".pbc");
00494   infile = fopen(pbcfilename, "r");
00495   if (infile != (FILE *) NULL) {
00496     printf("Opening %s.\n", pbcfilename);
00497   } else {
00498     // No such file. Return.
00499     return false;
00500   }
00501 
00502   // Read the number of pbc groups.
00503   stringptr = readnumberline(inputline, infile, pbcfilename);
00504   numberofpbcgroups = (int) strtol (stringptr, &stringptr, 0);
00505   if (numberofpbcgroups == 0) {
00506     // It looks this file contains no point.
00507     fclose(infile);
00508     return false;
00509   }
00510   // Initialize 'pbcgrouplist';
00511   pbcgrouplist = new pbcgroup[numberofpbcgroups];
00512 
00513   // Read the list of pbc groups.
00514   for (i = 0; i < numberofpbcgroups; i++) {
00515     pg = &(pbcgrouplist[i]);
00516     // Initialize pbcgroup i;
00517     pg->numberofpointpairs = 0;
00518     pg->pointpairlist = (int *) NULL;
00519     // Read 'fmark1', 'fmark2'.
00520     stringptr = readnumberline(inputline, infile, pbcfilename);
00521     if (*stringptr == '\0') break;
00522     pg->fmark1 = (int) strtol(stringptr, &stringptr, 0);
00523     stringptr = findnextnumber(stringptr);
00524     if (*stringptr == '\0') break;
00525     pg->fmark2 = (int) strtol(stringptr, &stringptr, 0);
00526     // Read 'transmat'.
00527     do {
00528       stringptr = readline(inputline, infile, NULL);
00529     } while ((*stringptr != '[') && (*stringptr != '\0'));
00530     if (*stringptr == '\0') break;
00531     for (j = 0; j < 4; j++) {
00532       for (k = 0; k < 4; k++) {
00533         // Read the entry of [j, k].
00534         stringptr = findnextnumber(stringptr);
00535         if (*stringptr == '\0') {
00536           // Try to read another line.
00537           stringptr = readnumberline(inputline, infile, pbcfilename);
00538           if (*stringptr == '\0') break;
00539         }
00540         pg->transmat[j][k] = (REAL) strtod(stringptr, &stringptr);
00541       }
00542       if (k < 4) break; // Not complete!
00543     }
00544     if (j < 4) break; // Not complete!
00545     // Read 'numberofpointpairs'.
00546     stringptr = readnumberline(inputline, infile, pbcfilename);
00547     if (*stringptr == '\0') break;
00548     pg->numberofpointpairs = (int) strtol(stringptr, &stringptr, 0);
00549     if (pg->numberofpointpairs > 0) {
00550       pg->pointpairlist = new int[pg->numberofpointpairs * 2];
00551       // Read the point pairs.
00552       index = 0;
00553       for (j = 0; j < pg->numberofpointpairs; j++) {
00554         stringptr = readnumberline(inputline, infile, pbcfilename);
00555         p1 = (int) strtol(stringptr, &stringptr, 0);
00556         stringptr = findnextnumber(stringptr);
00557         p2 = (int) strtol(stringptr, &stringptr, 0);
00558         pg->pointpairlist[index++] = p1;
00559         pg->pointpairlist[index++] = p2;
00560       }
00561     }
00562   }
00563   fclose(infile);
00564 
00565   if (i < numberofpbcgroups) {
00566     // Failed to read to additional points due to some error.
00567     delete [] pbcgrouplist;
00568     pbcgrouplist = (pbcgroup *) NULL;
00569     numberofpbcgroups = 0;
00570     return false;
00571   }
00572   return true;
00573 }
00574 
00576 //                                                                           //
00577 // load_var()    Load variant constraints applied on facets, segments, nodes.//
00578 //                                                                           //
00579 // 'filename' is the filename of the original inputfile without suffix. The  //
00580 // constraints are found in file 'filename.var'.                             //
00581 //                                                                           //
00583 
00584 bool tetgenio::load_var(char* filename)
00585 {
00586   FILE *infile;
00587   char varfilename[FILENAMESIZE];
00588   char inputline[INPUTLINESIZE];
00589   char *stringptr;
00590   int index;
00591   int i;
00592 
00593   // Variant constraints are saved in file "filename.var".
00594   strcpy(varfilename, filename);
00595   strcat(varfilename, ".var");
00596   infile = fopen(varfilename, "r");
00597   if (infile != (FILE *) NULL) {
00598     printf("Opening %s.\n", varfilename);
00599   } else {
00600     // No such file. Return.
00601     return false;
00602   }
00603 
00604   // Read the facet constraint section.
00605   stringptr = readnumberline(inputline, infile, varfilename);
00606   if (*stringptr != '\0') {
00607     numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0);
00608   } else {
00609     numberoffacetconstraints = 0;
00610   }
00611   if (numberoffacetconstraints > 0) {
00612     // Initialize 'facetconstraintlist'.
00613     facetconstraintlist = new REAL[numberoffacetconstraints * 2];
00614     index = 0;
00615     for (i = 0; i < numberoffacetconstraints; i++) {
00616       stringptr = readnumberline(inputline, infile, varfilename);
00617       stringptr = findnextnumber(stringptr);
00618       if (*stringptr == '\0') {
00619         printf("Error:  facet constraint %d has no facet marker.\n",
00620                firstnumber + i);
00621         break;
00622       } else {
00623         facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00624       }
00625       stringptr = findnextnumber(stringptr);
00626       if (*stringptr == '\0') {
00627         printf("Error:  facet constraint %d has no maximum area bound.\n",
00628                firstnumber + i);
00629         break;
00630       } else {
00631         facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00632       }
00633     }
00634     if (i < numberoffacetconstraints) {
00635       // This must be caused by an error.
00636       fclose(infile);
00637       return false;
00638     }
00639   }
00640 
00641   // Read the segment constraint section.
00642   stringptr = readnumberline(inputline, infile, varfilename);
00643   if (*stringptr != '\0') {
00644     numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0);
00645   } else {
00646     numberofsegmentconstraints = 0;
00647   }
00648   if (numberofsegmentconstraints > 0) {
00649     // Initialize 'segmentconstraintlist'.
00650     segmentconstraintlist = new REAL[numberofsegmentconstraints * 3];
00651     index = 0;
00652     for (i = 0; i < numberofsegmentconstraints; i++) {
00653       stringptr = readnumberline(inputline, infile, varfilename);
00654       stringptr = findnextnumber(stringptr);
00655       if (*stringptr == '\0') {
00656         printf("Error:  segment constraint %d has no frist endpoint.\n",
00657                firstnumber + i);
00658         break;
00659       } else {
00660         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00661       }
00662       stringptr = findnextnumber(stringptr);
00663       if (*stringptr == '\0') {
00664         printf("Error:  segment constraint %d has no second endpoint.\n",
00665                firstnumber + i);
00666         break;
00667       } else {
00668         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00669       }
00670       stringptr = findnextnumber(stringptr);
00671       if (*stringptr == '\0') {
00672         printf("Error:  segment constraint %d has no maximum length bound.\n",
00673                firstnumber + i);
00674         break;
00675       } else {
00676         segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00677       }
00678     }
00679     if (i < numberofsegmentconstraints) {
00680       // This must be caused by an error.
00681       fclose(infile);
00682       return false;
00683     }
00684   }
00685 
00686   fclose(infile);
00687   return true;
00688 }
00689 
00691 //                                                                           //
00692 // load_mtr()    Load a size specification map from file.                    //
00693 //                                                                           //
00694 // 'filename' is the filename of the original inputfile without suffix. The  //
00695 // size map is found in file 'filename.mtr'.                                 //
00696 //                                                                           //
00698 
00699 bool tetgenio::load_mtr(char* filename)
00700 {
00701   FILE *infile;
00702   char mtrfilename[FILENAMESIZE];
00703   char inputline[INPUTLINESIZE];
00704   char *stringptr;
00705   REAL mtr;
00706   int mtrindex;
00707   int i, j;
00708 
00709   strcpy(mtrfilename, filename);
00710   strcat(mtrfilename, ".mtr");
00711   infile = fopen(mtrfilename, "r");
00712   if (infile != (FILE *) NULL) {
00713     printf("Opening %s.\n", mtrfilename);
00714   } else {
00715     // No such file. Return.
00716     return false;
00717   }
00718 
00719   // Read number of points, number of columns (1, 3, or 6).
00720   stringptr = readnumberline(inputline, infile, mtrfilename);
00721   stringptr = findnextnumber(stringptr); // Skip number of points.
00722   if (*stringptr != '\0') {
00723     numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0);
00724   }
00725   if (numberofpointmtrs == 0) {
00726     // Column number doesn't match. Set a default number (1).
00727     numberofpointmtrs = 1;
00728   }
00729 
00730   // Allocate space for pointmtrlist.
00731   pointmtrlist = new REAL[numberofpoints * numberofpointmtrs];
00732   if (pointmtrlist == (REAL *) NULL) {
00733     printf("Error:  Out of memory.\n");
00734     terminatetetgen(1);
00735   }
00736   mtrindex = 0;
00737   for (i = 0; i < numberofpoints; i++) {
00738     // Read metrics.
00739     stringptr = readnumberline(inputline, infile, mtrfilename);
00740     for (j = 0; j < numberofpointmtrs; j++) {
00741       if (*stringptr == '\0') {
00742         printf("Error:  Metric %d is missing value #%d in %s.\n",
00743                i + firstnumber, j + 1, mtrfilename);
00744         terminatetetgen(1);
00745       }
00746       mtr = (REAL) strtod(stringptr, &stringptr);
00747       pointmtrlist[mtrindex++] = mtr;
00748       stringptr = findnextnumber(stringptr);
00749     }
00750   }
00751 
00752   fclose(infile);
00753   return true;
00754 }
00755 
00757 //                                                                           //
00758 // load_poly()    Load a piecewise linear complex from a .poly or .smesh.    //
00759 //                                                                           //
00760 // 'filename' is the inputfile without suffix. The PLC is in 'filename.poly' //
00761 // or 'filename.smesh', and possibly plus 'filename.node' (when the first    //
00762 // line of the file starts with a zero).                                     //
00763 //                                                                           //
00765 
00766 bool tetgenio::load_poly(char* filename)
00767 {
00768   FILE *infile, *polyfile;
00769   char innodefilename[FILENAMESIZE];
00770   char inpolyfilename[FILENAMESIZE];
00771   char insmeshfilename[FILENAMESIZE];
00772   char inputline[INPUTLINESIZE];
00773   char *stringptr, *infilename;
00774   int smesh, markers, currentmarker;
00775   int readnodefile, index;
00776   int i, j, k;
00777 
00778   // Assembling the actual file names we want to open.
00779   strcpy(innodefilename, filename);
00780   strcpy(inpolyfilename, filename);
00781   strcpy(insmeshfilename, filename);
00782   strcat(innodefilename, ".node");
00783   strcat(inpolyfilename, ".poly");
00784   strcat(insmeshfilename, ".smesh");
00785 
00786   // First assume it is a .poly file.
00787   smesh = 0;
00788   // Try to open a .poly file.
00789   polyfile = fopen(inpolyfilename, "r");
00790   if (polyfile == (FILE *) NULL) {
00791     // .poly doesn't exist! Try to open a .smesh file.
00792     polyfile = fopen(insmeshfilename, "r");
00793     if (polyfile == (FILE *) NULL) {
00794       printf("File I/O Error:  Cannot access file %s and %s.\n",
00795              inpolyfilename, insmeshfilename);
00796       return false;
00797     } else {
00798       printf("Opening %s.\n", insmeshfilename);
00799     }
00800     smesh = 1;
00801   } else {
00802     printf("Opening %s.\n", inpolyfilename);
00803   }
00804   // Initialize the default values.
00805   mesh_dim = 3;  // Three-dimemsional accoordinates.
00806   numberofpointattributes = 0;  // no point attribute.
00807   markers = 0;  // no boundary marker.
00808   // Read number of points, number of dimensions, number of point
00809   //   attributes, and number of boundary markers.
00810   stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00811   numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00812   stringptr = findnextnumber(stringptr);
00813   if (*stringptr != '\0') {
00814     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00815   }
00816   stringptr = findnextnumber(stringptr);
00817   if (*stringptr != '\0') {
00818     numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00819   }
00820   stringptr = findnextnumber(stringptr);
00821   if (*stringptr != '\0') {
00822     markers = (int) strtol (stringptr, &stringptr, 0);
00823   }
00824   if (numberofpoints > 0) {
00825     readnodefile = 0;
00826     if (smesh) {
00827       infilename = insmeshfilename;
00828     } else {
00829       infilename = inpolyfilename;
00830     }
00831     infile = polyfile;
00832   } else {
00833     // If the .poly or .smesh file claims there are zero points, that
00834     //   means the points should be read from a separate .node file.
00835     readnodefile = 1;
00836     infilename = innodefilename;
00837   }
00838 
00839   if (readnodefile) {
00840     // Read the points from the .node file.
00841     printf("Opening %s.\n", innodefilename);
00842     infile = fopen(innodefilename, "r");
00843     if (infile == (FILE *) NULL) {
00844       printf("File I/O Error:  Cannot access file %s.\n", innodefilename);
00845       return false;
00846     }
00847     // Initialize the default values.
00848     mesh_dim = 3;  // Three-dimemsional accoordinates.
00849     numberofpointattributes = 0;  // no point attribute.
00850     markers = 0;  // no boundary marker.
00851     // Read number of points, number of dimensions, number of point
00852     //   attributes, and number of boundary markers.
00853     stringptr = readnumberline(inputline, infile, innodefilename);
00854     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00855     stringptr = findnextnumber(stringptr);
00856     if (*stringptr != '\0') {
00857       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00858     }
00859     stringptr = findnextnumber(stringptr);
00860     if (*stringptr != '\0') {
00861       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00862     }
00863     stringptr = findnextnumber(stringptr);
00864     if (*stringptr != '\0') {
00865       markers = (int) strtol (stringptr, &stringptr, 0);
00866     }
00867   }
00868 
00869   if ((mesh_dim != 3) && (mesh_dim != 2)) {
00870     printf("Input error:  TetGen only works for 2D & 3D point sets.\n");
00871     fclose(infile);
00872     return false;
00873   }
00874   if (numberofpoints < (mesh_dim + 1)) {
00875     printf("Input error:  TetGen needs at least %d points.\n", mesh_dim + 1);
00876     fclose(infile);
00877     return false;
00878   }
00879 
00880   // Load the list of nodes.
00881   if (!load_node_call(infile, markers, infilename)) {
00882     fclose(infile);
00883     return false;
00884   }
00885 
00886   if (readnodefile) {
00887     fclose(infile);
00888   }
00889 
00890   facet *f;
00891   polygon *p;
00892 
00893   if (mesh_dim == 3) {
00894 
00895     // Read number of facets and number of boundary markers.
00896     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00897     numberoffacets = (int) strtol (stringptr, &stringptr, 0);
00898     if (numberoffacets <= 0) {
00899       // No facet list, return.
00900       fclose(polyfile);
00901       return true;
00902     }
00903     stringptr = findnextnumber(stringptr);
00904     if (*stringptr == '\0') {
00905       markers = 0;  // no boundary marker.
00906     } else {
00907       markers = (int) strtol (stringptr, &stringptr, 0);
00908     }
00909 
00910     // Initialize the 'facetlist', 'facetmarkerlist'.
00911     facetlist = new facet[numberoffacets];
00912     if (markers == 1) {
00913       facetmarkerlist = new int[numberoffacets];
00914     }
00915 
00916     // Read data into 'facetlist', 'facetmarkerlist'.
00917     if (smesh == 0) {
00918       // Facets are in .poly file format.
00919       for (i = 1; i <= numberoffacets; i++) {
00920         f = &(facetlist[i - 1]);
00921         init(f);
00922         f->numberofholes = 0;
00923         currentmarker = 0;
00924         // Read number of polygons, number of holes, and a boundary marker.
00925         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00926         f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
00927         stringptr = findnextnumber(stringptr);
00928         if (*stringptr != '\0') {
00929           f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
00930           if (markers == 1) {
00931             stringptr = findnextnumber(stringptr);
00932             if (*stringptr != '\0') {
00933               currentmarker = (int) strtol(stringptr, &stringptr, 0);
00934             }
00935           }
00936         }
00937         // Initialize facetmarker if it needs.
00938         if (markers == 1) {
00939           facetmarkerlist[i - 1] = currentmarker;
00940         }
00941         // Each facet should has at least one polygon.
00942         if (f->numberofpolygons <= 0) {
00943           printf("Error:  Wrong number of polygon in %d facet.\n", i);
00944           break;
00945         }
00946         // Initialize the 'f->polygonlist'.
00947         f->polygonlist = new polygon[f->numberofpolygons];
00948         // Go through all polygons, read in their vertices.
00949         for (j = 1; j <= f->numberofpolygons; j++) {
00950           p = &(f->polygonlist[j - 1]);
00951           init(p);
00952           // Read number of vertices of this polygon.
00953           stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00954           p->numberofvertices = (int) strtol(stringptr, &stringptr, 0);
00955           if (p->numberofvertices < 1) {
00956             printf("Error:  Wrong polygon %d in facet %d\n", j, i);
00957             break;
00958           }
00959           // Initialize 'p->vertexlist'.
00960           p->vertexlist = new int[p->numberofvertices];
00961           // Read all vertices of this polygon.
00962           for (k = 1; k <= p->numberofvertices; k++) {
00963             stringptr = findnextnumber(stringptr);
00964             if (*stringptr == '\0') {
00965               // Try to load another non-empty line and continue to read the
00966               //   rest of vertices.
00967               stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00968               if (*stringptr == '\0') {
00969                 printf("Error: Missing %d endpoints of polygon %d in facet %d",
00970                        p->numberofvertices - k, j, i);
00971                 break;
00972               }
00973             }
00974             p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
00975           }
00976         }
00977         if (j <= f->numberofpolygons) {
00978           // This must be caused by an error. However, there're j - 1
00979           //   polygons have been read. Reset the 'f->numberofpolygon'.
00980           if (j == 1) {
00981             // This is the first polygon.
00982             delete [] f->polygonlist;
00983           }
00984           f->numberofpolygons = j - 1;
00985           // No hole will be read even it exists.
00986           f->numberofholes = 0;
00987           break;
00988         }
00989         // If this facet has hole pints defined, read them.
00990         if (f->numberofholes > 0) {
00991           // Initialize 'f->holelist'.
00992           f->holelist = new REAL[f->numberofholes * 3];
00993           // Read the holes' coordinates.
00994           index = 0;
00995           for (j = 1; j <= f->numberofholes; j++) {
00996             stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00997             for (k = 1; k <= 3; k++) {
00998               stringptr = findnextnumber(stringptr);
00999               if (*stringptr == '\0') {
01000                 printf("Error:  Hole %d in facet %d has no coordinates", j, i);
01001                 break;
01002               }
01003               f->holelist[index++] = (REAL) strtod (stringptr, &stringptr);
01004             }
01005             if (k <= 3) {
01006               // This must be caused by an error.
01007               break;
01008             }
01009           }
01010           if (j <= f->numberofholes) {
01011             // This must be caused by an error.
01012             break;
01013           }
01014         }
01015       }
01016       if (i <= numberoffacets) {
01017         // This must be caused by an error.
01018         numberoffacets = i - 1;
01019         fclose(polyfile);
01020         return false;
01021       }
01022     } else { // poly == 0
01023       // Read the facets from a .smesh file.
01024       for (i = 1; i <= numberoffacets; i++) {
01025         f = &(facetlist[i - 1]);
01026         init(f);
01027         // Initialize 'f->facetlist'. In a .smesh file, each facetlist only
01028         //   contains exactly one polygon, no hole.
01029         f->numberofpolygons = 1;
01030         f->polygonlist = new polygon[f->numberofpolygons];
01031         p = &(f->polygonlist[0]);
01032         init(p);
01033         // Read number of vertices of this polygon.
01034         stringptr = readnumberline(inputline, polyfile, insmeshfilename);
01035         p->numberofvertices = (int) strtol (stringptr, &stringptr, 0);
01036         if (p->numberofvertices < 1) {
01037           printf("Error:  Wrong number of vertex in facet %d\n", i);
01038           break;
01039         }
01040         // Initialize 'p->vertexlist'.
01041         p->vertexlist = new int[p->numberofvertices];
01042         for (k = 1; k <= p->numberofvertices; k++) {
01043           stringptr = findnextnumber(stringptr);
01044           if (*stringptr == '\0') {
01045             // Try to load another non-empty line and continue to read the
01046             //   rest of vertices.
01047             stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01048             if (*stringptr == '\0') {
01049               printf("Error:  Missing %d endpoints in facet %d",
01050                      p->numberofvertices - k, i);
01051               break;
01052             }
01053           }
01054           p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
01055         }
01056         if (k <= p->numberofvertices) {
01057           // This must be caused by an error.
01058           break;
01059         }
01060         // Read facet's boundary marker at last.
01061         if (markers == 1) {
01062           stringptr = findnextnumber(stringptr);
01063           if (*stringptr == '\0') {
01064             currentmarker = 0;
01065           } else {
01066             currentmarker = (int) strtol(stringptr, &stringptr, 0);
01067           }
01068           facetmarkerlist[i - 1] = currentmarker;
01069         }
01070       }
01071       if (i <= numberoffacets) {
01072         // This must be caused by an error.
01073         numberoffacets = i - 1;
01074         fclose(polyfile);
01075         return false;
01076       }
01077     }
01078 
01079     // Read the hole section.
01080     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01081     if (*stringptr != '\0') {
01082       numberofholes = (int) strtol (stringptr, &stringptr, 0);
01083     } else {
01084       numberofholes = 0;
01085     }
01086     if (numberofholes > 0) {
01087       // Initialize 'holelist'.
01088       holelist = new REAL[numberofholes * 3];
01089       for (i = 0; i < 3 * numberofholes; i += 3) {
01090         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01091         stringptr = findnextnumber(stringptr);
01092         if (*stringptr == '\0') {
01093           printf("Error:  Hole %d has no x coord.\n", firstnumber + (i / 3));
01094           break;
01095         } else {
01096           holelist[i] = (REAL) strtod(stringptr, &stringptr);
01097         }
01098         stringptr = findnextnumber(stringptr);
01099         if (*stringptr == '\0') {
01100           printf("Error:  Hole %d has no y coord.\n", firstnumber + (i / 3));
01101           break;
01102         } else {
01103           holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
01104         }
01105         stringptr = findnextnumber(stringptr);
01106         if (*stringptr == '\0') {
01107           printf("Error:  Hole %d has no z coord.\n", firstnumber + (i / 3));
01108           break;
01109         } else {
01110           holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
01111         }
01112       }
01113       if (i < 3 * numberofholes) {
01114         // This must be caused by an error.
01115         fclose(polyfile);
01116         return false;
01117       }
01118     }
01119 
01120     // Read the region section.  The 'region' section is optional, if we
01121     //   don't reach the end-of-file, try read it in.
01122     stringptr = readnumberline(inputline, polyfile, NULL);
01123     if (stringptr != (char *) NULL && *stringptr != '\0') {
01124       numberofregions = (int) strtol (stringptr, &stringptr, 0);
01125     } else {
01126       numberofregions = 0;
01127     }
01128     if (numberofregions > 0) {
01129       // Initialize 'regionlist'.
01130       regionlist = new REAL[numberofregions * 5];
01131       index = 0;
01132       for (i = 0; i < numberofregions; i++) {
01133         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01134         stringptr = findnextnumber(stringptr);
01135         if (*stringptr == '\0') {
01136           printf("Error:  Region %d has no x coordinate.\n", firstnumber + i);
01137           break;
01138         } else {
01139           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01140         }
01141         stringptr = findnextnumber(stringptr);
01142         if (*stringptr == '\0') {
01143           printf("Error:  Region %d has no y coordinate.\n", firstnumber + i);
01144           break;
01145         } else {
01146           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01147         }
01148         stringptr = findnextnumber(stringptr);
01149         if (*stringptr == '\0') {
01150           printf("Error:  Region %d has no z coordinate.\n", firstnumber + i);
01151           break;
01152         } else {
01153           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01154         }
01155         stringptr = findnextnumber(stringptr);
01156         if (*stringptr == '\0') {
01157           printf("Error:  Region %d has no region attrib.\n", firstnumber + i);
01158           break;
01159         } else {
01160           regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01161         }
01162         stringptr = findnextnumber(stringptr);
01163         if (*stringptr == '\0') {
01164           regionlist[index] = regionlist[index - 1];
01165         } else {
01166           regionlist[index] = (REAL) strtod(stringptr, &stringptr);
01167         }
01168         index++;
01169       }
01170       if (i < numberofregions) {
01171         // This must be caused by an error.
01172         fclose(polyfile);
01173         return false;
01174       }
01175     }
01176 
01177   } else {
01178 
01179     // Read a PSLG from Triangle's poly file.
01180     assert(mesh_dim == 2);
01181     // A PSLG is a facet of a PLC.
01182     numberoffacets = 1;
01183     // Initialize the 'facetlist'.
01184     facetlist = new facet[numberoffacets];
01185     facetmarkerlist = (int *) NULL; // No facet markers.
01186     f = &(facetlist[0]);
01187     init(f);
01188     // Read number of segments.
01189     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01190     // Segments are degenerate polygons.
01191     f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
01192     if (f->numberofpolygons > 0) {
01193       f->polygonlist = new polygon[f->numberofpolygons];
01194     }
01195     // Go through all segments, read in their vertices.
01196     for (j = 0; j < f->numberofpolygons; j++) {
01197       p = &(f->polygonlist[j]);
01198       init(p);
01199       // Read in a segment.
01200       stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01201       stringptr = findnextnumber(stringptr); // Skip its index.
01202       p->numberofvertices = 2; // A segment always has two vertices.
01203       p->vertexlist = new int[p->numberofvertices];
01204       p->vertexlist[0] = (int) strtol (stringptr, &stringptr, 0);
01205       stringptr = findnextnumber(stringptr);
01206       p->vertexlist[1] = (int) strtol (stringptr, &stringptr, 0);
01207     }
01208     // Read number of holes.
01209     stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01210     f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
01211     if (f->numberofholes > 0) {
01212       // Initialize 'f->holelist'.
01213       f->holelist = new REAL[f->numberofholes * 3];
01214       // Read the holes' coordinates.
01215       for (j = 0; j < f->numberofholes; j++) {
01216         // Read a 2D hole point.
01217         stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01218         stringptr = findnextnumber(stringptr); // Skip its index.
01219         f->holelist[j * 3] = (REAL) strtod (stringptr, &stringptr);
01220         stringptr = findnextnumber(stringptr);
01221         f->holelist[j * 3 + 1] = (REAL) strtod (stringptr, &stringptr);
01222         f->holelist[j * 3 + 2] = 0.0; // The z-coord.
01223       }
01224     }
01225     // The regions are skipped.
01226 
01227   }
01228 
01229   // End of reading poly/smesh file.
01230   fclose(polyfile);
01231 
01232   // Try to load a .var file if it exists.
01233   load_var(filename);
01234   // Try to load a .mtr file if it exists.
01235   load_mtr(filename);
01236   // Try to read a .pbc file if it exists.
01237   load_pbc(filename);
01238 
01239   return true;
01240 }
01241 
01243 //                                                                           //
01244 // load_off()    Load a polyhedron described in a .off file.                 //
01245 //                                                                           //
01246 // The .off format is one of file formats of the Geomview, an interactive    //
01247 // program for viewing and manipulating geometric objects.  More information //
01248 // is available form: http://www.geomview.org.                               //
01249 //                                                                           //
01250 // 'filename' is a input filename with extension .off or without extension ( //
01251 // the .off will be added in this case). On completion, the polyhedron is    //
01252 // returned in 'pointlist' and 'facetlist'.                                  //
01253 //                                                                           //
01255 
01256 bool tetgenio::load_off(char* filename)
01257 {
01258   FILE *fp;
01259   tetgenio::facet *f;
01260   tetgenio::polygon *p;
01261   char infilename[FILENAMESIZE];
01262   char buffer[INPUTLINESIZE];
01263   char *bufferp;
01264   double *coord;
01265   int nverts = 0, iverts = 0;
01266   int nfaces = 0, ifaces = 0;
01267   int nedges = 0;
01268   int line_count = 0, i;
01269 
01270   strncpy(infilename, filename, 1024 - 1);
01271   infilename[FILENAMESIZE - 1] = '\0';
01272   if (infilename[0] == '\0') {
01273     printf("Error:  No filename.\n");
01274     return false;
01275   }
01276   if (strcmp(&infilename[strlen(infilename) - 4], ".off") != 0) {
01277     strcat(infilename, ".off");
01278   }
01279 
01280   if (!(fp = fopen(infilename, "r"))) {
01281     printf("File I/O Error:  Unable to open file %s\n", infilename);
01282     return false;
01283   }
01284   printf("Opening %s.\n", infilename);
01285 
01286   // OFF requires the index starts from '0'.
01287   firstnumber = 0;
01288 
01289   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01290     // Check section
01291     if (nverts == 0) {
01292       // Read header
01293       bufferp = strstr(bufferp, "OFF");
01294       if (bufferp != NULL) {
01295         // Read mesh counts
01296         bufferp = findnextnumber(bufferp); // Skip field "OFF".
01297         if (*bufferp == '\0') {
01298           // Read a non-empty line.
01299           bufferp = readline(buffer, fp, &line_count);
01300         }
01301         if ((sscanf(bufferp, "%d%d%d", &nverts, &nfaces, &nedges) != 3)
01302             || (nverts == 0)) {
01303           printf("Syntax error reading header on line %d in file %s\n",
01304                  line_count, infilename);
01305           fclose(fp);
01306           return false;
01307         }
01308         // Allocate memory for 'tetgenio'
01309         if (nverts > 0) {
01310           numberofpoints = nverts;
01311           pointlist = new REAL[nverts * 3];
01312         }
01313         if (nfaces > 0) {
01314           numberoffacets = nfaces;
01315           facetlist = new tetgenio::facet[nfaces];
01316         }
01317       }
01318     } else if (iverts < nverts) {
01319       // Read vertex coordinates
01320       coord = &pointlist[iverts * 3];
01321       for (i = 0; i < 3; i++) {
01322         if (*bufferp == '\0') {
01323           printf("Syntax error reading vertex coords on line %d in file %s\n",
01324                  line_count, infilename);
01325           fclose(fp);
01326           return false;
01327         }
01328         coord[i] = (REAL) strtod(bufferp, &bufferp);
01329         bufferp = findnextnumber(bufferp);
01330       }
01331       iverts++;
01332     } else if (ifaces < nfaces) {
01333       // Get next face
01334       f = &facetlist[ifaces];
01335       init(f);
01336       // In .off format, each facet has one polygon, no hole.
01337       f->numberofpolygons = 1;
01338       f->polygonlist = new tetgenio::polygon[1];
01339       p = &f->polygonlist[0];
01340       init(p);
01341       // Read the number of vertices, it should be greater than 0.
01342       p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01343       if (p->numberofvertices == 0) {
01344         printf("Syntax error reading polygon on line %d in file %s\n",
01345                line_count, infilename);
01346         fclose(fp);
01347         return false;
01348       }
01349       // Allocate memory for face vertices
01350       p->vertexlist = new int[p->numberofvertices];
01351       for (i = 0; i < p->numberofvertices; i++) {
01352         bufferp = findnextnumber(bufferp);
01353         if (*bufferp == '\0') {
01354           printf("Syntax error reading polygon on line %d in file %s\n",
01355                  line_count, infilename);
01356           fclose(fp);
01357           return false;
01358         }
01359         p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01360       }
01361       ifaces++;
01362     } else {
01363       // Should never get here
01364       printf("Found extra text starting at line %d in file %s\n", line_count,
01365              infilename);
01366       break;
01367     }
01368   }
01369 
01370   // Close file
01371   fclose(fp);
01372 
01373   // Check whether read all points
01374   if (iverts != nverts) {
01375     printf("Expected %d vertices, but read only %d vertices in file %s\n",
01376            nverts, iverts, infilename);
01377     return false;
01378   }
01379 
01380   // Check whether read all faces
01381   if (ifaces != nfaces) {
01382     printf("Expected %d faces, but read only %d faces in file %s\n",
01383            nfaces, ifaces, infilename);
01384     return false;
01385   }
01386 
01387   return true;
01388 }
01389 
01391 //                                                                           //
01392 // load_ply()    Load a polyhedron described in a .ply file.                 //
01393 //                                                                           //
01394 // 'filename' is the file name with extension .ply or without extension (the //
01395 // .ply will be added in this case).                                         //
01396 //                                                                           //
01397 // This is a simplified version of reading .ply files, which only reads the  //
01398 // set of vertices and the set of faces. Other informations (such as color,  //
01399 // material, texture, etc) in .ply file are ignored. Complete routines for   //
01400 // reading and writing ,ply files are available from: http://www.cc.gatech.  //
01401 // edu/projects/large_models/ply.html.  Except the header section, ply file  //
01402 // format has exactly the same format for listing vertices and polygons as   //
01403 // off file format.                                                          //
01404 //                                                                           //
01405 // On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
01406 //                                                                           //
01408 
01409 bool tetgenio::load_ply(char* filename)
01410 {
01411   FILE *fp;
01412   tetgenio::facet *f;
01413   tetgenio::polygon *p;
01414   char infilename[FILENAMESIZE];
01415   char buffer[INPUTLINESIZE];
01416   char *bufferp, *str;
01417   double *coord;
01418   int endheader = 0, format = 0;
01419   int nverts = 0, iverts = 0;
01420   int nfaces = 0, ifaces = 0;
01421   int line_count = 0, i;
01422 
01423   strncpy(infilename, filename, FILENAMESIZE - 1);
01424   infilename[FILENAMESIZE - 1] = '\0';
01425   if (infilename[0] == '\0') {
01426     printf("Error:  No filename.\n");
01427     return false;
01428   }
01429   if (strcmp(&infilename[strlen(infilename) - 4], ".ply") != 0) {
01430     strcat(infilename, ".ply");
01431   }
01432 
01433   if (!(fp = fopen(infilename, "r"))) {
01434     printf("Error:  Unable to open file %s\n", infilename);
01435     return false;
01436   }
01437   printf("Opening %s.\n", infilename);
01438 
01439   // PLY requires the index starts from '0'.
01440   firstnumber = 0;
01441 
01442   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01443     if (!endheader) {
01444       // Find if it is the keyword "end_header".
01445       str = strstr(bufferp, "end_header");
01446       // strstr() is case sensitive.
01447       if (!str) str = strstr(bufferp, "End_header");
01448       if (!str) str = strstr(bufferp, "End_Header");
01449       if (str) {
01450         // This is the end of the header section.
01451         endheader = 1;
01452         continue;
01453       }
01454       // Parse the number of vertices and the number of faces.
01455       if (nverts == 0 || nfaces == 0) {
01456         // Find if it si the keyword "element".
01457         str = strstr(bufferp, "element");
01458         if (!str) str = strstr(bufferp, "Element");
01459         if (str) {
01460           bufferp = findnextfield(str);
01461           if (*bufferp == '\0') {
01462             printf("Syntax error reading element type on line%d in file %s\n",
01463                    line_count, infilename);
01464             fclose(fp);
01465             return false;
01466           }
01467           if (nverts == 0) {
01468             // Find if it is the keyword "vertex".
01469             str = strstr(bufferp, "vertex");
01470             if (!str) str = strstr(bufferp, "Vertex");
01471             if (str) {
01472               bufferp = findnextnumber(str);
01473               if (*bufferp == '\0') {
01474                 printf("Syntax error reading vertex number on line");
01475                 printf(" %d in file %s\n", line_count, infilename);
01476                 fclose(fp);
01477                 return false;
01478               }
01479               nverts = (int) strtol(bufferp, &bufferp, 0);
01480               // Allocate memory for 'tetgenio'
01481               if (nverts > 0) {
01482                 numberofpoints = nverts;
01483                 pointlist = new REAL[nverts * 3];
01484               }
01485             }
01486           }
01487           if (nfaces == 0) {
01488             // Find if it is the keyword "face".
01489             str = strstr(bufferp, "face");
01490             if (!str) str = strstr(bufferp, "Face");
01491             if (str) {
01492               bufferp = findnextnumber(str);
01493               if (*bufferp == '\0') {
01494                 printf("Syntax error reading face number on line");
01495                 printf(" %d in file %s\n", line_count, infilename);
01496                 fclose(fp);
01497                 return false;
01498               }
01499               nfaces = (int) strtol(bufferp, &bufferp, 0);
01500               // Allocate memory for 'tetgenio'
01501               if (nfaces > 0) {
01502                 numberoffacets = nfaces;
01503                 facetlist = new tetgenio::facet[nfaces];
01504               }
01505             }
01506           }
01507         } // It is not the string "element".
01508       }
01509       if (format == 0) {
01510         // Find the keyword "format".
01511         str = strstr(bufferp, "format");
01512         if (!str) str = strstr(bufferp, "Format");
01513         if (str) {
01514           format = 1;
01515           bufferp = findnextfield(str);
01516           // Find if it is the string "ascii".
01517           str = strstr(bufferp, "ascii");
01518           if (!str) str = strstr(bufferp, "ASCII");
01519           if (!str) {
01520             printf("This routine only reads ascii format of ply files.\n");
01521             printf("Hint: You can convert the binary to ascii format by\n");
01522             printf("  using the provided ply tools:\n");
01523             printf("  ply2ascii < %s > ascii_%s\n", infilename, infilename);
01524             fclose(fp);
01525             return false;
01526           }
01527         }
01528       }
01529     } else if (iverts < nverts) {
01530       // Read vertex coordinates
01531       coord = &pointlist[iverts * 3];
01532       for (i = 0; i < 3; i++) {
01533         if (*bufferp == '\0') {
01534           printf("Syntax error reading vertex coords on line %d in file %s\n",
01535                  line_count, infilename);
01536           fclose(fp);
01537           return false;
01538         }
01539         coord[i] = (REAL) strtod(bufferp, &bufferp);
01540         bufferp = findnextnumber(bufferp);
01541       }
01542       iverts++;
01543     } else if (ifaces < nfaces) {
01544       // Get next face
01545       f = &facetlist[ifaces];
01546       init(f);
01547       // In .off format, each facet has one polygon, no hole.
01548       f->numberofpolygons = 1;
01549       f->polygonlist = new tetgenio::polygon[1];
01550       p = &f->polygonlist[0];
01551       init(p);
01552       // Read the number of vertices, it should be greater than 0.
01553       p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01554       if (p->numberofvertices == 0) {
01555         printf("Syntax error reading polygon on line %d in file %s\n",
01556                line_count, infilename);
01557         fclose(fp);
01558         return false;
01559       }
01560       // Allocate memory for face vertices
01561       p->vertexlist = new int[p->numberofvertices];
01562       for (i = 0; i < p->numberofvertices; i++) {
01563         bufferp = findnextnumber(bufferp);
01564         if (*bufferp == '\0') {
01565           printf("Syntax error reading polygon on line %d in file %s\n",
01566                  line_count, infilename);
01567           fclose(fp);
01568           return false;
01569         }
01570         p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01571       }
01572       ifaces++;
01573     } else {
01574       // Should never get here
01575       printf("Found extra text starting at line %d in file %s\n", line_count,
01576              infilename);
01577       break;
01578     }
01579   }
01580 
01581   // Close file
01582   fclose(fp);
01583 
01584   // Check whether read all points
01585   if (iverts != nverts) {
01586     printf("Expected %d vertices, but read only %d vertices in file %s\n",
01587            nverts, iverts, infilename);
01588     return false;
01589   }
01590 
01591   // Check whether read all faces
01592   if (ifaces != nfaces) {
01593     printf("Expected %d faces, but read only %d faces in file %s\n",
01594            nfaces, ifaces, infilename);
01595     return false;
01596   }
01597 
01598   return true;
01599 }
01600 
01602 //                                                                           //
01603 // load_stl()    Load a surface mesh described in a .stl file.               //
01604 //                                                                           //
01605 // 'filename' is the file name with extension .stl or without extension (the //
01606 // .stl will be added in this case).                                         //
01607 //                                                                           //
01608 // The .stl or stereolithography format is an ASCII or binary file used in   //
01609 // manufacturing.  It is a list of the triangular surfaces that describe a   //
01610 // computer generated solid model. This is the standard input for most rapid //
01611 // prototyping machines.                                                     //
01612 //                                                                           //
01613 // On completion, 'pointlist' and 'facetlist' together return the polyhedron.//
01614 // Note: After load_stl(), there exist many duplicated points in 'pointlist'.//
01615 // They will be unified during the Delaunay tetrahedralization process.      //
01616 //                                                                           //
01618 
01619 bool tetgenio::load_stl(char* filename)
01620 {
01621   FILE *fp;
01622   tetgenmesh::list *plist;
01623   tetgenio::facet *f;
01624   tetgenio::polygon *p;
01625   char infilename[FILENAMESIZE];
01626   char buffer[INPUTLINESIZE];
01627   char *bufferp, *str;
01628   double *coord;
01629   int solid = 0;
01630   int nverts = 0, iverts = 0;
01631   int nfaces = 0;
01632   int line_count = 0, i;
01633 
01634   strncpy(infilename, filename, FILENAMESIZE - 1);
01635   infilename[FILENAMESIZE - 1] = '\0';
01636   if (infilename[0] == '\0') {
01637     printf("Error:  No filename.\n");
01638     return false;
01639   }
01640   if (strcmp(&infilename[strlen(infilename) - 4], ".stl") != 0) {
01641     strcat(infilename, ".stl");
01642   }
01643 
01644   if (!(fp = fopen(infilename, "r"))) {
01645     printf("Error:  Unable to open file %s\n", infilename);
01646     return false;
01647   }
01648   printf("Opening %s.\n", infilename);
01649 
01650   // STL file has no number of points available. Use a list to read points.
01651   plist = new tetgenmesh::list(sizeof(double) * 3, NULL, 1024);
01652 
01653   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01654     // The ASCII .stl file must start with the lower case keyword solid and
01655     //   end with endsolid.
01656     if (solid == 0) {
01657       // Read header
01658       bufferp = strstr(bufferp, "solid");
01659       if (bufferp != NULL) {
01660         solid = 1;
01661       }
01662     } else {
01663       // We're inside the block of the solid.
01664       str = bufferp;
01665       // Is this the end of the solid.
01666       bufferp = strstr(bufferp, "endsolid");
01667       if (bufferp != NULL) {
01668         solid = 0;
01669       } else {
01670         // Read the XYZ coordinates if it is a vertex.
01671         bufferp = str;
01672         bufferp = strstr(bufferp, "vertex");
01673         if (bufferp != NULL) {
01674           coord = (double *) plist->append(NULL);
01675           for (i = 0; i < 3; i++) {
01676             bufferp = findnextnumber(bufferp);
01677             if (*bufferp == '\0') {
01678               printf("Syntax error reading vertex coords on line %d\n",
01679                    line_count);
01680               delete plist;
01681               fclose(fp);
01682               return false;
01683             }
01684             coord[i] = (REAL) strtod(bufferp, &bufferp);
01685           }
01686         }
01687       }
01688     }
01689   }
01690   fclose(fp);
01691 
01692   nverts = plist->len();
01693   // nverts should be an integer times 3 (every 3 vertices denote a face).
01694   if (nverts == 0 || (nverts % 3 != 0)) {
01695     printf("Error:  Wrong number of vertices in file %s.\n", infilename);
01696     delete plist;
01697     return false;
01698   }
01699   numberofpoints = nverts;
01700   pointlist = new REAL[nverts * 3];
01701   for (i = 0; i < nverts; i++) {
01702     coord = (double *) (* plist)[i];
01703     iverts = i * 3;
01704     pointlist[iverts] = (REAL) coord[0];
01705     pointlist[iverts + 1] = (REAL) coord[1];
01706     pointlist[iverts + 2] = (REAL) coord[2];
01707   }
01708 
01709   nfaces = (int) (nverts / 3);
01710   numberoffacets = nfaces;
01711   facetlist = new tetgenio::facet[nfaces];
01712 
01713   // Default use '1' as the array starting index.
01714   firstnumber = 1;
01715   iverts = firstnumber;
01716   for (i = 0; i < nfaces; i++) {
01717     f = &facetlist[i];
01718     init(f);
01719     // In .stl format, each facet has one polygon, no hole.
01720     f->numberofpolygons = 1;
01721     f->polygonlist = new tetgenio::polygon[1];
01722     p = &f->polygonlist[0];
01723     init(p);
01724     // Each polygon has three vertices.
01725     p->numberofvertices = 3;
01726     p->vertexlist = new int[p->numberofvertices];
01727     p->vertexlist[0] = iverts;
01728     p->vertexlist[1] = iverts + 1;
01729     p->vertexlist[2] = iverts + 2;
01730     iverts += 3;
01731   }
01732 
01733   delete plist;
01734   return true;
01735 }
01736 
01738 //                                                                           //
01739 // load_medit()    Load a surface mesh described in .mesh file.              //
01740 //                                                                           //
01741 // 'filename' is the file name with extension .mesh or without entension (   //
01742 // the .mesh will be added in this case). .mesh is the file format of Medit, //
01743 // a user-friendly interactive mesh viewing program.                         //
01744 //                                                                           //
01745 // This routine ONLY reads the sections containing vertices, triangles, and  //
01746 // quadrilaters. Other sections (such as tetrahedra, edges, ...) are ignored.//
01747 //                                                                           //
01749 
01750 bool tetgenio::load_medit(char* filename)
01751 {
01752   FILE *fp;
01753   tetgenio::facet *tmpflist, *f;
01754   tetgenio::polygon *p;
01755   char infilename[FILENAMESIZE];
01756   char buffer[INPUTLINESIZE];
01757   char *bufferp, *str;
01758   double *coord;
01759   int *tmpfmlist;
01760   int dimension = 0;
01761   int nverts = 0;
01762   int nfaces = 0;
01763   int line_count = 0;
01764   int corners = 0; // 3 (triangle) or 4 (quad).
01765   int i, j;
01766 
01767   strncpy(infilename, filename, FILENAMESIZE - 1);
01768   infilename[FILENAMESIZE - 1] = '\0';
01769   if (infilename[0] == '\0') {
01770     printf("Error:  No filename.\n");
01771     return false;
01772   }
01773   if (strcmp(&infilename[strlen(infilename) - 5], ".mesh") != 0) {
01774     strcat(infilename, ".mesh");
01775   }
01776 
01777   if (!(fp = fopen(infilename, "r"))) {
01778     printf("Error:  Unable to open file %s\n", infilename);
01779     return false;
01780   }
01781   printf("Opening %s.\n", infilename);
01782 
01783   // Default uses the index starts from '1'.
01784   firstnumber = 1;
01785 
01786   while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01787     if (*bufferp == '#') continue;  // A comment line is skipped.
01788     if (dimension == 0) {
01789       // Find if it is the keyword "Dimension".
01790       str = strstr(bufferp, "Dimension");
01791       if (!str) str = strstr(bufferp, "dimension");
01792       if (!str) str = strstr(bufferp, "DIMENSION");
01793       if (str) {
01794         // Read the dimensions
01795         bufferp = findnextnumber(str); // Skip field "Dimension".
01796         if (*bufferp == '\0') {
01797           // Read a non-empty line.
01798           bufferp = readline(buffer, fp, &line_count);
01799         }
01800         dimension = (int) strtol(bufferp, &bufferp, 0);
01801         if (dimension != 2 && dimension != 3) {
01802           printf("Unknown dimension in file on line %d in file %s\n",
01803                  line_count, infilename);
01804           fclose(fp);
01805           return false;
01806         }
01807         mesh_dim = dimension;
01808       }
01809     }
01810     if (nverts == 0) {
01811       // Find if it is the keyword "Vertices".
01812       str = strstr(bufferp, "Vertices");
01813       if (!str) str = strstr(bufferp, "vertices");
01814       if (!str) str = strstr(bufferp, "VERTICES");
01815       if (str) {
01816         // Read the number of vertices.
01817         bufferp = findnextnumber(str); // Skip field "Vertices".
01818         if (*bufferp == '\0') {
01819           // Read a non-empty line.
01820           bufferp = readline(buffer, fp, &line_count);
01821         }
01822         nverts = (int) strtol(bufferp, &bufferp, 0);
01823         // Allocate memory for 'tetgenio'
01824         if (nverts > 0) {
01825           numberofpoints = nverts;
01826           pointlist = new REAL[nverts * 3];
01827         }
01828         // Read the follwoing node list.
01829         for (i = 0; i < nverts; i++) {
01830           bufferp = readline(buffer, fp, &line_count);
01831           if (bufferp == NULL) {
01832             printf("Unexpected end of file on line %d in file %s\n",
01833                    line_count, infilename);
01834             fclose(fp);
01835             return false;
01836           }
01837           // Read vertex coordinates
01838           coord = &pointlist[i * 3];
01839           for (j = 0; j < 3; j++) {
01840             if (*bufferp == '\0') {
01841               printf("Syntax error reading vertex coords on line");
01842               printf(" %d in file %s\n", line_count, infilename);
01843               fclose(fp);
01844               return false;
01845             }
01846             if ((j < 2) || (dimension == 3)) {
01847               coord[j] = (REAL) strtod(bufferp, &bufferp);
01848             } else {
01849               assert((j == 2) && (dimension == 2));
01850               coord[j] = 0.0;
01851             }
01852             bufferp = findnextnumber(bufferp);
01853           }
01854         }
01855         continue;
01856       }
01857     }
01858     if (nfaces == 0) {
01859       // Find if it is the keyword "Triangles" or "Quadrilaterals".
01860       corners = 0;
01861       str = strstr(bufferp, "Triangles");
01862       if (!str) str = strstr(bufferp, "triangles");
01863       if (!str) str = strstr(bufferp, "TRIANGLES");
01864       if (str) {
01865         corners = 3;
01866       } else {
01867         str = strstr(bufferp, "Quadrilaterals");
01868         if (!str) str = strstr(bufferp, "quadrilaterals");
01869         if (!str) str = strstr(bufferp, "QUADRILATERALS");
01870         if (str) {
01871           corners = 4;
01872         }
01873       }
01874       if (corners == 3 || corners == 4) {
01875         // Read the number of triangles (or quadrilaterals).
01876         bufferp = findnextnumber(str); // Skip field "Triangles".
01877         if (*bufferp == '\0') {
01878           // Read a non-empty line.
01879           bufferp = readline(buffer, fp, &line_count);
01880         }
01881         nfaces = strtol(bufferp, &bufferp, 0);
01882         // Allocate memory for 'tetgenio'
01883         if (nfaces > 0) {
01884           if (numberoffacets > 0) {
01885             // facetlist has already been allocated. Enlarge arrays.
01886             tmpflist = new tetgenio::facet[numberoffacets + nfaces];
01887             tmpfmlist = new int[numberoffacets + nfaces];
01888             // Copy the data of old arrays into new arrays.
01889             for (i = 0; i < numberoffacets; i++) {
01890               f = &(tmpflist[i]);
01891               tetgenio::init(f);
01892               *f = facetlist[i];
01893               tmpfmlist[i] = facetmarkerlist[i];
01894             }
01895             // Release old arrays.
01896             delete [] facetlist;
01897             delete [] facetmarkerlist;
01898             // Remember the new arrays.
01899             facetlist = tmpflist;
01900             facetmarkerlist = tmpfmlist;
01901           } else {
01902             // This is the first time to allocate facetlist.
01903             facetlist = new tetgenio::facet[nfaces];
01904             facetmarkerlist = new int[nfaces];
01905           }
01906         }
01907         // Read the following list of faces.
01908         for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
01909           bufferp = readline(buffer, fp, &line_count);
01910           if (bufferp == NULL) {
01911             printf("Unexpected end of file on line %d in file %s\n",
01912                    line_count, infilename);
01913             fclose(fp);
01914             return false;
01915           }
01916           f = &facetlist[i];
01917           tetgenio::init(f);
01918           // In .mesh format, each facet has one polygon, no hole.
01919           f->numberofpolygons = 1;
01920           f->polygonlist = new tetgenio::polygon[1];
01921           p = &f->polygonlist[0];
01922           tetgenio::init(p);
01923           p->numberofvertices = corners;
01924           // Allocate memory for face vertices
01925           p->vertexlist = new int[p->numberofvertices];
01926           // Read the vertices of the face.
01927           for (j = 0; j < corners; j++) {
01928             if (*bufferp == '\0') {
01929               printf("Syntax error reading face on line %d in file %s\n",
01930                      line_count, infilename);
01931               fclose(fp);
01932               return false;
01933             }
01934             p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0);
01935             if (firstnumber == 1) {
01936               // Check if a '0' index appears.
01937               if (p->vertexlist[j] == 0) {
01938                 // The first index is set to be 0.
01939                 firstnumber = 0;
01940               }
01941             }
01942             bufferp = findnextnumber(bufferp);
01943           }
01944           // Read the marker of the face if it exists.
01945           facetmarkerlist[i] = 0;
01946           if (*bufferp != '\0') {
01947             facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
01948           }
01949         }
01950         // Have read in a list of triangles/quads.
01951         numberoffacets += nfaces;
01952         nfaces = 0;
01953       }
01954     }
01955     // if (nverts > 0 && nfaces > 0) break; // Ignore other data.
01956   }
01957 
01958   // Close file
01959   fclose(fp);
01960 
01961   return true;
01962 }
01963 
01965 //                                                                           //
01966 // load_plc()    Load a piecewise linear complex from file.                  //
01967 //                                                                           //
01968 // This is main entrance for loading plcs from different file formats into   //
01969 // tetgenio.  'filename' is the input file name without extention. 'object'  //
01970 // indicates which file format is used to describ the plc.                   //
01971 //                                                                           //
01973 
01974 bool tetgenio::load_plc(char* filename, int object)
01975 {
01976   enum tetgenbehavior::objecttype type;
01977 
01978   type = (enum tetgenbehavior::objecttype) object;
01979   switch (type) {
01980   case tetgenbehavior::NODES:
01981     return load_node(filename);
01982   case tetgenbehavior::POLY:
01983     return load_poly(filename);
01984   case tetgenbehavior::OFF:
01985     return load_off(filename);
01986   case tetgenbehavior::PLY:
01987     return load_ply(filename);
01988   case tetgenbehavior::STL:
01989     return load_stl(filename);
01990   case tetgenbehavior::MEDIT:
01991     return load_medit(filename);
01992   default:
01993     return load_poly(filename);
01994   }
01995 }
01996 
01998 //                                                                           //
01999 // load_tetmesh()    Load a tetrahedral mesh from files.                     //
02000 //                                                                           //
02001 // 'filename' is the inputfile without suffix.  The nodes of the tetrahedral //
02002 // mesh is in "filename.node",  the elements is in "filename.ele", if the    //
02003 // "filename.face" and "filename.vol" exists, they will also be read.        //
02004 //                                                                           //
02006 
02007 bool tetgenio::load_tetmesh(char* filename)
02008 {
02009   FILE *infile;
02010   char innodefilename[FILENAMESIZE];
02011   char inelefilename[FILENAMESIZE];
02012   char infacefilename[FILENAMESIZE];
02013   char inedgefilename[FILENAMESIZE];
02014   char involfilename[FILENAMESIZE];
02015   char inputline[INPUTLINESIZE];
02016   char *stringptr, *infilename;
02017   REAL attrib, volume;
02018   int volelements;
02019   int markers, corner;
02020   int index, attribindex;
02021   int i, j;
02022 
02023   markers = 0;
02024 
02025   // Assembling the actual file names we want to open.
02026   strcpy(innodefilename, filename);
02027   strcpy(inelefilename, filename);
02028   strcpy(infacefilename, filename);
02029   strcpy(inedgefilename, filename);
02030   strcpy(involfilename, filename);
02031   strcat(innodefilename, ".node");
02032   strcat(inelefilename, ".ele");
02033   strcat(infacefilename, ".face");
02034   strcat(inedgefilename, ".edge");
02035   strcat(involfilename, ".vol");
02036 
02037   // Read the points from a .node file.
02038   infilename = innodefilename;
02039   printf("Opening %s.\n", infilename);
02040   infile = fopen(infilename, "r");
02041   if (infile == (FILE *) NULL) {
02042     printf("File I/O Error:  Cannot access file %s.\n", infilename);
02043     return false;
02044   }
02045   // Read the first line of the file.
02046   stringptr = readnumberline(inputline, infile, infilename);
02047   // Is this list of points generated from rbox?
02048   stringptr = strstr(inputline, "rbox");
02049   if (stringptr == NULL) {
02050     // Read number of points, number of dimensions, number of point
02051     //   attributes, and number of boundary markers.
02052     stringptr = inputline;
02053     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02054     stringptr = findnextnumber(stringptr);
02055     if (*stringptr == '\0') {
02056       mesh_dim = 3;
02057     } else {
02058       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02059     }
02060     stringptr = findnextnumber(stringptr);
02061     if (*stringptr == '\0') {
02062       numberofpointattributes = 0;
02063     } else {
02064       numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
02065     }
02066     stringptr = findnextnumber(stringptr);
02067     if (*stringptr == '\0') {
02068       markers = 0;  // Default value.
02069     } else {
02070       markers = (int) strtol (stringptr, &stringptr, 0);
02071     }
02072   } else {
02073     // It is a rbox (qhull) input file.
02074     stringptr = inputline;
02075     // Get the dimension.
02076     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02077     // Get the number of points.
02078     stringptr = readnumberline(inputline, infile, infilename);
02079     numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02080     // There is no index column.
02081     useindex = 0;
02082   }
02083 
02084   // Load the list of nodes.
02085   if (!load_node_call(infile, markers, infilename)) {
02086     fclose(infile);
02087     return false;
02088   }
02089   fclose(infile);
02090 
02091   // Read the elements from an .ele file.
02092   if (mesh_dim == 3) {
02093     infilename = inelefilename;
02094     infile = fopen(infilename, "r");
02095     if (infile != (FILE *) NULL) {
02096       printf("Opening %s.\n", infilename);
02097       // Read number of elements, number of corners (4 or 10), number of
02098       //   element attributes.
02099       stringptr = readnumberline(inputline, infile, infilename);
02100       numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0);
02101       stringptr = findnextnumber(stringptr);
02102       if (*stringptr == '\0') {
02103         numberofcorners = 4;  // Default read 4 nodes per element.
02104       } else {
02105         numberofcorners = (int) strtol(stringptr, &stringptr, 0);
02106       }
02107       stringptr = findnextnumber(stringptr);
02108       if (*stringptr == '\0') {
02109         numberoftetrahedronattributes = 0; // Default no attribute.
02110       } else {
02111         numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0);
02112       }
02113       if (numberofcorners != 4 && numberofcorners != 10) {
02114         printf("Error:  Wrong number of corners %d (should be 4 or 10).\n",
02115                numberofcorners);
02116         fclose(infile);
02117         return false;
02118       }
02119       // Allocate memory for tetrahedra.
02120       if (numberoftetrahedra > 0) {
02121         tetrahedronlist = new int[numberoftetrahedra * numberofcorners];
02122         if (tetrahedronlist == (int *) NULL) {
02123           printf("Error:  Out of memory.\n");
02124           terminatetetgen(1);
02125         }
02126         // Allocate memory for output tetrahedron attributes if necessary.
02127         if (numberoftetrahedronattributes > 0) {
02128           tetrahedronattributelist = new REAL[numberoftetrahedra *
02129                                           numberoftetrahedronattributes];
02130           if (tetrahedronattributelist == (REAL *) NULL) {
02131             printf("Error:  Out of memory.\n");
02132             terminatetetgen(1);
02133           }
02134         }
02135       }
02136       // Read the list of tetrahedra.
02137       index = 0;
02138       attribindex = 0;
02139       for (i = 0; i < numberoftetrahedra; i++) {
02140         // Read tetrahedron index and the tetrahedron's corners.
02141         stringptr = readnumberline(inputline, infile, infilename);
02142         for (j = 0; j < numberofcorners; j++) {
02143           stringptr = findnextnumber(stringptr);
02144           if (*stringptr == '\0') {
02145             printf("Error:  Tetrahedron %d is missing vertex %d in %s.\n",
02146                    i + firstnumber, j + 1, infilename);
02147             terminatetetgen(1);
02148           }
02149           corner = (int) strtol(stringptr, &stringptr, 0);
02150           if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02151             printf("Error:  Tetrahedron %d has an invalid vertex index.\n",
02152                    i + firstnumber);
02153             terminatetetgen(1);
02154           }
02155           tetrahedronlist[index++] = corner;
02156         }
02157         // Read the tetrahedron's attributes.
02158         for (j = 0; j < numberoftetrahedronattributes; j++) {
02159           stringptr = findnextnumber(stringptr);
02160           if (*stringptr == '\0') {
02161             attrib = 0.0;
02162           } else {
02163             attrib = (REAL) strtod(stringptr, &stringptr);
02164           }
02165           tetrahedronattributelist[attribindex++] = attrib;
02166         }
02167       }
02168       fclose(infile);
02169     }
02170   } // if (meshdim == 3)
02171 
02172   // Read the hullfaces or subfaces from a .face file if it exists.
02173   if (mesh_dim == 3) {
02174     infilename = infacefilename;
02175   } else {
02176     infilename = inelefilename;
02177   }
02178   infile = fopen(infilename, "r");
02179   if (infile != (FILE *) NULL) {
02180     printf("Opening %s.\n", infilename);
02181     // Read number of faces, boundary markers.
02182     stringptr = readnumberline(inputline, infile, infilename);
02183     numberoftrifaces = (int) strtol (stringptr, &stringptr, 0);
02184     stringptr = findnextnumber(stringptr);
02185     if (mesh_dim == 2) {
02186       // Skip a number.
02187       stringptr = findnextnumber(stringptr);
02188     }
02189     if (*stringptr == '\0') {
02190       markers = 0;  // Default there is no marker per face.
02191     } else {
02192       markers = (int) strtol (stringptr, &stringptr, 0);
02193     }
02194     if (numberoftrifaces > 0) {
02195       trifacelist = new int[numberoftrifaces * 3];
02196       if (trifacelist == (int *) NULL) {
02197         printf("Error:  Out of memory.\n");
02198         terminatetetgen(1);
02199       }
02200       if (markers) {
02201         trifacemarkerlist = new int[numberoftrifaces * 3];
02202         if (trifacemarkerlist == (int *) NULL) {
02203           printf("Error:  Out of memory.\n");
02204           terminatetetgen(1);
02205         }
02206       }
02207     }
02208     // Read the list of faces.
02209     index = 0;
02210     for (i = 0; i < numberoftrifaces; i++) {
02211       // Read face index and the face's three corners.
02212       stringptr = readnumberline(inputline, infile, infilename);
02213       for (j = 0; j < 3; j++) {
02214         stringptr = findnextnumber(stringptr);
02215         if (*stringptr == '\0') {
02216           printf("Error:  Face %d is missing vertex %d in %s.\n",
02217                  i + firstnumber, j + 1, infilename);
02218           terminatetetgen(1);
02219         }
02220         corner = (int) strtol(stringptr, &stringptr, 0);
02221         if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02222           printf("Error:  Face %d has an invalid vertex index.\n",
02223                  i + firstnumber);
02224           terminatetetgen(1);
02225         }
02226         trifacelist[index++] = corner;
02227       }
02228       // Read the boundary marker if it exists.
02229       if (markers) {
02230         stringptr = findnextnumber(stringptr);
02231         if (*stringptr == '\0') {
02232           attrib = 0.0;
02233         } else {
02234           attrib = (REAL) strtod(stringptr, &stringptr);
02235         }
02236         trifacemarkerlist[i] = (int) attrib;
02237       }
02238     }
02239     fclose(infile);
02240   }
02241 
02242   // Read the boundary edges from a .edge file if it exists.
02243   infilename = inedgefilename;
02244   infile = fopen(infilename, "r");
02245   if (infile != (FILE *) NULL) {
02246     printf("Opening %s.\n", infilename);
02247     // Read number of boundary edges.
02248     stringptr = readnumberline(inputline, infile, infilename);
02249     numberofedges = (int) strtol (stringptr, &stringptr, 0);
02250     if (numberofedges > 0) {
02251       edgelist = new int[numberofedges * 2];
02252       if (edgelist == (int *) NULL) {
02253         printf("Error:  Out of memory.\n");
02254         terminatetetgen(1);
02255       }
02256     }
02257     // Read the list of faces.
02258     index = 0;
02259     for (i = 0; i < numberofedges; i++) {
02260       // Read face index and the edge's two endpoints.
02261       stringptr = readnumberline(inputline, infile, infilename);
02262       for (j = 0; j < 2; j++) {
02263         stringptr = findnextnumber(stringptr);
02264         if (*stringptr == '\0') {
02265           printf("Error:  Edge %d is missing vertex %d in %s.\n",
02266                  i + firstnumber, j + 1, infilename);
02267           terminatetetgen(1);
02268         }
02269         corner = (int) strtol(stringptr, &stringptr, 0);
02270         if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02271           printf("Error:  Edge %d has an invalid vertex index.\n",
02272                  i + firstnumber);
02273           terminatetetgen(1);
02274         }
02275         edgelist[index++] = corner;
02276       }
02277     }
02278     fclose(infile);
02279   }
02280 
02281   // Read the volume constraints from a .vol file if it exists.
02282   infilename = involfilename;
02283   infile = fopen(infilename, "r");
02284   if (infile != (FILE *) NULL) {
02285     printf("Opening %s.\n", infilename);
02286     // Read number of tetrahedra.
02287     stringptr = readnumberline(inputline, infile, infilename);
02288     volelements = (int) strtol (stringptr, &stringptr, 0);
02289     if (volelements != numberoftetrahedra) {
02290       printf("Warning:  %s and %s disagree on number of tetrahedra.\n",
02291              inelefilename, involfilename);
02292       volelements = 0;
02293     }
02294     if (volelements > 0) {
02295       tetrahedronvolumelist = new REAL[volelements];
02296       if (tetrahedronvolumelist == (REAL *) NULL) {
02297         printf("Error:  Out of memory.\n");
02298         terminatetetgen(1);
02299       }
02300     }
02301     // Read the list of volume constraints.
02302     for (i = 0; i < volelements; i++) {
02303       stringptr = readnumberline(inputline, infile, infilename);
02304       stringptr = findnextnumber(stringptr);
02305       if (*stringptr == '\0') {
02306         volume = -1.0; // No constraint on this tetrahedron.
02307       } else {
02308         volume = (REAL) strtod(stringptr, &stringptr);
02309       }
02310       tetrahedronvolumelist[i] = volume;
02311     }
02312     fclose(infile);
02313   }
02314 
02315   // Try to load a .mtr file if it exists.
02316   load_mtr(filename);
02317   // Try to read a .pbc file if it exists.
02318   load_pbc(filename);
02319 
02320   return true;
02321 }
02322 
02324 //                                                                           //
02325 // load_voronoi()    Load a Voronoi diagram from files.                      //
02326 //                                                                           //
02327 // 'filename' is the inputfile without suffix.  The Voronoi diagram is read  //
02328 // from files: filename.v.node, filename.v.edge, and filename.v.face.        //
02329 //                                                                           //
02331 
02332 bool tetgenio::load_voronoi(char* filename)
02333 {
02334   FILE *infile;
02335   char innodefilename[FILENAMESIZE];
02336   char inedgefilename[FILENAMESIZE];
02337   char inputline[INPUTLINESIZE];
02338   char *stringptr, *infilename;
02339   voroedge *vedge;
02340   REAL x, y, z;
02341   int firstnode, corner;
02342   int index;
02343   int i, j;
02344 
02345   // Assembling the actual file names we want to open.
02346   strcpy(innodefilename, filename);
02347   strcpy(inedgefilename, filename);
02348   strcat(innodefilename, ".v.node");
02349   strcat(inedgefilename, ".v.edge");
02350 
02351   // Read the points from a .v.node file.
02352   infilename = innodefilename;
02353   printf("Opening %s.\n", infilename);
02354   infile = fopen(infilename, "r");
02355   if (infile == (FILE *) NULL) {
02356     printf("File I/O Error:  Cannot access file %s.\n", infilename);
02357     return false;
02358   }
02359   // Read the first line of the file.
02360   stringptr = readnumberline(inputline, infile, infilename);
02361   // Is this list of points generated from rbox?
02362   stringptr = strstr(inputline, "rbox");
02363   if (stringptr == NULL) {
02364     // Read number of points, number of dimensions, number of point
02365     //   attributes, and number of boundary markers.
02366     stringptr = inputline;
02367     numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02368     stringptr = findnextnumber(stringptr);
02369     if (*stringptr == '\0') {
02370       mesh_dim = 3;  // Default.
02371     } else {
02372       mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02373     }
02374     useindex = 1;  // There is an index column.
02375   } else {
02376     // It is a rbox (qhull) input file.
02377     stringptr = inputline;
02378     // Get the dimension.
02379     mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02380     // Get the number of points.
02381     stringptr = readnumberline(inputline, infile, infilename);
02382     numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02383     useindex = 0;  // No index column.
02384   }
02385   // Initialize 'vpointlist'.
02386   vpointlist = new REAL[numberofvpoints * 3];
02387   if (vpointlist == (REAL *) NULL) {
02388     printf("Error:  Out of memory.\n");
02389     terminatetetgen(1);
02390   }
02391   // Read the point section.
02392   index = 0;
02393   for (i = 0; i < numberofvpoints; i++) {
02394     stringptr = readnumberline(inputline, infile, infilename);
02395     if (useindex) {
02396       if (i == 0) {
02397         firstnode = (int) strtol (stringptr, &stringptr, 0);
02398         if ((firstnode == 0) || (firstnode == 1)) {
02399           firstnumber = firstnode;
02400         }
02401       }
02402       stringptr = findnextnumber(stringptr);
02403     } // if (useindex)
02404     if (*stringptr == '\0') {
02405       printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
02406       terminatetetgen(1);
02407     }
02408     x = (REAL) strtod(stringptr, &stringptr);
02409     stringptr = findnextnumber(stringptr);
02410     if (*stringptr == '\0') {
02411       printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
02412       terminatetetgen(1);
02413     }
02414     y = (REAL) strtod(stringptr, &stringptr);
02415     if (mesh_dim == 3) {
02416       stringptr = findnextnumber(stringptr);
02417       if (*stringptr == '\0') {
02418         printf("Error:  Point %d has no z coordinate.\n", firstnumber + i);
02419         terminatetetgen(1);
02420       }
02421       z = (REAL) strtod(stringptr, &stringptr);
02422     } else {
02423       z = 0.0; // mesh_dim == 2;
02424     }
02425     vpointlist[index++] = x;
02426     vpointlist[index++] = y;
02427     vpointlist[index++] = z;
02428   }
02429   fclose(infile);
02430 
02431   // Read the Voronoi edges from a .v.edge file if it exists.
02432   infilename = inedgefilename;
02433   infile = fopen(infilename, "r");
02434   if (infile != (FILE *) NULL) {
02435     printf("Opening %s.\n", infilename);
02436     // Read number of boundary edges.
02437     stringptr = readnumberline(inputline, infile, infilename);
02438     numberofvedges = (int) strtol (stringptr, &stringptr, 0);
02439     if (numberofvedges > 0) {
02440       vedgelist = new voroedge[numberofvedges];
02441     }
02442     // Read the list of faces.
02443     index = 0;
02444     for (i = 0; i < numberofvedges; i++) {
02445       // Read edge index and the edge's two endpoints.
02446       stringptr = readnumberline(inputline, infile, infilename);
02447       vedge = &(vedgelist[i]);
02448       for (j = 0; j < 2; j++) {
02449         stringptr = findnextnumber(stringptr);
02450         if (*stringptr == '\0') {
02451           printf("Error:  Edge %d is missing vertex %d in %s.\n",
02452                  i + firstnumber, j + 1, infilename);
02453           terminatetetgen(1);
02454         }
02455         corner = (int) strtol(stringptr, &stringptr, 0);
02456         j == 0 ? vedge->v1 = corner : vedge->v2 = corner;
02457       }
02458       if (vedge->v2 < 0) {
02459         for (j = 0; j < mesh_dim; j++) {
02460           stringptr = findnextnumber(stringptr);
02461           if (*stringptr == '\0') {
02462             printf("Error:  Edge %d is missing normal in %s.\n",
02463                    i + firstnumber, infilename);
02464             terminatetetgen(1);
02465           }
02466           vedge->vnormal[j] = (REAL) strtod(stringptr, &stringptr);
02467         }
02468         if (mesh_dim == 2) {
02469           vedge->vnormal[2] = 0.0;
02470         }
02471       } else {
02472         vedge->vnormal[0] = 0.0;
02473         vedge->vnormal[1] = 0.0;
02474         vedge->vnormal[2] = 0.0;
02475       }
02476     }
02477     fclose(infile);
02478   }
02479 
02480   return true;
02481 }
02482 
02484 //                                                                           //
02485 // save_nodes()    Save points to a .node file.                              //
02486 //                                                                           //
02487 // 'filename' is a string containing the file name without suffix.           //
02488 //                                                                           //
02490 
02491 void tetgenio::save_nodes(char* filename)
02492 {
02493   FILE *fout;
02494   char outnodefilename[FILENAMESIZE];
02495   char outmtrfilename[FILENAMESIZE];
02496   int i, j;
02497 
02498   sprintf(outnodefilename, "%s.node", filename);
02499   printf("Saving nodes to %s\n", outnodefilename);
02500   fout = fopen(outnodefilename, "w");
02501   fprintf(fout, "%d  %d  %d  %d\n", numberofpoints, mesh_dim,
02502           numberofpointattributes, pointmarkerlist != NULL ? 1 : 0);
02503   for (i = 0; i < numberofpoints; i++) {
02504     if (mesh_dim == 2) {
02505       fprintf(fout, "%d  %.16g  %.16g", i + firstnumber, pointlist[i * 2],
02506               pointlist[i * 2 + 1]);
02507     } else {
02508       fprintf(fout, "%d  %.16g  %.16g  %.16g", i + firstnumber,
02509               pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
02510     }
02511     for (j = 0; j < numberofpointattributes; j++) {
02512       fprintf(fout, "  %.16g",
02513               pointattributelist[i * numberofpointattributes + j]);
02514     }
02515     if (pointmarkerlist != NULL) {
02516       fprintf(fout, "  %d", pointmarkerlist[i]);
02517     }
02518     fprintf(fout, "\n");
02519   }
02520   fclose(fout);
02521 
02522   // If the point metrics exist, output them to a .mtr file.
02523   if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
02524     sprintf(outmtrfilename, "%s.mtr", filename);
02525     printf("Saving metrics to %s\n", outmtrfilename);
02526     fout = fopen(outmtrfilename, "w");
02527     fprintf(fout, "%d  %d\n", numberofpoints, numberofpointmtrs);
02528     for (i = 0; i < numberofpoints; i++) {
02529       for (j = 0; j < numberofpointmtrs; j++) {
02530         fprintf(fout, "%.16g ", pointmtrlist[i * numberofpointmtrs + j]);
02531       }
02532       fprintf(fout, "\n");
02533     }
02534     fclose(fout);
02535   }
02536 }
02537 
02539 //                                                                           //
02540 // save_elements()    Save elements to a .ele file.                          //
02541 //                                                                           //
02542 // 'filename' is a string containing the file name without suffix.           //
02543 //                                                                           //
02545 
02546 void tetgenio::save_elements(char* filename)
02547 {
02548   FILE *fout;
02549   char outelefilename[FILENAMESIZE];
02550   int i, j;
02551 
02552   sprintf(outelefilename, "%s.ele", filename);
02553   printf("Saving elements to %s\n", outelefilename);
02554   fout = fopen(outelefilename, "w");
02555   fprintf(fout, "%d  %d  %d\n", numberoftetrahedra, numberofcorners,
02556           numberoftetrahedronattributes);
02557   for (i = 0; i < numberoftetrahedra; i++) {
02558     fprintf(fout, "%d", i + firstnumber);
02559     for (j = 0; j < numberofcorners; j++) {
02560       fprintf(fout, "  %5d", tetrahedronlist[i * numberofcorners + j]);
02561     }
02562     for (j = 0; j < numberoftetrahedronattributes; j++) {
02563       fprintf(fout, "  %g",
02564         tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
02565     }
02566     fprintf(fout, "\n");
02567   }
02568 
02569   fclose(fout);
02570 }
02571 
02573 //                                                                           //
02574 // save_faces()    Save faces to a .face file.                               //
02575 //                                                                           //
02576 // 'filename' is a string containing the file name without suffix.           //
02577 //                                                                           //
02579 
02580 void tetgenio::save_faces(char* filename)
02581 {
02582   FILE *fout;
02583   char outfacefilename[FILENAMESIZE];
02584   int i;
02585 
02586   sprintf(outfacefilename, "%s.face", filename);
02587   printf("Saving faces to %s\n", outfacefilename);
02588   fout = fopen(outfacefilename, "w");
02589   fprintf(fout, "%d  %d\n", numberoftrifaces,
02590           trifacemarkerlist != NULL ? 1 : 0);
02591   for (i = 0; i < numberoftrifaces; i++) {
02592     fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber, trifacelist[i * 3],
02593             trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
02594     if (trifacemarkerlist != NULL) {
02595       fprintf(fout, "  %d", trifacemarkerlist[i]);
02596     }
02597     fprintf(fout, "\n");
02598   }
02599 
02600   fclose(fout);
02601 }
02602 
02604 //                                                                           //
02605 // save_edges()    Save egdes to a .edge file.                               //
02606 //                                                                           //
02607 // 'filename' is a string containing the file name without suffix.           //
02608 //                                                                           //
02610 
02611 void tetgenio::save_edges(char* filename)
02612 {
02613   FILE *fout;
02614   char outedgefilename[FILENAMESIZE];
02615   int i;
02616 
02617   sprintf(outedgefilename, "%s.edge", filename);
02618   printf("Saving edges to %s\n", outedgefilename);
02619   fout = fopen(outedgefilename, "w");
02620   fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02621   for (i = 0; i < numberofedges; i++) {
02622     fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
02623             edgelist[i * 2 + 1]);
02624     if (edgemarkerlist != NULL) {
02625       fprintf(fout, "  %d", edgemarkerlist[i]);
02626     }
02627     fprintf(fout, "\n");
02628   }
02629 
02630   fclose(fout);
02631 }
02632 
02634 //                                                                           //
02635 // save_neighbors()    Save egdes to a .neigh file.                          //
02636 //                                                                           //
02637 // 'filename' is a string containing the file name without suffix.           //
02638 //                                                                           //
02640 
02641 void tetgenio::save_neighbors(char* filename)
02642 {
02643   FILE *fout;
02644   char outneighborfilename[FILENAMESIZE];
02645   int i;
02646 
02647   sprintf(outneighborfilename, "%s.neigh", filename);
02648   printf("Saving neighbors to %s\n", outneighborfilename);
02649   fout = fopen(outneighborfilename, "w");
02650   fprintf(fout, "%d  %d\n", numberoftetrahedra, mesh_dim + 1);
02651   for (i = 0; i < numberoftetrahedra; i++) {
02652     if (mesh_dim == 2) {
02653       fprintf(fout, "%d  %5d  %5d  %5d", i + firstnumber,  neighborlist[i * 3],
02654               neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]);
02655     } else {
02656       fprintf(fout, "%d  %5d  %5d  %5d  %5d", i + firstnumber,
02657               neighborlist[i * 4], neighborlist[i * 4 + 1],
02658               neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]);
02659     }
02660     fprintf(fout, "\n");
02661   }
02662 
02663   fclose(fout);
02664 }
02665 
02667 //                                                                           //
02668 // save_poly()    Save segments or facets to a .poly file.                   //
02669 //                                                                           //
02670 // 'filename' is a string containing the file name without suffix.  It only  //
02671 // save the facets, holes and regions.  The nodes are saved in a .node file  //
02672 // by routine save_nodes().                                                  //
02673 //                                                                           //
02675 
02676 void tetgenio::save_poly(char* filename)
02677 {
02678   FILE *fout;
02679   facet *f;
02680   polygon *p;
02681   char outpolyfilename[FILENAMESIZE];
02682   int i, j, k;
02683 
02684   sprintf(outpolyfilename, "%s.poly", filename);
02685   printf("Saving poly to %s\n", outpolyfilename);
02686   fout = fopen(outpolyfilename, "w");
02687 
02688   // The zero indicates that the vertices are in a separate .node file.
02689   //   Followed by number of dimensions, number of vertex attributes,
02690   //   and number of boundary markers (zero or one).
02691   fprintf(fout, "%d  %d  %d  %d\n", 0, mesh_dim, numberofpointattributes,
02692           pointmarkerlist != NULL ? 1 : 0);
02693 
02694   // Save segments or facets.
02695   if (mesh_dim == 2) {
02696     // Number of segments, number of boundary markers (zero or one).
02697     fprintf(fout, "%d  %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02698     for (i = 0; i < numberofedges; i++) {
02699       fprintf(fout, "%d  %4d  %4d", i + firstnumber, edgelist[i * 2],
02700               edgelist[i * 2 + 1]);
02701       if (edgemarkerlist != NULL) {
02702         fprintf(fout, "  %d", edgemarkerlist[i]);
02703       }
02704       fprintf(fout, "\n");
02705     }
02706   } else {
02707     // Number of facets, number of boundary markers (zero or one).
02708     fprintf(fout, "%d  %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0);
02709     for (i = 0; i < numberoffacets; i++) {
02710       f = &(facetlist[i]);
02711       fprintf(fout, "%d  %d  %d  # %d\n", f->numberofpolygons,f->numberofholes,
02712             facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber);
02713       // Output polygons of this facet.
02714       for (j = 0; j < f->numberofpolygons; j++) {
02715         p = &(f->polygonlist[j]);
02716         fprintf(fout, "%d  ", p->numberofvertices);
02717         for (k = 0; k < p->numberofvertices; k++) {
02718           if (((k + 1) % 10) == 0) {
02719             fprintf(fout, "\n  ");
02720           }
02721           fprintf(fout, "  %d", p->vertexlist[k]);
02722         }
02723         fprintf(fout, "\n");
02724       }
02725       // Output holes of this facet.
02726       for (j = 0; j < f->numberofholes; j++) {
02727         fprintf(fout, "%d  %.12g  %.12g  %.12g\n", j + firstnumber,
02728            f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]);
02729       }
02730     }
02731   }
02732 
02733   // Save holes.
02734   fprintf(fout, "%d\n", numberofholes);
02735   for (i = 0; i < numberofholes; i++) {
02736     // Output x, y coordinates.
02737     fprintf(fout, "%d  %.12g  %.12g", i + firstnumber, holelist[i * mesh_dim],
02738             holelist[i * mesh_dim + 1]);
02739     if (mesh_dim == 3) {
02740       // Output z coordinate.
02741       fprintf(fout, "  %.12g", holelist[i * mesh_dim + 2]);
02742     }
02743     fprintf(fout, "\n");
02744   }
02745 
02746   // Save regions.
02747   fprintf(fout, "%d\n", numberofregions);
02748   for (i = 0; i < numberofregions; i++) {
02749     if (mesh_dim == 2) {
02750       // Output the index, x, y coordinates, attribute (region number)
02751       //   and maximum area constraint (maybe -1).
02752       fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
02753               regionlist[i * 4], regionlist[i * 4 + 1],
02754               regionlist[i * 4 + 2], regionlist[i * 4 + 3]);
02755     } else {
02756       // Output the index, x, y, z coordinates, attribute (region number)
02757       //   and maximum volume constraint (maybe -1).
02758       fprintf(fout, "%d  %.12g  %.12g  %.12g  %.12g  %.12g\n", i + firstnumber,
02759               regionlist[i * 5], regionlist[i * 5 + 1],
02760               regionlist[i * 5 + 2], regionlist[i * 5 + 3],
02761               regionlist[i * 5 + 4]);
02762     }
02763   }
02764 
02765   fclose(fout);
02766 }
02767 
02769 //                                                                           //
02770 // readline()   Read a nonempty line from a file.                            //
02771 //                                                                           //
02772 // A line is considered "nonempty" if it contains something more than white  //
02773 // spaces.  If a line is considered empty, it will be dropped and the next   //
02774 // line will be read, this process ends until reaching the end-of-file or a  //
02775 // non-empty line.  Return NULL if it is the end-of-file, otherwise, return  //
02776 // a pointer to the first non-whitespace character of the line.              //
02777 //                                                                           //
02779 
02780 char* tetgenio::readline(char *string, FILE *infile, int *linenumber)
02781 {
02782   char *result;
02783 
02784   // Search for a non-empty line.
02785   do {
02786     result = fgets(string, INPUTLINESIZE - 1, infile);
02787     if (linenumber) (*linenumber)++;
02788     if (result == (char *) NULL) {
02789       return (char *) NULL;
02790     }
02791     // Skip white spaces.
02792     while ((*result == ' ') || (*result == '\t')) result++;
02793     // If it's end of line, read another line and try again.
02794   } while (*result == '\0');
02795   return result;
02796 }
02797 
02799 //                                                                           //
02800 // findnextfield()   Find the next field of a string.                        //
02801 //                                                                           //
02802 // Jumps past the current field by searching for whitespace or a comma, then //
02803 // jumps past the whitespace or the comma to find the next field.            //
02804 //                                                                           //
02806 
02807 char* tetgenio::findnextfield(char *string)
02808 {
02809   char *result;
02810 
02811   result = string;
02812   // Skip the current field.  Stop upon reaching whitespace or a comma.
02813   while ((*result != '\0') && (*result != ' ') &&  (*result != '\t') &&
02814          (*result != ',') && (*result != ';')) {
02815     result++;
02816   }
02817   // Now skip the whitespace or the comma, stop at anything else that looks
02818   //   like a character, or the end of a line.
02819   while ((*result == ' ') || (*result == '\t') || (*result == ',') ||
02820          (*result == ';')) {
02821     result++;
02822   }
02823   return result;
02824 }
02825 
02827 //                                                                           //
02828 // readnumberline()   Read a nonempty number line from a file.               //
02829 //                                                                           //
02830 // A line is considered "nonempty" if it contains something that looks like  //
02831 // a number.  Comments (prefaced by `#') are ignored.                        //
02832 //                                                                           //
02834 
02835 char* tetgenio::readnumberline(char *string, FILE *infile, char *infilename)
02836 {
02837   char *result;
02838 
02839   // Search for something that looks like a number.
02840   do {
02841     result = fgets(string, INPUTLINESIZE, infile);
02842     if (result == (char *) NULL) {
02843       if (infilename != (char *) NULL) {
02844         printf("  Error:  Unexpected end of file in %s.\n", infilename);
02845         terminatetetgen(1);
02846       }
02847       return result;
02848     }
02849     // Skip anything that doesn't look like a number, a comment,
02850     //   or the end of a line.
02851     while ((*result != '\0') && (*result != '#')
02852            && (*result != '.') && (*result != '+') && (*result != '-')
02853            && ((*result < '0') || (*result > '9'))) {
02854       result++;
02855     }
02856     // If it's a comment or end of line, read another line and try again.
02857   } while ((*result == '#') || (*result == '\0'));
02858   return result;
02859 }
02860 
02862 //                                                                           //
02863 // findnextnumber()   Find the next field of a number string.                //
02864 //                                                                           //
02865 // Jumps past the current field by searching for whitespace or a comma, then //
02866 // jumps past the whitespace or the comma to find the next field that looks  //
02867 // like a number.                                                            //
02868 //                                                                           //
02870 
02871 char* tetgenio::findnextnumber(char *string)
02872 {
02873   char *result;
02874 
02875   result = string;
02876   // Skip the current field.  Stop upon reaching whitespace or a comma.
02877   while ((*result != '\0') && (*result != '#') && (*result != ' ') &&
02878          (*result != '\t') && (*result != ',')) {
02879     result++;
02880   }
02881   // Now skip the whitespace and anything else that doesn't look like a
02882   //   number, a comment, or the end of a line.
02883   while ((*result != '\0') && (*result != '#')
02884          && (*result != '.') && (*result != '+') && (*result != '-')
02885          && ((*result < '0') || (*result > '9'))) {
02886     result++;
02887   }
02888   // Check for a comment (prefixed with `#').
02889   if (*result == '#') {
02890     *result = '\0';
02891   }
02892   return result;
02893 }
02894 
02895 //
02896 // End of class 'tetgenio' implementation
02897 //
02898 
02899 static REAL PI = 3.14159265358979323846264338327950288419716939937510582;
02900 
02901 //
02902 // Begin of class 'tetgenbehavior' implementation
02903 //
02904 
02906 //                                                                           //
02907 // tetgenbehavior()    Initialize veriables of 'tetgenbehavior'.             //
02908 //                                                                           //
02910 
02911 tetgenbehavior::tetgenbehavior()
02912 {
02913   // Initialize command line switches.
02914   plc = 0;
02915   quality = 0;
02916   refine = 0;
02917   coarse = 0;
02918   metric = 0;
02919   minratio = 2.0;
02920   goodratio = 0.0;
02921   minangle = 20.0;
02922   goodangle = 0.0;
02923   maxdihedral = 165.0;
02924   mindihedral = 5.0;
02925   varvolume = 0;
02926   fixedvolume = 0;
02927   maxvolume = -1.0;
02928   regionattrib = 0;
02929   insertaddpoints = 0;
02930   diagnose = 0;
02931   offcenter = 0;
02932   conformdel = 0;
02933   alpha1 = sqrt(2.0);
02934   alpha2 = 1.0;
02935   alpha3 = 0.6;
02936   zeroindex = 0;
02937   facesout = 0;
02938   edgesout = 0;
02939   neighout = 0;
02940   voroout = 0;
02941   meditview = 0;
02942   gidview = 0;
02943   geomview = 0;
02944   optlevel = 3;
02945   optpasses = 3;
02946   order = 1;
02947   nojettison = 0;
02948   nobound = 0;
02949   nonodewritten = 0;
02950   noelewritten = 0;
02951   nofacewritten = 0;
02952   noiterationnum = 0;
02953   nobisect = 0;
02954   noflip = 0;
02955   steiner = -1;
02956   fliprepair = 1;
02957   nomerge = 0;
02958   docheck = 0;
02959   quiet = 0;
02960   verbose = 0;
02961   useshelles = 0;
02962   epsilon = 1.0e-8;
02963   epsilon2 = 1.0e-5;
02964   object = NONE;
02965   // Initialize strings
02966   commandline[0] = '\0';
02967   infilename[0] = '\0';
02968   outfilename[0] = '\0';
02969   addinfilename[0] = '\0';
02970   bgmeshfilename[0] = '\0';
02971 }
02972 
02974 //                                                                           //
02975 // versioninfo()    Print the version information of TetGen.                 //
02976 //                                                                           //
02978 
02979 void tetgenbehavior::versioninfo()
02980 {
02981   printf("Version 1.4.2 (April 16, 2007).\n");
02982   printf("\n");
02983   printf("Copyright (C) 2002 - 2007\n");
02984   printf("Hang Si\n");
02985   printf("Mohrenstr. 39, 10117 Berlin, Germany\n");
02986   printf("si@wias-berlin.de\n");
02987 }
02988 
02990 //                                                                           //
02991 // syntax()    Print list of command line switches and exit the program.     //
02992 //                                                                           //
02994 
02995 void tetgenbehavior::syntax()
02996 {
02997   printf("  tetgen [-prq_Ra_AiMYS_T_dzo_fenvgGOJBNEFICQVh] input_file\n");
02998   printf("    -p  Tetrahedralizes a piecewise linear complex (PLC).\n");
02999   printf("    -r  Reconstructs a previously generated mesh.\n");
03000   printf("    -q  Quality mesh generation (adding new mesh points to ");
03001   printf("improve mesh quality).\n");
03002   printf("    -R  Mesh coarsening (deleting redundant mesh points).\n");
03003   printf("    -a  Applies a maximum tetrahedron volume constraint.\n");
03004   printf("    -A  Assigns attributes to identify tetrahedra in different ");
03005   printf("regions.\n");
03006   printf("    -i  Inserts a list of additional points into mesh.\n");
03007   printf("    -M  Does not merge coplanar facets.\n");
03008   printf("    -Y  Suppresses boundary facets/segments splitting.\n");
03009   printf("    -S  Specifies maximum number of added points.\n");
03010   printf("    -T  Sets a tolerance for coplanar test (default 1e-8).\n");
03011   printf("    -d  Detects self-intersections of facets of the PLC.\n");
03012   printf("    -z  Numbers all output items starting from zero.\n");
03013   printf("    -o2 Generates second-order subparametric elements.\n");
03014   printf("    -f  Outputs all faces to .face file.");
03015   printf("file.\n");
03016   printf("    -e  Outputs all edges to .edge file.\n");
03017   printf("    -n  Outputs tetrahedra neighbors to .neigh file.\n");
03018   printf("    -v  Outputs Voronoi diagram to files.\n");
03019   printf("    -g  Outputs mesh to .mesh file for viewing by Medit.\n");
03020   printf("    -G  Outputs mesh to .msh file for viewing by Gid.\n");
03021   printf("    -O  Outputs mesh to .off file for viewing by Geomview.\n");
03022   printf("    -J  No jettison of unused vertices from output .node file.\n");
03023   printf("    -B  Suppresses output of boundary information.\n");
03024   printf("    -N  Suppresses output of .node file.\n");
03025   printf("    -E  Suppresses output of .ele file.\n");
03026   printf("    -F  Suppresses output of .face file.\n");
03027   printf("    -I  Suppresses mesh iteration numbers.\n");
03028   printf("    -C  Checks the consistency of the final mesh.\n");
03029   printf("    -Q  Quiet:  No terminal output except errors.\n");
03030   printf("    -V  Verbose:  Detailed information, more terminal output.\n");
03031   printf("    -h  Help:  A brief instruction for using TetGen.\n");
03032 }
03033 
03035 //                                                                           //
03036 // usage()    Print a brief instruction for using TetGen.                    //
03037 //                                                                           //
03039 
03040 void tetgenbehavior::usage()
03041 {
03042   printf("TetGen\n");
03043   printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
03044   printf("Triangulator\n");
03045   versioninfo();
03046   printf("\n");
03047   printf("What Can TetGen Do?\n");
03048   printf("\n");
03049   printf("  TetGen generates exact Delaunay tetrahedralizations, exact\n");
03050   printf("  constrained Delaunay tetrahedralizations, and quality ");
03051   printf("tetrahedral\n  meshes. The latter are nicely graded and whose ");
03052   printf("tetrahedra have\n  radius-edge ratio bounded, thus are suitable ");
03053   printf("for finite element and\n  finite volume analysis.\n");
03054   printf("\n");
03055   printf("Command Line Syntax:\n");
03056   printf("\n");
03057   printf("  Below is the command line syntax of TetGen with a list of ");
03058   printf("short\n");
03059   printf("  descriptions. Underscores indicate that numbers may optionally\n");
03060   printf("  follow certain switches.  Do not leave any space between a ");
03061   printf("switch\n");
03062   printf("  and its numeric parameter.  \'input_file\' contains input data\n");
03063   printf("  depending on the switches you supplied which may be a ");
03064   printf("  piecewise\n");
03065   printf("  linear complex or a list of nodes.  File formats and detailed\n");
03066   printf("  description of command line switches are found in user's ");
03067   printf("manual.\n");
03068   printf("\n");
03069   syntax();
03070   printf("\n");
03071   printf("Examples of How to Use TetGen:\n");
03072   printf("\n");
03073   printf("  \'tetgen object\' reads vertices from object.node, and writes ");
03074   printf("their\n  Delaunay tetrahedralization to object.1.node and ");
03075   printf("object.1.ele.\n");
03076   printf("\n");
03077   printf("  \'tetgen -p object\' reads a PLC from object.poly or object.");
03078   printf("smesh (and\n  possibly object.node) and writes its constrained ");
03079   printf("Delaunay\n  tetrahedralization to object.1.node, object.1.ele and ");
03080   printf("object.1.face.\n");
03081   printf("\n");
03082   printf("  \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
03083   printf("  object.smesh (and possibly object.node), generates a mesh ");
03084   printf("whose\n  tetrahedra have radius-edge ratio smaller than 1.414 and ");
03085   printf("have volume\n  of 0.1 or less, and writes the mesh to ");
03086   printf("object.1.node, object.1.ele\n  and object.1.face.\n");
03087   printf("\n");
03088   printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
03089 }
03090 
03092 //                                                                           //
03093 // parse_commandline()    Read the command line, identify switches, and set  //
03094 //                        up options and file names.                         //
03095 //                                                                           //
03096 // 'argc' and 'argv' are the same parameters passed to the function main()   //
03097 // of a C/C++ program. They together represent the command line user invoked //
03098 // from an environment in which TetGen is running.                           //
03099 //                                                                           //
03100 // When TetGen is invoked from an environment. 'argc' is nonzero, switches   //
03101 // and input filename should be supplied as zero-terminated strings in       //
03102 // argv[0] through argv[argc - 1] and argv[0] shall be the name used to      //
03103 // invoke TetGen, i.e. "tetgen".  Switches are previously started with a     //
03104 // dash '-' to identify them from the input filename.                        //
03105 //                                                                           //
03106 // When TetGen is called from within another program. 'argc' is set to zero. //
03107 // switches are given in one zero-terminated string (no previous dash is     //
03108 // required.), and 'argv' is a pointer points to this string.  No input      //
03109 // filename is required (usually the input data has been directly created by //
03110 // user in the 'tetgenio' structure).  A default filename 'tetgen-tmpfile'   //
03111 // will be created for debugging output purpose.                             //
03112 //                                                                           //
03114 
03115 bool tetgenbehavior::parse_commandline(int argc, char **argv)
03116 {
03117   int startindex;
03118   int increment;
03119   int meshnumber;
03120   int scount;
03121   int i, j, k;
03122   char workstring[1024];
03123 
03124   // First determine the input style of the switches.
03125   if (argc == 0) {
03126     startindex = 0;                    // Switches are given without a dash.
03127     argc = 1;                    // For running the following for-loop once.
03128     commandline[0] = '\0';
03129   } else {
03130     startindex = 1;
03131     strcpy(commandline, argv[0]);
03132     strcat(commandline, " ");
03133   }
03134 
03135   // Rcount used to count the number of '-R' be used.
03136   scount = 0;
03137 
03138   for (i = startindex; i < argc; i++) {
03139     // Remember the command line switches.
03140     strcat(commandline, argv[i]);
03141     strcat(commandline, " ");
03142     if (startindex == 1) {
03143       // Is this string a filename?
03144       if (argv[i][0] != '-') {
03145         strncpy(infilename, argv[i], 1024 - 1);
03146         infilename[1024 - 1] = '\0';
03147         // Go to the next string directly.
03148         continue;
03149       }
03150     }
03151     // Parse the individual switch from the string.
03152     for (j = startindex; argv[i][j] != '\0'; j++) {
03153       if (argv[i][j] == 'p') {
03154         plc = 1;
03155       } else if (argv[i][j] == 'r') {
03156         refine = 1;
03157       } else if (argv[i][j] == 'R') {
03158         coarse = 1;
03159       } else if (argv[i][j] == 'q') {
03160         quality++;
03161         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03162             (argv[i][j + 1] == '.')) {
03163           k = 0;
03164           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03165                  (argv[i][j + 1] == '.')) {
03166             j++;
03167             workstring[k] = argv[i][j];
03168             k++;
03169           }
03170           workstring[k] = '\0';
03171           if (quality == 1) {
03172             minratio = (REAL) strtod(workstring, (char **) NULL);
03173           } else if (quality == 2) {
03174             mindihedral = (REAL) strtod(workstring, (char **) NULL);
03175           } else if (quality == 3) {
03176             maxdihedral = (REAL) strtod(workstring, (char **) NULL);
03177           } else if (quality == 4) {
03178             alpha2 = (REAL) strtod(workstring, (char **) NULL);
03179           } else if (quality == 5) {
03180             alpha1 = (REAL) strtod(workstring, (char **) NULL);
03181           }
03182         }
03183       } else if (argv[i][j] == 'm') {
03184         metric++;
03185         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03186             (argv[i][j + 1] == '.')) {
03187           k = 0;
03188           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03189                  (argv[i][j + 1] == '.')) {
03190             j++;
03191             workstring[k] = argv[i][j];
03192             k++;
03193           }
03194           workstring[k] = '\0';
03195           if (metric == 1) {
03196             alpha1 = (REAL) strtod(workstring, (char **) NULL);
03197           } else if (metric == 2) {
03198             alpha2 = (REAL) strtod(workstring, (char **) NULL);
03199           }
03200         }
03201       } else if (argv[i][j] == 'a') {
03202         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03203             (argv[i][j + 1] == '.')) {
03204           fixedvolume = 1;
03205           k = 0;
03206           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03207                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03208                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03209             j++;
03210             workstring[k] = argv[i][j];
03211             k++;
03212           }
03213           workstring[k] = '\0';
03214           maxvolume = (REAL) strtod(workstring, (char **) NULL);
03215         } else {
03216           varvolume = 1;
03217         }
03218       } else if (argv[i][j] == 'A') {
03219         regionattrib++;
03220       } else if (argv[i][j] == 'i') {
03221         insertaddpoints = 1;
03222       } else if (argv[i][j] == 'd') {
03223         diagnose = 1;
03224       } else if (argv[i][j] == 'z') {
03225         zeroindex = 1;
03226       } else if (argv[i][j] == 'f') {
03227         facesout = 1;
03228       } else if (argv[i][j] == 'e') {
03229         edgesout++;
03230       } else if (argv[i][j] == 'n') {
03231         neighout++;
03232       } else if (argv[i][j] == 'v') {
03233         voroout = 1;
03234       } else if (argv[i][j] == 'g') {
03235         meditview = 1;
03236       } else if (argv[i][j] == 'G') {
03237         gidview = 1;
03238       } else if (argv[i][j] == 'O') {
03239         geomview = 1;
03240       } else if (argv[i][j] == 'M') {
03241         nomerge = 1;
03242       } else if (argv[i][j] == 'Y') {
03243         nobisect++;
03244       } else if (argv[i][j] == 'J') {
03245         nojettison = 1;
03246       } else if (argv[i][j] == 'B') {
03247         nobound = 1;
03248       } else if (argv[i][j] == 'N') {
03249         nonodewritten = 1;
03250       } else if (argv[i][j] == 'E') {
03251         noelewritten = 1;
03252       } else if (argv[i][j] == 'F') {
03253         nofacewritten = 1;
03254       } else if (argv[i][j] == 'I') {
03255         noiterationnum = 1;
03256       } else if (argv[i][j] == 'o') {
03257         if (argv[i][j + 1] == '2') {
03258           j++;
03259           order = 2;
03260         }
03261       } else if (argv[i][j] == 'S') {
03262         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03263             (argv[i][j + 1] == '.')) {
03264           k = 0;
03265           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03266                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03267                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03268             j++;
03269             workstring[k] = argv[i][j];
03270             k++;
03271           }
03272           workstring[k] = '\0';
03273           steiner = (int) strtol(workstring, (char **) NULL, 0);
03274         }
03275       } else if (argv[i][j] == 's') {
03276         scount++;
03277         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03278             (argv[i][j + 1] == '.')) {
03279           k = 0;
03280           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03281                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03282                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03283             j++;
03284             workstring[k] = argv[i][j];
03285             k++;
03286           }
03287           workstring[k] = '\0';
03288           if (scount == 1) {
03289             optlevel = (int) strtol(workstring, (char **) NULL, 0);
03290           } else if (scount == 2) {
03291             optpasses = (int) strtol(workstring, (char **) NULL, 0);
03292           }
03293         }
03294       } else if (argv[i][j] == 'D') {
03295         conformdel++;
03296       } else if (argv[i][j] == 'T') {
03297         if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03298             (argv[i][j + 1] == '.')) {
03299           k = 0;
03300           while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03301                  (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03302                  (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03303             j++;
03304             workstring[k] = argv[i][j];
03305             k++;
03306           }
03307           workstring[k] = '\0';
03308           epsilon = (REAL) strtod(workstring, (char **) NULL);
03309         }
03310       } else if (argv[i][j] == 'C') {
03311         docheck++;
03312       } else if (argv[i][j] == 'X') {
03313         fliprepair = 0;
03314       } else if (argv[i][j] == 'Q') {
03315         quiet = 1;
03316       } else if (argv[i][j] == 'V') {
03317         verbose++;
03318       // } else if (argv[i][j] == 'v') {
03319         // versioninfo();
03320         // terminatetetgen(0);
03321       } else if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
03322                  (argv[i][j] == '?')) {
03323         usage();
03324         terminatetetgen(0);
03325       } else {
03326         printf("Warning:  Unknown switch -%c.\n", argv[i][j]);
03327       }
03328     }
03329   }
03330 
03331   if (startindex == 0) {
03332     // Set a temporary filename for debugging output.
03333     strcpy(infilename, "tetgen-tmpfile");
03334   } else {
03335     if (infilename[0] == '\0') {
03336       // No input file name. Print the syntax and exit.
03337       syntax();
03338       terminatetetgen(0);
03339     }
03340     // Recognize the object from file extension if it is available.
03341     if (!strcmp(&infilename[strlen(infilename) - 5], ".node")) {
03342       infilename[strlen(infilename) - 5] = '\0';
03343       object = NODES;
03344     } else if (!strcmp(&infilename[strlen(infilename) - 5], ".poly")) {
03345       infilename[strlen(infilename) - 5] = '\0';
03346       object = POLY;
03347       plc = 1;
03348     } else if (!strcmp(&infilename[strlen(infilename) - 6], ".smesh")) {
03349       infilename[strlen(infilename) - 6] = '\0';
03350       object = POLY;
03351       plc = 1;
03352     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".off")) {
03353       infilename[strlen(infilename) - 4] = '\0';
03354       object = OFF;
03355       plc = 1;
03356     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ply")) {
03357       infilename[strlen(infilename) - 4] = '\0';
03358       object = PLY;
03359       plc = 1;
03360     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".stl")) {
03361       infilename[strlen(infilename) - 4] = '\0';
03362       object = STL;
03363       plc = 1;
03364     } else if (!strcmp(&infilename[strlen(infilename) - 5], ".mesh")) {
03365       infilename[strlen(infilename) - 5] = '\0';
03366       object = MEDIT;
03367       plc = 1;
03368     } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ele")) {
03369       infilename[strlen(infilename) - 4] = '\0';
03370       object = MESH;
03371       refine = 1;
03372     }
03373   }
03374   plc = plc || diagnose;
03375   useshelles = plc || refine || coarse || quality;
03376   goodratio = minratio;
03377   goodratio *= goodratio;
03378 
03379   // Detect improper combinations of switches.
03380   if (plc && refine) {
03381     printf("Error:  Switch -r cannot use together with -p.\n");
03382     return false;
03383   }
03384   if (refine && (plc || noiterationnum)) {
03385     printf("Error:  Switches %s cannot use together with -r.\n",
03386            "-p, -d, and -I");
03387     return false;
03388   }
03389   if (diagnose && (quality || insertaddpoints || (order == 2) || neighout
03390       || docheck)) {
03391     printf("Error:  Switches %s cannot use together with -d.\n",
03392            "-q, -i, -o2, -n, and -C");
03393     return false;
03394   }
03395 
03396   // Be careful not to allocate space for element area constraints that
03397   //   will never be assigned any value (other than the default -1.0).
03398   if (!refine && !plc) {
03399     varvolume = 0;
03400   }
03401   // Be careful not to add an extra attribute to each element unless the
03402   //   input supports it (PLC in, but not refining a preexisting mesh).
03403   if (refine || !plc) {
03404     regionattrib = 0;
03405   }
03406   // If '-a' or '-aa' is in use, enable '-q' option too.
03407   if (fixedvolume || varvolume) {
03408     if (quality == 0) {
03409       quality = 1;
03410     }
03411   }
03412   // Calculate the goodangle for testing bad subfaces.
03413   goodangle = cos(minangle * PI / 180.0);
03414   goodangle *= goodangle;
03415 
03416   increment = 0;
03417   strcpy(workstring, infilename);
03418   j = 1;
03419   while (workstring[j] != '\0') {
03420     if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
03421       increment = j + 1;
03422     }
03423     j++;
03424   }
03425   meshnumber = 0;
03426   if (increment > 0) {
03427     j = increment;
03428     do {
03429       if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
03430         meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
03431       } else {
03432         increment = 0;
03433       }
03434       j++;
03435     } while (workstring[j] != '\0');
03436   }
03437   if (noiterationnum) {
03438     strcpy(outfilename, infilename);
03439   } else if (increment == 0) {
03440     strcpy(outfilename, infilename);
03441     strcat(outfilename, ".1");
03442   } else {
03443     workstring[increment] = '%';
03444     workstring[increment + 1] = 'd';
03445     workstring[increment + 2] = '\0';
03446     sprintf(outfilename, workstring, meshnumber + 1);
03447   }
03448   // Additional input file name has the end ".a".
03449   strcpy(addinfilename, infilename);
03450   strcat(addinfilename, ".a");
03451   // Background filename has the form "*.b.ele", "*.b.node", ...
03452   strcpy(bgmeshfilename, infilename);
03453   strcat(bgmeshfilename, ".b");
03454 
03455   return true;
03456 }
03457 
03458 //
03459 // End of class 'tetgenbehavior' implementation
03460 //
03461 
03462 //
03463 // Begin of class 'tetgenmesh' implementation
03464 //
03465 
03466 //
03467 // Begin of class 'list', 'memorypool' and 'link' implementation
03468 //
03469 
03470 // Following are predefined compare functions for primitive data types.
03471 //   These functions take two pointers of the corresponding date type,
03472 //   perform the comparation. Return -1, 0 or 1 indicating the default
03473 //   linear order of two operators.
03474 
03475 // Compare two 'integers'.
03476 int tetgenmesh::compare_2_ints(const void* x, const void* y) {
03477   if (* (int *) x < * (int *) y) {
03478     return -1;
03479   } else if (* (int *) x > * (int *) y) {
03480     return 1;
03481   } else {
03482     return 0;
03483   }
03484 }
03485 
03486 // Compare two 'longs'.  Note: in 64-bit machine the 'long' type is 64-bit
03487 //   (8-byte) where the 'int' only 32-bit (4-byte).
03488 int tetgenmesh::compare_2_longs(const void* x, const void* y) {
03489   if (* (long *) x < * (long *) y) {
03490     return -1;
03491   } else if (* (long *) x > * (long *) y) {
03492     return 1;
03493   } else {
03494     return 0;
03495   }
03496 }
03497 
03498 // Compare two 'unsigned longs'.
03499 int tetgenmesh::compare_2_unsignedlongs(const void* x, const void* y) {
03500   if (* (unsigned long *) x < * (unsigned long *) y) {
03501     return -1;
03502   } else if (* (unsigned long *) x > * (unsigned long *) y) {
03503     return 1;
03504   } else {
03505     return 0;
03506   }
03507 }
03508 
03510 //                                                                           //
03511 // set_compfunc()    Determine the size of primitive data types and set the  //
03512 //                   corresponding predefined linear order functions.        //
03513 //                                                                           //
03514 // 'str' is a zero-end string indicating a primitive data type, like 'int',  //
03515 // 'long' or 'unsigned long'.  Every string ending with a '*' is though as a //
03516 // type of pointer and the type 'unsign long' is used for it.                //
03517 //                                                                           //
03518 // When the type of 'str' is determined, the size of this type (in byte) is  //
03519 // returned in 'itbytes', and the pointer of corresponding predefined linear //
03520 // order functions is returned in 'pcomp'.                                   //
03521 //                                                                           //
03523 
03524 void tetgenmesh::set_compfunc(char* str, int* itbytes, compfunc* pcomp)
03525 {
03526   // First figure out whether it is a pointer or not.
03527   if (str[strlen(str) - 1] == '*') {
03528     *itbytes = sizeof(unsigned long);
03529     *pcomp = &compare_2_unsignedlongs;
03530     return;
03531   }
03532   // Then determine other types.
03533   if (strcmp(str, "int") == 0) {
03534     *itbytes = sizeof(int);
03535     *pcomp = &compare_2_ints;
03536   } else if (strcmp(str, "long") == 0) {
03537     *itbytes = sizeof(long);
03538     *pcomp = &compare_2_longs;
03539   } else if (strcmp(str, "unsigned long") == 0) {
03540     *itbytes = sizeof(unsigned long);
03541     *pcomp = &compare_2_unsignedlongs;
03542   } else {
03543     // It is an unknown type.
03544     printf("Error in set_compfunc():  unknown type %s.\n", str);
03545     terminatetetgen(1);
03546   }
03547 }
03548 
03550 //                                                                           //
03551 // listinit()    Initialize a list for storing a data type.                  //
03552 //                                                                           //
03553 // Determine the size of each item, set the maximum size allocated at onece, //
03554 // set the expand size in case the list is full, and set the linear order    //
03555 // function if it is provided (default is NULL).                             //
03556 //                                                                           //
03558 
03559 void tetgenmesh::list::
03560 listinit(int itbytes, compfunc pcomp, int mitems,int exsize)
03561 {
03562 #ifdef SELF_CHECK
03563   assert(itbytes > 0 && mitems > 0 && exsize > 0);
03564 #endif
03565   itembytes = itbytes;
03566   comp = pcomp;
03567   maxitems = mitems;
03568   expandsize = exsize;
03569   base = (char *) malloc(maxitems * itembytes);
03570   if (base == (char *) NULL) {
03571     printf("Error:  Out of memory.\n");
03572     terminatetetgen(1);
03573   }
03574   items = 0;
03575 }
03576 
03578 //                                                                           //
03579 // append()    Add a new item at the end of the list.                        //
03580 //                                                                           //
03581 // A new space at the end of this list will be allocated for storing the new //
03582 // item. If the memory is not sufficient, reallocation will be performed. If //
03583 // 'appitem' is not NULL, the contents of this pointer will be copied to the //
03584 // new allocated space.  Returns the pointer to the new allocated space.     //
03585 //                                                                           //
03587 
03588 void* tetgenmesh::list::append(void *appitem)
03589 {
03590   // Do we have enough space?
03591   if (items == maxitems) {
03592     char* newbase = (char *) realloc(base, (maxitems + expandsize) *
03593                                      itembytes);
03594     if (newbase == (char *) NULL) {
03595       printf("Error:  Out of memory.\n");
03596       terminatetetgen(1);
03597     }
03598     base = newbase;
03599     maxitems += expandsize;
03600   }
03601   if (appitem != (void *) NULL) {
03602     memcpy(base + items * itembytes, appitem, itembytes);
03603   }
03604   items++;
03605   return (void *) (base + (items - 1) * itembytes);
03606 }
03607 
03609 //                                                                           //
03610 // insert()    Insert an item before 'pos' (range from 0 to items - 1).      //
03611 //                                                                           //
03612 // A new space will be inserted at the position 'pos', that is, items lie    //
03613 // after pos (including the item at pos) will be moved one space downwords.  //
03614 // If 'insitem' is not NULL, its contents will be copied into the new        //
03615 // inserted space. Return a pointer to the new inserted space.               //
03616 //                                                                           //
03618 
03619 void* tetgenmesh::list::insert(int pos, void* insitem)
03620 {
03621   if (pos >= items) {
03622     return append(insitem);
03623   }
03624   // Do we have enough space.
03625   if (items == maxitems) {
03626     char* newbase = (char *) realloc(base, (maxitems + expandsize) *
03627                                      itembytes);
03628     if (newbase == (char *) NULL) {
03629       printf("Error:  Out of memory.\n");
03630       terminatetetgen(1);
03631     }
03632     base = newbase;
03633     maxitems += expandsize;
03634   }
03635   // Do block move.
03636   memmove(base + (pos + 1) * itembytes,   // dest
03637           base + pos * itembytes,         // src
03638           (items - pos) * itembytes);     // size in bytes
03639   // Insert the item.
03640   if (insitem != (void *) NULL) {
03641     memcpy(base + pos * itembytes, insitem, itembytes);
03642   }
03643   items++;
03644   return (void *) (base + pos * itembytes);
03645 }
03646 
03648 //                                                                           //
03649 // del()    Delete an item at 'pos' (range from 0 to items - 1).             //
03650 //                                                                           //
03651 // The space at 'pos' will be overlapped by other item. If 'order' is 1, the //
03652 // remaining items of the list have the same order as usual, i.e., items lie //
03653 // after pos will be moved one space upwords. If 'order' is 0, the last item //
03654 // of the list will be moved up to pos.                                      //
03655 //                                                                           //
03657 
03658 void tetgenmesh::list::del(int pos, int order)
03659 {
03660   // If 'pos' is the last item of the list, nothing need to do.
03661   if (pos >= 0 && pos < items - 1) {
03662     if (order == 1) {
03663       // Do block move.
03664       memmove(base + pos * itembytes,       // dest
03665               base + (pos + 1) * itembytes, // src
03666               (items - pos - 1) * itembytes);
03667     } else {
03668       // Use the last item to overlap the del item.
03669       memcpy(base + pos * itembytes, // item at pos
03670              base + (items - 1) * itembytes, // item at last
03671              itembytes);
03672     }
03673   }
03674   if (items > 0) {
03675     items--;
03676   }
03677 }
03678 
03680 //                                                                           //
03681 // hasitem()    Search in this list to find if 'checkitem' exists.           //
03682 //                                                                           //
03683 // This routine assumes that a linear order function has been set.  It loops //
03684 // through the entire list, compares each item to 'checkitem'. If it exists, //
03685 // return its position (between 0 to items - 1), otherwise, return -1.       //
03686 //                                                                           //
03688 
03689 int tetgenmesh::list::hasitem(void* checkitem)
03690 {
03691   int i;
03692 
03693   for (i = 0; i < items; i++) {
03694     if (comp != (compfunc) NULL) {
03695       if ((* comp)((void *)(base + i * itembytes), checkitem) == 0) {
03696         return i;
03697       }
03698     }
03699   }
03700   return -1;
03701 }
03702 
03704 //                                                                           //
03705 // sort()    Sort the items with respect to a linear order function.         //
03706 //                                                                           //
03707 // Uses QuickSort routines (qsort) of the standard C/C++ library (stdlib.h). //
03708 //                                                                           //
03710 
03711 void tetgenmesh::list::sort()
03712 {
03713   qsort((void *) base, (size_t) items, (size_t) itembytes, comp);
03714 }
03715 
03717 //                                                                           //
03718 // memorypool()   The constructors of memorypool.                            //
03719 //                                                                           //
03721 
03722 tetgenmesh::memorypool::memorypool()
03723 {
03724   firstblock = nowblock = (void **) NULL;
03725   nextitem = (void *) NULL;
03726   deaditemstack = (void *) NULL;
03727   pathblock = (void **) NULL;
03728   pathitem = (void *) NULL;
03729   itemwordtype = POINTER;
03730   alignbytes = 0;
03731   itembytes = itemwords = 0;
03732   itemsperblock = 0;
03733   items = maxitems = 0l;
03734   unallocateditems = 0;
03735   pathitemsleft = 0;
03736 }
03737 
03738 tetgenmesh::memorypool::
03739 memorypool(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03740 {
03741   poolinit(bytecount, itemcount, wtype, alignment);
03742 }
03743 
03745 //                                                                           //
03746 // ~memorypool()   Free to the operating system all memory taken by a pool.  //
03747 //                                                                           //
03749 
03750 tetgenmesh::memorypool::~memorypool()
03751 {
03752   while (firstblock != (void **) NULL) {
03753     nowblock = (void **) *(firstblock);
03754     free(firstblock);
03755     firstblock = nowblock;
03756   }
03757 }
03758 
03760 //                                                                           //
03761 // poolinit()    Initialize a pool of memory for allocation of items.        //
03762 //                                                                           //
03763 // A `pool' is created whose records have size at least `bytecount'.  Items  //
03764 // will be allocated in `itemcount'-item blocks.  Each item is assumed to be //
03765 // a collection of words, and either pointers or floating-point values are   //
03766 // assumed to be the "primary" word type.  (The "primary" word type is used  //
03767 // to determine alignment of items.)  If `alignment' isn't zero, all items   //
03768 // will be `alignment'-byte aligned in memory.  `alignment' must be either a //
03769 // multiple or a factor of the primary word size;  powers of two are safe.   //
03770 // `alignment' is normally used to create a few unused bits at the bottom of //
03771 // each item's pointer, in which information may be stored.                  //
03772 //                                                                           //
03774 
03775 void tetgenmesh::memorypool::
03776 poolinit(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03777 {
03778   int wordsize;
03779 
03780   // Initialize values in the pool.
03781   itemwordtype = wtype;
03782   wordsize = (itemwordtype == POINTER) ? sizeof(void *) : sizeof(REAL);
03783   // Find the proper alignment, which must be at least as large as:
03784   //   - The parameter `alignment'.
03785   //   - The primary word type, to avoid unaligned accesses.
03786   //   - sizeof(void *), so the stack of dead items can be maintained
03787   //       without unaligned accesses.
03788   if (alignment > wordsize) {
03789     alignbytes = alignment;
03790   } else {
03791     alignbytes = wordsize;
03792   }
03793   if ((int) sizeof(void *) > alignbytes) {
03794     alignbytes = (int) sizeof(void *);
03795   }
03796   itemwords = ((bytecount + alignbytes - 1) /  alignbytes)
03797             * (alignbytes / wordsize);
03798   itembytes = itemwords * wordsize;
03799   itemsperblock = itemcount;
03800 
03801   // Allocate a block of items.  Space for `itemsperblock' items and one
03802   //   pointer (to point to the next block) are allocated, as well as space
03803   //   to ensure alignment of the items.
03804   firstblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *)
03805                                 + alignbytes);
03806   if (firstblock == (void **) NULL) {
03807     printf("Error:  Out of memory.\n");
03808     terminatetetgen(1);
03809   }
03810   // Set the next block pointer to NULL.
03811   *(firstblock) = (void *) NULL;
03812   restart();
03813 }
03814 
03816 //                                                                           //
03817 // restart()   Deallocate all items in this pool.                            //
03818 //                                                                           //
03819 // The pool is returned to its starting state, except that no memory is      //
03820 // freed to the operating system.  Rather, the previously allocated blocks   //
03821 // are ready to be reused.                                                   //
03822 //                                                                           //
03824 
03825 void tetgenmesh::memorypool::restart()
03826 {
03827   unsigned long alignptr;
03828 
03829   items = 0;
03830   maxitems = 0;
03831 
03832   // Set the currently active block.
03833   nowblock = firstblock;
03834   // Find the first item in the pool.  Increment by the size of (void *).
03835   alignptr = (unsigned long) (nowblock + 1);
03836   // Align the item on an `alignbytes'-byte boundary.
03837   nextitem = (void *)
03838     (alignptr + (unsigned long) alignbytes -
03839      (alignptr % (unsigned long) alignbytes));
03840   // There are lots of unallocated items left in this block.
03841   unallocateditems = itemsperblock;
03842   // The stack of deallocated items is empty.
03843   deaditemstack = (void *) NULL;
03844 }
03845 
03847 //                                                                           //
03848 // alloc()   Allocate space for an item.                                     //
03849 //                                                                           //
03851 
03852 void* tetgenmesh::memorypool::alloc()
03853 {
03854   void *newitem;
03855   void **newblock;
03856   unsigned long alignptr;
03857 
03858   // First check the linked list of dead items.  If the list is not
03859   //   empty, allocate an item from the list rather than a fresh one.
03860   if (deaditemstack != (void *) NULL) {
03861     newitem = deaditemstack;                     // Take first item in list.
03862     deaditemstack = * (void **) deaditemstack;
03863   } else {
03864     // Check if there are any free items left in the current block.
03865     if (unallocateditems == 0) {
03866       // Check if another block must be allocated.
03867       if (*nowblock == (void *) NULL) {
03868         // Allocate a new block of items, pointed to by the previous block.
03869         newblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *)
03870                                     + alignbytes);
03871         if (newblock == (void **) NULL) {
03872           printf("Error:  Out of memory.\n");
03873           terminatetetgen(1);
03874         }
03875         *nowblock = (void *) newblock;
03876         // The next block pointer is NULL.
03877         *newblock = (void *) NULL;
03878       }
03879       // Move to the new block.
03880       nowblock = (void **) *nowblock;
03881       // Find the first item in the block.
03882       //   Increment by the size of (void *).
03883       alignptr = (unsigned long) (nowblock + 1);
03884       // Align the item on an `alignbytes'-byte boundary.
03885       nextitem = (void *)
03886         (alignptr + (unsigned long) alignbytes -
03887          (alignptr % (unsigned long) alignbytes));
03888       // There are lots of unallocated items left in this block.
03889       unallocateditems = itemsperblock;
03890     }
03891     // Allocate a new item.
03892     newitem = nextitem;
03893     // Advance `nextitem' pointer to next free item in block.
03894     if (itemwordtype == POINTER) {
03895       nextitem = (void *) ((void **) nextitem + itemwords);
03896     } else {
03897       nextitem = (void *) ((REAL *) nextitem + itemwords);
03898     }
03899     unallocateditems--;
03900     maxitems++;
03901   }
03902   items++;
03903   return newitem;
03904 }
03905 
03907 //                                                                           //
03908 // dealloc()   Deallocate space for an item.                                 //
03909 //                                                                           //
03910 // The deallocated space is stored in a queue for later reuse.               //
03911 //                                                                           //
03913 
03914 void tetgenmesh::memorypool::dealloc(void *dyingitem)
03915 {
03916   // Push freshly killed item onto stack.
03917   *((void **) dyingitem) = deaditemstack;
03918   deaditemstack = dyingitem;
03919   items--;
03920 }
03921 
03923 //                                                                           //
03924 // traversalinit()   Prepare to traverse the entire list of items.           //
03925 //                                                                           //
03926 // This routine is used in conjunction with traverse().                      //
03927 //                                                                           //
03929 
03930 void tetgenmesh::memorypool::traversalinit()
03931 {
03932   unsigned long alignptr;
03933 
03934   // Begin the traversal in the first block.
03935   pathblock = firstblock;
03936   // Find the first item in the block.  Increment by the size of (void *).
03937   alignptr = (unsigned long) (pathblock + 1);
03938   // Align with item on an `alignbytes'-byte boundary.
03939   pathitem = (void *)
03940     (alignptr + (unsigned long) alignbytes -
03941      (alignptr % (unsigned long) alignbytes));
03942   // Set the number of items left in the current block.
03943   pathitemsleft = itemsperblock;
03944 }
03945 
03947 //                                                                           //
03948 // traverse()   Find the next item in the list.                              //
03949 //                                                                           //
03950 // This routine is used in conjunction with traversalinit().  Be forewarned  //
03951 // that this routine successively returns all items in the list, including   //
03952 // deallocated ones on the deaditemqueue. It's up to you to figure out which //
03953 // ones are actually dead.  It can usually be done more space-efficiently by //
03954 // a routine that knows something about the structure of the item.           //
03955 //                                                                           //
03957 
03958 void* tetgenmesh::memorypool::traverse()
03959 {
03960   void *newitem;
03961   unsigned long alignptr;
03962 
03963   // Stop upon exhausting the list of items.
03964   if (pathitem == nextitem) {
03965     return (void *) NULL;
03966   }
03967   // Check whether any untraversed items remain in the current block.
03968   if (pathitemsleft == 0) {
03969     // Find the next block.
03970     pathblock = (void **) *pathblock;
03971     // Find the first item in the block.  Increment by the size of (void *).
03972     alignptr = (unsigned long) (pathblock + 1);
03973     // Align with item on an `alignbytes'-byte boundary.
03974     pathitem = (void *)
03975       (alignptr + (unsigned long) alignbytes -
03976        (alignptr % (unsigned long) alignbytes));
03977     // Set the number of items left in the current block.
03978     pathitemsleft = itemsperblock;
03979   }
03980   newitem = pathitem;
03981   // Find the next item in the block.
03982   if (itemwordtype == POINTER) {
03983     pathitem = (void *) ((void **) pathitem + itemwords);
03984   } else {
03985     pathitem = (void *) ((REAL *) pathitem + itemwords);
03986   }
03987   pathitemsleft--;
03988   return newitem;
03989 }
03990 
03992 //                                                                           //
03993 // linkinit()    Initialize a link for storing items.                        //
03994 //                                                                           //
03995 // The input parameters are the size of each item, a pointer of a linear     //
03996 // order function and the number of items allocating in one memory bulk.     //
03997 //                                                                           //
03999 
04000 void tetgenmesh::link::linkinit(int bytecount, compfunc pcomp, int itemcount)
04001 {
04002 #ifdef SELF_CHECK
04003   assert(bytecount > 0 && itemcount > 0);
04004 #endif
04005   // Remember the real size of each item.
04006   linkitembytes = bytecount;
04007   // Set the linear order function for this link.
04008   comp = pcomp;
04009 
04010   // Call the constructor of 'memorypool' to initialize its variables.
04011   //   like: itembytes, itemwords, items, ... Each node has size
04012   //   bytecount + 2 * sizeof(void **), and total 'itemcount + 2' (because
04013   //   link has additional two nodes 'head' and 'tail').
04014   poolinit(bytecount + 2 * sizeof(void **), itemcount + 2, POINTER, 0);
04015 
04016   // Initial state of this link.
04017   head = (void **) alloc();
04018   tail = (void **) alloc();
04019   *head = (void *) tail;
04020   *(head + 1) = NULL;
04021   *tail = NULL;
04022   *(tail + 1) = (void *) head;
04023   nextlinkitem = *head;
04024   curpos = 1;
04025   linkitems = 0;
04026 }
04027 
04029 //                                                                           //
04030 // clear()   Deallocate all nodes in this link.                              //
04031 //                                                                           //
04032 // The link is returned to its starting state, except that no memory is      //
04033 // freed to the operating system.  Rather, the previously allocated blocks   //
04034 // are ready to be reused.                                                   //
04035 //                                                                           //
04037 
04038 void tetgenmesh::link::clear()
04039 {
04040   // Reset the pool.
04041   restart();
04042 
04043   // Initial state of this link.
04044   head = (void **) alloc();
04045   tail = (void **) alloc();
04046   *head = (void *) tail;
04047   *(head + 1) = NULL;
04048   *tail = NULL;
04049   *(tail + 1) = (void *) head;
04050   nextlinkitem = *head;
04051   curpos = 1;
04052   linkitems = 0;
04053 }
04054 
04056 //                                                                           //
04057 // move()    Causes 'nextlinkitem' to traverse the specified number of nodes,//
04058 //           updates 'curpos' to be the node to which 'nextlinkitem' points. //
04059 //                                                                           //
04060 // 'numberofnodes' is a number indicating how many nodes need be traversed   //
04061 // (not counter the current node) need be traversed. It may be positive(move //
04062 // forward) or negative (move backward).  Return TRUE if it is successful.   //
04063 //                                                                           //
04065 
04066 bool tetgenmesh::link::move(int numberofnodes)
04067 {
04068   void **nownode;
04069   int i;
04070 
04071   nownode = (void **) nextlinkitem;
04072   if (numberofnodes > 0) {
04073     // Move forward.
04074     i = 0;
04075     while ((i < numberofnodes) && *nownode) {
04076       nownode = (void **) *nownode;
04077       i++;
04078     }
04079     if (*nownode == NULL) return false;
04080     nextlinkitem = (void *) nownode;
04081     curpos += numberofnodes;
04082   } else if (numberofnodes < 0) {
04083     // Move backward.
04084     i = 0;
04085     numberofnodes = -numberofnodes;
04086     while ((i < numberofnodes) && *(nownode + 1)) {
04087       nownode = (void **) *(nownode + 1);
04088       i++;
04089     }
04090     if (*(nownode + 1) == NULL) return false;
04091     nextlinkitem = (void *) nownode;
04092     curpos -= numberofnodes;
04093   }
04094   return true;
04095 }
04096 
04098 //                                                                           //
04099 // locate()    Locates the node at the specified position.                   //
04100 //                                                                           //
04101 // The number 'pos' (between 1 and 'linkitems') indicates the location. This //
04102 // routine first decides the shortest path traversing from 'curpos' to 'pos',//
04103 // i.e., from head, tail or 'curpos'.   Routine 'move()' is called to really //
04104 // traverse the link. If success, 'nextlinkitem' points to the node, 'curpos'//
04105 // and 'pos' are equal. Otherwise, return FALSE.                             //
04106 //                                                                           //
04108 
04109 bool tetgenmesh::link::locate(int pos)
04110 {
04111   int headdist, taildist, curdist;
04112   int abscurdist, mindist;
04113 
04114   if (pos < 1 || pos > linkitems) return false;
04115 
04116   headdist = pos - 1;
04117   taildist = linkitems - pos;
04118   curdist = pos - curpos;
04119   abscurdist = curdist >= 0 ? curdist : -curdist;
04120 
04121   if (headdist > taildist) {
04122     if (taildist > abscurdist) {
04123       mindist = curdist;
04124     } else {
04125       // taildist <= abs(curdist)
04126       mindist = -taildist;
04127       goend();
04128     }
04129   } else {
04130     // headdist <= taildist
04131     if (headdist > abscurdist) {
04132       mindist = curdist;
04133     } else {
04134       // headdist <= abs(curdist)
04135       mindist = headdist;
04136       rewind();
04137     }
04138   }
04139 
04140   return move(mindist);
04141 }
04142 
04144 //                                                                           //
04145 // add()    Add a node at the end of this link.                              //
04146 //                                                                           //
04147 // A new node is appended to the end of the link.  If 'newitem' is not NULL, //
04148 // its conents will be copied to the data slot of the new node. Returns the  //
04149 // pointer to the newest added node.                                         //
04150 //                                                                           //
04152 
04153 void* tetgenmesh::link::add(void* newitem)
04154 {
04155   void **newnode = tail;
04156   if (newitem != (void *) NULL) {
04157     memcpy((void *)(newnode + 2), newitem, linkitembytes);
04158   }
04159   tail = (void **) alloc();
04160   *tail = NULL;
04161   *newnode = (void*) tail;
04162   *(tail + 1) = (void*) newnode;
04163   linkitems++;
04164   return (void *)(newnode + 2);
04165 }
04166 
04168 //                                                                           //
04169 // insert()    Inserts a node before the specified position.                 //
04170 //                                                                           //
04171 // 'pos' (between 1 and 'linkitems') indicates the inserting position.  This //
04172 // routine inserts a new node before the node of 'pos'.  If 'newitem' is not //
04173 // NULL,  its conents will be copied into the data slot of the new node.  If //
04174 // 'pos' is larger than 'linkitems', it is equal as 'add()'.  A pointer to   //
04175 // the newest inserted item is returned.                                     //
04176 //                                                                           //
04178 
04179 void* tetgenmesh::link::insert(int pos, void* insitem)
04180 {
04181   if (!locate(pos)) {
04182     return add(insitem);
04183   }
04184 
04185   void **nownode = (void **) nextlinkitem;
04186 
04187   // Insert a node before 'nownode'.
04188   void **newnode = (void **) alloc();
04189   if (insitem != (void *) NULL) {
04190     memcpy((void *)(newnode + 2), insitem, linkitembytes);
04191   }
04192 
04193   *(void **)(*(nownode + 1)) = (void *) newnode;
04194   *newnode = (void *) nownode;
04195   *(newnode + 1) = *(nownode + 1);
04196   *(nownode + 1) = (void *) newnode;
04197 
04198   linkitems++;
04199 
04200   nextlinkitem = (void *) newnode;
04201   return (void *)(newnode + 2);
04202 }
04203 
04205 //                                                                           //
04206 // del()    Delete a node.                                                   //
04207 //                                                                           //
04208 // Returns a pointer of the deleted data. If you try to delete a non-existed //
04209 // node (e.g. link is empty or a wrong index is given) return NULL.          //
04210 //                                                                           //
04212 
04213 void* tetgenmesh::link::deletenode(void** deadnode)
04214 {
04215   void **nextnode = (void **) *deadnode;
04216   void **prevnode = (void **) *(deadnode + 1);
04217   *prevnode = (void *) nextnode;
04218   *(nextnode + 1) = (void *) prevnode;
04219 
04220   dealloc((void *) deadnode);
04221   linkitems--;
04222 
04223   nextlinkitem = (void *) nextnode;
04224   return (void *)(deadnode + 2);
04225 }
04226 
04228 //                                                                           //
04229 // del()    Delete a node at the specified position.                         //
04230 //                                                                           //
04231 // 'pos' between 1 and 'linkitems'.  Returns a pointer of the deleted data.  //
04232 // If you try to delete a non-existed node (e.g. link is empty or a wrong    //
04233 // index is given) return NULL.                                              //
04234 //                                                                           //
04236 
04237 void* tetgenmesh::link::del(int pos)
04238 {
04239   if (!locate(pos) || (linkitems == 0)) {
04240     return (void *) NULL;
04241   }
04242   return deletenode((void **) nextlinkitem);
04243 }
04244 
04246 //                                                                           //
04247 // getitem()    The link traversal routine.                                  //
04248 //                                                                           //
04249 // Returns the node to which 'nextlinkitem' points. Returns a 'NULL' if the  //
04250 // end of the link is reaching.  Both 'nextlinkitem' and 'curpos' will be    //
04251 // updated after this operation.                                             //
04252 //                                                                           //
04254 
04255 void* tetgenmesh::link::getitem()
04256 {
04257   if (nextlinkitem == (void *) tail) return NULL;
04258   void **nownode = (void **) nextlinkitem;
04259   nextlinkitem = *nownode;
04260   curpos += 1;
04261   return (void *)(nownode + 2);
04262 }
04263 
04265 //                                                                           //
04266 // getnitem()    Returns the node at a specified position.                   //
04267 //                                                                           //
04268 // 'pos' between 1 and 'linkitems'. After this operation, 'nextlinkitem' and //
04269 // 'curpos' will be updated to indicate this node.                           //
04270 //                                                                           //
04272 
04273 void* tetgenmesh::link::getnitem(int pos)
04274 {
04275   if (!locate(pos)) return NULL;
04276   return (void *)((void **) nextlinkitem + 2);
04277 }
04278 
04280 //                                                                           //
04281 // hasitem()    Search in this link to find if 'checkitem' exists.           //
04282 //                                                                           //
04283 // If 'checkitem' exists, return its position (between 1 to 'linkitems'),    //
04284 // otherwise, return -1. This routine requires the linear order function has //
04285 // been set.                                                                 //
04286 //                                                                           //
04288 
04289 int tetgenmesh::link::hasitem(void* checkitem)
04290 {
04291   void *pathitem;
04292   int count;
04293 
04294   rewind();
04295   pathitem = getitem();
04296   count = 0;
04297   while (pathitem) {
04298     count ++;
04299     if (comp) {
04300       if ((* comp)(pathitem, checkitem) == 0) {
04301         return count;
04302       }
04303     }
04304     pathitem = getitem();
04305   }
04306   return -1;
04307 }
04308 
04309 //
04310 // End of class 'list', 'memorypool' and 'link' implementation
04311 //
04312 
04313 //
04314 // Begin of mesh manipulation primitives
04315 //
04316 
04317 //
04318 // Begin of tables initialization.
04319 //
04320 
04321 // For enumerating three edges of a triangle.
04322 
04323 int tetgenmesh::plus1mod3[3] = {1, 2, 0};
04324 int tetgenmesh::minus1mod3[3] = {2, 0, 1};
04325 
04326 // Table 've' takes an edge version as input, returns the next edge version
04327 //   in the same edge ring.
04328 
04329 int tetgenmesh::ve[6] = { 2, 5, 4, 1, 0, 3 };
04330 
04331 // Tables 'vo', 'vd' and 'va' take an edge version, return the positions of
04332 //   the origin, destination and apex in the triangle.
04333 
04334 int tetgenmesh::vo[6] = { 0, 1, 1, 2, 2, 0 };
04335 int tetgenmesh::vd[6] = { 1, 0, 2, 1, 0, 2 };
04336 int tetgenmesh::va[6] = { 2, 2, 0, 0, 1, 1 };
04337 
04338 // The following tables are for tetrahedron primitives (operate on trifaces).
04339 
04340 // For 'org()', 'dest()' and 'apex()'.  Use 'loc' as the first index and
04341 //   'ver' as the second index.
04342 
04343 int tetgenmesh::locver2org[4][6]  = {
04344   {0, 1, 1, 2, 2, 0},
04345   {0, 3, 3, 1, 1, 0},
04346   {1, 3, 3, 2, 2, 1},
04347   {2, 3, 3, 0, 0, 2}
04348 };
04349 int tetgenmesh::locver2dest[4][6] = {
04350   {1, 0, 2, 1, 0, 2},
04351   {3, 0, 1, 3, 0, 1},
04352   {3, 1, 2, 3, 1, 2},
04353   {3, 2, 0, 3, 2, 0}
04354 };
04355 int tetgenmesh::locver2apex[4][6] = {
04356   {2, 2, 0, 0, 1, 1},
04357   {1, 1, 0, 0, 3, 3},
04358   {2, 2, 1, 1, 3, 3},
04359   {0, 0, 2, 2, 3, 3}
04360 };
04361 
04362 // For oppo() primitives, use 'loc' as the index.
04363 
04364 int tetgenmesh::loc2oppo[4] = { 3, 2, 0, 1 };
04365 
04366 // For fnext() primitive.  Use 'loc' as the first index and 'ver' as the
04367 //   second index. Returns a new 'loc' and new 'ver' in an array. (It is
04368 //   only valid for edge version equals one of {0, 2, 4}.)
04369 
04370 int tetgenmesh::locver2nextf[4][6][2] = {
04371   { {1, 5}, {-1, -1}, {2, 5}, {-1, -1}, {3, 5}, {-1, -1} },
04372   { {3, 3}, {-1, -1}, {2, 1}, {-1, -1}, {0, 1}, {-1, -1} },
04373   { {1, 3}, {-1, -1}, {3, 1}, {-1, -1}, {0, 3}, {-1, -1} },
04374   { {2, 3}, {-1, -1}, {1, 1}, {-1, -1}, {0, 5}, {-1, -1} }
04375 };
04376 
04377 // The edge number (from 0 to 5) of a tet is defined as follows:
04378 //   0 - (v0, v1), 1 - (v1, v2), 2 - (v2, v0)
04379 //   3 - (v3, v0), 4 - (v3, v1), 5 - (v3, v2).
04380 
04381 int tetgenmesh::locver2edge[4][6] = {
04382   {0, 0, 1, 1, 2, 2},
04383   {3, 3, 4, 4, 0, 0},
04384   {4, 4, 5, 5, 1, 1},
04385   {5, 5, 3, 3, 2, 2}
04386 };
04387 
04388 int tetgenmesh::edge2locver[6][2] = {
04389   {0, 0}, // 0  v0 -> v1
04390   {0, 2}, // 1  v1 -> v2
04391   {0, 4}, // 2  v2 -> v1
04392   {1, 0}, // 3  v0 -> v3
04393   {1, 2}, // 4  v1 -> v3
04394   {2, 2}  // 5  v2 -> v3
04395 };
04396 
04397 //
04398 // End of tables initialization.
04399 //
04400 
04401 // Some macros for convenience
04402 
04403 #define Div2  >> 1
04404 #define Mod2  & 01
04405 
04406 // NOTE: These bit operators should only be used in macros below.
04407 
04408 // Get orient(Range from 0 to 2) from face version(Range from 0 to 5).
04409 
04410 #define Orient(V)   ((V) Div2)
04411 
04412 // Determine edge ring(0 or 1) from face version(Range from 0 to 5).
04413 
04414 #define EdgeRing(V) ((V) Mod2)
04415 
04416 //
04417 // Begin of primitives for tetrahedra
04418 //
04419 
04420 // Each tetrahedron contains four pointers to its neighboring tetrahedra,
04421 //   with face indices.  To save memory, both information are kept in a
04422 //   single pointer. To make this possible, all tetrahedra are aligned to
04423 //   eight-byte boundaries, so that the last three bits of each pointer are
04424 //   zeros. A face index (in the range 0 to 3) is compressed into the last
04425 //   two bits of each pointer by the function 'encode()'.  The function
04426 //   'decode()' decodes a pointer, extracting a face index and a pointer to
04427 //   the beginning of a tetrahedron.
04428 
04429 inline void tetgenmesh::decode(tetrahedron ptr, triface& t) {
04430   t.loc = (int) ((unsigned long) (ptr) & (unsigned long) 3l);
04431   t.tet = (tetrahedron *) ((unsigned long) (ptr) & ~(unsigned long) 7l);
04432 }
04433 
04434 inline tetgenmesh::tetrahedron tetgenmesh::encode(triface& t) {
04435   return (tetrahedron) ((unsigned long) t.tet | (unsigned long) t.loc);
04436 }
04437 
04438 // sym() finds the abutting tetrahedron on the same face.
04439 
04440 inline void tetgenmesh::sym(triface& t1, triface& t2) {
04441   tetrahedron ptr = t1.tet[t1.loc];
04442   decode(ptr, t2);
04443 }
04444 
04445 inline void tetgenmesh::symself(triface& t) {
04446   tetrahedron ptr = t.tet[t.loc];
04447   decode(ptr, t);
04448 }
04449 
04450 // Bond two tetrahedra together at their faces.
04451 
04452 inline void tetgenmesh::bond(triface& t1, triface& t2) {
04453   t1.tet[t1.loc] = encode(t2);
04454   t2.tet[t2.loc] = encode(t1);
04455 }
04456 
04457 // Dissolve a bond (from one side).  Note that the other tetrahedron will
04458 //   still think it is connected to this tetrahedron.  Usually, however,
04459 //   the other tetrahedron is being deleted entirely, or bonded to another
04460 //   tetrahedron, so it doesn't matter.
04461 
04462 inline void tetgenmesh::dissolve(triface& t) {
04463   t.tet[t.loc] = (tetrahedron) dummytet;
04464 }
04465 
04466 // These primitives determine or set the origin, destination, apex or
04467 //   opposition of a tetrahedron with respect to 'loc' and 'ver'.
04468 
04469 inline tetgenmesh::point tetgenmesh::org(triface& t) {
04470   return (point) t.tet[locver2org[t.loc][t.ver] + 4];
04471 }
04472 
04473 inline tetgenmesh::point tetgenmesh::dest(triface& t) {
04474   return (point) t.tet[locver2dest[t.loc][t.ver] + 4];
04475 }
04476 
04477 inline tetgenmesh::point tetgenmesh::apex(triface& t) {
04478   return (point) t.tet[locver2apex[t.loc][t.ver] + 4];
04479 }
04480 
04481 inline tetgenmesh::point tetgenmesh::oppo(triface& t) {
04482   return (point) t.tet[loc2oppo[t.loc] + 4];
04483 }
04484 
04485 inline void tetgenmesh::setorg(triface& t, point pointptr) {
04486   t.tet[locver2org[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04487 }
04488 
04489 inline void tetgenmesh::setdest(triface& t, point pointptr) {
04490   t.tet[locver2dest[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04491 }
04492 
04493 inline void tetgenmesh::setapex(triface& t, point pointptr) {
04494   t.tet[locver2apex[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04495 }
04496 
04497 inline void tetgenmesh::setoppo(triface& t, point pointptr) {
04498   t.tet[loc2oppo[t.loc] + 4] = (tetrahedron) pointptr;
04499 }
04500 
04501 // These primitives were drived from Mucke's triangle-edge data structure
04502 //   to change face-edge relation in a tetrahedron (esym, enext and enext2)
04503 //   or between two tetrahedra (fnext).
04504 
04505 // If e0 = e(i, j), e1 = e(j, i), that is e0 and e1 are the two directions
04506 //   of the same undirected edge of a face. e0.sym() = e1 and vice versa.
04507 
04508 inline void tetgenmesh::esym(triface& t1, triface& t2) {
04509   t2.tet = t1.tet;
04510   t2.loc = t1.loc;
04511   t2.ver = t1.ver + (EdgeRing(t1.ver) ? -1 : 1);
04512 }
04513 
04514 inline void tetgenmesh::esymself(triface& t) {
04515   t.ver += (EdgeRing(t.ver) ? -1 : 1);
04516 }
04517 
04518 // If e0 and e1 are both in the same edge ring of a face, e1 = e0.enext().
04519 
04520 inline void tetgenmesh::enext(triface& t1, triface& t2) {
04521   t2.tet = t1.tet;
04522   t2.loc = t1.loc;
04523   t2.ver = ve[t1.ver];
04524 }
04525 
04526 inline void tetgenmesh::enextself(triface& t) {
04527   t.ver = ve[t.ver];
04528 }
04529 
04530 // enext2() is equal to e2 = e0.enext().enext()
04531 
04532 inline void tetgenmesh::enext2(triface& t1, triface& t2) {
04533   t2.tet = t1.tet;
04534   t2.loc = t1.loc;
04535   t2.ver = ve[ve[t1.ver]];
04536 }
04537 
04538 inline void tetgenmesh::enext2self(triface& t) {
04539   t.ver = ve[ve[t.ver]];
04540 }
04541 
04542 // If f0 and f1 are both in the same face ring of a face, f1 = f0.fnext().
04543 //   If f1 exists, return true. Otherwise, return false, i.e., f0 is a
04544 //   boundary or hull face.
04545 
04546 inline bool tetgenmesh::fnext(triface& t1, triface& t2)
04547 {
04548   // Get the next face.
04549   t2.loc = locver2nextf[t1.loc][t1.ver][0];
04550   // Is the next face in the same tet?
04551   if (t2.loc != -1) {
04552     // It's in the same tet. Get the edge version.
04553     t2.ver = locver2nextf[t1.loc][t1.ver][1];
04554     t2.tet = t1.tet;
04555   } else {
04556     // The next face is in the neigbhour of 't1'.
04557     sym(t1, t2);
04558     if (t2.tet != dummytet) {
04559       // Find the corresponding edge in t2.
04560       point torg;
04561       int tloc, tver, i;
04562       t2.ver = 0;
04563       torg = org(t1);
04564       for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04565         enextself(t2);
04566       }
04567       // Go to the next face in t2.
04568       tloc = t2.loc;
04569       tver = t2.ver;
04570       t2.loc = locver2nextf[tloc][tver][0];
04571       t2.ver = locver2nextf[tloc][tver][1];
04572     }
04573   }
04574   return t2.tet != dummytet;
04575 }
04576 
04577 inline bool tetgenmesh::fnextself(triface& t1)
04578 {
04579   triface t2;
04580 
04581   // Get the next face.
04582   t2.loc = locver2nextf[t1.loc][t1.ver][0];
04583   // Is the next face in the same tet?
04584   if (t2.loc != -1) {
04585     // It's in the same tet. Get the edge version.
04586     t2.ver = locver2nextf[t1.loc][t1.ver][1];
04587     t1.loc = t2.loc;
04588     t1.ver = t2.ver;
04589   } else {
04590     // The next face is in the neigbhour of 't1'.
04591     sym(t1, t2);
04592     if (t2.tet != dummytet) {
04593       // Find the corresponding edge in t2.
04594       point torg;
04595       int i;
04596       t2.ver = 0;
04597       torg = org(t1);
04598       for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04599         enextself(t2);
04600       }
04601       t1.loc = locver2nextf[t2.loc][t2.ver][0];
04602       t1.ver = locver2nextf[t2.loc][t2.ver][1];
04603       t1.tet = t2.tet;
04604     }
04605   }
04606   return t2.tet != dummytet;
04607 }
04608 
04609 // enextfnext() and enext2fnext() are combination primitives of enext(),
04610 //   enext2() and fnext().
04611 
04612 inline void tetgenmesh::enextfnext(triface& t1, triface& t2) {
04613   enext(t1, t2);
04614   fnextself(t2);
04615 }
04616 
04617 inline void tetgenmesh::enextfnextself(triface& t) {
04618   enextself(t);
04619   fnextself(t);
04620 }
04621 
04622 inline void tetgenmesh::enext2fnext(triface& t1, triface& t2) {
04623   enext2(t1, t2);
04624   fnextself(t2);
04625 }
04626 
04627 inline void tetgenmesh::enext2fnextself(triface& t) {
04628   enext2self(t);
04629   fnextself(t);
04630 }
04631 
04632 // Primitives to infect or cure a tetrahedron with the virus.   The last
04633 //   third bit of the pointer is marked for infection.  These rely on the
04634 //   assumption that all tetrahedron are aligned to eight-byte boundaries.
04635 
04636 inline void tetgenmesh::infect(triface& t) {
04637   t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] | (unsigned long) 4l);
04638 }
04639 
04640 inline void tetgenmesh::uninfect(triface& t) {
04641   t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] & ~ (unsigned long) 4l);
04642 }
04643 
04644 // Test a tetrahedron for viral infection.
04645 
04646 inline bool tetgenmesh::infected(triface& t) {
04647   return (((unsigned long) t.tet[0] & (unsigned long) 4l) != 0);
04648 }
04649 
04650 // Check or set a tetrahedron's attributes.
04651 
04652 inline REAL tetgenmesh::elemattribute(tetrahedron* ptr, int attnum) {
04653   return ((REAL *) (ptr))[elemattribindex + attnum];
04654 }
04655 
04656 inline void tetgenmesh::
04657 setelemattribute(tetrahedron* ptr, int attnum, REAL value){
04658   ((REAL *) (ptr))[elemattribindex + attnum] = value;
04659 }
04660 
04661 // Check or set a tetrahedron's maximum volume bound.
04662 
04663 inline REAL tetgenmesh::volumebound(tetrahedron* ptr) {
04664   return ((REAL *) (ptr))[volumeboundindex];
04665 }
04666 
04667 inline void tetgenmesh::setvolumebound(tetrahedron* ptr, REAL value) {
04668   ((REAL *) (ptr))[volumeboundindex] = value;
04669 }
04670 
04671 //
04672 // End of primitives for tetrahedra
04673 //
04674 
04675 //
04676 // Begin of primitives for subfaces/subsegments
04677 //
04678 
04679 // Each subface contains three pointers to its neighboring subfaces, with
04680 //   edge versions.  To save memory, both information are kept in a single
04681 //   pointer. To make this possible, all subfaces are aligned to eight-byte
04682 //   boundaries, so that the last three bits of each pointer are zeros. An
04683 //   edge version (in the range 0 to 5) is compressed into the last three
04684 //   bits of each pointer by 'sencode()'.  'sdecode()' decodes a pointer,
04685 //   extracting an edge version and a pointer to the beginning of a subface.
04686 
04687 inline void tetgenmesh::sdecode(shellface sptr, face& s) {
04688   s.shver = (int) ((unsigned long) (sptr) & (unsigned long) 7l);
04689   s.sh = (shellface *) ((unsigned long) (sptr) & ~ (unsigned long) 7l);
04690 }
04691 
04692 inline tetgenmesh::shellface tetgenmesh::sencode(face& s) {
04693   return (shellface) ((unsigned long) s.sh | (unsigned long) s.shver);
04694 }
04695 
04696 // spivot() finds the other subface (from this subface) that shares the
04697 //   same edge.
04698 
04699 inline void tetgenmesh::spivot(face& s1, face& s2) {
04700   shellface sptr = s1.sh[Orient(s1.shver)];
04701   sdecode(sptr, s2);
04702 }
04703 
04704 inline void tetgenmesh::spivotself(face& s) {
04705   shellface sptr = s.sh[Orient(s.shver)];
04706   sdecode(sptr, s);
04707 }
04708 
04709 // sbond() bonds two subfaces together, i.e., after bonding, both faces
04710 //   are pointing to each other.
04711 
04712 inline void tetgenmesh::sbond(face& s1, face& s2) {
04713   s1.sh[Orient(s1.shver)] = sencode(s2);
04714   s2.sh[Orient(s2.shver)] = sencode(s1);
04715 }
04716 
04717 // sbond1() only bonds s2 to s1, i.e., after bonding, s1 is pointing to s2,
04718 //   but s2 is not pointing to s1.
04719 
04720 inline void tetgenmesh::sbond1(face& s1, face& s2) {
04721   s1.sh[Orient(s1.shver)] = sencode(s2);
04722 }
04723 
04724 // Dissolve a subface bond (from one side).  Note that the other subface
04725 //   will still think it's connected to this subface.
04726 
04727 inline void tetgenmesh::sdissolve(face& s) {
04728   s.sh[Orient(s.shver)] = (shellface) dummysh;
04729 }
04730 
04731 // These primitives determine or set the origin, destination, or apex
04732 //   of a subface with respect to the edge version.
04733 
04734 inline tetgenmesh::point tetgenmesh::sorg(face& s) {
04735   return (point) s.sh[3 + vo[s.shver]];
04736 }
04737 
04738 inline tetgenmesh::point tetgenmesh::sdest(face& s) {
04739   return (point) s.sh[3 + vd[s.shver]];
04740 }
04741 
04742 inline tetgenmesh::point tetgenmesh::sapex(face& s) {
04743   return (point) s.sh[3 + va[s.shver]];
04744 }
04745 
04746 inline void tetgenmesh::setsorg(face& s, point pointptr) {
04747   s.sh[3 + vo[s.shver]] = (shellface) pointptr;
04748 }
04749 
04750 inline void tetgenmesh::setsdest(face& s, point pointptr) {
04751   s.sh[3 + vd[s.shver]] = (shellface) pointptr;
04752 }
04753 
04754 inline void tetgenmesh::setsapex(face& s, point pointptr) {
04755   s.sh[3 + va[s.shver]] = (shellface) pointptr;
04756 }
04757 
04758 // These primitives were drived from Mucke[2]'s triangle-edge data structure
04759 //   to change face-edge relation in a subface (sesym, senext and senext2).
04760 
04761 inline void tetgenmesh::sesym(face& s1, face& s2) {
04762   s2.sh = s1.sh;
04763   s2.shver = s1.shver + (EdgeRing(s1.shver) ? -1 : 1);
04764 }
04765 
04766 inline void tetgenmesh::sesymself(face& s) {
04767   s.shver += (EdgeRing(s.shver) ? -1 : 1);
04768 }
04769 
04770 inline void tetgenmesh::senext(face& s1, face& s2) {
04771   s2.sh = s1.sh;
04772   s2.shver = ve[s1.shver];
04773 }
04774 
04775 inline void tetgenmesh::senextself(face& s) {
04776   s.shver = ve[s.shver];
04777 }
04778 
04779 inline void tetgenmesh::senext2(face& s1, face& s2) {
04780   s2.sh = s1.sh;
04781   s2.shver = ve[ve[s1.shver]];
04782 }
04783 
04784 inline void tetgenmesh::senext2self(face& s) {
04785   s.shver = ve[ve[s.shver]];
04786 }
04787 
04788 // If f0 and f1 are both in the same face ring, then f1 = f0.fnext(),
04789 
04790 inline void tetgenmesh::sfnext(face& s1, face& s2) {
04791   getnextsface(&s1, &s2);
04792 }
04793 
04794 inline void tetgenmesh::sfnextself(face& s) {
04795   getnextsface(&s, NULL);
04796 }
04797 
04798 // These primitives read or set a pointer of the badface structure.  The
04799 //   pointer is stored sh[11].
04800 
04801 inline tetgenmesh::badface* tetgenmesh::shell2badface(face& s) {
04802   return (badface*) s.sh[11];
04803 }
04804 
04805 inline void tetgenmesh::setshell2badface(face& s, badface* value) {
04806   s.sh[11] = (shellface) value;
04807 }
04808 
04809 // Check or set a subface's maximum area bound.
04810 
04811 inline REAL tetgenmesh::areabound(face& s) {
04812   return ((REAL *) (s.sh))[areaboundindex];
04813 }
04814 
04815 inline void tetgenmesh::setareabound(face& s, REAL value) {
04816   ((REAL *) (s.sh))[areaboundindex] = value;
04817 }
04818 
04819 // These two primitives read or set a shell marker.  Shell markers are used
04820 //   to hold user boundary information.
04821 
04822 inline int tetgenmesh::shellmark(face& s) {
04823   return ((int *) (s.sh))[shmarkindex];
04824 }
04825 
04826 inline void tetgenmesh::setshellmark(face& s, int value) {
04827   ((int *) (s.sh))[shmarkindex] = value;
04828 }
04829 
04830 // These two primitives set or read the type of the subface or subsegment.
04831 
04832 inline enum tetgenmesh::shestype tetgenmesh::shelltype(face& s) {
04833   return (enum shestype) ((int *) (s.sh))[shmarkindex + 1];
04834 }
04835 
04836 inline void tetgenmesh::setshelltype(face& s, enum shestype value) {
04837   ((int *) (s.sh))[shmarkindex + 1] = (int) value;
04838 }
04839 
04840 // These two primitives set or read the pbc group of the subface.
04841 
04842 inline int tetgenmesh::shellpbcgroup(face& s) {
04843   return ((int *) (s.sh))[shmarkindex + 2];
04844 }
04845 
04846 inline void tetgenmesh::setshellpbcgroup(face& s, int value) {
04847   ((int *) (s.sh))[shmarkindex + 2] = value;
04848 }
04849 
04850 // Primitives to infect or cure a subface with the virus. These rely on the
04851 //   assumption that all tetrahedra are aligned to eight-byte boundaries.
04852 
04853 inline void tetgenmesh::sinfect(face& s) {
04854   s.sh[6] = (shellface) ((unsigned long) s.sh[6] | (unsigned long) 4l);
04855 }
04856 
04857 inline void tetgenmesh::suninfect(face& s) {
04858   s.sh[6] = (shellface)((unsigned long) s.sh[6] & ~(unsigned long) 4l);
04859 }
04860 
04861 // Test a subface for viral infection.
04862 
04863 inline bool tetgenmesh::sinfected(face& s) {
04864   return (((unsigned long) s.sh[6] & (unsigned long) 4l) != 0);
04865 }
04866 
04867 //
04868 // End of primitives for subfaces/subsegments
04869 //
04870 
04871 //
04872 // Begin of primitives for interacting between tetrahedra and subfaces
04873 //
04874 
04875 // tspivot() finds a subface abutting on this tetrahdera.
04876 
04877 inline void tetgenmesh::tspivot(triface& t, face& s) {
04878   shellface sptr = (shellface) t.tet[8 + t.loc];
04879   sdecode(sptr, s);
04880 }
04881 
04882 // stpivot() finds a tetrahedron abutting a subface.
04883 
04884 inline void tetgenmesh::stpivot(face& s, triface& t) {
04885   tetrahedron ptr = (tetrahedron) s.sh[6 + EdgeRing(s.shver)];
04886   decode(ptr, t);
04887 }
04888 
04889 // tsbond() bond a tetrahedron to a subface.
04890 
04891 inline void tetgenmesh::tsbond(triface& t, face& s) {
04892   t.tet[8 + t.loc] = (tetrahedron) sencode(s);
04893   s.sh[6 + EdgeRing(s.shver)] = (shellface) encode(t);
04894 }
04895 
04896 // tsdissolve() dissolve a bond (from the tetrahedron side).
04897 
04898 inline void tetgenmesh::tsdissolve(triface& t) {
04899   t.tet[8 + t.loc] = (tetrahedron) dummysh;
04900 }
04901 
04902 // stdissolve() dissolve a bond (from the subface side).
04903 
04904 inline void tetgenmesh::stdissolve(face& s) {
04905   s.sh[6 + EdgeRing(s.shver)] = (shellface) dummytet;
04906 }
04907 
04908 //
04909 // End of primitives for interacting between tetrahedra and subfaces
04910 //
04911 
04912 //
04913 // Begin of primitives for interacting between subfaces and subsegs
04914 //
04915 
04916 // sspivot() finds a subsegment abutting a subface.
04917 
04918 inline void tetgenmesh::sspivot(face& s, face& edge) {
04919   shellface sptr = (shellface) s.sh[8 + Orient(s.shver)];
04920   sdecode(sptr, edge);
04921 }
04922 
04923 // ssbond() bond a subface to a subsegment.
04924 
04925 inline void tetgenmesh::ssbond(face& s, face& edge) {
04926   s.sh[8 + Orient(s.shver)] = sencode(edge);
04927   edge.sh[0] = sencode(s);
04928 }
04929 
04930 // ssdisolve() dissolve a bond (from the subface side)
04931 
04932 inline void tetgenmesh::ssdissolve(face& s) {
04933   s.sh[8 + Orient(s.shver)] = (shellface) dummysh;
04934 }
04935 
04936 //
04937 // End of primitives for interacting between subfaces and subsegs
04938 //
04939 
04940 //
04941 // Begin of primitives for interacting between tet and subsegs.
04942 //
04943 
04944 inline void tetgenmesh::tsspivot1(triface& t, face& seg)
04945 {
04946   shellface sptr = (shellface) t.tet[8 + locver2edge[t.loc][t.ver]];
04947   sdecode(sptr, seg);
04948 }
04949 
04950 // Only bond/dissolve at tet's side, but not vice versa.
04951 
04952 inline void tetgenmesh::tssbond1(triface& t, face& seg)
04953 {
04954   t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) sencode(seg);
04955 }
04956 
04957 inline void tetgenmesh::tssdissolve1(triface& t)
04958 {
04959   t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) dummysh;
04960 }
04961 
04962 //
04963 // End of primitives for interacting between tet and subsegs.
04964 //
04965 
04966 //
04967 // Begin of primitives for points
04968 //
04969 
04970 inline int tetgenmesh::pointmark(point pt) {
04971   return ((int *) (pt))[pointmarkindex];
04972 }
04973 
04974 inline void tetgenmesh::setpointmark(point pt, int value) {
04975   ((int *) (pt))[pointmarkindex] = value;
04976 }
04977 
04978 // These two primitives set and read the type of the point.
04979 
04980 inline enum tetgenmesh::verttype tetgenmesh::pointtype(point pt) {
04981   return (enum verttype) ((int *) (pt))[pointmarkindex + 1];
04982 }
04983 
04984 inline void tetgenmesh::setpointtype(point pt, enum verttype value) {
04985   ((int *) (pt))[pointmarkindex + 1] = (int) value;
04986 }
04987 
04988 // These following primitives set and read a pointer to a tetrahedron
04989 //   a subface/subsegment, a point, or a tet of background mesh.
04990 
04991 inline tetgenmesh::tetrahedron tetgenmesh::point2tet(point pt) {
04992   return ((tetrahedron *) (pt))[point2simindex];
04993 }
04994 
04995 inline void tetgenmesh::setpoint2tet(point pt, tetrahedron value) {
04996   ((tetrahedron *) (pt))[point2simindex] = value;
04997 }
04998 
04999 inline tetgenmesh::shellface tetgenmesh::point2sh(point pt) {
05000   return (shellface) ((tetrahedron *) (pt))[point2simindex + 1];
05001 }
05002 
05003 inline void tetgenmesh::setpoint2sh(point pt, shellface value) {
05004   ((tetrahedron *) (pt))[point2simindex + 1] = (tetrahedron) value;
05005 }
05006 
05007 inline tetgenmesh::point tetgenmesh::point2ppt(point pt) {
05008   return (point) ((tetrahedron *) (pt))[point2simindex + 2];
05009 }
05010 
05011 inline void tetgenmesh::setpoint2ppt(point pt, point value) {
05012   ((tetrahedron *) (pt))[point2simindex + 2] = (tetrahedron) value;
05013 }
05014 
05015 inline tetgenmesh::tetrahedron tetgenmesh::point2bgmtet(point pt) {
05016   return ((tetrahedron *) (pt))[point2simindex + 3];
05017 }
05018 
05019 inline void tetgenmesh::setpoint2bgmtet(point pt, tetrahedron value) {
05020   ((tetrahedron *) (pt))[point2simindex + 3] = value;
05021 }
05022 
05023 // These primitives set and read a pointer to its pbc point.
05024 
05025 inline tetgenmesh::point tetgenmesh::point2pbcpt(point pt) {
05026   return (point) ((tetrahedron *) (pt))[point2pbcptindex];
05027 }
05028 
05029 inline void tetgenmesh::setpoint2pbcpt(point pt, point value) {
05030   ((tetrahedron *) (pt))[point2pbcptindex] = (tetrahedron) value;
05031 }
05032 
05033 //
05034 // End of primitives for points
05035 //
05036 
05037 //
05038 // Begin of advanced primitives
05039 //
05040 
05041 // adjustedgering() adjusts the edge version so that it belongs to the
05042 //   indicated edge ring.  The 'direction' only can be 0(CCW) or 1(CW).
05043 //   If the edge is not in the wanted edge ring, reverse it.
05044 
05045 inline void tetgenmesh::adjustedgering(triface& t, int direction) {
05046   if (EdgeRing(t.ver) != direction) {
05047     esymself(t);
05048   }
05049 }
05050 
05051 inline void tetgenmesh::adjustedgering(face& s, int direction) {
05052   if (EdgeRing(s.shver) != direction) {
05053     sesymself(s);
05054   }
05055 }
05056 
05057 // isdead() returns TRUE if the tetrahedron or subface has been dealloced.
05058 
05059 inline bool tetgenmesh::isdead(triface* t) {
05060   if (t->tet == (tetrahedron *) NULL) return true;
05061   else return t->tet[4] == (tetrahedron) NULL;
05062 }
05063 
05064 inline bool tetgenmesh::isdead(face* s) {
05065   if (s->sh == (shellface *) NULL) return true;
05066   else return s->sh[3] == (shellface) NULL;
05067 }
05068 
05069 // isfacehaspoint() returns TRUE if the 'testpoint' is one of the vertices
05070 //   of the tetface 't' subface 's'.
05071 
05072 inline bool tetgenmesh::isfacehaspoint(triface* t, point testpoint) {
05073   return ((org(*t) == testpoint) || (dest(*t) == testpoint) ||
05074           (apex(*t) == testpoint));
05075 }
05076 
05077 inline bool tetgenmesh::isfacehaspoint(face* s, point testpoint) {
05078   return (s->sh[3] == (shellface) testpoint) ||
05079          (s->sh[4] == (shellface) testpoint) ||
05080          (s->sh[5] == (shellface) testpoint);
05081 }
05082 
05083 // isfacehasedge() returns TRUE if the edge (given by its two endpoints) is
05084 //   one of the three edges of the subface 's'.
05085 
05086 inline bool tetgenmesh::isfacehasedge(face* s, point tend1, point tend2) {
05087   return (isfacehaspoint(s, tend1) && isfacehaspoint(s, tend2));
05088 }
05089 
05090 // issymexist() returns TRUE if the adjoining tetrahedron is not 'duumytet'.
05091 
05092 inline bool tetgenmesh::issymexist(triface* t) {
05093   tetrahedron *ptr = (tetrahedron *)
05094     ((unsigned long)(t->tet[t->loc]) & ~(unsigned long)7l);
05095   return ptr != dummytet;
05096 }
05097 
05099 //                                                                           //
05100 // getnextsface()    Finds the next subface in the face ring.                //
05101 //                                                                           //
05102 // For saving space in the data structure of subface, there only exists one  //
05103 // face ring around a segment (see programming manual).  This routine imple- //
05104 // ments the double face ring as desired in Muecke's data structure.         //
05105 //                                                                           //
05107 
05108 void tetgenmesh::getnextsface(face* s1, face* s2)
05109 {
05110   face neighsh, spinsh;
05111   face testseg;
05112 
05113   sspivot(*s1, testseg);
05114   if (testseg.sh != dummysh) {
05115     testseg.shver = 0;
05116     if (sorg(testseg) == sorg(*s1)) {
05117       spivot(*s1, neighsh);
05118     } else {
05119       spinsh = *s1;
05120       do {
05121         neighsh = spinsh;
05122         spivotself(spinsh);
05123       } while (spinsh.sh != s1->sh);
05124     }
05125   } else {
05126     spivot(*s1, neighsh);
05127   }
05128   if (sorg(neighsh) != sorg(*s1)) {
05129     sesymself(neighsh);
05130   }
05131   if (s2 != (face *) NULL) {
05132     *s2 = neighsh;
05133   } else {
05134     *s1 = neighsh;
05135   }
05136 }
05137 
05139 //                                                                           //
05140 // tsspivot()    Finds a subsegment abutting on a tetrahderon's edge.        //
05141 //                                                                           //
05142 // The edge is represented in the primary edge of 'checkedge'. If there is a //
05143 // subsegment bonded at this edge, it is returned in handle 'checkseg', the  //
05144 // edge direction of 'checkseg' is conformed to 'checkedge'. If there isn't, //
05145 // set 'checkseg.sh = dummysh' to indicate it is not a subsegment.           //
05146 //                                                                           //
05147 // To find whether an edge of a tetrahedron is a subsegment or not. First we //
05148 // need find a subface around this edge to see if it contains a subsegment.  //
05149 // The reason is there is no direct connection between a tetrahedron and its //
05150 // adjoining subsegments.                                                    //
05151 //                                                                           //
05153 
05154 void tetgenmesh::tsspivot(triface* checkedge, face* checkseg)
05155 {
05156   triface spintet;
05157   face parentsh;
05158   point tapex;
05159   int hitbdry;
05160 
05161   spintet = *checkedge;
05162   tapex = apex(*checkedge);
05163   hitbdry = 0;
05164   do {
05165     tspivot(spintet, parentsh);
05166     // Does spintet have a (non-fake) subface attached?
05167     if ((parentsh.sh != dummysh) && (sapex(parentsh) != NULL)) {
05168       // Find a subface! Find the edge in it.
05169       findedge(&parentsh, org(*checkedge), dest(*checkedge));
05170       sspivot(parentsh, *checkseg);
05171       if (checkseg->sh != dummysh) {
05172         // Find a subsegment! Correct its edge direction before return.
05173         if (sorg(*checkseg) != org(*checkedge)) {
05174           sesymself(*checkseg);
05175         }
05176       }
05177       return;
05178     }
05179     if (!fnextself(spintet)) {
05180       hitbdry++;
05181       if (hitbdry < 2) {
05182         esym(*checkedge, spintet);
05183         if (!fnextself(spintet)) {
05184           hitbdry++;
05185         }
05186       }
05187     }
05188   } while ((apex(spintet) != tapex) && (hitbdry < 2));
05189   // Not find.
05190   checkseg->sh = dummysh;
05191 }
05192 
05194 //                                                                           //
05195 // sstpivot()    Finds a tetrahedron abutting a subsegment.                  //
05196 //                                                                           //
05197 // This is the inverse operation of 'tsspivot()'.  One subsegment shared by  //
05198 // arbitrary number of tetrahedron, the returned tetrahedron is not unique.  //
05199 // The edge direction of the returned tetrahedron is conformed to the given  //
05200 // subsegment.                                                               //
05201 //                                                                           //
05203 
05204 void tetgenmesh::sstpivot(face* checkseg, triface* retedge)
05205 {
05206   face parentsh;
05207 
05208   // Get the subface which holds the subsegment.
05209   sdecode(checkseg->sh[0], parentsh);
05210 #ifdef SELF_CHECK
05211   assert(parentsh.sh != dummysh);
05212 #endif
05213   // Get a tetraheron to which the subface attches.
05214   stpivot(parentsh, *retedge);
05215   if (retedge->tet == dummytet) {
05216     sesymself(parentsh);
05217     stpivot(parentsh, *retedge);
05218 #ifdef SELF_CHECK
05219     assert(retedge->tet != dummytet);
05220 #endif
05221   }
05222   // Correct the edge direction before return.
05223   findedge(retedge, sorg(*checkseg), sdest(*checkseg));
05224 }
05225 
05227 //                                                                           //
05228 // findorg()    Finds a point in the given handle (tetrahedron or subface).  //
05229 //                                                                           //
05230 // If 'dorg' is a one of vertices of the given handle,  set the origin of    //
05231 // this handle be that point and return TRUE.  Otherwise, return FALSE and   //
05232 // 'tface' remains unchanged.                                                //
05233 //                                                                           //
05235 
05236 bool tetgenmesh::findorg(triface* tface, point dorg)
05237 {
05238   if (org(*tface) == dorg) {
05239     return true;
05240   } else {
05241     if (dest(*tface) == dorg) {
05242       enextself(*tface);
05243       return true;
05244     } else {
05245       if (apex(*tface) == dorg) {
05246         enext2self(*tface);
05247         return true;
05248       } else {
05249         if (oppo(*tface) == dorg) {
05250           // Keep 'tface' referring to the same tet after fnext().
05251           adjustedgering(*tface, CCW);
05252           fnextself(*tface);
05253           enext2self(*tface);
05254           return true;
05255         }
05256       }
05257     }
05258   }
05259   return false;
05260 }
05261 
05262 bool tetgenmesh::findorg(face* sface, point dorg)
05263 {
05264   if (sorg(*sface) == dorg) {
05265     return true;
05266   } else {
05267     if (sdest(*sface) == dorg) {
05268       senextself(*sface);
05269       return true;
05270     } else {
05271       if (sapex(*sface) == dorg) {
05272         senext2self(*sface);
05273         return true;
05274       }
05275     }
05276   }
05277   return false;
05278 }
05279 
05281 //                                                                           //
05282 // findedge()    Find an edge in the given handle (tetrahedron or subface).  //
05283 //                                                                           //
05284 // The edge is given in two points 'eorg' and 'edest'.  It is assumed that   //
05285 // the edge must exist in the given handle (tetrahedron or subface).  This   //
05286 // routine sets the right edge version for the input handle.                 //
05287 //                                                                           //
05289 
05290 void tetgenmesh::findedge(triface* tface, point eorg, point edest)
05291 {
05292   int i;
05293 
05294   for (i = 0; i < 3; i++) {
05295     if (org(*tface) == eorg) {
05296       if (dest(*tface) == edest) {
05297         // Edge is found, return.
05298         return;
05299       }
05300     } else {
05301       if (org(*tface) == edest) {
05302         if (dest(*tface) == eorg) {
05303           // Edge is found, inverse the direction and return.
05304           esymself(*tface);
05305           return;
05306         }
05307       }
05308     }
05309     enextself(*tface);
05310   }
05311   // It should never be here.
05312   printf("Internalerror in findedge():  Unable to find an edge in tet.\n");
05313   internalerror();
05314 }
05315 
05316 void tetgenmesh::findedge(face* sface, point eorg, point edest)
05317 {
05318   int i;
05319 
05320   for (i = 0; i < 3; i++) {
05321     if (sorg(*sface) == eorg) {
05322       if (sdest(*sface) == edest) {
05323         // Edge is found, return.
05324         return;
05325       }
05326     } else {
05327       if (sorg(*sface) == edest) {
05328         if (sdest(*sface) == eorg) {
05329           // Edge is found, inverse the direction and return.
05330           sesymself(*sface);
05331           return;
05332         }
05333       }
05334     }
05335     senextself(*sface);
05336   }
05337   printf("Internalerror in findedge():  Unable to find an edge in subface.\n");
05338   internalerror();
05339 }
05340 
05342 //                                                                           //
05343 // findface()    Find the face has the given origin, destination and apex.   //
05344 //                                                                           //
05345 // On input, 'fface' is a handle which may contain the three corners or may  //
05346 // not or may be dead.  On return, it represents exactly the face with the   //
05347 // given origin, destination and apex.                                       //
05348 //                                                                           //
05350 
05351 void tetgenmesh::findface(triface *fface, point forg, point fdest, point fapex)
05352 {
05353   triface spintet;
05354   enum finddirectionresult collinear;
05355   int hitbdry;
05356 
05357   if (!isdead(fface)) {
05358     // First check the easiest case, that 'fface' is just the right one.
05359     if (org(*fface) == forg && dest(*fface) == fdest &&
05360         apex(*fface) == fapex) return;
05361   } else {
05362     // The input handle is dead, use the 'recenttet' if it is alive.
05363     if (!isdead(&recenttet)) *fface = recenttet;
05364   }
05365 
05366   if (!isdead(fface)) {
05367     if (!findorg(fface, forg)) {
05368       // 'forg' is not a corner of 'fface', locate it.
05369       preciselocate(forg, fface, tetrahedrons->items);
05370     }
05371     // It is possible that forg is not found in a non-convex mesh.
05372     if (org(*fface) == forg) {
05373       collinear = finddirection(fface, fdest, tetrahedrons->items);
05374       if (collinear == RIGHTCOLLINEAR) {
05375         // fdest is just the destination.
05376       } else if (collinear == LEFTCOLLINEAR) {
05377         enext2self(*fface);
05378         esymself(*fface);
05379       } else if (collinear == TOPCOLLINEAR) {
05380         fnextself(*fface);
05381         enext2self(*fface);
05382         esymself(*fface);
05383       }
05384     }
05385     // It is possible taht fdest is not found in a non-convex mesh.
05386     if ((org(*fface) == forg) && (dest(*fface) == fdest)) {
05387       // Find the apex of 'fapex'.
05388       spintet = *fface;
05389       hitbdry = 0;
05390       do {
05391         if (apex(spintet) == fapex) {
05392           // We have done. Be careful the edge direction of 'spintet',
05393           //   it may reversed because of hitting boundary once.
05394           if (org(spintet) != org(*fface)) {
05395             esymself(spintet);
05396           }
05397           *fface = spintet;
05398           return;
05399         }
05400         if (!fnextself(spintet)) {
05401           hitbdry ++;
05402           if (hitbdry < 2) {
05403             esym(*fface, spintet);
05404             if (!fnextself(spintet)) {
05405               hitbdry ++;
05406             }
05407           }
05408         }
05409       } while (hitbdry < 2 && apex(spintet) != apex(*fface));
05410       // It is possible that fapex is not found in a non-convex mesh.
05411     }
05412   }
05413 
05414   if (isdead(fface) || (org(*fface) != forg) || (dest(*fface) != fdest) ||
05415       (apex(*fface) != fapex)) {
05416     // Too bad, the input handle is useless. We have to find a handle
05417     //   for 'fface' contains the 'forg' and 'fdest'. Here a brute force
05418     //   search is performed.
05419     if (b->verbose > 1) {
05420       printf("Warning in findface():  Perform a brute-force searching.\n");
05421     }
05422     enum verttype forgty, fdestty, fapexty;
05423     int share, i;
05424     forgty = pointtype(forg);
05425     fdestty = pointtype(fdest);
05426     fapexty = pointtype(fapex);
05427     setpointtype(forg, DEADVERTEX);
05428     setpointtype(fdest, DEADVERTEX);
05429     setpointtype(fapex, DEADVERTEX);
05430     tetrahedrons->traversalinit();
05431     fface->tet = tetrahedrontraverse();
05432     while (fface->tet != (tetrahedron *) NULL) {
05433       share = 0;
05434       for (i = 0; i < 4; i++) {
05435         if (pointtype((point) fface->tet[4 + i]) == DEADVERTEX) share ++;
05436       }
05437       if (share == 3) {
05438         // Found! Set the correct face and desired corners.
05439         if (pointtype((point) fface->tet[4]) != DEADVERTEX) {
05440           fface->loc = 2;
05441         } else if (pointtype((point) fface->tet[5]) != DEADVERTEX) {
05442           fface->loc = 3;
05443         } else if (pointtype((point) fface->tet[6]) != DEADVERTEX) {
05444           fface->loc = 1;
05445         } else { // pointtype((point) fface->tet[7]) != DEADVERTEX
05446           fface->loc = 0;
05447         }
05448         findedge(fface, forg, fdest);
05449         break;
05450       }
05451       fface->tet = tetrahedrontraverse();
05452     }
05453     setpointtype(forg, forgty);
05454     setpointtype(fdest, fdestty);
05455     setpointtype(fapex, fapexty);
05456     if (fface->tet == (tetrahedron *) NULL) {
05457       // It is impossible to reach here.
05458       printf("Internal error:  Fail to find the indicated face.\n");
05459       internalerror();
05460     }
05461   }
05462 }
05463 
05465 //                                                                           //
05466 // getonextseg()    Get the next SEGMENT counterclockwise with the same org. //
05467 //                                                                           //
05468 // 's' is a subface. This routine reteuns the segment which is counterclock- //
05469 // wise with the origin of s.                                                //
05470 //                                                                           //
05472 
05473 void tetgenmesh::getonextseg(face* s, face* lseg)
05474 {
05475   face checksh, checkseg;
05476   point forg;
05477 
05478   forg = sorg(*s);
05479   checksh = *s;
05480   do {
05481     // Go to the edge at forg's left side.
05482     senext2self(checksh);
05483     // Check if there is a segment attaching this edge.
05484     sspivot(checksh, checkseg);
05485     if (checkseg.sh != dummysh) break;
05486     // No segment! Go to the neighbor of this subface.
05487     spivotself(checksh);
05488 #ifdef SELF_CHECK
05489     // It should always meet a segment before come back.
05490     assert(checksh.sh != s->sh);
05491 #endif
05492     if (sorg(checksh) != forg) {
05493       sesymself(checksh);
05494 #ifdef SELF_CHECK
05495       assert(sorg(checksh) == forg);
05496 #endif
05497     }
05498   } while (true);
05499   if (sorg(checkseg) != forg) sesymself(checkseg);
05500   *lseg = checkseg;
05501 }
05502 
05504 //                                                                           //
05505 // getseghasorg()    Get the segment containing the given point.             //
05506 //                                                                           //
05507 // 'dorg' is an endpoint of a segment S. 'sseg' is a subsegment of S. This   //
05508 // routine search a subsegment (along sseg) of S containing dorg. On return, //
05509 // 'sseg' contains 'dorg' as its origin.                                     //
05510 //                                                                           //
05512 
05513 void tetgenmesh::getseghasorg(face* sseg, point dorg)
05514 {
05515   face nextseg;
05516   point checkpt;
05517 
05518   nextseg = *sseg;
05519   checkpt = sorg(nextseg);
05520   while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05521     // Search dorg along the original direction of sseg.
05522     senext2self(nextseg);
05523     spivotself(nextseg);
05524     nextseg.shver = 0;
05525     if (sdest(nextseg) != checkpt) sesymself(nextseg);
05526     checkpt = sorg(nextseg);
05527   }
05528   if (checkpt == dorg) {
05529     *sseg = nextseg;
05530     return;
05531   }
05532   nextseg = *sseg;
05533   checkpt = sdest(nextseg);
05534   while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05535     // Search dorg along the destinational direction of sseg.
05536     senextself(nextseg);
05537     spivotself(nextseg);
05538     nextseg.shver = 0;
05539     if (sorg(nextseg) != checkpt) sesymself(nextseg);
05540     checkpt = sdest(nextseg);
05541   }
05542   if (checkpt == dorg) {
05543     sesym(nextseg, *sseg);
05544     return;
05545   }
05546   // Should never be here.
05547   printf("Internalerror in getseghasorg():  Unable to find the subseg.\n");
05548   internalerror();
05549 }
05550 
05552 //                                                                           //
05553 // getsubsegfarorg()    Get the origin of the parent segment of a subseg.    //
05554 //                                                                           //
05556 
05557 tetgenmesh::point tetgenmesh::getsubsegfarorg(face* sseg)
05558 {
05559   face prevseg;
05560   point checkpt;
05561 
05562   checkpt = sorg(*sseg);
05563   senext2(*sseg, prevseg);
05564   spivotself(prevseg);
05565   // Search dorg along the original direction of sseg.
05566   while (prevseg.sh != dummysh) {
05567     prevseg.shver = 0;
05568     if (sdest(prevseg) != checkpt) sesymself(prevseg);
05569     checkpt = sorg(prevseg);
05570     senext2self(prevseg);
05571     spivotself(prevseg);
05572   }
05573   return checkpt;
05574 }
05575 
05577 //                                                                           //
05578 // getsubsegfardest()    Get the dest. of the parent segment of a subseg.    //
05579 //                                                                           //
05581 
05582 tetgenmesh::point tetgenmesh::getsubsegfardest(face* sseg)
05583 {
05584   face nextseg;
05585   point checkpt;
05586 
05587   checkpt = sdest(*sseg);
05588   senext(*sseg, nextseg);
05589   spivotself(nextseg);
05590   // Search dorg along the destinational direction of sseg.
05591   while (nextseg.sh != dummysh) {
05592     nextseg.shver = 0;
05593     if (sorg(nextseg) != checkpt) sesymself(nextseg);
05594     checkpt = sdest(nextseg);
05595     senextself(nextseg);
05596     spivotself(nextseg);
05597   }
05598   return checkpt;
05599 }
05600 
05602 //                                                                           //
05603 // printtet()    Print out the details of a tetrahedron on screen.           //
05604 //                                                                           //
05605 // It's also used when the highest level of verbosity (`-VVV') is specified. //
05606 //                                                                           //
05608 
05609 void tetgenmesh::printtet(triface* tface)
05610 {
05611   triface tmpface, prtface;
05612   point tmppt;
05613   face tmpsh;
05614   int facecount;
05615 
05616   printf("Tetra x%lx with loc(%i) and ver(%i):",
05617          (unsigned long)(tface->tet), tface->loc, tface->ver);
05618   if (infected(*tface)) {
05619     printf(" (infected)");
05620   }
05621   printf("\n");
05622 
05623   tmpface = *tface;
05624   facecount = 0;
05625   while(facecount < 4) {
05626     tmpface.loc = facecount;
05627     sym(tmpface, prtface);
05628     if(prtface.tet == dummytet) {
05629       printf("      [%i] Outer space.\n", facecount);
05630     } else {
05631       printf("      [%i] x%lx  loc(%i).", facecount,
05632              (unsigned long)(prtface.tet), prtface.loc);
05633       if (infected(prtface)) {
05634         printf(" (infected)");
05635       }
05636       printf("\n");
05637     }
05638     facecount ++;
05639   }
05640 
05641   tmppt = org(*tface);
05642   if(tmppt == (point) NULL) {
05643     printf("      Org [%i] NULL\n", locver2org[tface->loc][tface->ver]);
05644   } else {
05645     printf("      Org [%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05646            locver2org[tface->loc][tface->ver], (unsigned long)(tmppt),
05647            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05648   }
05649   tmppt = dest(*tface);
05650   if(tmppt == (point) NULL) {
05651     printf("      Dest[%i] NULL\n", locver2dest[tface->loc][tface->ver]);
05652   } else {
05653     printf("      Dest[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05654            locver2dest[tface->loc][tface->ver], (unsigned long)(tmppt),
05655            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05656   }
05657   tmppt = apex(*tface);
05658   if(tmppt == (point) NULL) {
05659     printf("      Apex[%i] NULL\n", locver2apex[tface->loc][tface->ver]);
05660   } else {
05661     printf("      Apex[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05662            locver2apex[tface->loc][tface->ver], (unsigned long)(tmppt),
05663            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05664   }
05665   tmppt = oppo(*tface);
05666   if(tmppt == (point) NULL) {
05667     printf("      Oppo[%i] NULL\n", loc2oppo[tface->loc]);
05668   } else {
05669     printf("      Oppo[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05670            loc2oppo[tface->loc], (unsigned long)(tmppt),
05671            tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05672   }
05673 
05674   if (b->useshelles) {
05675     tmpface = *tface;
05676     facecount = 0;
05677     while(facecount < 6) {
05678       tmpface.loc = facecount;
05679       tspivot(tmpface, tmpsh);
05680       if(tmpsh.sh != dummysh) {
05681         printf("      [%i] x%lx  ID(%i) ", facecount,
05682                (unsigned long)(tmpsh.sh), shellmark(tmpsh));
05683         if (sorg(tmpsh) == (point) NULL) {
05684           printf("(fake)");
05685         }
05686         printf("\n");
05687       }
05688       facecount ++;
05689     }
05690   }
05691 }
05692 
05694 //                                                                           //
05695 // printsh()    Print out the details of a subface or subsegment on screen.  //
05696 //                                                                           //
05697 // It's also used when the highest level of verbosity (`-VVV') is specified. //
05698 //                                                                           //
05700 
05701 void tetgenmesh::printsh(face* sface)
05702 {
05703   face prtsh;
05704   triface prttet;
05705   point printpoint;
05706 
05707   if (sapex(*sface) != NULL) {
05708     printf("subface x%lx, ver %d, mark %d:",
05709            (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05710   } else {
05711     printf("Subsegment x%lx, ver %d, mark %d:",
05712            (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05713   }
05714   if (sinfected(*sface)) {
05715     printf(" (infected)");
05716   }
05717   if (shell2badface(*sface)) {
05718     printf(" (queued)");
05719   }
05720   if (sapex(*sface) != NULL) {
05721     if (shelltype(*sface) == SHARP) {
05722       printf(" (sharp)");
05723     }
05724   } else {
05725     if (shelltype(*sface) == SHARP) {
05726       printf(" (sharp)");
05727     }
05728   }
05729   if (checkpbcs) {
05730     if (shellpbcgroup(*sface) >= 0) {
05731       printf(" (pbc %d)", shellpbcgroup(*sface));
05732     }
05733   }
05734   printf("\n");
05735 
05736   sdecode(sface->sh[0], prtsh);
05737   if (prtsh.sh == dummysh) {
05738     printf("      [0] = No shell\n");
05739   } else {
05740     printf("      [0] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05741   }
05742   sdecode(sface->sh[1], prtsh);
05743   if (prtsh.sh == dummysh) {
05744     printf("      [1] = No shell\n");
05745   } else {
05746     printf("      [1] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05747   }
05748   sdecode(sface->sh[2], prtsh);
05749   if (prtsh.sh == dummysh) {
05750     printf("      [2] = No shell\n");
05751   } else {
05752     printf("      [2] = x%lx  %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05753   }
05754 
05755   printpoint = sorg(*sface);
05756   if (printpoint == (point) NULL)
05757     printf("      Org [%d] = NULL\n", vo[sface->shver]);
05758   else
05759     printf("      Org [%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05760            vo[sface->shver], (unsigned long)(printpoint), printpoint[0],
05761            printpoint[1], printpoint[2], pointmark(printpoint));
05762   printpoint = sdest(*sface);
05763   if (printpoint == (point) NULL)
05764     printf("      Dest[%d] = NULL\n", vd[sface->shver]);
05765   else
05766     printf("      Dest[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05767             vd[sface->shver], (unsigned long)(printpoint), printpoint[0],
05768             printpoint[1], printpoint[2], pointmark(printpoint));
05769 
05770   if (sapex(*sface) != NULL) {
05771     printpoint = sapex(*sface);
05772     if (printpoint == (point) NULL)
05773       printf("      Apex[%d] = NULL\n", va[sface->shver]);
05774     else
05775       printf("      Apex[%d] = x%lx  (%.12g,%.12g,%.12g) %d\n",
05776              va[sface->shver], (unsigned long)(printpoint), printpoint[0],
05777              printpoint[1], printpoint[2], pointmark(printpoint));
05778 
05779     decode(sface->sh[6], prttet);
05780     if (prttet.tet == dummytet) {
05781       printf("      [6] = Outer space\n");
05782     } else {
05783       printf("      [6] = x%lx  %d\n",
05784              (unsigned long)(prttet.tet), prttet.loc);
05785     }
05786     decode(sface->sh[7], prttet);
05787     if (prttet.tet == dummytet) {
05788       printf("      [7] = Outer space\n");
05789     } else {
05790       printf("      [7] = x%lx  %d\n",
05791              (unsigned long)(prttet.tet), prttet.loc);
05792     }
05793 
05794     sdecode(sface->sh[8], prtsh);
05795     if (prtsh.sh == dummysh) {
05796       printf("      [8] = No subsegment\n");
05797     } else {
05798       printf("      [8] = x%lx  %d\n",
05799              (unsigned long)(prtsh.sh), prtsh.shver);
05800     }
05801     sdecode(sface->sh[9], prtsh);
05802     if (prtsh.sh == dummysh) {
05803       printf("      [9] = No subsegment\n");
05804     } else {
05805       printf("      [9] = x%lx  %d\n",
05806              (unsigned long)(prtsh.sh), prtsh.shver);
05807     }
05808     sdecode(sface->sh[10], prtsh);
05809     if (prtsh.sh == dummysh) {
05810       printf("      [10]= No subsegment\n");
05811     } else {
05812       printf("      [10]= x%lx  %d\n",
05813              (unsigned long)(prtsh.sh), prtsh.shver);
05814     }
05815   }
05816 }
05817 
05818 //
05819 // End of advanced primitives
05820 //
05821 
05822 //
05823 // End of mesh manipulation primitives
05824 //
05825 
05826 //
05827 // Begin of mesh items searching routines
05828 //
05829 
05831 //                                                                           //
05832 // makepoint2tetmap()    Construct a mapping from points to tetrahedra.      //
05833 //                                                                           //
05834 // Traverses all the tetrahedra,  provides each corner of each tetrahedron   //
05835 // with a pointer to that tetrahedera.  Some pointers will be overwritten by //
05836 // other pointers because each point may be a corner of several tetrahedra,  //
05837 // but in the end every point will point to a tetrahedron that contains it.  //
05838 //                                                                           //
05840 
05841 void tetgenmesh::makepoint2tetmap()
05842 {
05843   triface tetloop;
05844   point pointptr;
05845 
05846   if (b->verbose > 0) {
05847     printf("  Constructing mapping from points to tetrahedra.\n");
05848   }
05849 
05850   // Initialize the point2tet field of each point.
05851   points->traversalinit();
05852   pointptr = pointtraverse();
05853   while (pointptr != (point) NULL) {
05854     setpoint2tet(pointptr, (tetrahedron) NULL);
05855     pointptr = pointtraverse();
05856   }
05857 
05858   tetrahedrons->traversalinit();
05859   tetloop.tet = tetrahedrontraverse();
05860   while (tetloop.tet != (tetrahedron *) NULL) {
05861     // Check all four points of the tetrahedron.
05862     tetloop.loc = 0;
05863     pointptr = org(tetloop);
05864     setpoint2tet(pointptr, encode(tetloop));
05865     pointptr = dest(tetloop);
05866     setpoint2tet(pointptr, encode(tetloop));
05867     pointptr = apex(tetloop);
05868     setpoint2tet(pointptr, encode(tetloop));
05869     pointptr = oppo(tetloop);
05870     setpoint2tet(pointptr, encode(tetloop));
05871     // Get the next tetrahedron in the list.
05872     tetloop.tet = tetrahedrontraverse();
05873   }
05874 }
05875 
05877 //                                                                           //
05878 // makeindex2pointmap()    Create a map from index to vertices.              //
05879 //                                                                           //
05880 // 'idx2verlist' returns the created map.  Traverse all vertices, a pointer  //
05881 // to each vertex is set into the array.  The pointer to the first vertex is //
05882 // saved in 'idx2verlist[0]'.  Don't forget to minus 'in->firstnumber' when  //
05883 // to get the vertex form its index.                                         //
05884 //                                                                           //
05886 
05887 void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
05888 {
05889   point pointloop;
05890   int idx;
05891 
05892   if (b->verbose > 0) {
05893     printf("  Constructing mapping from indices to points.\n");
05894   }
05895 
05896   idx2verlist = new point[points->items];
05897 
05898   points->traversalinit();
05899   pointloop = pointtraverse();
05900   idx = 0;
05901   while (pointloop != (point) NULL) {
05902     idx2verlist[idx] = pointloop;
05903     idx++;
05904     pointloop = pointtraverse();
05905   }
05906 }
05907 
05909 //                                                                           //
05910 // makesegmentmap()    Create a map from vertices (their indices) to         //
05911 //                     segments incident at the same vertices.               //
05912 //                                                                           //
05913 // Two arrays 'idx2seglist' and 'segsperverlist' together return the map.    //
05914 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
05915 // number of segments.  idx2seglist contains row information and             //
05916 // segsperverlist contains all (non-zero) elements.  The i-th entry of       //
05917 // idx2seglist is the starting position of i-th row's (non-zero) elements in //
05918 // segsperverlist.  The number of elements of i-th row is calculated by the  //
05919 // (i+1)-th entry minus i-th entry of idx2seglist.                           //
05920 //                                                                           //
05921 // NOTE: These two arrays will be created inside this routine, don't forget  //
05922 // to free them after using.                                                 //
05923 //                                                                           //
05925 
05926 void tetgenmesh::makesegmentmap(int*& idx2seglist, shellface**& segsperverlist)
05927 {
05928   shellface *shloop;
05929   int i, j, k;
05930 
05931   if (b->verbose > 0) {
05932     printf("  Constructing mapping from points to segments.\n");
05933   }
05934 
05935   // Create and initialize 'idx2seglist'.
05936   idx2seglist = new int[points->items + 1];
05937   for (i = 0; i < points->items + 1; i++) idx2seglist[i] = 0;
05938 
05939   // Loop the set of segments once, counter the number of segments sharing
05940   //   each vertex.
05941   subsegs->traversalinit();
05942   shloop = shellfacetraverse(subsegs);
05943   while (shloop != (shellface *) NULL) {
05944     // Increment the number of sharing segments for each endpoint.
05945     for (i = 0; i < 2; i++) {
05946       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05947       idx2seglist[j]++;
05948     }
05949     shloop = shellfacetraverse(subsegs);
05950   }
05951 
05952   // Calculate the total length of array 'facesperverlist'.
05953   j = idx2seglist[0];
05954   idx2seglist[0] = 0;  // Array starts from 0 element.
05955   for (i = 0; i < points->items; i++) {
05956     k = idx2seglist[i + 1];
05957     idx2seglist[i + 1] = idx2seglist[i] + j;
05958     j = k;
05959   }
05960   // The total length is in the last unit of idx2seglist.
05961   segsperverlist = new shellface*[idx2seglist[i]];
05962   // Loop the set of segments again, set the info. of segments per vertex.
05963   subsegs->traversalinit();
05964   shloop = shellfacetraverse(subsegs);
05965   while (shloop != (shellface *) NULL) {
05966     for (i = 0; i < 2; i++) {
05967       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05968       segsperverlist[idx2seglist[j]] = shloop;
05969       idx2seglist[j]++;
05970     }
05971     shloop = shellfacetraverse(subsegs);
05972   }
05973   // Contents in 'idx2seglist' are shifted, now shift them back.
05974   for (i = points->items - 1; i >= 0; i--) {
05975     idx2seglist[i + 1] = idx2seglist[i];
05976   }
05977   idx2seglist[0] = 0;
05978 }
05979 
05981 //                                                                           //
05982 // makesubfacemap()    Create a map from vertices (their indices) to         //
05983 //                     subfaces incident at the same vertices.               //
05984 //                                                                           //
05985 // Two arrays 'idx2facelist' and 'facesperverlist' together return the map.  //
05986 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
05987 // number of subfaces.  idx2facelist contains row information and            //
05988 // facesperverlist contains all (non-zero) elements.  The i-th entry of      //
05989 // idx2facelist is the starting position of i-th row's(non-zero) elements in //
05990 // facesperverlist.  The number of elements of i-th row is calculated by the //
05991 // (i+1)-th entry minus i-th entry of idx2facelist.                          //
05992 //                                                                           //
05993 // NOTE: These two arrays will be created inside this routine, don't forget  //
05994 // to free them after using.                                                 //
05995 //                                                                           //
05997 
05998 void tetgenmesh::
05999 makesubfacemap(int*& idx2facelist, shellface**& facesperverlist)
06000 {
06001   shellface *shloop;
06002   int i, j, k;
06003 
06004   if (b->verbose > 0) {
06005     printf("  Constructing mapping from points to subfaces.\n");
06006   }
06007 
06008   // Create and initialize 'idx2facelist'.
06009   idx2facelist = new int[points->items + 1];
06010   for (i = 0; i < points->items + 1; i++) idx2facelist[i] = 0;
06011 
06012   // Loop the set of subfaces once, counter the number of subfaces sharing
06013   //   each vertex.
06014   subfaces->traversalinit();
06015   shloop = shellfacetraverse(subfaces);
06016   while (shloop != (shellface *) NULL) {
06017     // Increment the number of sharing segments for each endpoint.
06018     for (i = 0; i < 3; i++) {
06019       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06020       idx2facelist[j]++;
06021     }
06022     shloop = shellfacetraverse(subfaces);
06023   }
06024 
06025   // Calculate the total length of array 'facesperverlist'.
06026   j = idx2facelist[0];
06027   idx2facelist[0] = 0;  // Array starts from 0 element.
06028   for (i = 0; i < points->items; i++) {
06029     k = idx2facelist[i + 1];
06030     idx2facelist[i + 1] = idx2facelist[i] + j;
06031     j = k;
06032   }
06033   // The total length is in the last unit of idx2facelist.
06034   facesperverlist = new shellface*[idx2facelist[i]];
06035   // Loop the set of segments again, set the info. of segments per vertex.
06036   subfaces->traversalinit();
06037   shloop = shellfacetraverse(subfaces);
06038   while (shloop != (shellface *) NULL) {
06039     for (i = 0; i < 3; i++) {
06040       j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06041       facesperverlist[idx2facelist[j]] = shloop;
06042       idx2facelist[j]++;
06043     }
06044     shloop = shellfacetraverse(subfaces);
06045   }
06046   // Contents in 'idx2facelist' are shifted, now shift them back.
06047   for (i = points->items - 1; i >= 0; i--) {
06048     idx2facelist[i + 1] = idx2facelist[i];
06049   }
06050   idx2facelist[0] = 0;
06051 }
06052 
06054 //                                                                           //
06055 // maketetrahedronmap()    Create a map from vertices (their indices) to     //
06056 //                         tetrahedra incident at the same vertices.         //
06057 //                                                                           //
06058 // Two arrays 'idx2tetlist' and 'tetsperverlist' together return the map.    //
06059 // They form a sparse matrix structure with size (n + 1) x (n + 1), n is the //
06060 // number of tetrahedra.  idx2tetlist contains row information and           //
06061 // tetsperverlist contains all (non-zero) elements.  The i-th entry of       //
06062 // idx2tetlist is the starting position of i-th row's (non-zero) elements in //
06063 // tetsperverlist.  The number of elements of i-th row is calculated by the  //
06064 // (i+1)-th entry minus i-th entry of idx2tetlist.                           //
06065 //                                                                           //
06066 // NOTE: These two arrays will be created inside this routine, don't forget  //
06067 // to free them after using.                                                 //
06068 //                                                                           //
06070 
06071 void tetgenmesh::
06072 maketetrahedronmap(int*& idx2tetlist, tetrahedron**& tetsperverlist)
06073 {
06074   tetrahedron *tetloop;
06075   int i, j, k;
06076 
06077   if (b->verbose > 0) {
06078     printf("  Constructing mapping from points to tetrahedra.\n");
06079   }
06080 
06081   // Create and initialize 'idx2tetlist'.
06082   idx2tetlist = new int[points->items + 1];
06083   for (i = 0; i < points->items + 1; i++) idx2tetlist[i] = 0;
06084 
06085   // Loop the set of tetrahedra once, counter the number of tetrahedra
06086   //   sharing each vertex.
06087   tetrahedrons->traversalinit();
06088   tetloop = tetrahedrontraverse();
06089   while (tetloop != (tetrahedron *) NULL) {
06090     // Increment the number of sharing tetrahedra for each endpoint.
06091     for (i = 0; i < 4; i++) {
06092       j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06093       idx2tetlist[j]++;
06094     }
06095     tetloop = tetrahedrontraverse();
06096   }
06097 
06098   // Calculate the total length of array 'tetsperverlist'.
06099   j = idx2tetlist[0];
06100   idx2tetlist[0] = 0;  // Array starts from 0 element.
06101   for (i = 0; i < points->items; i++) {
06102     k = idx2tetlist[i + 1];
06103     idx2tetlist[i + 1] = idx2tetlist[i] + j;
06104     j = k;
06105   }
06106   // The total length is in the last unit of idx2tetlist.
06107   tetsperverlist = new tetrahedron*[idx2tetlist[i]];
06108   // Loop the set of tetrahedra again, set the info. of tet. per vertex.
06109   tetrahedrons->traversalinit();
06110   tetloop = tetrahedrontraverse();
06111   while (tetloop != (tetrahedron *) NULL) {
06112     for (i = 0; i < 4; i++) {
06113       j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06114       tetsperverlist[idx2tetlist[j]] = tetloop;
06115       idx2tetlist[j]++;
06116     }
06117     tetloop = tetrahedrontraverse();
06118   }
06119   // Contents in 'idx2tetlist' are shifted, now shift them back.
06120   for (i = points->items - 1; i >= 0; i--) {
06121     idx2tetlist[i + 1] = idx2tetlist[i];
06122   }
06123   idx2tetlist[0] = 0;
06124 }
06125 
06126 //
06127 // End of mesh items searching routines
06128 //
06129 
06130 //
06131 // Begin of linear algebra functions
06132 //
06133 
06134 // dot() returns the dot product: v1 dot v2.
06135 
06136 inline REAL tetgenmesh::dot(REAL* v1, REAL* v2)
06137 {
06138   return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
06139 }
06140 
06141 // cross() computes the cross product: n = v1 cross v2.
06142 
06143 inline void tetgenmesh::cross(REAL* v1, REAL* v2, REAL* n)
06144 {
06145   n[0] =   v1[1] * v2[2] - v2[1] * v1[2];
06146   n[1] = -(v1[0] * v2[2] - v2[0] * v1[2]);
06147   n[2] =   v1[0] * v2[1] - v2[0] * v1[1];
06148 }
06149 
06150 // initm44() initializes a 4x4 matrix.
06151 static void initm44(REAL a00, REAL a01, REAL a02, REAL a03,
06152                     REAL a10, REAL a11, REAL a12, REAL a13,
06153                     REAL a20, REAL a21, REAL a22, REAL a23,
06154                     REAL a30, REAL a31, REAL a32, REAL a33,
06155                     REAL M[4][4])
06156 {
06157   M[0][0] = a00; M[0][1] = a01; M[0][2] = a02; M[0][3] = a03;
06158   M[1][0] = a10; M[1][1] = a11; M[1][2] = a12; M[1][3] = a13;
06159   M[2][0] = a20; M[2][1] = a21; M[2][2] = a22; M[2][3] = a23;
06160   M[3][0] = a30; M[3][1] = a31; M[3][2] = a32; M[3][3] = a33;
06161 }
06162 
06163 // m4xm4() multiplies 2 4x4 matrics:  m1 = m1 * m2.
06164 static void m4xm4(REAL m1[4][4], REAL m2[4][4])
06165 {
06166   REAL tmp[4];
06167   int i, j;
06168 
06169   for (i = 0; i < 4; i++) {   // i-th row
06170     for (j = 0; j < 4; j++) { // j-th col
06171       tmp[j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j]
06172              + m1[i][2] * m2[2][j] + m1[i][3] * m2[3][j];
06173     }
06174     for (j = 0; j < 4; j++)
06175       m1[i][j] = tmp[j];
06176   }
06177 }
06178 
06179 // m4xv4() multiplies a 4x4 matrix and 4x1 vector: v2 = m * v1
06180 static void m4xv4(REAL v2[4], REAL m[4][4], REAL v1[4])
06181 {
06182   v2[0] = m[0][0]*v1[0] + m[0][1]*v1[1] + m[0][2]*v1[2] + m[0][3]*v1[3];
06183   v2[1] = m[1][0]*v1[0] + m[1][1]*v1[1] + m[1][2]*v1[2] + m[1][3]*v1[3];
06184   v2[2] = m[2][0]*v1[0] + m[2][1]*v1[1] + m[2][2]*v1[2] + m[2][3]*v1[3];
06185   v2[3] = m[3][0]*v1[0] + m[3][1]*v1[1] + m[3][2]*v1[2] + m[3][3]*v1[3];
06186 }
06187 
06189 //                                                                           //
06190 // lu_decmp()    Compute the LU decomposition of a matrix.                   //
06191 //                                                                           //
06192 // Compute the LU decomposition of a (non-singular) square matrix A using    //
06193 // partial pivoting and implicit row exchanges.  The result is:              //
06194 //     A = P * L * U,                                                        //
06195 // where P is a permutation matrix, L is unit lower triangular, and U is     //
06196 // upper triangular.  The factored form of A is used in combination with     //
06197 // 'lu_solve()' to solve linear equations: Ax = b, or invert a matrix.       //
06198 //                                                                           //
06199 // The inputs are a square matrix 'lu[N..n+N-1][N..n+N-1]', it's size is 'n'.//
06200 // On output, 'lu' is replaced by the LU decomposition of a rowwise permuta- //
06201 // tion of itself, 'ps[N..n+N-1]' is an output vector that records the row   //
06202 // permutation effected by the partial pivoting, effectively,  'ps' array    //
06203 // tells the user what the permutation matrix P is; 'd' is output as +1/-1   //
06204 // depending on whether the number of row interchanges was even or odd,      //
06205 // respectively.                                                             //
06206 //                                                                           //
06207 // Return true if the LU decomposition is successfully computed, otherwise,  //
06208 // return false in case that A is a singular matrix.                         //
06209 //                                                                           //
06211 
06212 bool tetgenmesh::lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N)
06213 {
06214   REAL scales[4];
06215   REAL pivot, biggest, mult, tempf;
06216   int pivotindex = 0;
06217   int i, j, k;
06218 
06219   *d = 1.0;                                      // No row interchanges yet.
06220 
06221   for (i = N; i < n + N; i++) {                             // For each row.
06222     // Find the largest element in each row for row equilibration
06223     biggest = 0.0;
06224     for (j = N; j < n + N; j++)
06225       if (biggest < (tempf = fabs(lu[i][j])))
06226         biggest  = tempf;
06227     if (biggest != 0.0)
06228       scales[i] = 1.0 / biggest;
06229     else {
06230       scales[i] = 0.0;
06231       return false;                            // Zero row: singular matrix.
06232     }
06233     ps[i] = i;                                 // Initialize pivot sequence.
06234   }
06235 
06236   for (k = N; k < n + N - 1; k++) {                      // For each column.
06237     // Find the largest element in each column to pivot around.
06238     biggest = 0.0;
06239     for (i = k; i < n + N; i++) {
06240       if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
06241         biggest = tempf;
06242         pivotindex = i;
06243       }
06244     }
06245     if (biggest == 0.0) {
06246       return false;                         // Zero column: singular matrix.
06247     }
06248     if (pivotindex != k) {                         // Update pivot sequence.
06249       j = ps[k];
06250       ps[k] = ps[pivotindex];
06251       ps[pivotindex] = j;
06252       *d = -(*d);                          // ...and change the parity of d.
06253     }
06254 
06255     // Pivot, eliminating an extra variable  each time
06256     pivot = lu[ps[k]][k];
06257     for (i = k + 1; i < n + N; i++) {
06258       lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
06259       if (mult != 0.0) {
06260         for (j = k + 1; j < n + N; j++)
06261           lu[ps[i]][j] -= mult * lu[ps[k]][j];
06262       }
06263     }
06264   }
06265 
06266   // (lu[ps[n + N - 1]][n + N - 1] == 0.0) ==> A is singular.
06267   return lu[ps[n + N - 1]][n + N - 1] != 0.0;
06268 }
06269 
06271 //                                                                           //
06272 // lu_solve()    Solves the linear equation:  Ax = b,  after the matrix A    //
06273 //               has been decomposed into the lower and upper triangular     //
06274 //               matrices L and U, where A = LU.                             //
06275 //                                                                           //
06276 // 'lu[N..n+N-1][N..n+N-1]' is input, not as the matrix 'A' but rather as    //
06277 // its LU decomposition, computed by the routine 'lu_decmp'; 'ps[N..n+N-1]'  //
06278 // is input as the permutation vector returned by 'lu_decmp';  'b[N..n+N-1]' //
06279 // is input as the right-hand side vector, and returns with the solution     //
06280 // vector. 'lu', 'n', and 'ps' are not modified by this routine and can be   //
06281 // left in place for successive calls with different right-hand sides 'b'.   //
06282 //                                                                           //
06284 
06285 void tetgenmesh::lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N)
06286 {
06287   int i, j;
06288   REAL X[4], dot;
06289 
06290   for (i = N; i < n + N; i++) X[i] = 0.0;
06291 
06292   // Vector reduction using U triangular matrix.
06293   for (i = N; i < n + N; i++) {
06294     dot = 0.0;
06295     for (j = N; j < i + N; j++)
06296       dot += lu[ps[i]][j] * X[j];
06297     X[i] = b[ps[i]] - dot;
06298   }
06299 
06300   // Back substitution, in L triangular matrix.
06301   for (i = n + N - 1; i >= N; i--) {
06302     dot = 0.0;
06303     for (j = i + 1; j < n + N; j++)
06304       dot += lu[ps[i]][j] * X[j];
06305     X[i] = (X[i] - dot) / lu[ps[i]][i];
06306   }
06307 
06308   for (i = N; i < n + N; i++) b[i] = X[i];
06309 }
06310 
06311 //
06312 // End of linear algebra functions
06313 //
06314 
06315 //
06316 // Begin of geometric tests
06317 //
06318 
06319 // All the following routines require the input objects are not degenerate.
06320 //   i.e., a triangle must has three non-collinear corners; an edge must
06321 //   has two identical endpoints.  Degenerate cases should have to detect
06322 //   first and then handled as special cases.
06323 
06325 //                                                                           //
06326 // edge_vert_col_inter()    Test whether an edge (ab) and a collinear vertex //
06327 //                          (p) are intersecting or not.                     //
06328 //                                                                           //
06329 // Possible cases are p is coincident to a (p = a), or to b (p = b), or p is //
06330 // inside ab (a < p < b), or outside ab (p < a or p > b). These cases can be //
06331 // quickly determined by comparing the corresponding coords of a, b, and p   //
06332 // (which are not all equal).                                                //
06333 //                                                                           //
06334 // The return value indicates one of the three cases: DISJOINT, SHAREVERTEX  //
06335 // (p = a or p = b), and INTERSECT (a < p < b).                              //
06336 //                                                                           //
06338 
06339 enum tetgenmesh::interresult tetgenmesh::edge_vert_col_inter(REAL* A, REAL* B,
06340   REAL* P)
06341 {
06342   int i = 0;
06343   do {
06344     if (A[i] < B[i]) {
06345       if (P[i] < A[i]) {
06346         return DISJOINT;
06347       } else if (P[i] > A[i]) {
06348         if (P[i] < B[i]) {
06349           return INTERSECT;
06350         } else if (P[i] > B[i]) {
06351           return DISJOINT;
06352         } else {
06353           // assert(P[i] == B[i]);
06354           return SHAREVERTEX;
06355         }
06356       } else {
06357         // assert(P[i] == A[i]);
06358         return SHAREVERTEX;
06359       }
06360     } else if (A[i] > B[i]) {
06361       if (P[i] < B[i]) {
06362         return DISJOINT;
06363       } else if (P[i] > B[i]) {
06364         if (P[i] < A[i]) {
06365           return INTERSECT;
06366         } else if (P[i] > A[i]) {
06367           return DISJOINT;
06368         } else {
06369           // assert(P[i] == A[i]);
06370           return SHAREVERTEX;
06371         }
06372       } else {
06373         // assert(P[i] == B[i]);
06374         return SHAREVERTEX;
06375       }
06376     }
06377     // i-th coordinates are equal, try i+1-th;
06378     i++;
06379   } while (i < 3);
06380   // Should never be here.
06381   return DISJOINT;
06382 }
06383 
06385 //                                                                           //
06386 // edge_edge_cop_inter()    Test whether two coplanar edges (ab, and pq) are //
06387 //                          intersecting or not.                             //
06388 //                                                                           //
06389 // Possible cases are ab and pq are disjointed, or proper intersecting (int- //
06390 // ersect at a point other than their endpoints), or both collinear and int- //
06391 // ersecting, or sharing at a common endpoint, or are coincident.            //
06392 //                                                                           //
06393 // A reference point R is required, which is exactly not coplanar with these //
06394 // two edges.  Since the caller knows these two edges are coplanar, it must  //
06395 // be able to provide (or calculate) such a point.                           //
06396 //                                                                           //
06397 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06398 // SHAREEDGE, and INTERSECT.                                                 //
06399 //                                                                           //
06401 
06402 enum tetgenmesh::interresult tetgenmesh:: edge_edge_cop_inter(REAL* A, REAL* B,
06403   REAL* P, REAL* Q, REAL* R)
06404 {
06405   REAL s1, s2, s3, s4;
06406 
06407 #ifdef SELF_CHECK
06408   assert(R != NULL);
06409 #endif
06410   s1 = orient3d(A, B, R, P);
06411   s2 = orient3d(A, B, R, Q);
06412   if (s1 * s2 > 0.0) {
06413     // Both p and q are at the same side of ab.
06414     return DISJOINT;
06415   }
06416   s3 = orient3d(P, Q, R, A);
06417   s4 = orient3d(P, Q, R, B);
06418   if (s3 * s4 > 0.0) {
06419     // Both a and b are at the same side of pq.
06420     return DISJOINT;
06421   }
06422 
06423   // Possible degenerate cases are:
06424   //   (1) Only one of p and q is collinear with ab;
06425   //   (2) Both p and q are collinear with ab;
06426   //   (3) Only one of a and b is collinear with pq.
06427   enum interresult abp, abq;
06428   enum interresult pqa, pqb;
06429 
06430   if (s1 == 0.0) {
06431     // p is collinear with ab.
06432     abp = edge_vert_col_inter(A, B, P);
06433     if (abp == INTERSECT) {
06434       // p is inside ab.
06435       return INTERSECT;
06436     }
06437     if (s2 == 0.0) {
06438       // q is collinear with ab. Case (2).
06439       abq = edge_vert_col_inter(A, B, Q);
06440       if (abq == INTERSECT) {
06441         // q is inside ab.
06442         return INTERSECT;
06443       }
06444       if (abp == SHAREVERTEX && abq == SHAREVERTEX) {
06445         // ab and pq are identical.
06446         return SHAREEDGE;
06447       }
06448       pqa = edge_vert_col_inter(P, Q, A);
06449       if (pqa == INTERSECT) {
06450         // a is inside pq.
06451         return INTERSECT;
06452       }
06453       pqb = edge_vert_col_inter(P, Q, B);
06454       if (pqb == INTERSECT) {
06455         // b is inside pq.
06456         return INTERSECT;
06457       }
06458       if (abp == SHAREVERTEX || abq == SHAREVERTEX) {
06459         // either p or q is coincident with a or b.
06460 #ifdef SELF_CHECK
06461         // ONLY one case is possible, otherwise, shoule be SHAREEDGE.
06462         assert(abp ^ abq);
06463 #endif
06464         return SHAREVERTEX;
06465       }
06466       // The last case. They are disjointed.
06467 #ifdef SELF_CHECK
06468       assert((abp == DISJOINT) && (abp == abq && abq == pqa && pqa == pqb));
06469 #endif
06470       return DISJOINT;
06471     } else {
06472       // p is collinear with ab. Case (1).
06473 #ifdef SELF_CHECK
06474       assert(abp == SHAREVERTEX || abp == DISJOINT);
06475 #endif
06476       return abp;
06477     }
06478   }
06479   // p is NOT collinear with ab.
06480   if (s2 == 0.0) {
06481     // q is collinear with ab. Case (1).
06482     abq = edge_vert_col_inter(A, B, Q);
06483 #ifdef SELF_CHECK
06484     assert(abq == SHAREVERTEX || abq == DISJOINT || abq == INTERSECT);
06485 #endif
06486     return abq;
06487   }
06488 
06489   // We have found p and q are not collinear with ab. However, it is still
06490   //   possible that a or b is collinear with pq (ONLY one of a and b).
06491   if (s3 == 0.0) {
06492     // a is collinear with pq. Case (3).
06493 #ifdef SELF_CHECK
06494     assert(s4 != 0.0);
06495 #endif
06496     pqa = edge_vert_col_inter(P, Q, A);
06497 #ifdef SELF_CHECK
06498     // This case should have been detected in above.
06499     assert(pqa != SHAREVERTEX);
06500     assert(pqa == INTERSECT || pqa == DISJOINT);
06501 #endif
06502     return pqa;
06503   }
06504   if (s4 == 0.0) {
06505     // b is collinear with pq. Case (3).
06506 #ifdef SELF_CHECK
06507     assert(s3 != 0.0);
06508 #endif
06509     pqb = edge_vert_col_inter(P, Q, B);
06510 #ifdef SELF_CHECK
06511     // This case should have been detected in above.
06512     assert(pqb != SHAREVERTEX);
06513     assert(pqb == INTERSECT || pqb == DISJOINT);
06514 #endif
06515     return pqb;
06516   }
06517 
06518   // ab and pq are intersecting properly.
06519   return INTERSECT;
06520 }
06521 
06523 //                                                                           //
06524 // Notations                                                                 //
06525 //                                                                           //
06526 // Let ABC be the plane passes through a, b, and c;  ABC+ be the halfspace   //
06527 // including the set of all points x, such that orient3d(a, b, c, x) > 0;    //
06528 // ABC- be the other halfspace, such that for each point x in ABC-,          //
06529 // orient3d(a, b, c, x) < 0.  For the set of x which are on ABC, orient3d(a, //
06530 // b, c, x) = 0.                                                             //
06531 //                                                                           //
06533 
06535 //                                                                           //
06536 // tri_vert_copl_inter()    Test whether a triangle (abc) and a coplanar     //
06537 //                          point (p) are intersecting or not.               //
06538 //                                                                           //
06539 // Possible cases are p is inside abc, or on an edge of, or coincident with  //
06540 // a vertex of, or outside abc.                                              //
06541 //                                                                           //
06542 // A reference point R is required. R is exactly not coplanar with abc and p.//
06543 // Since the caller knows they are coplanar, it must be able to provide (or  //
06544 // calculate) such a point.                                                  //
06545 //                                                                           //
06546 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06547 // and INTERSECT.                                                            //
06548 //                                                                           //
06550 
06551 enum tetgenmesh::interresult tetgenmesh::tri_vert_cop_inter(REAL* A, REAL* B,
06552   REAL* C, REAL* P, REAL* R)
06553 {
06554   REAL s1, s2, s3;
06555   int sign;
06556 
06557 #ifdef SELF_CHECK
06558   assert(R != (REAL *) NULL);
06559 #endif
06560   // Adjust the orientation of a, b, c and r, so that we can assume that
06561   //   r is strictly in ABC- (i.e., r is above ABC wrt. right-hand rule).
06562   s1 = orient3d(A, B, C, R);
06563 #ifdef SELF_CHECK
06564   assert(s1 != 0.0);
06565 #endif
06566   sign = s1 < 0.0 ? 1 : -1;
06567 
06568   // Test starts from here.
06569   s1 = orient3d(A, B, R, P) * sign;
06570   if (s1 < 0.0) {
06571     // p is in ABR-.
06572     return DISJOINT;
06573   }
06574   s2 = orient3d(B, C, R, P) * sign;
06575   if (s2 < 0.0) {
06576     // p is in BCR-.
06577     return DISJOINT;
06578   }
06579   s3 = orient3d(C, A, R, P) * sign;
06580   if (s3 < 0.0) {
06581     // p is in CAR-.
06582     return DISJOINT;
06583   }
06584   if (s1 == 0.0) {
06585     // p is on ABR.
06586     if (s2 == 0.0) {
06587       // p is on BCR.
06588 #ifdef SELF_CHECK
06589       assert(s3 > 0.0);
06590 #endif
06591       // p is coincident with b.
06592       return SHAREVERTEX;
06593     }
06594     if (s3 == 0.0) {
06595       // p is on CAR.
06596       // p is coincident with a.
06597       return SHAREVERTEX;
06598     }
06599     // p is on edge ab.
06600     return INTERSECT;
06601   }
06602   // p is in ABR+.
06603   if (s2 == 0.0) {
06604     // p is on BCR.
06605     if (s3 == 0.0) {
06606       // p is on CAR.
06607       // p is coincident with c.
06608       return SHAREVERTEX;
06609     }
06610     // p is on edge bc.
06611     return INTERSECT;
06612   }
06613   if (s3 == 0.0) {
06614     // p is on CAR.
06615     // p is on edge ca.
06616     return INTERSECT;
06617   }
06618 
06619   // p is strictly inside abc.
06620   return INTERSECT;
06621 }
06622 
06624 //                                                                           //
06625 // tri_edge_cop_inter()    Test whether a triangle (abc) and a coplanar edge //
06626 //                         (pq) are intersecting or not.                     //
06627 //                                                                           //
06628 // A reference point R is required. R is exactly not coplanar with abc and   //
06629 // pq.  Since the caller knows they are coplanar, it must be able to provide //
06630 // (or calculate) such a point.                                              //
06631 //                                                                           //
06632 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06633 // SHAREEDGE, and INTERSECT.                                                 //
06634 //                                                                           //
06636 
06637 enum tetgenmesh::interresult tetgenmesh::tri_edge_cop_inter(REAL* A, REAL* B,
06638   REAL* C, REAL* P, REAL* Q, REAL* R)
06639 {
06640   enum interresult abpq, bcpq, capq;
06641   enum interresult abcp, abcq;
06642 
06643   // Test if pq is intersecting one of edges of abc.
06644   abpq = edge_edge_cop_inter(A, B, P, Q, R);
06645   if (abpq == INTERSECT || abpq == SHAREEDGE) {
06646     return abpq;
06647   }
06648   bcpq = edge_edge_cop_inter(B, C, P, Q, R);
06649   if (bcpq == INTERSECT || bcpq == SHAREEDGE) {
06650     return bcpq;
06651   }
06652   capq = edge_edge_cop_inter(C, A, P, Q, R);
06653   if (capq == INTERSECT || capq == SHAREEDGE) {
06654     return capq;
06655   }
06656 
06657   // Test if p and q is inside abc.
06658   abcp = tri_vert_cop_inter(A, B, C, P, R);
06659   if (abcp == INTERSECT) {
06660     return INTERSECT;
06661   }
06662   abcq = tri_vert_cop_inter(A, B, C, Q, R);
06663   if (abcq == INTERSECT) {
06664     return INTERSECT;
06665   }
06666 
06667   // Combine the test results of edge intersectings and triangle insides
06668   //   to detect whether abc and pq are sharing vertex or disjointed.
06669   if (abpq == SHAREVERTEX) {
06670     // p or q is coincident with a or b.
06671 #ifdef SELF_CHECK
06672     assert(abcp ^ abcq);
06673 #endif
06674     return SHAREVERTEX;
06675   }
06676   if (bcpq == SHAREVERTEX) {
06677     // p or q is coincident with b or c.
06678 #ifdef SELF_CHECK
06679     assert(abcp ^ abcq);
06680 #endif
06681     return SHAREVERTEX;
06682   }
06683   if (capq == SHAREVERTEX) {
06684     // p or q is coincident with c or a.
06685 #ifdef SELF_CHECK
06686     assert(abcp ^ abcq);
06687 #endif
06688     return SHAREVERTEX;
06689   }
06690 
06691   // They are disjointed.
06692   return DISJOINT;
06693 }
06694 
06696 //                                                                           //
06697 // tri_edge_inter_tail()    Test whether a triangle (abc) and an edge (pq)   //
06698 //                          are intersecting or not.                         //
06699 //                                                                           //
06700 // s1 and s2 are results of pre-performed orientation tests. s1 = orient3d(  //
06701 // a, b, c, p); s2 = orient3d(a, b, c, q).  To separate this routine from    //
06702 // tri_edge_inter() can save two orientation tests in tri_tri_inter().       //
06703 //                                                                           //
06704 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06705 // SHAREEDGE, and INTERSECT.                                                 //
06706 //                                                                           //
06708 
06709 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter_tail(REAL* A, REAL* B,
06710   REAL* C, REAL* P, REAL* Q, REAL s1, REAL s2)
06711 {
06712   REAL s3, s4, s5;
06713   int sign;
06714 
06715   if (s1 * s2 > 0.0) {
06716     // p, q are at the same halfspace of ABC, no intersection.
06717     return DISJOINT;
06718   }
06719 
06720   if (s1 * s2 < 0.0) {
06721     // p, q are both not on ABC (and not sharing vertices, edges of abc).
06722     // Adjust the orientation of a, b, c and p, so that we can assume that
06723     //   p is strictly in ABC-, and q is strictly in ABC+.
06724     sign = s1 < 0.0 ? 1 : -1;
06725     s3 = orient3d(A, B, P, Q) * sign;
06726     if (s3 < 0.0) {
06727       // q is at ABP-.
06728       return DISJOINT;
06729     }
06730     s4 = orient3d(B, C, P, Q) * sign;
06731     if (s4 < 0.0) {
06732       // q is at BCP-.
06733       return DISJOINT;
06734     }
06735     s5 = orient3d(C, A, P, Q) * sign;
06736     if (s5 < 0.0) {
06737       // q is at CAP-.
06738       return DISJOINT;
06739     }
06740     if (s3 == 0.0) {
06741       // q is on ABP.
06742       if (s4 == 0.0) {
06743         // q is on BCP (and q must in CAP+).
06744 #ifdef SELF_CHECK
06745         assert(s5 > 0.0);
06746 #endif
06747         // pq intersects abc at vertex b.
06748         return SHAREVERTEX;
06749       }
06750       if (s5 == 0.0) {
06751         // q is on CAP (and q must in BCP+).
06752         // pq intersects abc at vertex a.
06753         return SHAREVERTEX;
06754       }
06755       // q in both BCP+ and CAP+.
06756       // pq crosses ab properly.
06757       return INTERSECT;
06758     }
06759     // q is in ABP+;
06760     if (s4 == 0.0) {
06761       // q is on BCP.
06762       if (s5 == 0.0) {
06763         // q is on CAP.
06764         // pq intersects abc at vertex c.
06765         return SHAREVERTEX;
06766       }
06767       // pq crosses bc properly.
06768       return INTERSECT;
06769     }
06770     // q is in BCP+;
06771     if (s5 == 0.0) {
06772       // q is on CAP.
06773       // pq crosses ca properly.
06774       return INTERSECT;
06775     }
06776     // q is in CAP+;
06777     // pq crosses abc properly.
06778     return INTERSECT;
06779   }
06780 
06781   if (s1 != 0.0 || s2 != 0.0) {
06782     // Either p or q is coplanar with abc. ONLY one of them is possible.
06783     if (s1 == 0.0) {
06784       // p is coplanar with abc, q can be used as reference point.
06785 #ifdef SELF_CHECK
06786       assert(s2 != 0.0);
06787 #endif
06788       return tri_vert_cop_inter(A, B, C, P, Q);
06789     } else {
06790       // q is coplanar with abc, p can be used as reference point.
06791 #ifdef SELF_CHECK
06792       assert(s2 == 0.0);
06793 #endif
06794       return tri_vert_cop_inter(A, B, C, Q, P);
06795     }
06796   }
06797 
06798   // pq is coplanar with abc.  Calculate a point which is exactly not
06799   //   coplanar with a, b, and c.
06800   REAL R[3], N[3];
06801   REAL ax, ay, az, bx, by, bz;
06802 
06803   ax = A[0] - B[0];
06804   ay = A[1] - B[1];
06805   az = A[2] - B[2];
06806   bx = A[0] - C[0];
06807   by = A[1] - C[1];
06808   bz = A[2] - C[2];
06809   N[0] = ay * bz - by * az;
06810   N[1] = az * bx - bz * ax;
06811   N[2] = ax * by - bx * ay;
06812   // The normal should not be a zero vector (otherwise, abc are collinear).
06813 #ifdef SELF_CHECK
06814   assert((fabs(N[0]) + fabs(N[1]) + fabs(N[2])) > 0.0);
06815 #endif
06816   // The reference point R is lifted from A to the normal direction with
06817   //   a distance d = average edge length of the triangle abc.
06818   R[0] = N[0] + A[0];
06819   R[1] = N[1] + A[1];
06820   R[2] = N[2] + A[2];
06821   // Becareful the case: if the non-zero component(s) in N is smaller than
06822   //   the machine epsilon (i.e., 2^(-16) for double), R will exactly equal
06823   //   to A due to the round-off error.  Do check if it is.
06824   if (R[0] == A[0] && R[1] == A[1] && R[2] == A[2]) {
06825     int i, j;
06826     for (i = 0; i < 3; i++) {
06827 #ifdef SELF_CHECK
06828       assert (R[i] == A[i]);
06829 #endif
06830       j = 2;
06831       do {
06832         if (N[i] > 0.0) {
06833           N[i] += (j * macheps);
06834         } else {
06835           N[i] -= (j * macheps);
06836         }
06837         R[i] = N[i] + A[i];
06838         j *= 2;
06839       } while (R[i] == A[i]);
06840     }
06841   }
06842 
06843   return tri_edge_cop_inter(A, B, C, P, Q, R);
06844 }
06845 
06847 //                                                                           //
06848 // tri_edge_inter()    Test whether a triangle (abc) and an edge (pq) are    //
06849 //                     intersecting or not.                                  //
06850 //                                                                           //
06851 // The return value indicates one of the four cases: DISJOINT, SHAREVERTEX,  //
06852 // SHAREEDGE, and INTERSECT.                                                 //
06853 //                                                                           //
06855 
06856 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter(REAL* A, REAL* B,
06857   REAL* C, REAL* P, REAL* Q)
06858 {
06859   REAL s1, s2;
06860 
06861   // Test the locations of p and q with respect to ABC.
06862   s1 = orient3d(A, B, C, P);
06863   s2 = orient3d(A, B, C, Q);
06864 
06865   return tri_edge_inter_tail(A, B, C, P, Q, s1, s2);
06866 }
06867 
06869 //                                                                           //
06870 // tri_tri_inter()    Test whether two triangle (abc) and (opq) are          //
06871 //                    intersecting or not.                                   //
06872 //                                                                           //
06873 // The return value indicates one of the five cases: DISJOINT, SHAREVERTEX,  //
06874 // SHAREEDGE, SHAREFACE, and INTERSECT.                                      //
06875 //                                                                           //
06877 
06878 enum tetgenmesh::interresult tetgenmesh::tri_tri_inter(REAL* A, REAL* B,
06879   REAL* C, REAL* O, REAL* P, REAL* Q)
06880 {
06881   REAL s_o, s_p, s_q;
06882   REAL s_a, s_b, s_c;
06883 
06884   s_o = orient3d(A, B, C, O);
06885   s_p = orient3d(A, B, C, P);
06886   s_q = orient3d(A, B, C, Q);
06887   if ((s_o * s_p > 0.0) && (s_o * s_q > 0.0)) {
06888     // o, p, q are all in the same halfspace of ABC.
06889     return DISJOINT;
06890   }
06891 
06892   s_a = orient3d(O, P, Q, A);
06893   s_b = orient3d(O, P, Q, B);
06894   s_c = orient3d(O, P, Q, C);
06895   if ((s_a * s_b > 0.0) && (s_a * s_c > 0.0)) {
06896     // a, b, c are all in the same halfspace of OPQ.
06897     return DISJOINT;
06898   }
06899 
06900   enum interresult abcop, abcpq, abcqo;
06901   int shareedge = 0;
06902 
06903   abcop = tri_edge_inter_tail(A, B, C, O, P, s_o, s_p);
06904   if (abcop == INTERSECT) {
06905     return INTERSECT;
06906   } else if (abcop == SHAREEDGE) {
06907     shareedge++;
06908   }
06909   abcpq = tri_edge_inter_tail(A, B, C, P, Q, s_p, s_q);
06910   if (abcpq == INTERSECT) {
06911     return INTERSECT;
06912   } else if (abcpq == SHAREEDGE) {
06913     shareedge++;
06914   }
06915   abcqo = tri_edge_inter_tail(A, B, C, Q, O, s_q, s_o);
06916   if (abcqo == INTERSECT) {
06917     return INTERSECT;
06918   } else if (abcqo == SHAREEDGE) {
06919     shareedge++;
06920   }
06921   if (shareedge == 3) {
06922     // opq are coincident with abc.
06923     return SHAREFACE;
06924   }
06925 #ifdef SELF_CHECK
06926   // It is only possible either no share edge or one.
06927   assert(shareedge == 0 || shareedge == 1);
06928 #endif
06929 
06930   // Continue to detect whether opq and abc are intersecting or not.
06931   enum interresult opqab, opqbc, opqca;
06932 
06933   opqab = tri_edge_inter_tail(O, P, Q, A, B, s_a, s_b);
06934   if (opqab == INTERSECT) {
06935     return INTERSECT;
06936   }
06937   opqbc = tri_edge_inter_tail(O, P, Q, B, C, s_b, s_c);
06938   if (opqbc == INTERSECT) {
06939     return INTERSECT;
06940   }
06941   opqca = tri_edge_inter_tail(O, P, Q, C, A, s_c, s_a);
06942   if (opqca == INTERSECT) {
06943     return INTERSECT;
06944   }
06945 
06946   // At this point, two triangles are not intersecting and not coincident.
06947   //   They may be share an edge, or share a vertex, or disjoint.
06948   if (abcop == SHAREEDGE) {
06949 #ifdef SELF_CHECK
06950     assert(abcpq == SHAREVERTEX && abcqo == SHAREVERTEX);
06951 #endif
06952     // op is coincident with an edge of abc.
06953     return SHAREEDGE;
06954   }
06955   if (abcpq == SHAREEDGE) {
06956 #ifdef SELF_CHECK
06957     assert(abcop == SHAREVERTEX && abcqo == SHAREVERTEX);
06958 #endif
06959     // pq is coincident with an edge of abc.
06960     return SHAREEDGE;
06961   }
06962   if (abcqo == SHAREEDGE) {
06963 #ifdef SELF_CHECK
06964     assert(abcop == SHAREVERTEX && abcpq == SHAREVERTEX);
06965 #endif
06966     // qo is coincident with an edge of abc.
06967     return SHAREEDGE;
06968   }
06969 
06970   // They may share a vertex or disjoint.
06971   if (abcop == SHAREVERTEX) {
06972     // o or p is coincident with a vertex of abc.
06973     if (abcpq == SHAREVERTEX) {
06974       // p is the coincident vertex.
06975 #ifdef SELF_CHECK
06976       assert(abcqo != SHAREVERTEX);
06977 #endif
06978     } else {
06979       // o is the coincident vertex.
06980 #ifdef SELF_CHECK
06981       assert(abcqo == SHAREVERTEX);
06982 #endif
06983     }
06984     return SHAREVERTEX;
06985   }
06986   if (abcpq == SHAREVERTEX) {
06987     // q is the coincident vertex.
06988 #ifdef SELF_CHECK
06989     assert(abcqo == SHAREVERTEX);
06990 #endif
06991     return SHAREVERTEX;
06992   }
06993 
06994   // They are disjoint.
06995   return DISJOINT;
06996 }
06997 
06999 //                                                                           //
07000 // insphere_sos()    Insphere test with symbolic perturbation.               //
07001 //                                                                           //
07002 // The input points a, b, c, and d should be non-coplanar. They must be ord- //
07003 // ered so that they have a positive orientation (as defined by orient3d()), //
07004 // or the sign of the result will be reversed.                               //
07005 //                                                                           //
07006 // Return a positive value if the point e lies inside the circumsphere of a, //
07007 // b, c, and d; a negative value if it lies outside.                         //
07008 //                                                                           //
07010 
07011 REAL tetgenmesh::insphere_sos(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
07012   int ia, int ib, int ic, int id, int ie)
07013 {
07014   REAL det;
07015 
07016   det = insphere(pa, pb, pc, pd, pe);
07017   if (det != 0.0) {
07018     return det;
07019   }
07020 
07021   // det = 0.0, use symbolic perturbation.
07022   REAL *p[5], *tmpp;
07023   REAL sign, det_c, det_d;
07024   int idx[5], perm, tmp;
07025   int n, i, j;
07026 
07027   p[0] = pa; idx[0] = ia;
07028   p[1] = pb; idx[1] = ib;
07029   p[2] = pc; idx[2] = ic;
07030   p[3] = pd; idx[3] = id;
07031   p[4] = pe; idx[4] = ie;
07032 
07033   // Bubble sort the points by the increasing order of the indices.
07034   n = 5;
07035   perm = 0; // The number of total swaps.
07036   for (i = 0; i < n - 1; i++) {
07037     for (j = 0; j < n - 1 - i; j++) {
07038       if (idx[j + 1] < idx[j]) {  // compare the two neighbors.
07039         tmp = idx[j];         // swap idx[j] and idx[j + 1]
07040         idx[j] = idx[j + 1];
07041         idx[j + 1] = tmp;
07042         tmpp = p[j];         // swap p[j] and p[j + 1]
07043         p[j] = p[j + 1];
07044         p[j + 1] = tmpp;
07045         perm++;
07046       }
07047     }
07048   }
07049 
07050   sign = (perm % 2 == 0) ? 1.0 : -1.0;
07051   det_c = orient3d(p[1], p[2], p[3], p[4]); // orient3d(b, c, d, e)
07052   if (det_c != 0.0) {
07053     return sign * det_c;
07054   }
07055   det_d = orient3d(p[0], p[2], p[3], p[4]); // orient3d(a, c, d, e)
07056   return -sign * det_d;
07057 }
07058 
07060 //                                                                           //
07061 // iscollinear()    Check if three points are approximately collinear.       //
07062 //                                                                           //
07063 // 'eps' is a relative error tolerance.  The collinearity is determined by   //
07064 // the value q = cos(theta), where theta is the angle between two vectors    //
07065 // A->B and A->C.  They're collinear if 1.0 - q <= epspp.                    //
07066 //                                                                           //
07068 
07069 bool tetgenmesh::iscollinear(REAL* A, REAL* B, REAL* C, REAL eps)
07070 {
07071   REAL abx, aby, abz;
07072   REAL acx, acy, acz;
07073   REAL Lv, Lw, dd;
07074   REAL d, q;
07075 
07076   // Limit of two closed points.
07077   q = longest * eps;
07078   q *= q;
07079 
07080   abx = A[0] - B[0];
07081   aby = A[1] - B[1];
07082   abz = A[2] - B[2];
07083   acx = A[0] - C[0];
07084   acy = A[1] - C[1];
07085   acz = A[2] - C[2];
07086   Lv = abx * abx + aby * aby + abz * abz;
07087   // Is AB (nearly) indentical?
07088   if (Lv < q) return true;
07089   Lw = acx * acx + acy * acy + acz * acz;
07090   // Is AC (nearly) indentical?
07091   if (Lw < q) return true;
07092   dd = abx * acx + aby * acy + abz * acz;
07093 
07094   d = (dd * dd) / (Lv * Lw);
07095   if (d > 1.0) d = 1.0; // Rounding.
07096   q = 1.0 - sqrt(d); // Notice 0 < q < 1.0.
07097 
07098   return q <= eps;
07099 }
07100 
07102 //                                                                           //
07103 // iscoplanar()    Check if four points are approximately coplanar.          //
07104 //                                                                           //
07105 // 'vol6' is six times of the signed volume of the tetrahedron formed by the //
07106 // four points. 'eps' is the relative error tolerance.  The coplanarity is   //
07107 // determined by the value: q = fabs(vol6) / L^3,  where L is the average    //
07108 // edge length of the tet. They're coplanar if q <= eps.                     //
07109 //                                                                           //
07111 
07112 bool tetgenmesh::
07113 iscoplanar(REAL* k, REAL* l, REAL* m, REAL* n, REAL vol6, REAL eps)
07114 {
07115   REAL L, q;
07116   REAL x, y, z;
07117 
07118   if (vol6 == 0.0) return true;
07119 
07120   x = k[0] - l[0];
07121   y = k[1] - l[1];
07122   z = k[2] - l[2];
07123   L = sqrt(x * x + y * y + z * z);
07124   x = l[0] - m[0];
07125   y = l[1] - m[1];
07126   z = l[2] - m[2];
07127   L += sqrt(x * x + y * y + z * z);
07128   x = m[0] - k[0];
07129   y = m[1] - k[1];
07130   z = m[2] - k[2];
07131   L += sqrt(x * x + y * y + z * z);
07132   x = k[0] - n[0];
07133   y = k[1] - n[1];
07134   z = k[2] - n[2];
07135   L += sqrt(x * x + y * y + z * z);
07136   x = l[0] - n[0];
07137   y = l[1] - n[1];
07138   z = l[2] - n[2];
07139   L += sqrt(x * x + y * y + z * z);
07140   x = m[0] - n[0];
07141   y = m[1] - n[1];
07142   z = m[2] - n[2];
07143   L += sqrt(x * x + y * y + z * z);
07144 #ifdef SELF_CHECK
07145   assert(L > 0.0);
07146 #endif
07147   L /= 6.0;
07148   q = fabs(vol6) / (L * L * L);
07149 
07150   return q <= eps;
07151 }
07152 
07154 //                                                                           //
07155 // iscospheric()    Check if five points are approximately coplanar.         //
07156 //                                                                           //
07157 // 'vol24' is the 24 times of the signed volume of the 4-dimensional simplex //
07158 // formed by the five points. 'eps' is the relative tolerance. The cosphere  //
07159 // case is determined by the value: q = fabs(vol24) / L^4,  where L is the   //
07160 // average edge length of the simplex. They're cosphere if q <= eps.         //
07161 //                                                                           //
07163 
07164 bool tetgenmesh::
07165 iscospheric(REAL* k, REAL* l, REAL* m, REAL* n, REAL* o, REAL vol24, REAL eps)
07166 {
07167   REAL L, q;
07168 
07169   // A 4D simplex has 10 edges.
07170   L = distance(k, l);
07171   L += distance(l, m);
07172   L += distance(m, k);
07173   L += distance(k, n);
07174   L += distance(l, n);
07175   L += distance(m, n);
07176   L += distance(k, o);
07177   L += distance(l, o);
07178   L += distance(m, o);
07179   L += distance(n, o);
07180 #ifdef SELF_CHECK
07181   assert(L > 0.0);
07182 #endif
07183   L /= 10.0;
07184   q = fabs(vol24) / (L * L * L * L);
07185 
07186   return q < eps;
07187 }
07188 
07189 //
07190 // End of geometric tests
07191 //
07192 
07193 //
07194 // Begin of Geometric quantities calculators
07195 //
07196 
07197 // distance() computs the Euclidean distance between two points.
07198 inline REAL tetgenmesh::distance(REAL* p1, REAL* p2)
07199 {
07200   return sqrt((p2[0] - p1[0]) * (p2[0] - p1[0]) +
07201               (p2[1] - p1[1]) * (p2[1] - p1[1]) +
07202               (p2[2] - p1[2]) * (p2[2] - p1[2]));
07203 }
07204 
07206 //                                                                           //
07207 // shortdistance()    Returns the shortest distance from point p to a line   //
07208 //                    defined by two points e1 and e2.                       //
07209 //                                                                           //
07210 // First compute the projection length l_p of the vector v1 = p - e1 along   //
07211 // the vector v2 = e2 - e1. Then Pythagoras' Theorem is used to compute the  //
07212 // shortest distance.                                                        //
07213 //                                                                           //
07214 // This routine allows that p is collinear with the line. In this case, the  //
07215 // return value is zero. The two points e1 and e2 should not be identical.   //
07216 //                                                                           //
07218 
07219 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2)
07220 {
07221   REAL v1[3], v2[3];
07222   REAL len, l_p;
07223 
07224   v1[0] = e2[0] - e1[0];
07225   v1[1] = e2[1] - e1[1];
07226   v1[2] = e2[2] - e1[2];
07227   v2[0] = p[0] - e1[0];
07228   v2[1] = p[1] - e1[1];
07229   v2[2] = p[2] - e1[2];
07230 
07231   len = sqrt(dot(v1, v1));
07232 #ifdef SELF_CHECK
07233   assert(len != 0.0);
07234 #endif
07235   v1[0] /= len;
07236   v1[1] /= len;
07237   v1[2] /= len;
07238   l_p = dot(v1, v2);
07239 
07240   return sqrt(dot(v2, v2) - l_p * l_p);
07241 }
07242 
07244 //                                                                           //
07245 // shortdistance()    Returns the shortest distance from point p to a face.  //
07246 //                                                                           //
07248 
07249 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2, REAL* e3)
07250 {
07251   REAL prj[3];
07252 
07253   projpt2face(p, e1, e2, e3, prj);
07254   return distance(p, prj);
07255 }
07256 
07258 //                                                                           //
07259 // interiorangle()    Return the interior angle (0 - 2 * PI) between vectors //
07260 //                    o->p1 and o->p2.                                       //
07261 //                                                                           //
07262 // 'n' is the normal of the plane containing face (o, p1, p2).  The interior //
07263 // angle is the total angle rotating from o->p1 around n to o->p2.  Exchange //
07264 // the position of p1 and p2 will get the complement angle of the other one. //
07265 // i.e., interiorangle(o, p1, p2) = 2 * PI - interiorangle(o, p2, p1).  Set  //
07266 // 'n' be NULL if you only want the interior angle between 0 - PI.           //
07267 //                                                                           //
07269 
07270 REAL tetgenmesh::interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n)
07271 {
07272   REAL v1[3], v2[3], np[3];
07273   REAL theta, costheta, lenlen;
07274   REAL ori, len1, len2;
07275 
07276   // Get the interior angle (0 - PI) between o->p1, and o->p2.
07277   v1[0] = p1[0] - o[0];
07278   v1[1] = p1[1] - o[1];
07279   v1[2] = p1[2] - o[2];
07280   v2[0] = p2[0] - o[0];
07281   v2[1] = p2[1] - o[1];
07282   v2[2] = p2[2] - o[2];
07283   len1 = sqrt(dot(v1, v1));
07284   len2 = sqrt(dot(v2, v2));
07285   lenlen = len1 * len2;
07286 #ifdef SELF_CHECK
07287   assert(lenlen != 0.0);
07288 #endif
07289   costheta = dot(v1, v2) / lenlen;
07290   if (costheta > 1.0) {
07291     costheta = 1.0; // Roundoff.
07292   } else if (costheta < -1.0) {
07293     costheta = -1.0; // Roundoff.
07294   }
07295   theta = acos(costheta);
07296   if (n != NULL) {
07297     // Get a point above the face (o, p1, p2);
07298     np[0] = o[0] + n[0];
07299     np[1] = o[1] + n[1];
07300     np[2] = o[2] + n[2];
07301     // Adjust theta (0 - 2 * PI).
07302     ori = orient3d(p1, o, np, p2);
07303     if (ori > 0.0) {
07304       theta = 2 * PI - theta;
07305     }
07306   }
07307 
07308   return theta;
07309 }
07310 
07312 //                                                                           //
07313 // projpt2edge()    Return the projection point from a point to an edge.     //
07314 //                                                                           //
07316 
07317 void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj)
07318 {
07319   REAL v1[3], v2[3];
07320   REAL len, l_p;
07321 
07322   v1[0] = e2[0] - e1[0];
07323   v1[1] = e2[1] - e1[1];
07324   v1[2] = e2[2] - e1[2];
07325   v2[0] = p[0] - e1[0];
07326   v2[1] = p[1] - e1[1];
07327   v2[2] = p[2] - e1[2];
07328 
07329   len = sqrt(dot(v1, v1));
07330 #ifdef SELF_CHECK
07331   assert(len != 0.0);
07332 #endif
07333   v1[0] /= len;
07334   v1[1] /= len;
07335   v1[2] /= len;
07336   l_p = dot(v1, v2);
07337 
07338   prj[0] = e1[0] + l_p * v1[0];
07339   prj[1] = e1[1] + l_p * v1[1];
07340   prj[2] = e1[2] + l_p * v1[2];
07341 }
07342 
07344 //                                                                           //
07345 // projpt2face()    Return the projection point from a point to a face.      //
07346 //                                                                           //
07348 
07349 void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj)
07350 {
07351   REAL fnormal[3], v1[3];
07352   REAL len, dist;
07353 
07354   // Get the unit face normal.
07355   facenormal(f1, f2, f3, fnormal, &len);
07356 #ifdef SELF_CHECK
07357   assert(len > 0.0);
07358 #endif
07359   fnormal[0] /= len;
07360   fnormal[1] /= len;
07361   fnormal[2] /= len;
07362   // Get the vector v1 = |p - f1|.
07363   v1[0] = p[0] - f1[0];
07364   v1[1] = p[1] - f1[1];
07365   v1[2] = p[2] - f1[2];
07366   // Get the project distance.
07367   dist = dot(fnormal, v1);
07368 
07369   // Get the project point.
07370   prj[0] = p[0] - dist * fnormal[0];
07371   prj[1] = p[1] - dist * fnormal[1];
07372   prj[2] = p[2] - dist * fnormal[2];
07373 }
07374 
07376 //                                                                           //
07377 // facenormal()    Calculate the normal of a face given by three points.     //
07378 //                                                                           //
07379 // In general, the face normal can be calculate by the cross product of any  //
07380 // pair of the three edge vectors.  However, if the three points are nearly  //
07381 // collinear, the rounding error may harm the result. To choose a good pair  //
07382 // of vectors is helpful to reduce the error.                                //
07383 //                                                                           //
07385 
07386 void tetgenmesh::facenormal(REAL* pa, REAL* pb, REAL* pc, REAL* n, REAL* nlen)
07387 {
07388   REAL v1[3], v2[3];
07389 
07390   v1[0] = pb[0] - pa[0];
07391   v1[1] = pb[1] - pa[1];
07392   v1[2] = pb[2] - pa[2];
07393   v2[0] = pc[0] - pa[0];
07394   v2[1] = pc[1] - pa[1];
07395   v2[2] = pc[2] - pa[2];
07396 
07397   cross(v1, v2, n);
07398   if (nlen != (REAL *) NULL) {
07399     *nlen = sqrt(dot(n, n));
07400   }
07401 }
07402 
07404 //                                                                           //
07405 // edgeorthonormal()    Return the unit normal of an edge in a given plane.  //
07406 //                                                                           //
07407 // The edge is from e1 to e2,  the plane is defined by given an additional   //
07408 // point op, which is non-collinear with the edge.  In addition, the side of //
07409 // the edge in which op lies defines the positive position of the normal.    //
07410 //                                                                           //
07411 // Let v1 be the unit vector from e1 to e2, v2 be the unit edge vector from  //
07412 // e1 to op, fn be the unit face normal calculated by fn = v1 x v2. Then the //
07413 // unit edge normal of e1e2 pointing to op is n = fn x v1.  Note, we should  //
07414 // not change the position of fn and v1, otherwise, we get the edge normal   //
07415 // pointing to the other side of op.                                         //
07416 //                                                                           //
07418 
07419 void tetgenmesh::edgeorthonormal(REAL* e1, REAL* e2, REAL* op, REAL* n)
07420 {
07421   REAL v1[3], v2[3], fn[3];
07422   REAL len;
07423 
07424   // Get the edge vector v1.
07425   v1[0] = e2[0] - e1[0];
07426   v1[1] = e2[1] - e1[1];
07427   v1[2] = e2[2] - e1[2];
07428   // Get the edge vector v2.
07429   v2[0] = op[0] - e1[0];
07430   v2[1] = op[1] - e1[1];
07431   v2[2] = op[2] - e1[2];
07432   // Get the face normal fn = v1 x v2.
07433   cross(v1, v2, fn);
07434   // Get the edge normal n pointing to op. n = fn x v1.
07435   cross(fn, v1, n);
07436   // Normalize the vector.
07437   len = sqrt(dot(n, n));
07438   n[0] /= len;
07439   n[1] /= len;
07440   n[2] /= len;
07441 }
07442 
07444 //                                                                           //
07445 // facedihedral()    Return the dihedral angle (in radian) between two       //
07446 //                   adjoining faces.                                        //
07447 //                                                                           //
07448 // 'pa', 'pb' are the shared edge of these two faces, 'pc1', and 'pc2' are   //
07449 // apexes of these two faces.  Return the angle (between 0 to 2*pi) between  //
07450 // the normal of face (pa, pb, pc1) and normal of face (pa, pb, pc2).        //
07451 //                                                                           //
07453 
07454 REAL tetgenmesh::facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2)
07455 {
07456   REAL n1[3], n2[3];
07457   REAL n1len, n2len;
07458   REAL costheta, ori;
07459   REAL theta;
07460 
07461   facenormal(pa, pb, pc1, n1, &n1len);
07462   facenormal(pa, pb, pc2, n2, &n2len);
07463   costheta = dot(n1, n2) / (n1len * n2len);
07464   // Be careful rounding error!
07465   if (costheta > 1.0) {
07466     costheta = 1.0;
07467   } else if (costheta < -1.0) {
07468     costheta = -1.0;
07469   }
07470   theta = acos(costheta);
07471   ori = orient3d(pa, pb, pc1, pc2);
07472   if (ori > 0.0) {
07473     theta = 2 * PI - theta;
07474   }
07475 
07476   return theta;
07477 }
07478 
07480 //                                                                           //
07481 // tetalldihedral()    Get all (six) dihedral angles of a tet.               //
07482 //                                                                           //
07483 // The tet is given by its four corners a, b, c, and d. If 'cosdd' is not    //
07484 // NULL, it returns the cosines of the 6 dihedral angles, the corresponding  //
07485 // edges are: ab, bc, ca, ad, bd, and cd. If 'cosmaxd' (or 'cosmind') is not //
07486 // NULL, it returns the cosine of the maximal (or minimal) dihedral angle.   //
07487 //                                                                           //
07489 
07490 void tetgenmesh::tetalldihedral(point pa, point pb, point pc, point pd,
07491   REAL* cosdd, REAL* cosmaxd, REAL* cosmind)
07492 {
07493   REAL N[4][3], cosd, len;
07494   int f1, f2, i, j;
07495 
07496   f1=0;
07497   f2=0;
07498 
07499   // Get four normals of faces of the tet.
07500   tetallnormal(pa, pb, pc, pd, N, NULL);
07501   // Normalize the normals.
07502   for (i = 0; i < 4; i++) {
07503     len = sqrt(dot(N[i], N[i]));
07504     if (len != 0.0) {
07505       for (j = 0; j < 3; j++) N[i][j] /= len;
07506     }
07507   }
07508 
07509   for (i = 0; i < 6; i++) {
07510     switch (i) {
07511     case 0: f1 = 2; f2 = 3; break; // edge ab.
07512     case 1: f1 = 0; f2 = 3; break; // edge bc.
07513     case 2: f1 = 1; f2 = 3; break; // edge ca.
07514     case 3: f1 = 1; f2 = 2; break; // edge ad.
07515     case 4: f1 = 2; f2 = 0; break; // edge bd.
07516     case 5: f1 = 0; f2 = 1; break; // edge cd.
07517     }
07518     cosd = -dot(N[f1], N[f2]);
07519     if (cosdd) cosdd[i] = cosd;
07520     if (i == 0) {
07521       if (cosmaxd) *cosmaxd = cosd;
07522       if (cosmind) *cosmind = cosd;
07523     } else {
07524       if (cosmaxd) *cosmaxd = cosd < *cosmaxd ? cosd : *cosmaxd;
07525       if (cosmind) *cosmind = cosd > *cosmind ? cosd : *cosmind;
07526     }
07527   }
07528 }
07529 
07531 //                                                                           //
07532 // tetallnormal()    Get the in-noramls of the four faces of a given tet.    //
07533 //                                                                           //
07534 // Let tet be abcd. N[4][3] returns the four normals, which are: N[0] cbd,   //
07535 // N[1] acd, N[2] bad, N[3] abc. These normals are unnormalized.             //
07536 //                                                                           //
07538 
07539 void tetgenmesh::tetallnormal(point pa, point pb, point pc, point pd,
07540   REAL N[4][3], REAL* volume)
07541 {
07542   REAL A[4][4], rhs[4], D;
07543   int indx[4];
07544   int i, j;
07545 
07546   // get the entries of A[3][3].
07547   for (i = 0; i < 3; i++) A[0][i] = pa[i] - pd[i];  // d->a vec
07548   for (i = 0; i < 3; i++) A[1][i] = pb[i] - pd[i];  // d->b vec
07549   for (i = 0; i < 3; i++) A[2][i] = pc[i] - pd[i];  // d->c vec
07550   // Compute the inverse of matrix A, to get 3 normals of the 4 faces.
07551   lu_decmp(A, 3, indx, &D, 0);     // Decompose the matrix just once.
07552   if (volume != NULL) {
07553     // Get the volume of the tet.
07554     *volume = fabs((A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2])) / 6.0;
07555   }
07556   for (j = 0; j < 3; j++) {
07557     for (i = 0; i < 3; i++) rhs[i] = 0.0;
07558     rhs[j] = 1.0;  // Positive means the inside direction
07559     lu_solve(A, 3, indx, rhs, 0);
07560     for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07561   }
07562   // Get the fourth normal by summing up the first three.
07563   for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07564 }
07565 
07567 //                                                                           //
07568 // tetaspectratio()    Calculate the aspect ratio of the tetrahedron.        //
07569 //                                                                           //
07570 // The aspect ratio of a tet is R/h, where R is the circumradius and h is    //
07571 // the shortest height of the tet.                                           //
07572 //                                                                           //
07574 
07575 REAL tetgenmesh::tetaspectratio(point pa, point pb, point pc, point pd)
07576 {
07577   REAL vda[3], vdb[3], vdc[3];
07578   REAL N[4][3], A[4][4], rhs[4], D;
07579   REAL H[4], volume, radius2, minheightinv;
07580   int indx[4];
07581   int i, j;
07582 
07583   // Set the matrix A = [vda, vdb, vdc]^T.
07584   for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
07585   for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
07586   for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
07587   // Lu-decompose the matrix A.
07588   lu_decmp(A, 3, indx, &D, 0);
07589   // Get the volume of abcd.
07590   volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
07591   // Check if it is zero.
07592   if (volume == 0.0) return 1.0e+200; // A degenerate tet.
07593   // if (volume < 0.0) volume = -volume;
07594   // Check the radiu-edge ratio of the tet.
07595   rhs[0] = 0.5 * dot(vda, vda);
07596   rhs[1] = 0.5 * dot(vdb, vdb);
07597   rhs[2] = 0.5 * dot(vdc, vdc);
07598   lu_solve(A, 3, indx, rhs, 0);
07599   // Get the circumcenter.
07600   // for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
07601   // Get the square of the circumradius.
07602   radius2 = dot(rhs, rhs);
07603 
07604   // Compute the 4 face normals (N[0], ..., N[3]).
07605   for (j = 0; j < 3; j++) {
07606     for (i = 0; i < 3; i++) rhs[i] = 0.0;
07607     rhs[j] = 1.0;  // Positive means the inside direction
07608     lu_solve(A, 3, indx, rhs, 0);
07609     for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07610   }
07611   // Get the fourth normal by summing up the first three.
07612   for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07613   // Normalized the normals.
07614   for (i = 0; i < 4; i++) {
07615     // H[i] is the inverse of the height of its corresponding face.
07616     H[i] = sqrt(dot(N[i], N[i]));
07617     // if (H[i] > 0.0) {
07618     //   for (j = 0; j < 3; j++) N[i][j] /= H[i];
07619     // }
07620   }
07621   // Get the radius of the inscribed sphere.
07622   // insradius = 1.0 / (H[0] + H[1] + H[2] + H[3]);
07623   // Get the biggest H[i] (corresponding to the smallest height).
07624   minheightinv = H[0];
07625   for (i = 1; i < 3; i++) {
07626     if (H[i] > minheightinv) minheightinv = H[i];
07627   }
07628 
07629   return sqrt(radius2) * minheightinv;
07630 }
07631 
07633 //                                                                           //
07634 // circumsphere()    Calculate the smallest circumsphere (center and radius) //
07635 //                   of the given three or four points.                      //
07636 //                                                                           //
07637 // The circumsphere of four points (a tetrahedron) is unique if they are not //
07638 // degenerate. If 'pd = NULL', the smallest circumsphere of three points is  //
07639 // the diametral sphere of the triangle if they are not degenerate.          //
07640 //                                                                           //
07641 // Return TRUE if the input points are not degenerate and the circumcenter   //
07642 // and circumradius are returned in 'cent' and 'radius' respectively if they //
07643 // are not NULLs. Otherwise, return FALSE indicated the points are degenrate.//
07644 //                                                                           //
07646 
07647 bool tetgenmesh::
07648 circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* cent, REAL* radius)
07649 {
07650   REAL A[4][4], rhs[4], D;
07651   int indx[4];
07652 
07653   // Compute the coefficient matrix A (3x3).
07654   A[0][0] = pb[0] - pa[0];
07655   A[0][1] = pb[1] - pa[1];
07656   A[0][2] = pb[2] - pa[2];
07657   A[1][0] = pc[0] - pa[0];
07658   A[1][1] = pc[1] - pa[1];
07659   A[1][2] = pc[2] - pa[2];
07660   if (pd != NULL) {
07661     A[2][0] = pd[0] - pa[0];
07662     A[2][1] = pd[1] - pa[1];
07663     A[2][2] = pd[2] - pa[2];
07664   } else {
07665     cross(A[0], A[1], A[2]);
07666   }
07667 
07668   // Compute the right hand side vector b (3x1).
07669   rhs[0] = 0.5 * dot(A[0], A[0]);
07670   rhs[1] = 0.5 * dot(A[1], A[1]);
07671   if (pd != NULL) {
07672     rhs[2] = 0.5 * dot(A[2], A[2]);
07673   } else {
07674     rhs[2] = 0.0;
07675   }
07676 
07677   // Solve the 3 by 3 equations use LU decomposition with partial pivoting
07678   //   and backward and forward substitute..
07679   if (!lu_decmp(A, 3, indx, &D, 0)) {
07680     if (radius != (REAL *) NULL) *radius = 0.0;
07681     return false;
07682   }
07683   lu_solve(A, 3, indx, rhs, 0);
07684   if (cent != (REAL *) NULL) {
07685     cent[0] = pa[0] + rhs[0];
07686     cent[1] = pa[1] + rhs[1];
07687     cent[2] = pa[2] + rhs[2];
07688   }
07689   if (radius != (REAL *) NULL) {
07690     *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
07691   }
07692   return true;
07693 }
07694 
07696 //                                                                           //
07697 // inscribedsphere()    Compute the radius and center of the biggest         //
07698 //                      inscribed sphere of a given tetrahedron.             //
07699 //                                                                           //
07700 // The tetrahedron is given by its four points, it must not be degenerate.   //
07701 // The center and radius are returned in 'cent' and 'radius' respectively if //
07702 // they are not NULLs.                                                       //
07703 //                                                                           //
07704 // Geometrical fact. For any simplex in d dimension,                         //
07705 //   r/h1 + r/h2 + ... r/hn = 1 (n <= d + 1);                                //
07706 // where r is the radius of inscribed ball, and h is the height of each side //
07707 // of the simplex. The value of 'r/h' is just the barycenter coordinates of  //
07708 // each vertex of the simplex. Therefore, we can compute the radius and      //
07709 // center of the smallest inscribed ball as following equations:             //
07710 //   r = 1.0 / (1/h1 + 1/h2 + ... + 1/hn);          (1)                      //
07711 //   C = r/h1 * P1 + r/h2 * P2 + ... + r/hn * Pn;   (2)                      //
07712 // where C is the vector of center, P1, P2, .. Pn are vectors of vertices.   //
07713 // Here (2) contains n linear equations with n variables.  (h, P) must be a  //
07714 // pair, h is the height from P to its opposite face.                        //
07715 //                                                                           //
07717 
07718 void tetgenmesh::inscribedsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
07719   REAL* cent, REAL* radius)
07720 {
07721   REAL N[4][3], H[4]; // Normals (colume vectors) and heights of each face.
07722   REAL rd;
07723   int i;
07724 
07725   // Get the all normals of the tet.
07726   tetallnormal(pa, pb, pc, pd, N, NULL);
07727   for (i = 0; i < 4; i++) {
07728     // H[i] is the inverse of height of its corresponding face.
07729     H[i] = sqrt(dot(N[i], N[i]));
07730   }
07731   // Compute the radius use eq. (1).
07732   rd = 1.0 / (H[0] + H[1] + H[2] + H[3]);
07733   if (radius != (REAL*) NULL) *radius = rd;
07734   if (cent != (REAL*) NULL) {
07735     // Compute the center use eq. (2).
07736     cent[0] = rd * (H[0] * pa[0] + H[1] * pb[0] + H[2] * pc[0] + H[3] * pd[0]);
07737     cent[1] = rd * (H[0] * pa[1] + H[1] * pb[1] + H[2] * pc[1] + H[3] * pd[1]);
07738     cent[2] = rd * (H[0] * pa[2] + H[1] * pb[2] + H[2] * pc[2] + H[3] * pd[2]);
07739   }
07740 }
07741 
07743 //                                                                           //
07744 // rotatepoint()    Create a point by rotating an existing point.            //
07745 //                                                                           //
07746 // Create a 3D point by rotating point 'p' with an angle 'rotangle' (in arc  //
07747 // degree) around a rotating axis given by a vector from point 'p1' to 'p2'. //
07748 // The rotation is according with right-hand rule, i.e., use your right-hand //
07749 // to grab the axis with your thumber pointing to its positive direction,    //
07750 // your fingers indicate the rotating direction.                             //
07751 //                                                                           //
07752 // The rotating steps are the following:                                     //
07753 //   1. Translate vector 'p1->p2' to origin, M1;                             //
07754 //   2. Rotate vector around the Y-axis until it lies in the YZ plane, M2;   //
07755 //   3. Rotate vector around the X-axis until it lies on the Z axis, M3;     //
07756 //   4. Perform the rotation of 'p' around the z-axis, M4;                   //
07757 //   5. Undo Step 3, M5;                                                     //
07758 //   6. Undo Step 2, M6;                                                     //
07759 //   7. Undo Step 1, M7;                                                     //
07760 // Use matrix multiplication to combine the above sequences, we get:         //
07761 //   p0' = T * p0, where T = M7 * M6 * M5 * M4 * M3 * M2 * M1                //
07762 //                                                                           //
07764 
07765 void tetgenmesh::rotatepoint(REAL* p, REAL rotangle, REAL* p1, REAL* p2)
07766 {
07767   REAL T[4][4], pp0[4], p0t[4], p2t[4];
07768   REAL roty, rotx, alphaR, projlen;
07769   REAL dx, dy, dz;
07770 
07771   initm44(1, 0, 0, -p1[0],
07772           0, 1, 0, -p1[1],
07773           0, 0, 1, -p1[2],
07774           0, 0, 0, 1, T);
07775   pp0[0] = p[0]; pp0[1] = p[1]; pp0[2] = p[2]; pp0[3] = 1.0;
07776   m4xv4(p0t, T, pp0); // Step 1
07777   pp0[0] = p2[0]; pp0[1] = p2[1]; pp0[2] = p2[2]; pp0[3] = 1.0;
07778   m4xv4(p2t, T, pp0); // Step 1
07779 
07780   // Get the rotation angle around y-axis;
07781   dx = p2t[0];
07782   dz = p2t[2];
07783   projlen = sqrt(dx * dx + dz * dz);
07784   if (projlen <= (b->epsilon * 1e-2) * longest) {
07785     roty = 0;
07786   } else {
07787     roty = acos(dz / projlen);
07788     if (dx < 0) {
07789       roty = -roty;
07790     }
07791   }
07792 
07793   initm44(cos(-roty), 0, sin(-roty), 0,
07794           0, 1, 0, 0,
07795           -sin(-roty), 0, cos(-roty), 0,
07796           0, 0, 0, 1, T);
07797   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07798   m4xv4(p0t, T, pp0); // Step 2
07799   pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
07800   m4xv4(p2t, T, pp0); // Step 2
07801 
07802   // Get the rotation angle around x-axis
07803   dy = p2t[1];
07804   dz = p2t[2];
07805   projlen = sqrt(dy * dy + dz * dz);
07806   if (projlen <= (b->epsilon * 1e-2) * longest) {
07807     rotx = 0;
07808   } else {
07809     rotx = acos(dz / projlen);
07810     if (dy < 0) {
07811       rotx = -rotx;
07812     }
07813   }
07814 
07815   initm44(1, 0, 0, 0,
07816           0, cos(rotx), -sin(rotx), 0,
07817           0, sin(rotx), cos(rotx), 0,
07818           0, 0, 0, 1, T);
07819   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07820   m4xv4(p0t, T, pp0); // Step 3
07821   // pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
07822   // m4xv4(p2t, T, pp0); // Step 3
07823 
07824   alphaR = rotangle;
07825   initm44(cos(alphaR), -sin(alphaR), 0, 0,
07826           sin(alphaR), cos(alphaR), 0, 0,
07827           0, 0, 1, 0,
07828           0, 0, 0, 1, T);
07829   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07830   m4xv4(p0t, T, pp0); // Step 4
07831 
07832   initm44(1, 0, 0, 0,
07833           0, cos(-rotx), -sin(-rotx), 0,
07834           0, sin(-rotx), cos(-rotx), 0,
07835           0, 0, 0, 1, T);
07836   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07837   m4xv4(p0t, T, pp0); // Step 5
07838 
07839   initm44(cos(roty), 0, sin(roty), 0,
07840           0, 1, 0, 0,
07841           -sin(roty), 0, cos(roty), 0,
07842           0, 0, 0, 1, T);
07843   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07844   m4xv4(p0t, T, pp0); // Step 6
07845 
07846   initm44(1, 0, 0, p1[0],
07847           0, 1, 0, p1[1],
07848           0, 0, 1, p1[2],
07849           0, 0, 0, 1, T);
07850   pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07851   m4xv4(p0t, T, pp0); // Step 7
07852 
07853   p[0] = p0t[0];
07854   p[1] = p0t[1];
07855   p[2] = p0t[2];
07856 }
07857 
07859 //                                                                           //
07860 // spherelineint()    3D line sphere (or circle) intersection.               //
07861 //                                                                           //
07862 // The line is given by two points p1, and p2, the sphere is centered at c   //
07863 // with radius r.  This function returns a pointer array p which first index //
07864 // indicates the number of intersection point, followed by coordinate pairs. //
07865 //                                                                           //
07866 // The following code are adapted from: http://astronomy.swin.edu.au/pbourke //
07867 // /geometry/sphereline. Paul Bourke pbourke@swin.edu.au                     //
07868 //                                                                           //
07870 
07871 void tetgenmesh::spherelineint(REAL* p1, REAL* p2, REAL* C, REAL R, REAL p[7])
07872 {
07873   REAL x1, y1, z1; //  P1 coordinates (point of line)
07874   REAL x2, y2, z2; //  P2 coordinates (point of line)
07875   REAL x3, y3, z3, r; //  P3 coordinates and radius (sphere)
07876   REAL a, b, c, mu, i ;
07877 
07878   x1 = p1[0]; y1 = p1[1]; z1 = p1[2];
07879   x2 = p2[0]; y2 = p2[1]; z2 = p2[2];
07880   x3 = C[0];  y3 = C[1];  z3 = C[2];
07881   r = R;
07882 
07883   a =   (x2 - x1) * (x2 - x1)
07884       + (y2 - y1) * (y2 - y1)
07885       + (z2 - z1) * (z2 - z1);
07886   b = 2 * ( (x2 - x1) * (x1 - x3)
07887           + (y2 - y1) * (y1 - y3)
07888           + (z2 - z1) * (z1 - z3) ) ;
07889   c =   (x3 * x3) + (y3 * y3) + (z3 * z3)
07890       + (x1 * x1) + (y1 * y1) + (z1 * z1)
07891       - 2 * (x3 * x1 + y3 * y1 + z3 * z1) - (r * r) ;
07892   i = b * b - 4 * a * c ;
07893 
07894   if (i < 0.0) {
07895     // no intersection
07896     p[0] = 0.0;
07897   } else if (i == 0.0) {
07898     // one intersection
07899     p[0] = 1.0;
07900     mu = -b / (2 * a) ;
07901     p[1] = x1 + mu * (x2 - x1);
07902     p[2] = y1 + mu * (y2 - y1);
07903     p[3] = z1 + mu * (z2 - z1);
07904   } else {
07905     // two intersections
07906     p[0] = 2.0;
07907     // first intersection
07908     mu = (-b + sqrt((b * b) - 4 * a * c)) / (2 * a);
07909     p[1] = x1 + mu * (x2 - x1);
07910     p[2] = y1 + mu * (y2 - y1);
07911     p[3] = z1 + mu * (z2 - z1);
07912     // second intersection
07913     mu = (-b - sqrt((b * b) - 4 * a * c)) / (2 * a);
07914     p[4] = x1 + mu * (x2 - x1);
07915     p[5] = y1 + mu * (y2 - y1);
07916     p[6] = z1 + mu * (z2 - z1);
07917   }
07918 }
07919 
07921 //                                                                           //
07922 // linelineint()    Calculate the shortest line between two lines in 3D.     //
07923 //                                                                           //
07924 // Two 3D lines generally don't intersect at a point, they may be parallel ( //
07925 // no intersections), or coincident (infinite intersections) but most often  //
07926 // only their projections onto a plane intersect. If they don't exactly int- //
07927 // ersect at a point they can be connected by a line segment, the shortest   //
07928 // segment is unique and is often considered to be their intersection in 3D. //
07929 //                                                                           //
07930 // The following code are adapted from: http://astronomy.swin.edu.au/pbourke //
07931 // /geometry/lineline3d. Paul Bourke pbourke@swin.edu.au                     //
07932 //                                                                           //
07933 // Calculate the line segment PaPb that is the shortest route between two    //
07934 // lines P1P2 and P3P4. This function returns a pointer array p which first  //
07935 // index indicates there exists solution or not, 0 means no solution, 1 meas //
07936 // has solution followed by two coordinate pairs.                            //
07937 //                                                                           //
07939 
07940 void tetgenmesh::linelineint(REAL *p1,REAL *p2, REAL *p3, REAL *p4, REAL p[7])
07941 {
07942   REAL p13[3], p43[3], p21[3];
07943   REAL d1343, d4321, d1321, d4343, d2121;
07944   REAL numer, denom;
07945   REAL mua, mub;
07946 
07947   p13[0] = p1[0] - p3[0];
07948   p13[1] = p1[1] - p3[1];
07949   p13[2] = p1[2] - p3[2];
07950   p43[0] = p4[0] - p3[0];
07951   p43[1] = p4[1] - p3[1];
07952   p43[2] = p4[2] - p3[2];
07953   if (p43[0] == 0.0 && p43[1] == 0.0 && p43[2] == 0.0) {
07954     p[0] = 0.0;
07955     return;
07956   }
07957 
07958   p21[0] = p2[0] - p1[0];
07959   p21[1] = p2[1] - p1[1];
07960   p21[2] = p2[2] - p1[2];
07961   if (p21[0] == 0.0 && p21[1] == 0.0 && p21[2] == 0.0) {
07962     p[0] = 0.0;
07963     return;
07964   }
07965 
07966   d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
07967   d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
07968   d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
07969   d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
07970   d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
07971 
07972   denom = d2121 * d4343 - d4321 * d4321;
07973   if (denom == 0.0) {
07974     p[0] = 0.0;
07975     return;
07976   }
07977   numer = d1343 * d4321 - d1321 * d4343;
07978   mua = numer / denom;
07979   mub = (d1343 + d4321 * mua) / d4343;
07980 
07981   p[0] = 1.0;
07982   p[1] = p1[0] + mua * p21[0];
07983   p[2] = p1[1] + mua * p21[1];
07984   p[3] = p1[2] + mua * p21[2];
07985   p[4] = p3[0] + mub * p43[0];
07986   p[5] = p3[1] + mub * p43[1];
07987   p[6] = p3[2] + mub * p43[2];
07988 }
07989 
07991 //                                                                           //
07992 // planelineint()    Calculate the intersection of a line and a plane.       //
07993 //                                                                           //
07994 // The equation of a plane (points P are on the plane with normal N and P3   //
07995 // on the plane) can be written as: N dot (P - P3) = 0. The equation of the  //
07996 // line (points P on the line passing through P1 and P2) can be written as:  //
07997 // P = P1 + u (P2 - P1). The intersection of these two occurs when:          //
07998 //   N dot (P1 + u (P2 - P1)) = N dot P3.                                    //
07999 // Solving for u gives:                                                      //
08000 //         N dot (P3 - P1)                                                   //
08001 //   u = ------------------.                                                 //
08002 //         N dot (P2 - P1)                                                   //
08003 // If the denominator is 0 then N (the normal to the plane) is perpendicular //
08004 // to the line.  Thus the line is either parallel to the plane and there are //
08005 // no solutions or the line is on the plane in which case there are an infi- //
08006 // nite number of solutions.                                                 //
08007 //                                                                           //
08008 // The plane is given by three points pa, pb, and pc, e1 and e2 defines the  //
08009 // line. If u is non-zero, The intersection point (if exists) returns in ip. //
08010 //                                                                           //
08012 
08013 void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
08014   REAL* ip, REAL* u)
08015 {
08016   REAL n[3], det, det1;
08017 
08018   // Calculate N.
08019   facenormal(pa, pb, pc, n, NULL);
08020   // Calculate N dot (e2 - e1).
08021   det = n[0] * (e2[0] - e1[0]) + n[1] * (e2[1] - e1[1])
08022       + n[2] * (e2[2] - e1[2]);
08023   if (det != 0.0) {
08024     // Calculate N dot (pa - e1)
08025     det1 = n[0] * (pa[0] - e1[0]) + n[1] * (pa[1] - e1[1])
08026          + n[2] * (pa[2] - e1[2]);
08027     *u = det1 / det;
08028     ip[0] = e1[0] + *u * (e2[0] - e1[0]);
08029     ip[1] = e1[1] + *u * (e2[1] - e1[1]);
08030     ip[2] = e1[2] + *u * (e2[2] - e1[2]);
08031   } else {
08032     *u = 0.0;
08033   }
08034 }
08035 
08036 //
08037 // End of Geometric quantities calculators
08038 //
08039 
08040 //
08041 // Begin of memory management routines
08042 //
08043 
08045 //                                                                           //
08046 // dummyinit()    Initialize the tetrahedron that fills "outer space" and    //
08047 //                the omnipresent subface.                                   //
08048 //                                                                           //
08049 // The tetrahedron that fills "outer space" called 'dummytet', is pointed to //
08050 // by every tetrahedron and subface on a boundary (be it outer or inner) of  //
08051 // the tetrahedralization. Also, 'dummytet' points to one of the tetrahedron //
08052 // on the convex hull(until the holes and concavities are carved), making it //
08053 // possible to find a starting tetrahedron for point location.               //
08054 //                                                                           //
08055 // The omnipresent subface,'dummysh', is pointed to by every tetrahedron or  //
08056 // subface that doesn't have a full complement of real subface to point to.  //
08057 //                                                                           //
08059 
08060 void tetgenmesh::dummyinit(int tetwords, int shwords)
08061 {
08062   unsigned long alignptr;
08063 
08064   // Set up 'dummytet', the 'tetrahedron' that occupies "outer space".
08065   dummytetbase = (tetrahedron *) new char[tetwords * sizeof(tetrahedron)
08066                                           + tetrahedrons->alignbytes];
08067   // Align 'dummytet' on a 'tetrahedrons->alignbytes'-byte boundary.
08068   alignptr = (unsigned long) dummytetbase;
08069   dummytet = (tetrahedron *)
08070     (alignptr + (unsigned long) tetrahedrons->alignbytes
08071      - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08072   // Initialize the four adjoining tetrahedra to be "outer space". These
08073   //   will eventually be changed by various bonding operations, but their
08074   //   values don't really matter, as long as they can legally be
08075   //   dereferenced.
08076   dummytet[0] = (tetrahedron) dummytet;
08077   dummytet[1] = (tetrahedron) dummytet;
08078   dummytet[2] = (tetrahedron) dummytet;
08079   dummytet[3] = (tetrahedron) dummytet;
08080   // Four null vertex points.
08081   dummytet[4] = (tetrahedron) NULL;
08082   dummytet[5] = (tetrahedron) NULL;
08083   dummytet[6] = (tetrahedron) NULL;
08084   dummytet[7] = (tetrahedron) NULL;
08085 
08086   if (b->useshelles) {
08087     // Set up 'dummysh', the omnipresent "subface" pointed to by any
08088     //   tetrahedron side or subface end that isn't attached to a real
08089     //   subface.
08090     dummyshbase = (shellface *) new char[shwords * sizeof(shellface)
08091                                          + subfaces->alignbytes];
08092     // Align 'dummysh' on a 'subfaces->alignbytes'-byte boundary.
08093     alignptr = (unsigned long) dummyshbase;
08094     dummysh = (shellface *)
08095       (alignptr + (unsigned long) subfaces->alignbytes
08096        - (alignptr % (unsigned long) subfaces->alignbytes));
08097     // Initialize the three adjoining subfaces to be the omnipresent
08098     //   subface. These will eventually be changed by various bonding
08099     //   operations, but their values don't really matter, as long as they
08100     //   can legally be dereferenced.
08101     dummysh[0] = (shellface) dummysh;
08102     dummysh[1] = (shellface) dummysh;
08103     dummysh[2] = (shellface) dummysh;
08104     // Three null vertex points.
08105     dummysh[3] = (shellface) NULL;
08106     dummysh[4] = (shellface) NULL;
08107     dummysh[5] = (shellface) NULL;
08108     // Initialize the two adjoining tetrahedra to be "outer space".
08109     dummysh[6] = (shellface) dummytet;
08110     dummysh[7] = (shellface) dummytet;
08111     // Initialize the three adjoining subsegments to be "out boundary".
08112     dummysh[8]  = (shellface) dummysh;
08113     dummysh[9]  = (shellface) dummysh;
08114     dummysh[10] = (shellface) dummysh;
08115     // Initialize the pointer to badface structure.
08116     dummysh[11] = (shellface) NULL;
08117     // Initialize the four adjoining subfaces of 'dummytet' to be the
08118     //   omnipresent subface.
08119     dummytet[8 ] = (tetrahedron) dummysh;
08120     dummytet[9 ] = (tetrahedron) dummysh;
08121     dummytet[10] = (tetrahedron) dummysh;
08122     dummytet[11] = (tetrahedron) dummysh;
08123   }
08124 }
08125 
08127 //                                                                           //
08128 // initializepools()    Calculate the sizes of the point, tetrahedron, and   //
08129 //                      subface. Initialize their memory pools.              //
08130 //                                                                           //
08131 // This routine also computes the indices 'pointmarkindex', 'point2simindex',//
08132 // and 'point2pbcptindex' used to find values within each point;  computes   //
08133 // indices 'highorderindex', 'elemattribindex', and 'volumeboundindex' used  //
08134 // to find values within each tetrahedron.                                   //
08135 //                                                                           //
08136 // There are two types of boundary elements, which are subfaces and subsegs, //
08137 // they are stored in seperate pools. However, the data structures of them   //
08138 // are the same.  A subsegment can be regarded as a degenerate subface, i.e.,//
08139 // one of its three corners is not used. We set the apex of it be 'NULL' to  //
08140 // distinguish it's a subsegment.                                            //
08141 //                                                                           //
08143 
08144 void tetgenmesh::initializepools()
08145 {
08146   enum wordtype wtype;
08147   int pointsize, elesize, shsize;
08148 
08149   // Default checkpbc = 0;
08150   if ((b->plc || b->refine) && (in->pbcgrouplist != NULL)) {
08151     checkpbcs = 1;
08152   }
08153   // Default varconstraint = 0;
08154   if (in->segmentconstraintlist || in->facetconstraintlist) {
08155     varconstraint = 1;
08156   }
08157 
08158   // The index within each point at which its metric tensor is found. It is
08159   //   saved directly after the list of point attributes.
08160   pointmtrindex = 3 + in->numberofpointattributes;
08161   // Decide the size (1, 3, or 6) of the metric tensor.
08162   if (b->metric) {
08163     // For '-m' option. A tensor field is provided (*.mtr or *.b.mtr file).
08164     if (bgm != (tetgenmesh *) NULL) {
08165       // A background mesh is allocated. It may not exist though.
08166       sizeoftensor = (bgm->in != (tetgenio *) NULL) ?
08167         bgm->in->numberofpointmtrs : in->numberofpointmtrs;
08168     } else {
08169       // No given background mesh - Itself is a background mesh.
08170       sizeoftensor = in->numberofpointmtrs;
08171     }
08172     // Make sure sizeoftensor is at least 1.
08173     sizeoftensor = (sizeoftensor > 0) ? sizeoftensor : 1;
08174   } else {
08175     // For '-q' option. Make sure to have space for saving a scalar value.
08176     sizeoftensor = b->quality ? 1 : 0;
08177   }
08178   // The index within each point at which an element pointer is found, where
08179   //   the index is measured in pointers. Ensure the index is aligned to a
08180   //   sizeof(tetrahedron)-byte address.
08181   point2simindex = ((pointmtrindex + sizeoftensor) * sizeof(REAL)
08182                  + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08183   if (b->plc || b->refine) {
08184     // Increase the point size by three pointers, which are:
08185     //   - a pointer to a tet, read by point2tet();
08186     //   - a pointer to a subface/subsegment , read by point2sh();
08187     //   - a pointer to a parent point, read by point2ppt()).
08188     if (b->metric) {
08189       // Increase one pointer to a tet of the background mesh.
08190       pointsize = (point2simindex + 4) * sizeof(tetrahedron);
08191     } else {
08192       pointsize = (point2simindex + 3) * sizeof(tetrahedron);
08193     }
08194     // The index within each point at which a pbc point is found.
08195     point2pbcptindex = (pointsize + sizeof(tetrahedron) - 1)
08196                      / sizeof(tetrahedron);
08197     if (checkpbcs) {
08198       // Increase the size by one pointer to a corresponding pbc point,
08199       //   read by point2pbcpt().
08200       pointsize = (point2pbcptindex + 1) * sizeof(tetrahedron);
08201     }
08202   } else {
08203     pointsize = point2simindex * sizeof(tetrahedron);
08204   }
08205   // The index within each point at which the boundary marker is found,
08206   //   Ensure the point marker is aligned to a sizeof(int)-byte address.
08207   pointmarkindex = (pointsize + sizeof(int) - 1) / sizeof(int);
08208   // Now point size is the ints (inidcated by pointmarkindex) plus:
08209   //   - an integer for boundary marker;
08210   //   - an integer for vertex type;
08211   pointsize = (pointmarkindex + 2) * sizeof(int);
08212   // Decide the wordtype used in vertex pool.
08213   wtype = (sizeof(REAL) >= sizeof(tetrahedron)) ? FLOATINGPOINT : POINTER;
08214   // Initialize the pool of vertices.
08215   points = new memorypool(pointsize, VERPERBLOCK, wtype, 0);
08216 
08217   // The number of bytes occupied by a tetrahedron.  There are four pointers
08218   //   to other tetrahedra, four pointers to corners, and possibly four
08219   //   pointers to subfaces.
08220   elesize = (8 + b->useshelles * 6) * sizeof(tetrahedron);
08221   // If Voronoi diagram is wanted, make sure we have additional space.
08222   if (b->voroout && (b->useshelles == 0)) {
08223     elesize = (8 + 4) * sizeof(tetrahedron);
08224   }
08225   // The index within each element at which its attributes are found, where
08226   //   the index is measured in REALs.
08227   elemattribindex = (elesize + sizeof(REAL) - 1) / sizeof(REAL);
08228   // The index within each element at which the maximum voulme bound is
08229   //   found, where the index is measured in REALs.  Note that if the
08230   //   `b->regionattrib' flag is set, an additional attribute will be added.
08231   volumeboundindex = elemattribindex + in->numberoftetrahedronattributes
08232                    + (b->regionattrib > 0);
08233   // If element attributes or an constraint are needed, increase the number
08234   //   of bytes occupied by an element.
08235   if (b->varvolume) {
08236     elesize = (volumeboundindex + 1) * sizeof(REAL);
08237   } else if (in->numberoftetrahedronattributes + b->regionattrib > 0) {
08238     elesize = volumeboundindex * sizeof(REAL);
08239   }
08240   // If element neighbor graph is requested (-n switch), an additional
08241   //   integer is allocated for each element.
08242   elemmarkerindex = (elesize + sizeof(int) - 1) / sizeof(int);
08243   if (b->neighout || b->voroout) {
08244     elesize = (elemmarkerindex + 1) * sizeof(int);
08245   }
08246   // If -o2 switch is used, an additional pointer pointed to the list of
08247   //   higher order nodes is allocated for each element.
08248   highorderindex = (elesize + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08249   if (b->order == 2) {
08250     elesize = (highorderindex + 1) * sizeof(tetrahedron);
08251   }
08252   // Having determined the memory size of an element, initialize the pool.
08253   tetrahedrons = new memorypool(elesize, ELEPERBLOCK, POINTER, 8);
08254 
08255   if (b->useshelles) {
08256     // The number of bytes occupied by a subface.  The list of pointers
08257     //   stored in a subface are: three to other subfaces, three to corners,
08258     //   three to subsegments, two to tetrahedra, and one to a badface.
08259     shsize = 12 * sizeof(shellface);
08260     // The index within each subface at which the maximum area bound is
08261     //   found, where the index is measured in REALs.
08262     areaboundindex = (shsize + sizeof(REAL) - 1) / sizeof(REAL);
08263     // If -q switch is in use, increase the number of bytes occupied by
08264     //   a subface for saving maximum area bound.
08265     if (b->quality && varconstraint) {
08266       shsize = (areaboundindex + 1) * sizeof(REAL);
08267     } else {
08268       shsize = areaboundindex * sizeof(REAL);
08269     }
08270     // The index within subface at which the facet marker is found. Ensure
08271     //   the marker is aligned to a sizeof(int)-byte address.
08272     shmarkindex = (shsize + sizeof(int) - 1) / sizeof(int);
08273     // Increase the number of bytes by two or three integers, one for facet
08274     //   marker, one for shellface type, and optionally one for pbc group.
08275     shsize = (shmarkindex + 2 + checkpbcs) * sizeof(int);
08276     // Initialize the pool of subfaces. Each subface record is eight-byte
08277     //   aligned so it has room to store an edge version (from 0 to 5) in
08278     //   the least three bits.
08279     subfaces = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08280     // Initialize the pool of subsegments. The subsegment's record is same
08281     //   with subface.
08282     subsegs = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08283     // Initialize the "outer space" tetrahedron and omnipresent subface.
08284     dummyinit(tetrahedrons->itemwords, subfaces->itemwords);
08285   } else {
08286     // Initialize the "outer space" tetrahedron.
08287     dummyinit(tetrahedrons->itemwords, 0);
08288   }
08289 }
08290 
08292 //                                                                           //
08293 // tetrahedrondealloc()    Deallocate space for a tet., marking it dead.     //
08294 //                                                                           //
08296 
08297 void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
08298 {
08299   // Set tetrahedron's vertices to NULL. This makes it possible to detect
08300   //   dead tetrahedra when traversing the list of all tetrahedra.
08301   dyingtetrahedron[4] = (tetrahedron) NULL;
08302   dyingtetrahedron[5] = (tetrahedron) NULL;
08303   dyingtetrahedron[6] = (tetrahedron) NULL;
08304   dyingtetrahedron[7] = (tetrahedron) NULL;
08305   tetrahedrons->dealloc((void *) dyingtetrahedron);
08306 }
08307 
08309 //                                                                           //
08310 // tetrahedrontraverse()    Traverse the tetrahedra, skipping dead ones.     //
08311 //                                                                           //
08313 
08314 tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse()
08315 {
08316   tetrahedron *newtetrahedron;
08317 
08318   do {
08319     newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
08320     if (newtetrahedron == (tetrahedron *) NULL) {
08321       return (tetrahedron *) NULL;
08322     }
08323   } while (newtetrahedron[7] == (tetrahedron) NULL);      // Skip dead ones.
08324   return newtetrahedron;
08325 }
08326 
08328 //                                                                           //
08329 // shellfacedealloc()    Deallocate space for a shellface, marking it dead.  //
08330 //                       Used both for dealloc a subface and subsegment.     //
08331 //                                                                           //
08333 
08334 void tetgenmesh::shellfacedealloc(memorypool *pool, shellface *dyingsh)
08335 {
08336   // Set shellface's vertices to NULL. This makes it possible to detect dead
08337   //   shellfaces when traversing the list of all shellfaces.
08338   dyingsh[3] = (shellface) NULL;
08339   dyingsh[4] = (shellface) NULL;
08340   dyingsh[5] = (shellface) NULL;
08341   pool->dealloc((void *) dyingsh);
08342 }
08343 
08345 //                                                                           //
08346 // shellfacetraverse()    Traverse the subfaces, skipping dead ones. Used    //
08347 //                        for both subfaces and subsegments pool traverse.   //
08348 //                                                                           //
08350 
08351 tetgenmesh::shellface* tetgenmesh::shellfacetraverse(memorypool *pool)
08352 {
08353   shellface *newshellface;
08354 
08355   do {
08356     newshellface = (shellface *) pool->traverse();
08357     if (newshellface == (shellface *) NULL) {
08358       return (shellface *) NULL;
08359     }
08360   } while (newshellface[3] == (shellface) NULL);          // Skip dead ones.
08361   return newshellface;
08362 }
08363 
08365 //                                                                           //
08366 // badfacedealloc()    Deallocate space for a badface, marking it dead.      //
08367 //                                                                           //
08369 
08370 void tetgenmesh::badfacedealloc(memorypool *pool, badface *dying)
08371 {
08372   // Set badface's forg to NULL. This makes it possible to detect dead
08373   //   ones when traversing the list of all items.
08374   dying->forg = (point) NULL;
08375   pool->dealloc((void *) dying);
08376 }
08377 
08379 //                                                                           //
08380 // badfacetraverse()    Traverse the pools, skipping dead ones.              //
08381 //                                                                           //
08383 
08384 tetgenmesh::badface* tetgenmesh::badfacetraverse(memorypool *pool)
08385 {
08386   badface *newsh;
08387 
08388   do {
08389     newsh = (badface *) pool->traverse();
08390     if (newsh == (badface *) NULL) {
08391       return (badface *) NULL;
08392     }
08393   } while (newsh->forg == (point) NULL);               // Skip dead ones.
08394   return newsh;
08395 }
08396 
08398 //                                                                           //
08399 // pointdealloc()    Deallocate space for a point, marking it dead.          //
08400 //                                                                           //
08402 
08403 void tetgenmesh::pointdealloc(point dyingpoint)
08404 {
08405   // Mark the point as dead. This  makes it possible to detect dead points
08406   //   when traversing the list of all points.
08407   setpointtype(dyingpoint, DEADVERTEX);
08408   points->dealloc((void *) dyingpoint);
08409 }
08410 
08412 //                                                                           //
08413 // pointtraverse()    Traverse the points, skipping dead ones.               //
08414 //                                                                           //
08416 
08417 tetgenmesh::point tetgenmesh::pointtraverse()
08418 {
08419   point newpoint;
08420 
08421   do {
08422     newpoint = (point) points->traverse();
08423     if (newpoint == (point) NULL) {
08424       return (point) NULL;
08425     }
08426   } while (pointtype(newpoint) == DEADVERTEX);            // Skip dead ones.
08427   return newpoint;
08428 }
08429 
08431 //                                                                           //
08432 // maketetrahedron()    Create a new tetrahedron.                            //
08433 //                                                                           //
08435 
08436 void tetgenmesh::maketetrahedron(triface *newtet)
08437 {
08438   newtet->tet = (tetrahedron *) tetrahedrons->alloc();
08439   // Initialize the four adjoining tetrahedra to be "outer space".
08440   newtet->tet[0] = (tetrahedron) dummytet;
08441   newtet->tet[1] = (tetrahedron) dummytet;
08442   newtet->tet[2] = (tetrahedron) dummytet;
08443   newtet->tet[3] = (tetrahedron) dummytet;
08444   // Four NULL vertices.
08445   newtet->tet[4] = (tetrahedron) NULL;
08446   newtet->tet[5] = (tetrahedron) NULL;
08447   newtet->tet[6] = (tetrahedron) NULL;
08448   newtet->tet[7] = (tetrahedron) NULL;
08449   // Initialize the four adjoining subfaces to be the omnipresent subface.
08450   if (b->useshelles) {
08451     newtet->tet[8 ] = (tetrahedron) dummysh;
08452     newtet->tet[9 ] = (tetrahedron) dummysh;
08453     newtet->tet[10] = (tetrahedron) dummysh;
08454     newtet->tet[11] = (tetrahedron) dummysh;
08455     newtet->tet[12] = (tetrahedron) dummysh;
08456     newtet->tet[13] = (tetrahedron) dummysh;
08457   }
08458   for (int i = 0; i < in->numberoftetrahedronattributes; i++) {
08459     setelemattribute(newtet->tet, i, 0.0);
08460   }
08461   if (b->varvolume) {
08462     setvolumebound(newtet->tet, -1.0);
08463   }
08464   // Initialize the location and version to be Zero.
08465   newtet->loc = 0;
08466   newtet->ver = 0;
08467 }
08468 
08470 //                                                                           //
08471 // makeshellface()    Create a new shellface with version zero. Used for     //
08472 //                    both subfaces and seusegments.                         //
08473 //                                                                           //
08475 
08476 void tetgenmesh::makeshellface(memorypool *pool, face *newface)
08477 {
08478   newface->sh = (shellface *) pool->alloc();
08479   //Initialize the three adjoining subfaces to be the omnipresent subface.
08480   newface->sh[0] = (shellface) dummysh;
08481   newface->sh[1] = (shellface) dummysh;
08482   newface->sh[2] = (shellface) dummysh;
08483   // Three NULL vertices.
08484   newface->sh[3] = (shellface) NULL;
08485   newface->sh[4] = (shellface) NULL;
08486   newface->sh[5] = (shellface) NULL;
08487   // Initialize the two adjoining tetrahedra to be "outer space".
08488   newface->sh[6] = (shellface) dummytet;
08489   newface->sh[7] = (shellface) dummytet;
08490   // Initialize the three adjoining subsegments to be the omnipresent
08491   //   subsegments.
08492   newface->sh [8] = (shellface) dummysh;
08493   newface->sh [9] = (shellface) dummysh;
08494   newface->sh[10] = (shellface) dummysh;
08495   // Initialize the pointer to badface structure.
08496   newface->sh[11] = (shellface) NULL;
08497   if (b->quality && varconstraint) {
08498     // Initialize the maximum area bound.
08499     setareabound(*newface, 0.0);
08500   }
08501   // Set the boundary marker to zero.
08502   setshellmark(*newface, 0);
08503   // Set the type.
08504   setshelltype(*newface, NSHARP);
08505   if (checkpbcs) {
08506     // Set the pbcgroup be ivalid.
08507     setshellpbcgroup(*newface, -1);
08508   }
08509   // Initialize the version to be Zero.
08510   newface->shver = 0;
08511 }
08512 
08514 //                                                                           //
08515 // makepoint()    Create a new point.                                        //
08516 //                                                                           //
08518 
08519 void tetgenmesh::makepoint(point* pnewpoint)
08520 {
08521   int ptmark, i;
08522 
08523   *pnewpoint = (point) points->alloc();
08524   // Initialize three coordinates.
08525   (*pnewpoint)[0] = 0.0;
08526   (*pnewpoint)[1] = 0.0;
08527   (*pnewpoint)[2] = 0.0;
08528   // Initialize the list of user-defined attributes.
08529   for (i = 0; i < in->numberofpointattributes; i++) {
08530     (*pnewpoint)[3 + i] = 0.0;
08531   }
08532   // Initialize the metric tensor.
08533   for (i = 0; i < sizeoftensor; i++) {
08534     (*pnewpoint)[pointmtrindex + i] = 0.0;
08535   }
08536   if (b->plc || b->refine) {
08537     // Initialize the point-to-simplex filed.
08538     setpoint2tet(*pnewpoint, NULL);
08539     setpoint2sh(*pnewpoint, NULL);
08540     setpoint2ppt(*pnewpoint, NULL);
08541     if (b->metric) {
08542       setpoint2bgmtet(*pnewpoint, NULL);
08543     }
08544     if (checkpbcs) {
08545       // Initialize the other pointer to its pbc point.
08546       setpoint2pbcpt(*pnewpoint, NULL);
08547     }
08548   }
08549   // Initialize the point marker (starting from in->firstnumber).
08550   ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
08551   setpointmark(*pnewpoint, ptmark);
08552   // Initialize the point type.
08553   setpointtype(*pnewpoint, UNUSEDVERTEX);
08554 }
08555 
08556 //
08557 // End of memory management routines
08558 //
08559 
08560 //
08561 // Begin of point location routines
08562 //
08563 
08565 //                                                                           //
08566 // randomnation()    Generate a random number between 0 and 'choices' - 1.   //
08567 //                                                                           //
08569 
08570 unsigned long tetgenmesh::randomnation(unsigned int choices)
08571 {
08572   unsigned long newrandom;
08573 
08574   if (choices >= 714025l) {
08575     newrandom = (randomseed * 1366l + 150889l) % 714025l;
08576     randomseed = (newrandom * 1366l + 150889l) % 714025l;
08577     newrandom = newrandom * (choices / 714025l) + randomseed;
08578     if (newrandom >= choices) {
08579       return newrandom - choices;
08580     } else {
08581       return newrandom;
08582     }
08583   } else {
08584     randomseed = (randomseed * 1366l + 150889l) % 714025l;
08585     return randomseed % choices;
08586   }
08587   // Old function.
08588   // randomseed = (randomseed * 1366l + 150889l) % 714025l;
08589   // return randomseed / (714025l / choices + 1);
08590 }
08591 
08593 //                                                                           //
08594 // distance2()    Returns the square "distance" of a tetrahedron to point p. //
08595 //                                                                           //
08597 
08598 REAL tetgenmesh::distance2(tetrahedron* tetptr, point p)
08599 {
08600   point p1, p2, p3, p4;
08601   REAL dx, dy, dz;
08602 
08603   p1 = (point) tetptr[4];
08604   p2 = (point) tetptr[5];
08605   p3 = (point) tetptr[6];
08606   p4 = (point) tetptr[7];
08607 
08608   dx = p[0] - 0.25 * (p1[0] + p2[0] + p3[0] + p4[0]);
08609   dy = p[1] - 0.25 * (p1[1] + p2[1] + p3[1] + p4[1]);
08610   dz = p[2] - 0.25 * (p1[2] + p2[2] + p3[2] + p4[2]);
08611 
08612   return dx * dx + dy * dy + dz * dz;
08613 }
08614 
08616 //                                                                           //
08617 // preciselocate()    Find a simplex containing a given point.               //
08618 //                                                                           //
08619 // This routine implements the simple Walk-through point location algorithm. //
08620 // Begins its search from 'searchtet', assume there is a line segment L from //
08621 // a vertex of 'searchtet' to the query point 'searchpt', and simply walk    //
08622 // towards 'searchpt' by traversing all faces intersected by L.              //
08623 //                                                                           //
08624 // On completion, 'searchtet' is a tetrahedron that contains 'searchpt'. The //
08625 // returned value indicates one of the following cases:                      //
08626 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchtet' //
08627 //     is a handle whose origin is the existing vertex.                      //
08628 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchtet' is a    //
08629 //     handle whose primary edge is the edge on which the point lies.        //
08630 //   - Returns ONFACE if the point lies strictly within a face. 'searchtet'  //
08631 //     is a handle whose primary face is the face on which the point lies.   //
08632 //   - Returns INTETRAHEDRON if the point lies strictly in a tetrahededron.  //
08633 //     'searchtet' is a handle on the tetrahedron that contains the point.   //
08634 //   - Returns OUTSIDE if the point lies outside the mesh. 'searchtet' is a  //
08635 //     handle whose location is the face the point is to 'above' of.         //
08636 //                                                                           //
08637 // WARNING: This routine is designed for convex triangulations, and will not //
08638 // generally work after the holes and concavities have been carved.          //
08639 //                                                                           //
08640 // If 'maxtetnumber' > 0, stop the searching process if the number of passed //
08641 // tets is larger than it and return OUTSIDE.                                //
08642 //                                                                           //
08644 
08645 enum tetgenmesh::locateresult tetgenmesh::preciselocate(point searchpt,
08646   triface* searchtet, long maxtetnumber)
08647 {
08648   triface backtracetet;
08649   triface walkthroface;
08650   point forg, fdest, fapex, toppo;
08651   REAL ori1, ori2, ori3, ori4;
08652   long tetnumber;
08653   int side;
08654 
08655   if (isdead(searchtet)) searchtet->tet = dummytet;
08656   if (searchtet->tet == dummytet) {
08657     searchtet->loc = 0;
08658     symself(*searchtet);
08659   }
08660   // 'searchtet' should be a valid tetrahedron now.
08661 #ifdef SELF_CHECK
08662   // assert(!isdead(searchtet) && (searchtet->tet != dummytet));
08663 #endif
08664   if (isdead(searchtet)) {
08665     printf("Warning:  Point location failed.\n");
08666     return OUTSIDE;
08667   }
08668 
08669   searchtet->ver = 0; // Keep in CCW edge ring.
08670   // Find a face of 'searchtet' such that the 'searchpt' lies strictly
08671   //   above it.  Such face should always exist.
08672   for (searchtet->loc = 0; searchtet->loc < 4; searchtet->loc++) {
08673     forg = org(*searchtet);
08674     fdest = dest(*searchtet);
08675     fapex = apex(*searchtet);
08676     ori1 = orient3d(forg, fdest, fapex, searchpt);
08677     if (ori1 < 0.0) break;
08678   }
08679 #ifdef SELF_CHECK
08680   assert(searchtet->loc < 4);
08681 #endif
08682 
08683   // Define 'tetnumber' for exit the loop when it's running endless.
08684   tetnumber = 0l;
08685   while ((maxtetnumber > 0l) && (tetnumber <= maxtetnumber)) {
08686     // Check if we are reaching the boundary of the triangulation.
08687     if (searchtet->tet == dummytet) {
08688       *searchtet = backtracetet;
08689       return OUTSIDE;
08690     }
08691     // Initialize the face for returning the walk-through face.
08692     walkthroface.tet = (tetrahedron *) NULL;
08693     // Adjust the edge ring, so that 'ori1 < 0.0' holds.
08694     searchtet->ver = 0;
08695     // 'toppo' remains unchange for the following orientation tests.
08696     toppo = oppo(*searchtet);
08697     // Check the three sides of 'searchtet' to find the face through which
08698     //   we can walk next.
08699     for (side = 0; side < 3; side++) {
08700       forg = org(*searchtet);
08701       fdest = dest(*searchtet);
08702       ori2 = orient3d(forg, fdest, toppo, searchpt);
08703       if (ori2 == 0.0) {
08704         // They are coplanar, check if 'searchpt' lies inside, or on an edge,
08705         //   or coindice with a vertex of face (forg, fdest, toppo).
08706         fapex = apex(*searchtet);
08707         ori3 = orient3d(fdest, fapex, toppo, searchpt);
08708         if (ori3 < 0.0) {
08709           // Outside the face (fdest, fapex, toppo), walk through it.
08710           enextself(*searchtet);
08711           fnext(*searchtet, walkthroface);
08712           break;
08713         }
08714         ori4 = orient3d(fapex, forg, toppo, searchpt);
08715         if (ori4 < 0.0) {
08716           // Outside the face (fapex, forg, toppo), walk through it.
08717           enext2self(*searchtet);
08718           fnext(*searchtet, walkthroface);
08719           break;
08720         }
08721         // Remember, ori1 < 0.0, which means 'searchpt' will not on edge
08722         //   (forg, fdest) or on vertex forg or fdest.
08723 #ifdef SELF_CHECK
08724         assert(ori1 < 0.0);
08725 #endif
08726         // The rest possible cases are:
08727         //   (1) 'searchpt' lies on edge (fdest, toppo);
08728         //   (2) 'searchpt' lies on edge (toppo, forg);
08729         //   (3) 'searchpt' coincident with toppo;
08730         //   (4) 'searchpt' lies inside face (forg, fdest, toppo).
08731         fnextself(*searchtet);
08732         if (ori3 == 0.0) {
08733           if (ori4 == 0.0) {
08734             // Case (4).
08735             enext2self(*searchtet);
08736             return ONVERTEX;
08737           } else {
08738             // Case (1).
08739             enextself(*searchtet);
08740             return ONEDGE;
08741           }
08742         }
08743         if (ori4 == 0.0) {
08744           // Case (2).
08745           enext2self(*searchtet);
08746           return ONEDGE;
08747         }
08748         // Case (4).
08749         return ONFACE;
08750       } else if (ori2 < 0.0) {
08751         // Outside the face (forg, fdest, toppo), walk through it.
08752         fnext(*searchtet, walkthroface);
08753         break;
08754       }
08755       // Go to check next side.
08756       enextself(*searchtet);
08757     }
08758     if (side >= 3) {
08759       // Found! Inside tetrahedron.
08760       return INTETRAHEDRON;
08761     }
08762     // We walk through the face 'walkthroface' and continue the searching.
08763 #ifdef SELF_CHECK
08764     assert(walkthroface.tet != (tetrahedron *) NULL);
08765 #endif
08766     // Store the face handle in 'backtracetet' before we take the real walk.
08767     //   So we are able to restore the handle to 'searchtet' if we are
08768     //   reaching the outer boundary.
08769     backtracetet = walkthroface;
08770     sym(walkthroface, *searchtet);
08771     tetnumber++;
08772   }
08773 
08774   // Should never be here.
08775   // printf("Internal error in preciselocate(): Point location failed.\n");
08776   // internalerror();
08777   return OUTSIDE;
08778 }
08779 
08781 //                                                                           //
08782 // locate()    Find a simplex containing a given point.                      //
08783 //                                                                           //
08784 // This routine implements Muecke's Jump-and-walk point location algorithm.  //
08785 // It improves the simple walk-through by "jumping" to a good starting point //
08786 // via random sampling.  Searching begins from one of handles:  the input    //
08787 // 'searchtet', a recently encountered tetrahedron 'recenttet',  or from one //
08788 // chosen from a random sample.  The choice is made by determining which one //
08789 // 's barycenter is closest to the point we are searcing for.  Having chosen //
08790 // the starting tetrahedron, the simple Walk-through algorithm is used to do //
08791 // the real walking.                                                         //
08792 //                                                                           //
08793 // The return value indicates the location of the 'searchpt' (INTETRAHEDRON, //
08794 // or ONFACE, ...). 'searchtet' is adjusted to a tetrahedron corresponding   //
08795 // to that value. See the introduction part of preciselocate() for detail.   //
08796 //                                                                           //
08797 // WARNING: This routine is designed for convex triangulations, and will not //
08798 // generally work after the holes and concavities have been carved.          //
08799 //                                                                           //
08801 
08802 enum tetgenmesh::locateresult tetgenmesh::locate(point searchpt,
08803   triface *searchtet)
08804 {
08805   tetrahedron *firsttet, *tetptr;
08806   void **sampleblock;
08807   long sampleblocks, samplesperblock, samplenum;
08808   long tetblocks, i, j;
08809   unsigned long alignptr;
08810   REAL searchdist, dist;
08811 
08812   // 'searchtet' should be a valid tetrahedron.
08813   if (isdead(searchtet)) {
08814     searchtet->tet = dummytet;
08815   }
08816   if (searchtet->tet == dummytet) {
08817     // This is an 'Outer Space' handle, get a hull tetrahedron.
08818     searchtet->loc = 0;
08819     symself(*searchtet);
08820   }
08821 #ifdef SELF_CHECK
08822   // assert(!isdead(searchtet));
08823 #endif
08824   if (isdead(searchtet)) {
08825     printf("Warning:  Point location failed.\n");
08826     return OUTSIDE;
08827   }
08828 
08829   // Get the distance from the suggested starting tet to the point we seek.
08830   searchdist = distance2(searchtet->tet, searchpt);
08831 
08832   // If a recently encountered tetrahedron has been recorded and has not
08833   //   been deallocated, test it as a good starting point.
08834   if (!isdead(&recenttet) && (recenttet.tet != searchtet->tet)) {
08835     dist = distance2(recenttet.tet, searchpt);
08836     if (dist < searchdist) {
08837       *searchtet = recenttet;
08838       searchdist = dist;
08839     }
08840   }
08841 
08842   // Select "good" candidate using k random samples, taking the closest one.
08843   //   The number of random samples taken is proportional to the fourth root
08844   //   of the number of tetrahedra in the mesh. The next bit of code assumes
08845   //   that the number of tetrahedra increases monotonically.
08846   while (SAMPLEFACTOR * samples * samples * samples * samples <
08847          tetrahedrons->items) {
08848     samples++;
08849   }
08850   // Find how much blocks in current tet pool.
08851   tetblocks = (tetrahedrons->maxitems + ELEPERBLOCK - 1) / ELEPERBLOCK;
08852   // Find the average samles per block. Each block at least have 1 sample.
08853   samplesperblock = 1 + (samples / tetblocks);
08854   sampleblocks = samples / samplesperblock;
08855   sampleblock = tetrahedrons->firstblock;
08856   for (i = 0; i < sampleblocks; i++) {
08857     alignptr = (unsigned long) (sampleblock + 1);
08858     firsttet = (tetrahedron *)
08859                (alignptr + (unsigned long) tetrahedrons->alignbytes
08860                - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08861     for (j = 0; j < samplesperblock; j++) {
08862       if (i == tetblocks - 1) {
08863         // This is the last block.
08864         samplenum = randomnation((int)
08865                       (tetrahedrons->maxitems - (i * ELEPERBLOCK)));
08866       } else {
08867         samplenum = randomnation(ELEPERBLOCK);
08868       }
08869       tetptr = (tetrahedron *)
08870                (firsttet + (samplenum * tetrahedrons->itemwords));
08871       if (tetptr[4] != (tetrahedron) NULL) {
08872         dist = distance2(tetptr, searchpt);
08873         if (dist < searchdist) {
08874           searchtet->tet = tetptr;
08875           searchdist = dist;
08876         }
08877       }
08878     }
08879     sampleblock = (void **) *sampleblock;
08880   }
08881 
08882   // Call simple walk-through to locate the point.
08883   return preciselocate(searchpt, searchtet, tetrahedrons->items);
08884 }
08885 
08887 //                                                                           //
08888 // adjustlocate()    Adjust the precise location of a vertex.                //
08889 //                                                                           //
08890 // 'precise' is the value returned from preciselocate().  It indicates the   //
08891 // exact location of the point 'searchpt' with respect to the tetrahedron    //
08892 // 'searchtet'.  'epspp' is a given relative tolerance.                      //
08893 //                                                                           //
08894 // This routine re-evaluates the orientations of searchpt with respect to    //
08895 // the four sides of searchtet. Detects the coplanarities by additinal tests //
08896 // which are based on the given tolerance. If 'precise' is ONFACE or ONEDGE, //
08897 // we can save one or two orientation tests.                                 //
08898 //                                                                           //
08899 // The return value indicates the location of the 'searchpt' (INTETRAHEDRON, //
08900 // or ONFACE, ...). 'searchtet' is adjusted to a tetrahedron corresponding   //
08901 // to that value. See the introduction part of preciselocate() for detail.   //
08902 //                                                                           //
08903 // WARNING:  This routine detect degenerate case using relative tolerance.   //
08904 // It is better used after locate() or preciselocate().  For general inputs, //
08905 // it may not able to tell the correct location.                             //
08906 //                                                                           //
08908 
08909 enum tetgenmesh::locateresult tetgenmesh::adjustlocate(point searchpt,
08910   triface* searchtet, enum locateresult precise, REAL epspp)
08911 {
08912   point torg, tdest, tapex, toppo;
08913   REAL s1, s2, s3, s4;
08914 
08915   // For the given 'searchtet', the orientations tests are:
08916   //  s1: (tdest, torg, tapex, searchpt);
08917   //  s2: (torg, tdest, toppo, searchpt);
08918   //  s3: (tdest, tapex, toppo, searchpt);
08919   //  s4: (tapex, torg, toppo, searchpt);
08920   adjustedgering(*searchtet, CCW);
08921   torg = org(*searchtet);
08922   tdest = dest(*searchtet);
08923   tapex = apex(*searchtet);
08924   toppo = oppo(*searchtet);
08925 
08926   switch (precise) {
08927   case ONVERTEX:
08928     // This case we don't need do any further test.
08929     return ONVERTEX;
08930   case ONEDGE:
08931     // (torg, tdest);
08932     s1 = 0.0;
08933     s2 = 0.0;
08934     break;
08935   case ONFACE:
08936     // (tdest, torg, tapex);
08937     s1 = 0.0;
08938     s2 = orient3d(torg, tdest, toppo, searchpt);
08939     break;
08940   default: // INTETRAHEDRON or OUTSIDE
08941     s1 = orient3d(tdest, torg, tapex, searchpt);
08942     s2 = orient3d(torg, tdest, toppo, searchpt);
08943   }
08944 
08945   if (s1 != 0.0) {
08946     if (iscoplanar(tdest, torg, tapex, searchpt, s1, epspp)) {
08947       s1 = 0.0;
08948     }
08949   }
08950   if (s1 < 0.0) {
08951     return OUTSIDE;
08952   }
08953 
08954   if (s2 != 0.0) {
08955     if (iscoplanar(torg, tdest, toppo, searchpt, s2, epspp)) {
08956       s2 = 0.0;
08957     }
08958   }
08959   if (s2 < 0.0) {
08960     fnextself(*searchtet);
08961     return OUTSIDE;
08962   }
08963 
08964   s3 = orient3d(tdest, tapex, toppo, searchpt);
08965   if (s3 != 0.0) {
08966     if (iscoplanar(tdest, tapex, toppo, searchpt, s3, epspp)) {
08967       s3 = 0.0;
08968     }
08969   }
08970   if (s3 < 0.0) {
08971     enextfnextself(*searchtet);
08972     return OUTSIDE;
08973   }
08974 
08975   s4 = orient3d(tapex, torg, toppo, searchpt);
08976   if (s4 != 0.0) {
08977     if (iscoplanar(tapex, torg, toppo, searchpt, s4, epspp)) {
08978       s4 = 0.0;
08979     }
08980   }
08981   if (s4 < 0.0) {
08982     enext2fnextself(*searchtet);
08983     return OUTSIDE;
08984   }
08985 
08986   // Determine degenerate cases.
08987   if (s1 == 0.0) {
08988     if (s2 == 0.0) {
08989       if (s3 == 0.0) {
08990         // On tdest.
08991         enextself(*searchtet);
08992         return ONVERTEX;
08993       }
08994       if (s4 == 0.0) {
08995         // On torg.
08996         return ONVERTEX;
08997       }
08998       // On edge (torg, tdest).
08999       return ONEDGE;
09000     }
09001     if (s3 == 0.0) {
09002       if (s4 == 0.0) {
09003         // On tapex.
09004         enext2self(*searchtet);
09005         return ONVERTEX;
09006       }
09007       // On edge (tdest, tapex).
09008       enextself(*searchtet);
09009       return ONEDGE;
09010     }
09011     if (s4 == 0.0) {
09012       // On edge (tapex, torg).
09013       enext2self(*searchtet);
09014       return ONEDGE;
09015     }
09016     // On face (torg, tdest, tapex).
09017     return ONFACE;
09018   }
09019   if (s2 == 0.0) {
09020     fnextself(*searchtet);
09021     if (s3 == 0.0) {
09022       if (s4 == 0.0) {
09023         // On toppo.
09024         enext2self(*searchtet);
09025         return ONVERTEX;
09026       }
09027       // On edge (tdest, toppo).
09028       enextself(*searchtet);
09029       return ONEDGE;
09030     }
09031     if (s4 == 0.0) {
09032       // On edge (toppo, torg).
09033       enext2self(*searchtet);
09034       return ONEDGE;
09035     }
09036     // On face (torg, tdest, toppo).
09037     return ONFACE;
09038   }
09039   if (s3 == 0.0) {
09040     enextfnextself(*searchtet);
09041     if (s4 == 0.0) {
09042       // On edge (tapex, toppo).
09043       enextself(*searchtet);
09044       return ONEDGE;
09045     }
09046     // On face (tdest, tapex, toppo).
09047     return ONFACE;
09048   }
09049   if (s4 == 0.0) {
09050     enext2fnextself(*searchtet);
09051     // On face (tapex, torg, toppo).
09052     return ONFACE;
09053   }
09054 
09055   // Inside tetrahedron.
09056   return INTETRAHEDRON;
09057 }
09058 
09060 //                                                                           //
09061 // hullwalk()    Find a tetrahedron on the hull to continue search.          //
09062 //                                                                           //
09064 
09065 enum tetgenmesh::locateresult tetgenmesh::hullwalk(point searchpt,
09066   triface *hulltet)
09067 {
09068   list* travtetlist;
09069   triface travtet, neightet;
09070   point pa, pb, pc;
09071   enum locateresult loc;
09072   REAL ori;
09073   int i;
09074 
09075   travtetlist = new list(sizeof(triface), NULL, 256);
09076   travtet = *hulltet;
09077   infect(travtet);
09078   travtetlist->append(&travtet);
09079 
09080   loc = OUTSIDE;
09081   for (i = 0; i < travtetlist->len(); i++) {
09082     travtet = * (triface *)(* travtetlist)[i];
09083     // Choose the CCW-edgering in face.
09084     travtet.ver = 0;
09085     // Look for a side where pt lies below it.
09086     for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09087       pa = org(travtet);
09088       pb = dest(travtet);
09089       pc = apex(travtet);
09090       ori = orient3d(pa, pb, pc, searchpt);
09091       if (ori > 0.0) break;
09092     }
09093     // Is pt above all (or coplanar with some of) the four sides?
09094     if (travtet.loc == 4) {
09095       hulltet->tet = travtet.tet;
09096       loc = adjustlocate(searchpt, hulltet, INTETRAHEDRON, b->epsilon);
09097       assert(loc != OUTSIDE);
09098     } else { // ori > 0.0
09099       // pt is below (behind) this side. We want to walk through it.
09100       sym(travtet, neightet);
09101       if (neightet.tet == dummytet) {
09102         // This is a hull side. Is p approximately on this side.
09103         loc = adjustlocate(searchpt, &travtet, OUTSIDE, b->epsilon);
09104       }
09105       if (loc == OUTSIDE) {
09106         // Let's collect all the neighbors for next searching.
09107         for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09108           sym(travtet, neightet);
09109           if ((neightet.tet != dummytet) && !infected(neightet)) {
09110             // Neighbor exists and not visited.
09111             infect(neightet);
09112             travtetlist->append(&neightet);
09113           }
09114         } // for (travtet.loc = 0;
09115       } // if (loc == OUTSIDE)
09116     } // if (travtet.loc == 4)
09117     if (loc != OUTSIDE) break;
09118   } // for (i = 0; i < travtetlist->len(); i++)
09119 
09120   // Uninfect traversed tets.
09121   for (i = 0; i < travtetlist->len(); i++) {
09122     travtet = * (triface *)(* travtetlist)[i];
09123     uninfect(travtet);
09124   }
09125 
09126   delete travtetlist;
09127   return loc;
09128 }
09129 
09131 //                                                                           //
09132 // locatesub()    Find a point in the surface mesh of a facet.               //
09133 //                                                                           //
09134 // Searching begins from the input 'searchsh', it should be a handle on the  //
09135 // convex hull of the facet triangulation.                                   //
09136 //                                                                           //
09137 // If 'stopatseg' is nonzero, the search will stop if it tries to walk       //
09138 // through a subsegment, and will return OUTSIDE.                            //
09139 //                                                                           //
09140 // On completion, 'searchsh' is a subface that contains 'searchpt'.          //
09141 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchsh'  //
09142 //     is a handle whose origin is the existing vertex.                      //
09143 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchsh' is a     //
09144 //     handle whose primary edge is the edge on which the point lies.        //
09145 //   - Returns ONFACE if the point lies strictly within a subface.           //
09146 //     'searchsh' is a handle on which the point lies.                       //
09147 //   - Returns OUTSIDE if the point lies outside the triangulation.          //
09148 //                                                                           //
09149 // WARNING: This routine is designed for convex triangulations, and will not //
09150 // not generally work after the holes and concavities have been carved.      //
09151 //                                                                           //
09153 
09154 enum tetgenmesh::locateresult tetgenmesh::locatesub(point searchpt,
09155   face* searchsh, int stopatseg, REAL epspp)
09156 {
09157   face backtracksh, spinsh, checkedge;
09158   point forg, fdest, fapex;
09159   REAL orgori, destori;
09160   REAL ori, sign;
09161   int moveleft, i;
09162 
09163   if (searchsh->sh == dummysh) {
09164     searchsh->shver = 0;
09165     spivotself(*searchsh);
09166 #ifdef SELF_CHECK
09167     assert(searchsh->sh != dummysh);
09168 #endif
09169   }
09170   // Find the sign to simulate that abovepoint is 'above' the facet.
09171   adjustedgering(*searchsh, CCW);
09172   forg = sorg(*searchsh);
09173   fdest = sdest(*searchsh);
09174   fapex = sapex(*searchsh);
09175   ori = orient3d(forg, fdest, fapex, abovepoint);
09176   sign = ori > 0.0 ? -1 : 1;
09177 
09178   // Orient 'searchsh' so that 'searchpt' is below it (i.e., searchpt has
09179   //   CCW orientation with respect to searchsh in plane).  Such edge
09180   //   should always exist. Save it as (forg, fdest).
09181   for (i = 0; i < 3; i++) {
09182     forg = sorg(*searchsh);
09183     fdest = sdest(*searchsh);
09184     ori = orient3d(forg, fdest, abovepoint, searchpt) * sign;
09185     if (ori > 0.0) break;
09186     senextself(*searchsh);
09187   }
09188 #ifdef SELF_CHECK
09189   assert(i < 3);
09190 #endif
09191 
09192   while (1) {
09193     fapex = sapex(*searchsh);
09194     // Check whether the apex is the point we seek.
09195     if (fapex[0] == searchpt[0] && fapex[1] == searchpt[1] &&
09196         fapex[2] == searchpt[2]) {
09197       senext2self(*searchsh);
09198       return ONVERTEX;
09199     }
09200     // Does the point lie on the other side of the line defined by the
09201     //   triangle edge opposite the triangle's destination?
09202     destori = orient3d(forg, fapex, abovepoint, searchpt) * sign;
09203     if (epspp > 0.0) {
09204       if (iscoplanar(forg, fapex, abovepoint, searchpt, destori, epspp)) {
09205         destori = 0.0;
09206       }
09207     }
09208     // Does the point lie on the other side of the line defined by the
09209     //   triangle edge opposite the triangle's origin?
09210     orgori = orient3d(fapex, fdest, abovepoint, searchpt) * sign;
09211     if (epspp > 0.0) {
09212       if (iscoplanar(fapex, fdest, abovepoint, searchpt, orgori, epspp)) {
09213         orgori = 0.0;
09214       }
09215     }
09216     if (destori > 0.0) {
09217       moveleft = 1;
09218     } else {
09219       if (orgori > 0.0) {
09220         moveleft = 0;
09221       } else {
09222         // The point must be on the boundary of or inside this triangle.
09223         if (destori == 0.0) {
09224           senext2self(*searchsh);
09225           return ONEDGE;
09226         }
09227         if (orgori == 0.0) {
09228           senextself(*searchsh);
09229           return ONEDGE;
09230         }
09231         return ONFACE;
09232       }
09233     }
09234     // Move to another triangle.  Leave a trace `backtracksh' in case
09235     //   walking off a boundary of the triangulation.
09236     if (moveleft) {
09237       senext2(*searchsh, backtracksh);
09238       fdest = fapex;
09239     } else {
09240       senext(*searchsh, backtracksh);
09241       forg = fapex;
09242     }
09243     // Check if we meet a segment.
09244     sspivot(backtracksh, checkedge);
09245     if (checkedge.sh != dummysh) {
09246       if (stopatseg) {
09247         // The flag indicates we should not cross a segment. Stop.
09248         *searchsh = backtracksh;
09249         return OUTSIDE;
09250       }
09251       // Try to walk through a segment. We need to find a coplanar subface
09252       //   sharing this segment to get into.
09253       spinsh = backtracksh;
09254       do {
09255         spivotself(spinsh);
09256         if (spinsh.sh == backtracksh.sh) {
09257           // Turn back, no coplanar subface is found.
09258           break;
09259         }
09260         // Are they belong to the same facet.
09261         if (shellmark(spinsh) == shellmark(backtracksh)) {
09262           // Find a coplanar subface. Walk into it.
09263           *searchsh = spinsh;
09264           break;
09265         }
09266         // Are they (nearly) coplanar?
09267         ori = orient3d(forg, fdest, sapex(backtracksh), sapex(spinsh));
09268         if (iscoplanar(forg, fdest, sapex(backtracksh), sapex(spinsh), ori,
09269                        b->epsilon)) {
09270           // Find a coplanar subface. Walk into it.
09271           *searchsh = spinsh;
09272           break;
09273         }
09274       } while (spinsh.sh != backtracksh.sh);
09275     } else {
09276       spivot(backtracksh, *searchsh);
09277     }
09278     // Check for walking right out of the triangulation.
09279     if ((searchsh->sh == dummysh) || (searchsh->sh == backtracksh.sh)) {
09280       // Go back to the last triangle.
09281       *searchsh = backtracksh;
09282       return OUTSIDE;
09283     }
09284     // To keep the same orientation wrt abovepoint.
09285     if (sorg(*searchsh) != forg) sesymself(*searchsh);
09286 #ifdef SELF_CHECK
09287     assert((sorg(*searchsh) == forg) && (sdest(*searchsh) == fdest));
09288 #endif
09289   }
09290 }
09291 
09293 //                                                                           //
09294 // adjustlocatesub()    Adjust the precise location of a vertex.             //
09295 //                                                                           //
09296 // 'precise' is the precise location (returned from locatesub()) of 'searcht'//
09297 // with respect to 'searchsh'. 'epspp' is the given relative tolerance.      //
09298 //                                                                           //
09299 // This routine re-evaluates the orientations of 'searchpt' with respect to  //
09300 // the three edges of 'searchsh'. Detects the collinearities by additinal    //
09301 // tests based on the given tolerance. If 'precise' is ONEDGE, one can save  //
09302 // one orientation test for the current edge of 'searchsh'.                  //
09303 //                                                                           //
09304 // On completion, 'searchsh' is a subface contains 'searchpt'. The returned  //
09305 // value indicates one of the following cases:                               //
09306 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchsh'  //
09307 //     is a handle whose origin is the existing vertex.                      //
09308 //   - Returns ONEDGE if the point lies on a mesh edge.  'searchsh' is a     //
09309 //     handle whose primary edge is the edge on which the point lies.        //
09310 //   - Returns ONFACE if the point lies strictly within a subface.           //
09311 //     'searchsh' is a handle on which the point lies.                       //
09312 //   - Returns OUTSIDE if the point lies outside 'searchsh'.                 //
09313 //                                                                           //
09315 
09316 enum tetgenmesh::locateresult tetgenmesh::
09317 adjustlocatesub(point searchpt, face* searchsh, enum locateresult precise,
09318                 REAL epspp)
09319 {
09320   point pa, pb, pc;
09321   bool s1, s2, s3;
09322 
09323   pa = sorg(*searchsh);
09324   pb = sdest(*searchsh);
09325   pc = sapex(*searchsh);
09326 
09327   if (precise == ONEDGE) {
09328     s1 = true;
09329   } else {
09330     s1 = iscollinear(pa, pb, searchpt, epspp);
09331   }
09332   s2 = iscollinear(pb, pc, searchpt, epspp);
09333   s3 = iscollinear(pc, pa, searchpt, epspp);
09334   if (s1) {
09335     if (s2) {
09336       // on vertex pb.
09337 #ifdef SELF_CHECK
09338       assert(!s3);
09339 #endif
09340       senextself(*searchsh);
09341       return ONVERTEX;
09342     } else if (s3) {
09343       // on vertex pa.
09344       return ONVERTEX;
09345     } else {
09346       // on edge pa->pb.
09347       return ONEDGE;
09348     }
09349   } else if (s2) {
09350     if (s3) {
09351       // on vertex pc.
09352       senext2self(*searchsh);
09353       return ONVERTEX;
09354     } else {
09355       // on edge pb->pc.
09356       senextself(*searchsh);
09357       return ONEDGE;
09358     }
09359   } else if (s3) {
09360     // on edge pc->pa.
09361     senext2self(*searchsh);
09362     return ONEDGE;
09363   } else {
09364     return precise;
09365   }
09366 }
09367 
09369 //                                                                           //
09370 // locateseg()    Find a point in subsegments.                               //
09371 //                                                                           //
09372 // Searching begins from the input 'searchseg', it should be a subsegment of //
09373 // the whole segment.                                                        //
09374 //                                                                           //
09375 // On completion, 'searchseg' is a subsegment that contains 'searchpt'.      //
09376 //   - Returns ONVERTEX if the point lies on an existing vertex. 'searchseg' //
09377 //     is a handle whose origin is the existing vertex.                      //
09378 //   - Returns ONEDGE if the point lies inside 'searchseg'.                  //
09379 //   - Returns OUTSIDE if the point lies outside the segment.                //
09380 //                                                                           //
09382 
09383 enum tetgenmesh::locateresult tetgenmesh::
09384 locateseg(point searchpt, face* searchseg)
09385 {
09386   face backtraceseg;
09387   point pa, pb;
09388   REAL dx, dy, dz;
09389   int moveleft;
09390   int i;
09391 
09392   moveleft = 0;
09393   while (1) {
09394     searchseg->shver = 0;
09395     pa = sorg(*searchseg);
09396     pb = sdest(*searchseg);
09397     // Find the biggest difference in x, y, and z coordinates of a and b.
09398     dx = fabs(pb[0] - pa[0]);
09399     dy = fabs(pb[1] - pa[1]);
09400     dz = fabs(pb[2] - pa[2]);
09401     if (dx > dy) {
09402       if (dx > dz) {
09403         i = 0;
09404       } else {
09405         i = 2;
09406       }
09407     } else {
09408       if (dy > dz) {
09409         i = 1;
09410       } else {
09411         i = 2;
09412       }
09413     }
09414     if (pa[i] < pb[i]) {
09415       if (searchpt[i] < pa[i]) {
09416         moveleft = 1;
09417       } else if (searchpt[i] > pa[i]) {
09418         if (searchpt[i] < pb[i]) {
09419           return ONEDGE;
09420         } else if (searchpt[i] > pb[i]) {
09421           moveleft = 0;
09422         } else {
09423 #ifdef SELF_CHECK
09424           assert(searchpt[i] == pb[i]);
09425 #endif
09426           sesymself(*searchseg);
09427           return ONVERTEX;
09428         }
09429       } else {
09430 #ifdef SELF_CHECK
09431         assert(searchpt[i] == pa[i]);
09432 #endif
09433         return ONVERTEX;
09434       }
09435     } else if (pa[i] > pb[i]) {
09436       if (searchpt[i] < pb[i]) {
09437         moveleft = 0;
09438       } else if (searchpt[i] > pb[i]) {
09439         if (searchpt[i] < pa[i]) {
09440           return ONEDGE;
09441         } else if (searchpt[i] > pa[i]) {
09442           moveleft = 1;
09443         } else {
09444 #ifdef SELF_CHECK
09445           assert(searchpt[i] == pa[i]);
09446 #endif
09447           return ONVERTEX;
09448         }
09449       } else {
09450 #ifdef SELF_CHECK
09451         assert(searchpt[i] == pb[i]);
09452 #endif
09453         sesymself(*searchseg);
09454         return ONVERTEX;
09455       }
09456     }
09457     backtraceseg = *searchseg;
09458     if (moveleft) {
09459       senext2self(*searchseg);
09460     } else {
09461       senextself(*searchseg);
09462     }
09463     spivotself(*searchseg);
09464     if (searchseg->sh == dummysh) {
09465       *searchseg = backtraceseg;
09466       break;
09467     }
09468   }
09469 
09470   return OUTSIDE;
09471 }
09472 
09474 //                                                                           //
09475 // adjustlocateseg()    Adjust the precise location of a vertex on segment.  //
09476 //                                                                           //
09477 // 'searchpt' is either inside or ouside the segment 'searchseg'. It will be //
09478 // adjusted to on vertex if it is very close to an endpoint of 'searchseg'.  //
09479 // 'epspp' is the given relative tolerance.                                  //
09480 //                                                                           //
09482 
09483 enum tetgenmesh::locateresult tetgenmesh::
09484 adjustlocateseg(point searchpt, face* searchseg, enum locateresult precise,
09485                 REAL epspp)
09486 {
09487   point pa, pb;
09488   REAL L, d, r;
09489 
09490   pa = sorg(*searchseg);
09491   pb = sdest(*searchseg);
09492   L = distance(pa, pb);
09493 
09494   // Is searchpt approximate to pa?
09495   d = distance(pa, searchpt);
09496   r = d / L;
09497   if (r <= epspp) {
09498     return ONVERTEX;
09499   }
09500   // Is searchpt approximate to pb?
09501   d = distance(pb, searchpt);
09502   r = d / L;
09503   if (r <= epspp) {
09504     sesymself(*searchseg);
09505     return ONVERTEX;
09506   }
09507 
09508   return precise;
09509 }
09510 
09511 //
09512 // End of point location routines
09513 //
09514 
09515 //
09516 // Begin of mesh transformation routines
09517 //
09518 
09520 //                                                                           //
09521 // Flip operations                                                           //
09522 //                                                                           //
09523 // If abc is a hull face, it is unflipable, and is locally Delaunay.  In the //
09524 // following, we assume abc is an interior face, and the other tetrahedron   //
09525 // adjoining at abc is bace.                                                 //
09526 //                                                                           //
09527 // If the convex hull CH of the set {a, b, c, d, e} only has four vertices,  //
09528 // i.e., one vertex lies inside CH, then abc is unflipable, and is locally   //
09529 // Delaunay. If CH is the vertex set itself, we have the following cases to  //
09530 // determine whether abc is flipable or not.                                 //
09531 //                                                                           //
09532 // If no four points of {a, b, c, d, e} are coplanar, a 2-to-3 flip can be   //
09533 // applied to abc if the edge de crosses the triangle abc; a 3-to-2 flip can //
09534 // be applied to abc if ab crosses cde, and abde exists, otherwise, face abc //
09535 // is unflipable, i.e., the tetrahedron abde is not present.                 //
09536 //                                                                           //
09537 // If four points of {a, b, c, d, e} are coplanar (two faces are coplanar).  //
09538 // Assume faces abd and abe are coplanar (it is impossible be abc). If a, b, //
09539 // d, e form a non-convex quadrilateral, then abc is unflipable, furthermore,//
09540 // it is locally Delaunay.  Assume they are convex quadrilateral, if abd and //
09541 // abe are hull faces, a 2-to-2 flip can be applied to abc;  if abd and abe  //
09542 // are interior faces,  assume two tetrahedra adjoining abd and abe at the   //
09543 // opposite sides are abdg and abef, respectively.  If g = f, a 4-to-4 flip  //
09544 // can be applied to abc, otherwise, abc is unflipable.                      //
09545 //                                                                           //
09546 // There are other cases which can cause abc unflipable. If abc is a subface,//
09547 // a 2-to-3 flip is forbidden;  if ab is a subsegment, flips 3-to-2, 2-to-2, //
09548 // and 4-to-4 are forbidden.                                                 //
09549 //                                                                           //
09551 
09553 //                                                                           //
09554 // categorizeface()    Determine the flip type of a given face.              //
09555 //                                                                           //
09556 // On input, 'horiz' represents the face abc we want to flip (imagine it is  //
09557 // parallel to the horizon).  Let the tet above it be abcd.                  //
09558 //                                                                           //
09559 // This routine determines the suitable type of flip operation for 'horiz'.  //
09560 //   - Returns T23 if a 2-to-3 flip is applicable. 'horiz' is same as input. //
09561 //   - Returns T32 if a 3-to-2 flip is applicable. 'horiz' returns the edge  //
09562 //     of abc which is the flipable.                                         //
09563 //   - Returns T22 if a 2-to-2 or 4-to-4 flip is applicable. 'horiz' returns //
09564 //     the edge of abc which is flipable.                                    //
09565 //   - Returns N32 indicates it is unflipable due to the absence of a tet.   //
09566 //     'horize' returns the unflipable edge.                                 //
09567 //   - Returns N40 indicates it is unflipable and is locally Delaunay.       //
09568 //   - Returns FORBIDDENFACE indicates abc is a subface.                     //
09569 //   - Returns FORBIDDENEDGE indicates the flipable edge of abc is a segment.//
09570 //     'horize' returns the flipable edge.                                   //
09571 //                                                                           //
09572 // Given a face abc, with two adjoining tetrahedra abcd and bace.  If abc is //
09573 // flipable, i.e., T23, T32, T22 or T44, its flip type can be determined by  //
09574 // doing five orientation tests: two tests for determining that d, e lie on  //
09575 // the different sides of abc, three tests for determining if the edge de    //
09576 // intersects the face abc.  However, if we use the neighbor information of  //
09577 // the mesh data structure, we can reduce the five orientation tests to at   //
09578 // most three tests, that is, the two tests for determining whether d and e  //
09579 // lie on the different sides of abc can be saved.                           //
09580 //                                                                           //
09582 
09583 enum tetgenmesh::fliptype tetgenmesh::categorizeface(triface& horiz)
09584 {
09585   triface symhoriz, casing;
09586   face checksh, checkseg;
09587   face cassh1, cassh2;
09588   point pa, pb, pc, pd, pe, pf, pg;
09589   point abdoppo, bcdoppo, cadoppo;
09590   REAL ori1, ori2, ori3;
09591   int adjtet;
09592 
09593   sym(horiz, symhoriz);
09594   if (symhoriz.tet == dummytet) {
09595     // A hull face is unflipable and locally Delaunay.
09596     return N40;
09597   }
09598 
09599   adjustedgering(horiz, CCW);
09600   findedge(&symhoriz, dest(horiz), org(horiz));
09601   pa = org(horiz);
09602   pb = dest(horiz);
09603   pc = apex(horiz);
09604   pd = oppo(horiz);
09605   pe = oppo(symhoriz);
09606 
09607   // Find the number of adjacent tetrahedra of abc, which have d, e, and one
09608   //   of corners of abc as their corners. This number can be 0, 1 and 2.
09609   abdoppo = bcdoppo = cadoppo = (point) NULL;
09610   adjtet = 0;
09611   fnext(horiz, casing); // at edge 'ab'.
09612   symself(casing);
09613   if (casing.tet != dummytet) {
09614     abdoppo = oppo(casing);
09615     if (abdoppo == pe) adjtet++;
09616   }
09617   enextfnext(horiz, casing); // at edge 'bc'.
09618   symself(casing);
09619   if (casing.tet != dummytet) {
09620     bcdoppo = oppo(casing);
09621     if (bcdoppo == pe) adjtet++;
09622   }
09623   enext2fnext(horiz, casing); // at edge 'ca'.
09624   symself(casing);
09625   if (casing.tet != dummytet) {
09626     cadoppo = oppo(casing);
09627     if (cadoppo == pe) adjtet++;
09628   }
09629 
09630   if (adjtet == 0) {
09631     // No adjacent tetrahedron. Types T23, T22 and T44 are possible.
09632     ori1 = orient3d(pa, pb, pd, pe);
09633     if (checksubfaces && ori1 != 0.0) {
09634       // Check if abd and abe are both boundary faces?
09635       fnext(horiz, casing);
09636       tspivot(casing, cassh1);
09637       fnext(symhoriz, casing);
09638       tspivot(casing, cassh2);
09639       if ((cassh1.sh != dummysh) && (cassh2.sh != dummysh)) {
09640         // abd and abe are both boundary faces. Check if ab is a segment.
09641         findedge(&cassh1, pa, pb);
09642         sspivot(cassh1, checkseg);
09643         if (checkseg.sh == dummysh) {
09644           // ab is not a segment - abd and abe belong to the same facet.
09645           //   The four points are forced to be coplanar.
09646           ori1 = 0.0;
09647         } else {
09648           // ab is a segment - abd and abe belong to two different facets.
09649           //   In principle, a, b, c and d can form a tetrahedron (since
09650           //   ori1 != 0.0).  However, we should avoid to create a very
09651           //   flat one which may form a sequence of extremely badly-shaped
09652           //   or even wrong orientational tets. Test with a larger epsilon.
09653           if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09654         }
09655       } else {
09656         // abd and abe are not both boundary faces. Check if abd and bae
09657         //   are approximately coplanar with respect to the epsilon.
09658         if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon)) ori1 = 0.0;
09659       }
09660     }
09661     if (ori1 < 0.0) {
09662       // e lies above abd, unflipable, tet abde is not present.
09663 #ifdef SELF_CHECK
09664       if (!nonconvex) {
09665         // abd and abe should not be hull faces, check it.
09666         fnext(horiz, casing);
09667         symself(casing);
09668         assert(casing.tet != dummytet);
09669         fnext(symhoriz, casing);
09670         symself(casing);
09671         assert(casing.tet != dummytet);
09672       }
09673 #endif
09674       if (checksubfaces) {
09675         // The nonconvexbility may be casued by existing an subsegment.
09676         tsspivot(&horiz, &checkseg);
09677         if (checkseg.sh != dummysh) {
09678           return FORBIDDENEDGE;
09679         }
09680       }
09681       return N32;
09682     }
09683     ori2 = orient3d(pb, pc, pd, pe);
09684     if (checksubfaces && ori2 != 0.0) {
09685       // Check if bcd and cbe are both boundary faces.
09686       enextfnext(horiz, casing);
09687       tspivot(casing, cassh1);
09688       enext2fnext(symhoriz, casing);
09689       tspivot(casing, cassh2);
09690       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09691         // bcd and cbe are both boundary faces. Check if bc is a segment.
09692         findedge(&cassh1, pb, pc);
09693         sspivot(cassh1, checkseg);
09694         if (checkseg.sh == dummysh) {
09695           // bc is not a segment - bcd and cbe belong to the same facet.
09696           //   The four points are forced to be coplanar.
09697           ori2 = 0.0;
09698         } else {
09699           if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09700         }
09701       } else {
09702         //  bcd and cbe are not both boundary faces. Check if bcd and cbe
09703         //   are approximately coplanar with respect to the epsilon.
09704         if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon)) ori2 = 0.0;
09705       }
09706     }
09707     if (ori2 < 0.0) {
09708       // e lies above bcd, unflipable, tet bcde is not present.
09709 #ifdef SELF_CHECK
09710       if (!nonconvex) {
09711         // bcd and cbe should not be hull faces, check it.
09712         enextfnext(horiz, casing);
09713         symself(casing);
09714         assert(casing.tet != dummytet);
09715         enext2fnext(symhoriz, casing);
09716         symself(casing);
09717         assert(casing.tet != dummytet);
09718       }
09719 #endif
09720       enextself(horiz);
09721       if (checksubfaces) {
09722         // The nonconvexbility may be casued by existing an subsegment.
09723         tsspivot(&horiz, &checkseg);
09724         if (checkseg.sh != dummysh) {
09725           return FORBIDDENEDGE;
09726         }
09727       }
09728       return N32;
09729     }
09730     ori3 = orient3d(pc, pa, pd, pe);
09731     if (checksubfaces && ori3 != 0.0) {
09732       // Check if cad and ace are both boundary faces.
09733       enext2fnext(horiz, casing);
09734       tspivot(casing, cassh1);
09735       enextfnext(symhoriz, casing);
09736       tspivot(casing, cassh2);
09737       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09738         // cad and ace are both boundary faces. Check if ca is a segment.
09739         findedge(&cassh1, pc, pa);
09740         sspivot(cassh1, checkseg);
09741         if (checkseg.sh == dummysh) {
09742           // ca is not a segment - cad and ace belong to the same facet.
09743           //   The four points are forced to be coplanar.
09744           ori3 = 0.0;
09745         } else {
09746           // ca is a segment - cad and ace belong to two different facets.
09747           //   In principle, c, a, d and e can form a tetrahedron (since
09748           //   ori3 != 0.0). Use a larger eps to test if they're coplanar.
09749           if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon * 1e+2)) ori3 = 0.0;
09750         }
09751       } else {
09752         // cad and ace are not both boundary faces. Check if cad and ace
09753         //   are approximately coplanar with respect to the epsilon.
09754         if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon)) ori3 = 0.0;
09755       }
09756     }
09757     if (ori3 < 0.0) {
09758       // e lies above cad, unflipable, tet cade is not present.
09759 #ifdef SELF_CHECK
09760       if (!nonconvex) {
09761         // cad and ace should not be hull faces, check it.
09762         enext2fnext(horiz, casing);
09763         symself(casing);
09764         assert(casing.tet != dummytet);
09765         enextfnext(symhoriz, casing);
09766         symself(casing);
09767         assert(casing.tet != dummytet);
09768       }
09769 #endif
09770       enext2self(horiz);
09771       if (checksubfaces) {
09772         // The nonconvexbility may be casued by existing an subsegment.
09773         tsspivot(&horiz, &checkseg);
09774         if (checkseg.sh != dummysh) {
09775           return FORBIDDENEDGE;
09776         }
09777       }
09778       return N32;
09779     }
09780     if (ori1 == 0.0) {
09781       // e is coplanar with abd.
09782       if (ori2 * ori3 == 0.0) {
09783         // only one zero is possible.
09784         // assert(!(ori2 == 0.0 && ori3 == 0.0));
09785         // Three points (d, e, and a or b) are collinear, abc is unflipable
09786         //   and locally Delaunay.
09787         return N40;
09788       }
09789     } else if (ori2 == 0.0) {
09790       // e is coplanar with bcd.
09791       if (ori1 * ori3 == 0.0) {
09792         // only one zero is possible.
09793         // assert(!(ori1 == 0.0 && ori3 == 0.0));
09794         // Three points (d, e, and b or c) are collinear, abc is unflipable
09795         //   and locally Delaunay.
09796         return N40;
09797       }
09798       // Adjust 'horiz' and 'symhoriz' be the edge bc.
09799       enextself(horiz);
09800       enext2self(symhoriz);
09801     } else if (ori3 == 0.0) {
09802       // e is coplanar with cad.
09803       if (ori1 * ori2 == 0.0) {
09804         // only one zero is possible.
09805         // assert(!(ori1 == 0.0 && ori2 == 0.0));
09806         // Three points (d, e, and c or a) are collinear, abc is unflipable
09807         //   and locally Delaunay.
09808         return N40;
09809       }
09810       // Adjust 'horiz' and 'symhoriz' be the edge ca.
09811       enext2self(horiz);
09812       enextself(symhoriz);
09813     } else {
09814       // e lies below all three faces, flipable.
09815       if (checksubfaces) {
09816         tspivot(horiz, checksh);
09817         if (checksh.sh != dummysh) {
09818           // To flip a subface is forbidden.
09819           return FORBIDDENFACE;
09820         }
09821       }
09822       return T23;
09823     }
09824     // Four points are coplanar, T22 or T44 is possible.
09825     if (checksubfaces) {
09826       tsspivot(&horiz, &checkseg);
09827       if (checkseg.sh != dummysh) {
09828         // To flip a subsegment is forbidden.
09829         return FORBIDDENEDGE;
09830       }
09831       tspivot(horiz, checksh);
09832       if (checksh.sh != dummysh) {
09833         // To flip a subface is forbidden.
09834         return FORBIDDENFACE;
09835       }
09836     }
09837     // Assume the four coplanar points are a, b, d, e, abd and abe are two
09838     //   coplanar faces. If both abd and abe are hull faces, flipable(T22).
09839     //   If they are interior faces, get the opposite tetrahedra abdf and
09840     //   abeg, if f = g, flipable (T44). Otherwise, unflipable.
09841     pf = pg = (point) NULL;
09842     fnext(horiz, casing);
09843     symself(casing);
09844     if (casing.tet != dummytet) {
09845       pf = oppo(casing);
09846     }
09847     fnext(symhoriz, casing);
09848     symself(casing);
09849     if (casing.tet != dummytet) {
09850       pg = oppo(casing);
09851     }
09852     if (pf == pg) {
09853       // Either T22 (pf == pg == NULL) or T44 (pf and pg) is possible.
09854       if (checksubfaces) {
09855         // Retreat the corner points a, b, and c.
09856         pa = org(horiz);
09857         pb = dest(horiz);
09858         pc = apex(horiz);
09859         // Be careful not to create an inverted tetrahedron. Check the case.
09860         ori1 = orient3d(pc, pd, pe, pa);
09861         if (ori1 <= 0) return N40;
09862         ori1 = orient3d(pd, pc, pe, pb);
09863         if (ori1 <= 0) return N40;
09864         if (pf != (point) NULL) {
09865           ori1 = orient3d(pd, pf, pe, pa);
09866           if (ori1 <= 0) return N40;
09867           ori1 = orient3d(pf, pd, pe, pb);
09868           if (ori1 <= 0) return N40;
09869         }
09870       }
09871       if (pf == (point) NULL) {
09872         // abd and abe are hull faces, flipable.
09873         return T22;
09874       } else {
09875         // abd and abe are interior faces, flipable.
09876 #ifdef SELF_CHECK
09877         assert(pf != (point) NULL);
09878 #endif
09879         return T44;
09880       }
09881     } else {
09882       // ab has more than four faces around it, unflipable.
09883       return N32;
09884     }
09885   } else if (adjtet == 1) {
09886     // One of its three edges is locally non-convex. Type T32 is possible.
09887     // Adjust current configuration so that edge ab is non-convex.
09888     if (bcdoppo == pe) {
09889       // Edge bc is non-convex. Adjust 'horiz' and 'symhoriz' be edge bc.
09890       enextself(horiz);
09891       enext2self(symhoriz);
09892       pa = org(horiz);
09893       pb = dest(horiz);
09894       pc = apex(horiz);
09895     } else if (cadoppo == pe) {
09896       // Edge ca is non-convex. Adjust 'horiz' and 'symhoriz' be edge ca.
09897       enext2self(horiz);
09898       enextself(symhoriz);
09899       pa = org(horiz);
09900       pb = dest(horiz);
09901       pc = apex(horiz);
09902     } else {
09903       // Edge ab is non-convex.
09904 #ifdef SELF_CHECK
09905       assert(abdoppo == pe);
09906 #endif
09907     } // Now ab is the non-convex edge.
09908     // In order to be flipable, ab should cross face cde. Check it.
09909     ori1 = orient3d(pc, pd, pe, pa);
09910     if (checksubfaces && ori1 != 0.0) {
09911       // Check if cad and ace are both boundary faces.
09912       enext2fnext(horiz, casing);
09913       tspivot(casing, cassh1);
09914       enextfnext(symhoriz, casing);
09915       tspivot(casing, cassh2);
09916       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09917         // cad and ace are both boundary faces. Check if ca is a segment.
09918         findedge(&cassh1, pc, pa);
09919         sspivot(cassh1, checkseg);
09920         if (checkseg.sh == dummysh) {
09921           // ca is not a segment. cad and ace belong to the same facet.
09922           //   The four points are forced to be coplanar.
09923           ori1 = 0.0;
09924         } else {
09925           // ca is a segment. cad and ace belong to different facets.
09926           //   In principle, c, d, e, and a can form a tetrahedron (since
09927           //   ori1 != 0.0).  However, we should avoid to create a very
09928           //   flat tet. Use a larger epsilon to test if they're coplanar.
09929           if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09930         }
09931       } else {
09932         // Check if c, d, e, and a are approximately coplanar.
09933         if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon)) ori1 = 0.0;
09934       }
09935     }
09936     if (ori1 <= 0.0) {
09937       // a lies above or is coplanar cde, abc is locally Delaunay.
09938       return N40;
09939     }
09940     ori2 = orient3d(pd, pc, pe, pb);
09941     if (checksubfaces && ori2 != 0.0) {
09942       // Check if bcd and cbe are both boundary faces.
09943       enextfnext(horiz, casing);
09944       tspivot(casing, cassh1);
09945       enext2fnext(symhoriz, casing);
09946       tspivot(casing, cassh2);
09947       if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09948         // bcd and cbe are both boundary faces. Check if bc is a segment.
09949         findedge(&cassh1, pb, pc);
09950         sspivot(cassh1, checkseg);
09951         if (checkseg.sh == dummysh) {
09952           // bc is not a segment. bcd and cbe belong to the same facet.
09953           //   The four points are forced to be coplanar.
09954           ori2 = 0.0;
09955         } else {
09956           // bc is a segment. bcd and cbe belong to different facets.
09957           //   In principle, d, c, e, and b can form a tetrahedron (since
09958           //   ori2 != 0.0).  However, we should avoid to create a very
09959           //   flat tet. Use a larger epsilon to test if they're coplanar.
09960           if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09961         }
09962       } else {
09963         // Check if d, c, e, and b are approximately coplanar.
09964         if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon)) ori2 = 0.0;
09965       }
09966     }
09967     if (ori2 <= 0.0) {
09968       // b lies above dce, unflipable, and abc is locally Delaunay.
09969       return N40;
09970     }
09971     // Edge ab crosses face cde properly.
09972     if (checksubfaces) {
09973       // If abc is subface, then ab must be a subsegment (because abde is
09974       //   a tetrahedron and ab crosses cde properly).
09975       tsspivot(&horiz, &checkseg);
09976       if (checkseg.sh != dummysh) {
09977         // To flip a subsegment is forbidden.
09978         return FORBIDDENEDGE;
09979       }
09980       // Both abd and bae should not be subfaces (because they're not
09981       //   coplanar and ab is not a subsegment). However, they may be
09982       //   subfaces and belong to a facet (created during facet recovery),
09983       //   that is, abde is an invalid tetrahedron. Find this case out.
09984       fnext(horiz, casing);
09985       tspivot(casing, cassh1);
09986       fnext(symhoriz, casing);
09987       tspivot(casing, cassh2);
09988       if (cassh1.sh != dummysh || cassh2.sh != dummysh) {
09989         if (!b->quiet) {
09990           // Unfortunately, they're subfaces. Corrections need be done here.
09991           printf("Warning:  A tetrahedron spans two subfaces of a facet.\n");
09992         }
09993         // Temporarily, let it be there.
09994         return N32;
09995       }
09996     }
09997     return T32;
09998   } else {
09999     // The convex hull of {a, b, c, d, e} has only four vertices, abc is
10000     //   unflipable, furthermore, it is locally Delaunay.
10001     return N40;
10002   }
10003 }
10004 
10006 //                                                                           //
10007 // enqueueflipface(), enqueueflipedge()    Queue a face (or an edge).        //
10008 //                                                                           //
10009 // The face (or edge) may be non-locally Delaunay. It is queued for process- //
10010 // ing in flip() (or flipsub()). The vertices of the face (edge) are stored  //
10011 // seperatly to ensure the face (or edge) is still the same one when we save //
10012 // it since other flips will cause this face (or edge) be changed or dead.   //
10013 //                                                                           //
10015 
10016 void tetgenmesh::enqueueflipface(triface& checkface, queue* flipqueue)
10017 {
10018   badface *queface;
10019   triface symface;
10020 
10021   sym(checkface, symface);
10022   if (symface.tet != dummytet) {
10023     queface = (badface *) flipqueue->push((void *) NULL);
10024     queface->tt = checkface;
10025     queface->foppo = oppo(symface);
10026   }
10027 }
10028 
10029 void tetgenmesh::enqueueflipedge(face& checkedge, queue* flipqueue)
10030 {
10031   badface *queface;
10032 
10033   queface = (badface *) flipqueue->push((void *) NULL);
10034   queface->ss = checkedge;
10035   queface->forg = sorg(checkedge);
10036   queface->fdest = sdest(checkedge);
10037 }
10038 
10040 //                                                                           //
10041 // flip23()    Perform a 2-to-3 flip.                                        //
10042 //                                                                           //
10043 // On input, 'flipface' represents the face will be flipped.  Let it is abc, //
10044 // the two tetrahedra sharing abc are abcd, bace. abc is not a subface.      //
10045 //                                                                           //
10046 // A 2-to-3 flip is to change two tetrahedra abcd, bace to three tetrahedra  //
10047 // edab, edbc, and edca.  As a result, face abc has been removed and three   //
10048 // new faces eda, edb and edc have been created.                             //
10049 //                                                                           //
10050 // On completion, 'flipface' returns edab.  If 'flipqueue' is not NULL, all  //
10051 // possibly non-Delaunay faces are added into it.                            //
10052 //                                                                           //
10054 
10055 void tetgenmesh::flip23(triface* flipface, queue* flipqueue)
10056 {
10057   triface abcd, bace;                                  // Old configuration.
10058   triface oldabd, oldbcd, oldcad;
10059   triface abdcasing, bcdcasing, cadcasing;
10060   triface oldbae, oldcbe, oldace;
10061   triface baecasing, cbecasing, acecasing;
10062   triface worktet;
10063   face abdsh, bcdsh, cadsh;                   // The six subfaces on the CH.
10064   face baesh, cbesh, acesh;
10065   face abseg, bcseg, caseg;                      // The nine segs on the CH.
10066   face adseg, bdseg, cdseg;
10067   face aeseg, beseg, ceseg;
10068   triface edab, edbc, edca;                            // New configuration.
10069   point pa, pb, pc, pd, pe;
10070   REAL attrib, volume;
10071   int i;
10072 
10073   abcd = *flipface;
10074   adjustedgering(abcd, CCW); // abcd represents edge ab.
10075   pa = org(abcd);
10076   pb = dest(abcd);
10077   pc = apex(abcd);
10078   pd = oppo(abcd);
10079   // sym(abcd, bace);
10080   // findedge(&bace, dest(abcd), org(abcd)); // bace represents edge ba.
10081   sym(abcd, bace);
10082   bace.ver = 0; // CCW.
10083   for (i = 0; (i < 3) && (org(bace) != pb); i++) {
10084     enextself(bace);
10085   }
10086   pe = oppo(bace);
10087 
10088   if (b->verbose > 2) {
10089     printf("    Do T23 on face (%d, %d, %d) %d, %d.\n", pointmark(pa),
10090            pointmark(pb), pointmark(pc), pointmark(pd), pointmark(pe));
10091   }
10092   flip23s++;
10093 
10094   // Storing the old configuration outside the convex hull.
10095   fnext(abcd, oldabd);
10096   enextfnext(abcd, oldbcd);
10097   enext2fnext(abcd, oldcad);
10098   fnext(bace, oldbae);
10099   enext2fnext(bace, oldcbe);
10100   enextfnext(bace, oldace);
10101   sym(oldabd, abdcasing);
10102   sym(oldbcd, bcdcasing);
10103   sym(oldcad, cadcasing);
10104   sym(oldbae, baecasing);
10105   sym(oldcbe, cbecasing);
10106   sym(oldace, acecasing);
10107   if (checksubfaces) {
10108     tspivot(oldabd, abdsh);
10109     tspivot(oldbcd, bcdsh);
10110     tspivot(oldcad, cadsh);
10111     tspivot(oldbae, baesh);
10112     tspivot(oldcbe, cbesh);
10113     tspivot(oldace, acesh);
10114   } else if (checksubsegs) {
10115     tsspivot1(abcd, abseg);
10116     enext(abcd, worktet);
10117     tsspivot1(worktet, bcseg);
10118     enext2(abcd, worktet);
10119     tsspivot1(worktet, caseg);
10120     enext2(oldabd, worktet);
10121     tsspivot1(worktet, adseg);
10122     enext2(oldbcd, worktet);
10123     tsspivot1(worktet, bdseg);
10124     enext2(oldcad, worktet);
10125     tsspivot1(worktet, cdseg);
10126     enext(oldbae, worktet);
10127     tsspivot1(worktet, aeseg);
10128     enext(oldcbe, worktet);
10129     tsspivot1(worktet, beseg);
10130     enext(oldace, worktet);
10131     tsspivot1(worktet, ceseg);
10132   }
10133 
10134   // Creating the new configuration inside the convex hull.
10135   edab.tet = abcd.tet; // Update abcd to be edab.
10136   setorg (edab, pe);
10137   setdest(edab, pd);
10138   setapex(edab, pa);
10139   setoppo(edab, pb);
10140   edbc.tet = bace.tet; // Update bace to be edbc.
10141   setorg (edbc, pe);
10142   setdest(edbc, pd);
10143   setapex(edbc, pb);
10144   setoppo(edbc, pc);
10145   maketetrahedron(&edca); // Create edca.
10146   setorg (edca, pe);
10147   setdest(edca, pd);
10148   setapex(edca, pc);
10149   setoppo(edca, pa);
10150   // Set the element attributes of the new tetrahedron 'edca'.
10151   for (i = 0; i < in->numberoftetrahedronattributes; i++) {
10152     attrib = elemattribute(abcd.tet, i);
10153     setelemattribute(edca.tet, i, attrib);
10154   }
10155   // Set the volume constraint of the new tetrahedron 'edca' if the -ra
10156   //   switches are not used together. In -ra case, the various volume
10157   //   constraints can be spreaded very far.
10158   if (b->varvolume && !b->refine) {
10159     volume = volumebound(abcd.tet);
10160     setvolumebound(edca.tet, volume);
10161   }
10162 
10163   // Clear old bonds in edab(was abcd) and edbc(was bace).
10164   for (i = 0; i < 4; i ++) {
10165     edab.tet[i] = (tetrahedron) dummytet;
10166   }
10167   for (i = 0; i < 4; i ++) {
10168     edbc.tet[i] = (tetrahedron) dummytet;
10169   }
10170   // Bond the faces inside the convex hull.
10171   edab.loc = 0;
10172   edca.loc = 1;
10173   bond(edab, edca);
10174   edab.loc = 1;
10175   edbc.loc = 0;
10176   bond(edab, edbc);
10177   edbc.loc = 1;
10178   edca.loc = 0;
10179   bond(edbc, edca);
10180   // Bond the faces on the convex hull.
10181   edab.loc = 2;
10182   bond(edab, abdcasing);
10183   edab.loc = 3;
10184   bond(edab, baecasing);
10185   edbc.loc = 2;
10186   bond(edbc, bcdcasing);
10187   edbc.loc = 3;
10188   bond(edbc, cbecasing);
10189   edca.loc = 2;
10190   bond(edca, cadcasing);
10191   edca.loc = 3;
10192   bond(edca, acecasing);
10193   // There may exist subfaces that need to be bonded to new configuarton.
10194   if (checksubfaces) {
10195     // Clear old flags in edab(was abcd) and edbc(was bace).
10196     for (i = 0; i < 4; i ++) {
10197       edab.loc = i;
10198       tsdissolve(edab);
10199       edbc.loc = i;
10200       tsdissolve(edbc);
10201     }
10202     if (abdsh.sh != dummysh) {
10203       edab.loc = 2;
10204       tsbond(edab, abdsh);
10205     }
10206     if (baesh.sh != dummysh) {
10207       edab.loc = 3;
10208       tsbond(edab, baesh);
10209     }
10210     if (bcdsh.sh != dummysh) {
10211       edbc.loc = 2;
10212       tsbond(edbc, bcdsh);
10213     }
10214     if (cbesh.sh != dummysh) {
10215       edbc.loc = 3;
10216       tsbond(edbc, cbesh);
10217     }
10218     if (cadsh.sh != dummysh) {
10219       edca.loc = 2;
10220       tsbond(edca, cadsh);
10221     }
10222     if (acesh.sh != dummysh) {
10223       edca.loc = 3;
10224       tsbond(edca, acesh);
10225     }
10226   } else if (checksubsegs) {
10227     for (i = 0; i < 6; i++) {
10228       edab.tet[8 + i] = (tetrahedron) dummysh;
10229     }
10230     for (i = 0; i < 6; i++) {
10231       edbc.tet[8 + i] = (tetrahedron) dummysh;
10232     }
10233     edab.loc = edab.ver = 0;
10234     edbc.loc = edab.ver = 0;
10235     edca.loc = edab.ver = 0;
10236     // Operate in tet edab (5 edges).
10237     enext(edab, worktet);
10238     tssbond1(worktet, adseg);
10239     enext2(edab, worktet);
10240     tssbond1(worktet, aeseg);
10241     fnext(edab, worktet);
10242     enextself(worktet);
10243     tssbond1(worktet, bdseg);
10244     enextself(worktet);
10245     tssbond1(worktet, beseg);
10246     enextfnext(edab, worktet);
10247     enextself(worktet);
10248     tssbond1(worktet, abseg);
10249     // Operate in tet edbc (5 edges)
10250     enext(edbc, worktet);
10251     tssbond1(worktet, bdseg);
10252     enext2(edbc, worktet);
10253     tssbond1(worktet, beseg);
10254     fnext(edbc, worktet);
10255     enextself(worktet);
10256     tssbond1(worktet, cdseg);
10257     enextself(worktet);
10258     tssbond1(worktet, ceseg);
10259     enextfnext(edbc, worktet);
10260     enextself(worktet);
10261     tssbond1(worktet, bcseg);
10262     // Operate in tet edca (5 edges)
10263     enext(edca, worktet);
10264     tssbond1(worktet, cdseg);
10265     enext2(edca, worktet);
10266     tssbond1(worktet, ceseg);
10267     fnext(edca, worktet);
10268     enextself(worktet);
10269     tssbond1(worktet, adseg);
10270     enextself(worktet);
10271     tssbond1(worktet, aeseg);
10272     enextfnext(edca, worktet);
10273     enextself(worktet);
10274     tssbond1(worktet, caseg);
10275   }
10276 
10277   edab.loc = 0;
10278   edbc.loc = 0;
10279   edca.loc = 0;
10280   if (b->verbose > 3) {
10281     printf("    Updating edab ");
10282     printtet(&edab);
10283     printf("    Updating edbc ");
10284     printtet(&edbc);
10285     printf("    Creating edca ");
10286     printtet(&edca);
10287   }
10288 
10289   if (flipqueue != (queue *) NULL) {
10290     enextfnext(edab, abdcasing);
10291     enqueueflipface(abdcasing, flipqueue);
10292     enext2fnext(edab, baecasing);
10293     enqueueflipface(baecasing, flipqueue);
10294     enextfnext(edbc, bcdcasing);
10295     enqueueflipface(bcdcasing, flipqueue);
10296     enext2fnext(edbc, cbecasing);
10297     enqueueflipface(cbecasing, flipqueue);
10298     enextfnext(edca, cadcasing);
10299     enqueueflipface(cadcasing, flipqueue);
10300     enext2fnext(edca, acecasing);
10301     enqueueflipface(acecasing, flipqueue);
10302   }
10303 
10304   // Save a live handle in 'recenttet'.
10305   recenttet = edbc;
10306   // Set the return handle be edab.
10307   *flipface = edab;
10308 }
10309 
10311 //                                                                           //
10312 // flip32()    Perform a 3-to-2 flip.                                        //
10313 //                                                                           //
10314 // On input, 'flipface' represents the face will be flipped.  Let it is eda, //
10315 // where edge ed is locally non-convex. Three tetrahedra sharing ed are edab,//
10316 // edbc, and edca.  ed is not a subsegment.                                  //
10317 //                                                                           //
10318 // A 3-to-2 flip is to change the three tetrahedra edab, edbc, and edca into //
10319 // another two tetrahedra abcd and bace.  As a result, the edge ed has been  //
10320 // removed and the face abc has been created.                                //
10321 //                                                                           //
10322 // On completion, 'flipface' returns abcd.  If 'flipqueue' is not NULL, all  //
10323 // possibly non-Delaunay faces are added into it.                            //
10324 //                                                                           //
10326 
10327 void tetgenmesh::flip32(triface* flipface, queue* flipqueue)
10328 {
10329   triface edab, edbc, edca;                            // Old configuration.
10330   triface oldabd, oldbcd, oldcad;
10331   triface abdcasing, bcdcasing, cadcasing;
10332   triface oldbae, oldcbe, oldace;
10333   triface baecasing, cbecasing, acecasing;
10334   triface worktet;
10335   face abdsh, bcdsh, cadsh;
10336   face baesh, cbesh, acesh;
10337   face abseg, bcseg, caseg;                      // The nine segs on the CH.
10338   face adseg, bdseg, cdseg;
10339   face aeseg, beseg, ceseg;
10340   triface abcd, bace;                                  // New configuration.
10341   point pa, pb, pc, pd, pe;
10342   int i;
10343 
10344   edab = *flipface;
10345   adjustedgering(edab, CCW);
10346   pa = apex(edab);
10347   pb = oppo(edab);
10348   pd = dest(edab);
10349   pe = org(edab);
10350   fnext(edab, edbc);
10351   symself(edbc);
10352   edbc.ver = 0;
10353   for (i = 0; (i < 3) && (org(edbc) != pe); i++) {
10354     enextself(edbc);
10355   }
10356   pc = oppo(edbc);
10357   fnext(edbc, edca);
10358   symself(edca);
10359   edca.ver = 0;
10360   for (i = 0; (i < 3) && (org(edca) != pe); i++) {
10361     enextself(edca);
10362   }
10363 
10364   if (b->verbose > 2) {
10365     printf("    Do T32 on edge (%d, %d) %d, %d, %d.\n", pointmark(pe),
10366            pointmark(pd), pointmark(pa), pointmark(pb), pointmark(pc));
10367   }
10368   flip32s++;
10369 
10370   // Storing the old configuration outside the convex hull.
10371   enextfnext(edab, oldabd);
10372   enext2fnext(edab, oldbae);
10373   enextfnext(edbc, oldbcd);
10374   enext2fnext(edbc, oldcbe);
10375   enextfnext(edca, oldcad);
10376   enext2fnext(edca, oldace);
10377   sym(oldabd, abdcasing);
10378   sym(oldbcd, bcdcasing);
10379   sym(oldcad, cadcasing);
10380   sym(oldbae, baecasing);
10381   sym(oldcbe, cbecasing);
10382   sym(oldace, acecasing);
10383   if (checksubfaces) {
10384     tspivot(oldabd, abdsh);
10385     tspivot(oldbcd, bcdsh);
10386     tspivot(oldcad, cadsh);
10387     tspivot(oldbae, baesh);
10388     tspivot(oldcbe, cbesh);
10389     tspivot(oldace, acesh);
10390   } else if (checksubsegs) {
10391     enext(edab, worktet);
10392     tsspivot1(worktet, adseg);
10393     enext2(edab, worktet);
10394     tsspivot1(worktet, aeseg);
10395     enext(edbc, worktet);
10396     tsspivot1(worktet, bdseg);
10397     enext2(edbc, worktet);
10398     tsspivot1(worktet, beseg);
10399     enext(edca, worktet);
10400     tsspivot1(worktet, cdseg);
10401     enext2(edca, worktet);
10402     tsspivot1(worktet, ceseg);
10403     enextfnext(edab, worktet);
10404     enextself(worktet);
10405     tsspivot1(worktet, abseg);
10406     enextfnext(edbc, worktet);
10407     enextself(worktet);
10408     tsspivot1(worktet, bcseg);
10409     enextfnext(edca, worktet);
10410     enextself(worktet);
10411     tsspivot1(worktet, caseg);
10412   }
10413 
10414   // Creating the new configuration inside the convex hull.
10415   abcd.tet = edab.tet; // Update edab to be abcd.
10416   setorg (abcd, pa);
10417   setdest(abcd, pb);
10418   setapex(abcd, pc);
10419   setoppo(abcd, pd);
10420   bace.tet = edbc.tet; // Update edbc to be bace.
10421   setorg (bace, pb);
10422   setdest(bace, pa);
10423   setapex(bace, pc);
10424   setoppo(bace, pe);
10425   // Dealloc a redundant tetrahedron (edca).
10426   tetrahedrondealloc(edca.tet);
10427 
10428   // Clear the old bonds in abcd (was edab) and bace (was edbc).
10429   for (i = 0; i < 4; i ++) {
10430     abcd.tet[i] = (tetrahedron) dummytet;
10431   }
10432   for (i = 0; i < 4; i ++) {
10433     bace.tet[i] = (tetrahedron) dummytet;
10434   }
10435   // Bond the inside face of the convex hull.
10436   abcd.loc = 0;
10437   bace.loc = 0;
10438   bond(abcd, bace);
10439   // Bond the outside faces of the convex hull.
10440   abcd.loc = 1;
10441   bond(abcd, abdcasing);
10442   abcd.loc = 2;
10443   bond(abcd, bcdcasing);
10444   abcd.loc = 3;
10445   bond(abcd, cadcasing);
10446   bace.loc = 1;
10447   bond(bace, baecasing);
10448   bace.loc = 3;
10449   bond(bace, cbecasing);
10450   bace.loc = 2;
10451   bond(bace, acecasing);
10452   if (checksubfaces) {
10453     // Clear old bonds in abcd(was edab) and bace(was edbc).
10454     for (i = 0; i < 4; i ++) {
10455       abcd.tet[8 + i] = (tetrahedron) dummysh;
10456     }
10457     for (i = 0; i < 4; i ++) {
10458       bace.tet[8 + i] = (tetrahedron) dummysh;
10459     }
10460     if (abdsh.sh != dummysh) {
10461       abcd.loc = 1;
10462       tsbond(abcd, abdsh);
10463     }
10464     if (bcdsh.sh != dummysh) {
10465       abcd.loc = 2;
10466       tsbond(abcd, bcdsh);
10467     }
10468     if (cadsh.sh != dummysh) {
10469       abcd.loc = 3;
10470       tsbond(abcd, cadsh);
10471     }
10472     if (baesh.sh != dummysh) {
10473       bace.loc = 1;
10474       tsbond(bace, baesh);
10475     }
10476     if (cbesh.sh != dummysh) {
10477       bace.loc = 3;
10478       tsbond(bace, cbesh);
10479     }
10480     if (acesh.sh != dummysh) {
10481       bace.loc = 2;
10482       tsbond(bace, acesh);
10483     }
10484   } else if (checksubsegs) {
10485     for (i = 0; i < 6; i++) {
10486       abcd.tet[8 + i] = (tetrahedron) dummysh;
10487     }
10488     for (i = 0; i < 6; i++) {
10489       bace.tet[8 + i] = (tetrahedron) dummysh;
10490     }
10491     abcd.loc = abcd.ver = 0;
10492     bace.loc = bace.ver = 0;
10493     tssbond1(abcd, abseg);     // 1
10494     enext(abcd, worktet);
10495     tssbond1(worktet, bcseg);  // 2
10496     enext2(abcd, worktet);
10497     tssbond1(worktet, caseg);  // 3
10498     fnext(abcd, worktet);
10499     enext2self(worktet);
10500     tssbond1(worktet, adseg);  // 4
10501     enextfnext(abcd, worktet);
10502     enext2self(worktet);
10503     tssbond1(worktet, bdseg);  // 5
10504     enext2fnext(abcd, worktet);
10505     enext2self(worktet);
10506     tssbond1(worktet, cdseg);  // 6
10507     tssbond1(bace, abseg);
10508     enext2(bace, worktet);
10509     tssbond1(worktet, bcseg);
10510     enext(bace, worktet);
10511     tssbond1(worktet, caseg);
10512     fnext(bace, worktet);
10513     enextself(worktet);
10514     tssbond1(worktet, aeseg);  // 7
10515     enext2fnext(bace, worktet);
10516     enextself(worktet);
10517     tssbond1(worktet, beseg);  // 8
10518     enextfnext(bace, worktet);
10519     enextself(worktet);
10520     tssbond1(worktet, ceseg);  // 9
10521   }
10522 
10523   abcd.loc = 0;
10524   bace.loc = 0;
10525   if (b->verbose > 3) {
10526     printf("    Updating abcd ");
10527     printtet(&abcd);
10528     printf("    Updating bace ");
10529     printtet(&bace);
10530     printf("    Deleting edca ");
10531     // printtet(&edca);
10532   }
10533 
10534   if (flipqueue != (queue *) NULL) {
10535     fnext(abcd, abdcasing);
10536     enqueueflipface(abdcasing, flipqueue);
10537     fnext(bace, baecasing);
10538     enqueueflipface(baecasing, flipqueue);
10539     enextfnext(abcd, bcdcasing);
10540     enqueueflipface(bcdcasing, flipqueue);
10541     enextfnext(bace, cbecasing);
10542     enqueueflipface(cbecasing, flipqueue);
10543     enext2fnext(abcd, cadcasing);
10544     enqueueflipface(cadcasing, flipqueue);
10545     enext2fnext(bace, acecasing);
10546     enqueueflipface(acecasing, flipqueue);
10547   }
10548 
10549   // Save a live handle in 'recenttet'.
10550   recenttet = abcd;
10551   // Set the return handle be abcd.
10552   *flipface = abcd;
10553 }
10554 
10556 //                                                                           //
10557 // flip22()    Perform a 2-to-2 (or 4-to-4) flip.                            //
10558 //                                                                           //
10559 // On input, 'flipface' represents the face will be flipped.  Let it is abe, //
10560 // ab is the flipable edge, the two tetrahedra sharing abe are abce and bade,//
10561 // hence a, b, c and d are coplanar. If abc, bad are interior faces, the two //
10562 // tetrahedra opposite to e are bacf and abdf.  ab is not a subsegment.      //
10563 //                                                                           //
10564 // A 2-to-2 flip is to change two tetrahedra abce and bade into another two  //
10565 // tetrahedra dcae and cdbe. If bacf and abdf exist, they're changed to cdaf //
10566 // and dcbf, thus a 4-to-4 flip.  As a result, two or four tetrahedra have   //
10567 // rotated counterclockwise (using right-hand rule with thumb points to e):  //
10568 // abce->dcae, bade->cdbe, and bacf->cdaf, abdf->dcbf.                       //
10569 //                                                                           //
10570 // If abc and bad are subfaces, a 2-to-2 flip is performed simultaneously by //
10571 // calling routine flip22sub(), hence abc->dca, bad->cdb.  The edge rings of //
10572 // the flipped subfaces dca and cdb have the same orientation as abc and bad.//
10573 // Hence, they have the same orientation as other subfaces of the facet with //
10574 // respect to the lift point of this facet.                                  //
10575 //                                                                           //
10576 // On completion, 'flipface' holds edge dc of tetrahedron dcae. 'flipqueue'  //
10577 // contains all possibly non-Delaunay faces if it is not NULL.               //
10578 //                                                                           //
10580 
10581 void tetgenmesh::flip22(triface* flipface, queue* flipqueue)
10582 {
10583   triface abce, bade;
10584   triface oldbce, oldcae, oldade, olddbe;
10585   triface bcecasing, caecasing, adecasing, dbecasing;
10586   face bcesh, caesh, adesh, dbesh;
10587   triface bacf, abdf;
10588   triface oldacf, oldcbf, oldbdf, olddaf;
10589   triface acfcasing, cbfcasing, bdfcasing, dafcasing;
10590   triface worktet;
10591   face acfsh, cbfsh, bdfsh, dafsh;
10592   face abc, bad;
10593   face adseg, dbseg, bcseg, caseg;  // Coplanar segs.
10594   face aeseg, deseg, beseg, ceseg;  // Above segs.
10595   face afseg, dfseg, bfseg, cfseg;  // Below segs.
10596   point pa, pb, pc, pd;
10597 #ifdef SELF_CHECK
10598   point pe, pf;
10599 #endif
10600   int mirrorflag, i;
10601 
10602   adjustedgering(*flipface, CCW); // 'flipface' is bae.
10603   fnext(*flipface, abce);
10604   esymself(abce);
10605   adjustedgering(*flipface, CW); // 'flipface' is abe.
10606   fnext(*flipface, bade);
10607 #ifdef SELF_CHECK
10608   assert(bade.tet != dummytet);
10609 #endif
10610   esymself(bade);
10611   pa = org(abce);
10612   pb = dest(abce);
10613   pc = apex(abce);
10614   pd = apex(bade);
10615 #ifdef SELF_CHECK
10616   pe = oppo(bade);
10617   assert(oppo(abce) == pe);
10618 #endif
10619   sym(abce, bacf);
10620   mirrorflag = bacf.tet != dummytet;
10621   if (mirrorflag) {
10622     // findedge(&bacf, pb, pa);
10623     bacf.ver = 0;
10624     for (i = 0; (i < 3) && (org(bacf) != pb); i++) {
10625       enextself(bacf);
10626     }
10627     sym(bade, abdf);
10628 #ifdef SELF_CHECK
10629     assert(abdf.tet != dummytet);
10630 #endif
10631     // findedge(&abdf, pa, pb);
10632     abdf.ver = 0;
10633     for (i = 0; (i < 3) && (org(abdf) != pa); i++) {
10634       enextself(abdf);
10635     }
10636 
10637 #ifdef SELF_CHECK
10638     pf = oppo(bacf);
10639     assert(oppo(abdf) == pf);
10640 #endif
10641   }
10642 
10643   if (b->verbose > 2) {
10644     printf("    Do %s on edge (%d, %d).\n", mirrorflag ? "T44" : "T22",
10645            pointmark(pa), pointmark(pb));
10646   }
10647   mirrorflag ? flip44s++ : flip22s++;
10648 
10649   // Save the old configuration at the convex hull.
10650   enextfnext(abce, oldbce);
10651   enext2fnext(abce, oldcae);
10652   enextfnext(bade, oldade);
10653   enext2fnext(bade, olddbe);
10654   sym(oldbce, bcecasing);
10655   sym(oldcae, caecasing);
10656   sym(oldade, adecasing);
10657   sym(olddbe, dbecasing);
10658   if (checksubfaces) {
10659     tspivot(oldbce, bcesh);
10660     tspivot(oldcae, caesh);
10661     tspivot(oldade, adesh);
10662     tspivot(olddbe, dbesh);
10663     tspivot(abce, abc);
10664     tspivot(bade, bad);
10665   } else if (checksubsegs) {
10666     // Coplanar segs: a->d->b->c.
10667     enext(bade, worktet);
10668     tsspivot1(worktet, adseg);
10669     enext2(bade, worktet);
10670     tsspivot1(worktet, dbseg);
10671     enext(abce, worktet);
10672     tsspivot1(worktet, bcseg);
10673     enext2(abce, worktet);
10674     tsspivot1(worktet, caseg);
10675     // Above segs: a->e, d->e, b->e, c->e.
10676     fnext(bade, worktet);
10677     enextself(worktet);
10678     tsspivot1(worktet, aeseg);
10679     enextfnext(bade, worktet);
10680     enextself(worktet);
10681     tsspivot1(worktet, deseg);
10682     enext2fnext(bade, worktet);
10683     enextself(worktet);
10684     tsspivot1(worktet, beseg);
10685     enextfnext(abce, worktet);
10686     enextself(worktet);
10687     tsspivot1(worktet, ceseg);
10688   }
10689   if (mirrorflag) {
10690     enextfnext(bacf, oldacf);
10691     enext2fnext(bacf, oldcbf);
10692     enextfnext(abdf, oldbdf);
10693     enext2fnext(abdf, olddaf);
10694     sym(oldacf, acfcasing);
10695     sym(oldcbf, cbfcasing);
10696     sym(oldbdf, bdfcasing);
10697     sym(olddaf, dafcasing);
10698     if (checksubfaces) {
10699       tspivot(oldacf, acfsh);
10700       tspivot(oldcbf, cbfsh);
10701       tspivot(oldbdf, bdfsh);
10702       tspivot(olddaf, dafsh);
10703     } else if (checksubsegs) {
10704       // Below segs: a->f, d->f, b->f, c->f.
10705       fnext(abdf, worktet);
10706       enext2self(worktet);
10707       tsspivot1(worktet, afseg);
10708       enext2fnext(abdf, worktet);
10709       enext2self(worktet);
10710       tsspivot1(worktet, dfseg);
10711       enextfnext(abdf, worktet);
10712       enext2self(worktet);
10713       tsspivot1(worktet, bfseg);
10714       enextfnext(bacf, worktet);
10715       enextself(worktet);
10716       tsspivot1(worktet, cfseg);
10717     }
10718   }
10719 
10720   // Rotate abce, bade one-quarter turn counterclockwise.
10721   bond(oldbce, caecasing);
10722   bond(oldcae, adecasing);
10723   bond(oldade, dbecasing);
10724   bond(olddbe, bcecasing);
10725   if (checksubfaces) {
10726     // Check for subfaces and rebond them to the rotated tets.
10727     if (caesh.sh == dummysh) {
10728       tsdissolve(oldbce);
10729     } else {
10730       tsbond(oldbce, caesh);
10731     }
10732     if (adesh.sh == dummysh) {
10733       tsdissolve(oldcae);
10734     } else {
10735       tsbond(oldcae, adesh);
10736     }
10737     if (dbesh.sh == dummysh) {
10738       tsdissolve(oldade);
10739     } else {
10740       tsbond(oldade, dbesh);
10741     }
10742     if (bcesh.sh == dummysh) {
10743       tsdissolve(olddbe);
10744     } else {
10745       tsbond(olddbe, bcesh);
10746     }
10747   } else if (checksubsegs) {
10748     // 5 edges in abce are changed.
10749     enext(abce, worktet);  // fit b->c into c->a.
10750     if (caseg.sh == dummysh) {
10751       tssdissolve1(worktet);
10752     } else {
10753       tssbond1(worktet, caseg);
10754     }
10755     enext2(abce, worktet); // fit c->a into a->d.
10756     if (adseg.sh == dummysh) {
10757       tssdissolve1(worktet);
10758     } else {
10759       tssbond1(worktet, adseg);
10760     }
10761     fnext(abce, worktet); // fit b->e into c->e.
10762     enextself(worktet);
10763     if (ceseg.sh == dummysh) {
10764       tssdissolve1(worktet);
10765     } else {
10766       tssbond1(worktet, ceseg);
10767     }
10768     enextfnext(abce, worktet); // fit c->e into a->e.
10769     enextself(worktet);
10770     if (aeseg.sh == dummysh) {
10771       tssdissolve1(worktet);
10772     } else {
10773       tssbond1(worktet, aeseg);
10774     }
10775     enext2fnext(abce, worktet); // fit a->e into d->e.
10776     enextself(worktet);
10777     if (deseg.sh == dummysh) {
10778       tssdissolve1(worktet);
10779     } else {
10780       tssbond1(worktet, deseg);
10781     }
10782     // 5 edges in bade are changed.
10783     enext(bade, worktet); // fit a->d into d->b.
10784     if (dbseg.sh == dummysh) {
10785       tssdissolve1(worktet);
10786     } else {
10787       tssbond1(worktet, dbseg);
10788     }
10789     enext2(bade, worktet); // fit d->b into b->c.
10790     if (bcseg.sh == dummysh) {
10791       tssdissolve1(worktet);
10792     } else {
10793       tssbond1(worktet, bcseg);
10794     }
10795     fnext(bade, worktet); // fit a->e into d->e.
10796     enextself(worktet);
10797     if (deseg.sh == dummysh) {
10798       tssdissolve1(worktet);
10799     } else {
10800       tssbond1(worktet, deseg);
10801     }
10802     enextfnext(bade, worktet); // fit d->e into b->e.
10803     enextself(worktet);
10804     if (beseg.sh == dummysh) {
10805       tssdissolve1(worktet);
10806     } else {
10807       tssbond1(worktet, beseg);
10808     }
10809     enext2fnext(bade, worktet); // fit b->e into c->e.
10810     enextself(worktet);
10811     if (ceseg.sh == dummysh) {
10812       tssdissolve1(worktet);
10813     } else {
10814       tssbond1(worktet, ceseg);
10815     }
10816   }
10817   if (mirrorflag) {
10818     // Rotate bacf, abdf one-quarter turn counterclockwise.
10819     bond(oldcbf, acfcasing);
10820     bond(oldacf, dafcasing);
10821     bond(olddaf, bdfcasing);
10822     bond(oldbdf, cbfcasing);
10823     if (checksubfaces) {
10824       // Check for subfaces and rebond them to the rotated tets.
10825       if (acfsh.sh == dummysh) {
10826         tsdissolve(oldcbf);
10827       } else {
10828         tsbond(oldcbf, acfsh);
10829       }
10830       if (dafsh.sh == dummysh) {
10831         tsdissolve(oldacf);
10832       } else {
10833         tsbond(oldacf, dafsh);
10834       }
10835       if (bdfsh.sh == dummysh) {
10836         tsdissolve(olddaf);
10837       } else {
10838         tsbond(olddaf, bdfsh);
10839       }
10840       if (cbfsh.sh == dummysh) {
10841         tsdissolve(oldbdf);
10842       } else {
10843         tsbond(oldbdf, cbfsh);
10844       }
10845     } else if (checksubsegs) {
10846       // 5 edges in bacf are changed.
10847       enext2(bacf, worktet); // fit b->c into c->a.
10848       if (caseg.sh == dummysh) {
10849         tssdissolve1(worktet);
10850       } else {
10851         tssbond1(worktet, caseg);
10852       }
10853       enext(bacf, worktet); // fit c->a into a->d.
10854       if (adseg.sh == dummysh) {
10855         tssdissolve1(worktet);
10856       } else {
10857         tssbond1(worktet, adseg);
10858       }
10859       fnext(bacf, worktet); // fit b->f into c->f.
10860       enext2self(worktet);
10861       if (cfseg.sh == dummysh) {
10862         tssdissolve1(worktet);
10863       } else {
10864         tssbond1(worktet, cfseg);
10865       }
10866       enext2fnext(bacf, worktet); // fit c->f into a->f.
10867       enext2self(worktet);
10868       if (afseg.sh == dummysh) {
10869         tssdissolve1(worktet);
10870       } else {
10871         tssbond1(worktet, afseg);
10872       }
10873       enextfnext(bacf, worktet); // fit a->f into d->f.
10874       enext2self(worktet);
10875       if (dfseg.sh == dummysh) {
10876         tssdissolve1(worktet);
10877       } else {
10878         tssbond1(worktet, dfseg);
10879       }
10880       // 5 edges in abdf are changed.
10881       enext2(abdf, worktet); // fit a->d into d->b.
10882       if (dbseg.sh == dummysh) {
10883         tssdissolve1(worktet);
10884       } else {
10885         tssbond1(worktet, dbseg);
10886       }
10887       enext(abdf, worktet); // fit d->b into b->c.
10888       if (bcseg.sh == dummysh) {
10889         tssdissolve1(worktet);
10890       } else {
10891         tssbond1(worktet, bcseg);
10892       }
10893       fnext(abdf, worktet); // fit a->f into d->f.
10894       enext2self(worktet);
10895       if (dfseg.sh == dummysh) {
10896         tssdissolve1(worktet);
10897       } else {
10898         tssbond1(worktet, dfseg);
10899       }
10900       enext2fnext(abdf, worktet); // fit d->f into b->f.
10901       enext2self(worktet);
10902       if (bfseg.sh == dummysh) {
10903         tssdissolve1(worktet);
10904       } else {
10905         tssbond1(worktet, bfseg);
10906       }
10907       enextfnext(abdf, worktet); // fit b->f into c->f.
10908       enext2self(worktet);
10909       if (cfseg.sh == dummysh) {
10910         tssdissolve1(worktet);
10911       } else {
10912         tssbond1(worktet, cfseg);
10913       }
10914     }
10915   }
10916 
10917   // New vertex assignments for the rotated tetrahedra.
10918   setorg(abce, pd); // Update abce to dcae
10919   setdest(abce, pc);
10920   setapex(abce, pa);
10921   setorg(bade, pc); // Update bade to cdbe
10922   setdest(bade, pd);
10923   setapex(bade, pb);
10924   if (mirrorflag) {
10925     setorg(bacf, pc); // Update bacf to cdaf
10926     setdest(bacf, pd);
10927     setapex(bacf, pa);
10928     setorg(abdf, pd); // Update abdf to dcbf
10929     setdest(abdf, pc);
10930     setapex(abdf, pb);
10931   }
10932 
10933   // Are there subfaces need to be flipped?
10934   if (checksubfaces && abc.sh != dummysh) {
10935 #ifdef SELF_CHECK
10936     assert(bad.sh != dummysh);
10937 #endif
10938     // Adjust the edge be ab, so the rotation of subfaces is according with
10939     //   the rotation of tetrahedra.
10940     findedge(&abc, pa, pb);
10941     // Flip an edge of two subfaces, ignore non-Delaunay edges.
10942     flip22sub(&abc, NULL);
10943   }
10944 
10945   if (b->verbose > 3) {
10946     printf("    Updating abce ");
10947     printtet(&abce);
10948     printf("    Updating bade ");
10949     printtet(&bade);
10950     if (mirrorflag) {
10951       printf("    Updating bacf ");
10952       printtet(&bacf);
10953       printf("    Updating abdf ");
10954       printtet(&abdf);
10955     }
10956   }
10957 
10958   if (flipqueue != (queue *) NULL) {
10959     enextfnext(abce, bcecasing);
10960     enqueueflipface(bcecasing, flipqueue);
10961     enext2fnext(abce, caecasing);
10962     enqueueflipface(caecasing, flipqueue);
10963     enextfnext(bade, adecasing);
10964     enqueueflipface(adecasing, flipqueue);
10965     enext2fnext(bade, dbecasing);
10966     enqueueflipface(dbecasing, flipqueue);
10967     if (mirrorflag) {
10968       enextfnext(bacf, acfcasing);
10969       enqueueflipface(acfcasing, flipqueue);
10970       enext2fnext(bacf, cbfcasing);
10971       enqueueflipface(cbfcasing, flipqueue);
10972       enextfnext(abdf, bdfcasing);
10973       enqueueflipface(bdfcasing, flipqueue);
10974       enext2fnext(abdf, dafcasing);
10975       enqueueflipface(dafcasing, flipqueue);
10976     }
10977     // The two new faces dcae (abce), cdbe (bade) may still not be locally
10978     //   Delaunay, and may need be flipped (flip23).  On the other hand, in
10979     //   conforming Delaunay algorithm, two new subfaces dca (abc), and cdb
10980     //   (bad) may be non-conforming Delaunay, they need be queued if they
10981     //   are locally Delaunay but non-conforming Delaunay.
10982     enqueueflipface(abce, flipqueue);
10983     enqueueflipface(bade, flipqueue);
10984   }
10985 
10986   // Save a live handle in 'recenttet'.
10987   recenttet = abce;
10988 }
10989 
10991 //                                                                           //
10992 // flip22sub()    Perform a 2-to-2 flip on a subface edge.                   //
10993 //                                                                           //
10994 // The flip edge is given by subface 'flipedge'.  Let it is abc, where ab is //
10995 // the flipping edge.  The other subface is bad,  where a, b, c, d form a    //
10996 // convex quadrilateral.  ab is not a subsegment.                            //
10997 //                                                                           //
10998 // A 2-to-2 subface flip is to change two subfaces abc and bad to another    //
10999 // two subfaces dca and cdb.  Hence, edge ab has been removed and dc becomes //
11000 // an edge. If a point e is above abc, this flip is equal to rotate abc and  //
11001 // bad counterclockwise using right-hand rule with thumb points to e. It is  //
11002 // important to know that the edge rings of the flipped subfaces dca and cdb //
11003 // are keeping the same orientation as their original subfaces. So they have //
11004 // the same orientation with respect to the lift point of this facet.        //
11005 //                                                                           //
11006 // During rotating, the face rings of the four edges bc, ca, ad, and de need //
11007 // be re-connected. If the edge is not a subsegment, then its face ring has  //
11008 // only two faces, a sbond() will bond them together. If it is a subsegment, //
11009 // one should use sbond1() twice to bond two different handles to the rotat- //
11010 // ing subface, one is predecssor (-casin), another is successor (-casout).  //
11011 //                                                                           //
11012 // If 'flipqueue' is not NULL, it returns four edges bc, ca, ad, de, which   //
11013 // may be non-Delaunay.                                                      //
11014 //                                                                           //
11016 
11017 void tetgenmesh::flip22sub(face* flipedge, queue* flipqueue)
11018 {
11019   face abc, bad;
11020   face oldbc, oldca, oldad, olddb;
11021   face bccasin, bccasout, cacasin, cacasout;
11022   face adcasin, adcasout, dbcasin, dbcasout;
11023   face bc, ca, ad, db;
11024   face spinsh;
11025   point pa, pb, pc, pd;
11026 
11027   abc = *flipedge;
11028   spivot(abc, bad);
11029   if (sorg(bad) != sdest(abc)) {
11030     sesymself(bad);
11031   }
11032   pa = sorg(abc);
11033   pb = sdest(abc);
11034   pc = sapex(abc);
11035   pd = sapex(bad);
11036 
11037   if (b->verbose > 2) {
11038     printf("    Flip sub edge (%d, %d).\n", pointmark(pa), pointmark(pb));
11039   }
11040 
11041   // Save the old configuration outside the quadrilateral.
11042   senext(abc, oldbc);
11043   senext2(abc, oldca);
11044   senext(bad, oldad);
11045   senext2(bad, olddb);
11046   // Get the outside connection. Becareful if there is a subsegment on the
11047   //   quadrilateral, two casings (casin and casout) are needed to save for
11048   //   keeping the face link.
11049   spivot(oldbc, bccasout);
11050   sspivot(oldbc, bc);
11051   if (bc.sh != dummysh) {
11052     // 'bc' is a subsegment.
11053     if (bccasout.sh != dummysh) {
11054       if (oldbc.sh != bccasout.sh) {
11055         // 'oldbc' is not self-bonded.
11056         spinsh = bccasout;
11057         do {
11058           bccasin = spinsh;
11059           spivotself(spinsh);
11060         } while (spinsh.sh != oldbc.sh);
11061       } else {
11062         bccasout.sh = dummysh;
11063       }
11064     }
11065     ssdissolve(oldbc);
11066   }
11067   spivot(oldca, cacasout);
11068   sspivot(oldca, ca);
11069   if (ca.sh != dummysh) {
11070     // 'ca' is a subsegment.
11071     if (cacasout.sh != dummysh) {
11072       if (oldca.sh != cacasout.sh) {
11073         // 'oldca' is not self-bonded.
11074         spinsh = cacasout;
11075         do {
11076           cacasin = spinsh;
11077           spivotself(spinsh);
11078         } while (spinsh.sh != oldca.sh);
11079       } else {
11080         cacasout.sh = dummysh;
11081       }
11082     }
11083     ssdissolve(oldca);
11084   }
11085   spivot(oldad, adcasout);
11086   sspivot(oldad, ad);
11087   if (ad.sh != dummysh) {
11088     // 'ad' is a subsegment.
11089     if (adcasout.sh != dummysh) {
11090       if (oldad.sh != adcasout.sh) {
11091         // 'adcasout' is not self-bonded.
11092         spinsh = adcasout;
11093         do {
11094           adcasin = spinsh;
11095           spivotself(spinsh);
11096         } while (spinsh.sh != oldad.sh);
11097       } else {
11098         adcasout.sh = dummysh;
11099       }
11100     }
11101     ssdissolve(oldad);
11102   }
11103   spivot(olddb, dbcasout);
11104   sspivot(olddb, db);
11105   if (db.sh != dummysh) {
11106     // 'db' is a subsegment.
11107     if (dbcasout.sh != dummysh) {
11108       if (olddb.sh != dbcasout.sh) {
11109         // 'dbcasout' is not self-bonded.
11110         spinsh = dbcasout;
11111         do {
11112           dbcasin = spinsh;
11113           spivotself(spinsh);
11114         } while (spinsh.sh != olddb.sh);
11115       } else {
11116         dbcasout.sh = dummysh;
11117       }
11118     }
11119     ssdissolve(olddb);
11120   }
11121 
11122   // Rotate abc and bad one-quarter turn counterclockwise.
11123   if (ca.sh != dummysh) {
11124     if (cacasout.sh != dummysh) {
11125       sbond1(cacasin, oldbc);
11126       sbond1(oldbc, cacasout);
11127     } else {
11128       // Bond 'oldbc' to itself.
11129       sbond(oldbc, oldbc);
11130       // Make sure that dummysh always correctly bonded.
11131       dummysh[0] = sencode(oldbc);
11132     }
11133     ssbond(oldbc, ca);
11134   } else {
11135     sbond(oldbc, cacasout);
11136   }
11137   if (ad.sh != dummysh) {
11138     if (adcasout.sh != dummysh) {
11139       sbond1(adcasin, oldca);
11140       sbond1(oldca, adcasout);
11141     } else {
11142       // Bond 'oldca' to itself.
11143       sbond(oldca, oldca);
11144       // Make sure that dummysh always correctly bonded.
11145       dummysh[0] = sencode(oldca);
11146     }
11147     ssbond(oldca, ad);
11148   } else {
11149     sbond(oldca, adcasout);
11150   }
11151   if (db.sh != dummysh) {
11152     if (dbcasout.sh != dummysh) {
11153       sbond1(dbcasin, oldad);
11154       sbond1(oldad, dbcasout);
11155     } else {
11156       // Bond 'oldad' to itself.
11157       sbond(oldad, oldad);
11158       // Make sure that dummysh always correctly bonded.
11159       dummysh[0] = sencode(oldad);
11160     }
11161     ssbond(oldad, db);
11162   } else {
11163     sbond(oldad, dbcasout);
11164   }
11165   if (bc.sh != dummysh) {
11166     if (bccasout.sh != dummysh) {
11167       sbond1(bccasin, olddb);
11168       sbond1(olddb, bccasout);
11169     } else {
11170       // Bond 'olddb' to itself.
11171       sbond(olddb, olddb);
11172       // Make sure that dummysh always correctly bonded.
11173       dummysh[0] = sencode(olddb);
11174     }
11175     ssbond(olddb, bc);
11176   } else {
11177     sbond(olddb, bccasout);
11178   }
11179 
11180   // New vertex assignments for the rotated subfaces.
11181   setsorg(abc, pd);  // Update abc to dca.
11182   setsdest(abc, pc);
11183   setsapex(abc, pa);
11184   setsorg(bad, pc);  // Update bad to cdb.
11185   setsdest(bad, pd);
11186   setsapex(bad, pb);
11187 
11188   if (flipqueue != (queue *) NULL) {
11189     enqueueflipedge(bccasout, flipqueue);
11190     enqueueflipedge(cacasout, flipqueue);
11191     enqueueflipedge(adcasout, flipqueue);
11192     enqueueflipedge(dbcasout, flipqueue);
11193   }
11194 }
11195 
11197 //                                                                           //
11198 // flip()    Flips non-locally Delaunay faces in flipqueue until it is empty.//
11199 //                                                                           //
11200 // Assumpation:  Current tetrahedralization is non-Delaunay after inserting  //
11201 // a point or performing a flip operation, all possibly non-Delaunay faces   //
11202 // are in 'flipqueue'.                                                       //
11203 //                                                                           //
11204 // If 'plastflip' is not NULL,  it is used to return a stack of recently     //
11205 // flipped faces.  This stack will be used to reverse the flips done in this //
11206 // routine later for removing a newly inserted point because it encroaches   //
11207 // any subfaces or subsegments.                                              //
11208 //                                                                           //
11209 // The return value is the total number of flips done during this invocation.//
11210 //                                                                           //
11212 
11213 long tetgenmesh::flip(queue* flipqueue, badface **plastflip)
11214 {
11215   badface *qface, *newflip;
11216   triface flipface, symface;
11217   point pa, pb, pc, pd, pe;
11218   enum fliptype fc;
11219   REAL sign, bakepsilon;
11220   long flipcount; //, maxfaces; - commented out to get gcc4.6 working
11221   int epscount, fcount;
11222   int ia, ib, ic, id, ie;
11223 
11224   if (b->verbose > 1) {
11225     printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
11226   }
11227 
11228   flipcount = flip23s + flip32s + flip22s + flip44s;
11229   if (checksubfaces) {
11230     //maxfaces = (4l * tetrahedrons->items + hullsize) / 2l; // commented out to get gcc 4.6 working
11231     fcount = 0;
11232   }
11233 
11234   if (plastflip != (badface **) NULL) {
11235     // Initialize the stack of the flip sequence.
11236     flipstackers->restart();
11237     *plastflip = (badface *) NULL;
11238   }
11239 
11240   // Loop until the queue is empty.
11241   while (!flipqueue->empty()) {
11242     qface = (badface *) flipqueue->pop();
11243     flipface = qface->tt;
11244     if (isdead(&flipface)) continue;
11245     sym(flipface, symface);
11246     // Only do check when the adjacent tet exists and it's not a "fake" tet.
11247     if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11248       // For positive orientation that insphere() test requires.
11249       adjustedgering(flipface, CW);
11250       pa = org(flipface);
11251       pb = dest(flipface);
11252       pc = apex(flipface);
11253       pd = oppo(flipface);
11254       pe = oppo(symface);
11255       if (symbolic) {
11256         ia = pointmark(pa);
11257         ib = pointmark(pb);
11258         ic = pointmark(pc);
11259         id = pointmark(pd);
11260         ie = pointmark(pe);
11261         sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
11262         assert(sign != 0.0);
11263       } else {
11264         sign = insphere(pa, pb, pc, pd, pe);
11265       }
11266     } else {
11267       sign = -1.0; // A hull face is locally Delaunay.
11268     }
11269     if (sign > 0.0) {
11270       // 'flipface' is non-locally Delaunay, try to flip it.
11271       if (checksubfaces) {
11272         fcount++;
11273         bakepsilon = b->epsilon;
11274         epscount = 0;
11275         while (epscount < 32) {
11276           fc = categorizeface(flipface);
11277           if (fc == N40) {
11278             b->epsilon *= 1e-1;
11279             epscount++;
11280             continue;
11281           }
11282           break;
11283         }
11284         b->epsilon = bakepsilon;
11285         if (epscount >= 32) {
11286           if (b->verbose > 0) {
11287             printf("Warning:  Can't flip a degenerate tetrahedron.\n");
11288           }
11289           fc = N40;
11290         }
11291       } else {
11292         fc = categorizeface(flipface);
11293 #ifdef SELF_CHECK
11294         assert(fc != N40);
11295 #endif
11296       }
11297       switch (fc) {
11298       // The following face types are flipable.
11299       case T44:
11300       case T22:
11301         flip22(&flipface, flipqueue);
11302         break;
11303       case T23:
11304         flip23(&flipface, flipqueue);
11305         break;
11306       case T32:
11307         flip32(&flipface, flipqueue);
11308         break;
11309       // The following face types are unflipable.
11310       case N32:
11311         break;
11312       case FORBIDDENFACE:
11313         break;
11314       case FORBIDDENEDGE:
11315         break;
11316       // This case is only possible when the domain is nonconvex.
11317       case N40:
11318         // assert(nonconvex);
11319         break;
11320       }
11321       if (plastflip != (badface **) NULL) {
11322         if ((fc == T44) || (fc == T22) || (fc == T23) || (fc == T32)) {
11323           // Push the flipped face into stack.
11324           newflip = (badface *) flipstackers->alloc();
11325           newflip->tt = flipface;
11326           newflip->key = (REAL) fc;
11327           newflip->forg = org(flipface);
11328           newflip->fdest = dest(flipface);
11329           newflip->fapex = apex(flipface);
11330           newflip->previtem = *plastflip;
11331           *plastflip = newflip;
11332         }
11333       }
11334     }
11335   }
11336 
11337   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11338   if (b->verbose > 1) {
11339     printf("    %ld flips.\n", flipcount);
11340   }
11341 
11342   return flipcount;
11343 }
11344 
11346 //                                                                           //
11347 // lawson()    Flip locally non-Delaunay faces by Lawson's algorithm.        //
11348 //                                                                           //
11350 
11351 long tetgenmesh::lawson(list *misseglist, queue* flipqueue)
11352 {
11353   badface *qface, *misseg;
11354   triface flipface, symface;
11355   triface starttet, spintet;
11356   face checksh, checkseg;
11357   point pa, pb, pc, pd, pe;
11358   point swappt;
11359   REAL sign, ori;
11360   long flipcount;
11361   int ia, ib, ic, id, ie;
11362   int hitbdry, i;
11363 
11364   if (b->verbose > 1) {
11365     printf("    Do flipface queue: %ld faces.\n", flipqueue->len());
11366   }
11367   flipcount = flip23s + flip32s + flip22s + flip44s;
11368 
11369   // Go through the stack of possible flips and decide whether to do them.
11370   //   Note that during the loop new possible flips will be pushed onto
11371   //   this stack, while they popped in this loop.
11372   while (!flipqueue->empty()) {
11373     qface = (badface *) flipqueue->pop();
11374     flipface = qface->tt;
11375     // Check if tet has already been flipped out of existence.
11376     if (!isdead(&flipface)) {
11377       sym(flipface, symface);
11378       // Check if this tet is the same as the one which was stacked.
11379       if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11380         flipface.ver = 0; // Select the CCW ring.
11381         pa = org(flipface);
11382         pb = dest(flipface);
11383         pc = apex(flipface);
11384         pd = oppo(flipface);
11385         pe = oppo(symface);
11386         if (symbolic) {
11387           ia = pointmark(pa);
11388           ib = pointmark(pb);
11389           ic = pointmark(pc);
11390           id = pointmark(pd);
11391           ie = pointmark(pe);
11392           sign = insphere_sos(pb, pa, pc, pd, pe, ib, ia, ic, id, ie);
11393         } else {
11394           sign = insphere(pb, pa, pc, pd, pe);
11395         }
11396         if (sign > 0.0) {
11397           for (i = 0; i < 3; i++) {
11398             ori = orient3d(pa, pb, pd, pe);
11399             if (ori > 0.0) {
11400               // Goto and check the next edge.
11401               swappt = pa;
11402               pa = pb;
11403               pb = pc;
11404               pc = swappt;
11405               enextself(flipface);
11406             } else {
11407               break; // either (ori < 0.0) or (ori == 0.0)
11408             }
11409           } // for (i = 0; ....)
11410           if (ori > 0.0) {
11411             // All three edges are convex, a 2-3 flip is possible.
11412             if (checksubfaces) {
11413               tspivot(flipface, checksh);
11414               if (checksh.sh != dummysh) {
11415                 // A subface is not flipable.
11416                 continue;
11417               }
11418             }
11419             flip23(&flipface, flipqueue);
11420           } else if (ori < 0.0) {
11421             // The edge (a, b) is non-convex, check for a 3-2 flip.
11422             fnext(flipface, symface);
11423             symself(symface);
11424             if (oppo(symface) == pe) {
11425               // Only three tets adjoining this edge.
11426               if (checksubfaces) {
11427                 tsspivot(&flipface, &checkseg);
11428                 if (checkseg.sh != dummysh) {
11429                   // A subsegment is not flipable.
11430                   continue;
11431                 }
11432               } else if (checksubsegs) {
11433                 tsspivot1(flipface, checkseg);
11434                 if (checkseg.sh != dummysh) {
11435                   if (b->verbose > 2) {
11436                     printf("    Queuing missing segment (%d, %d).\n",
11437                       pointmark(org(flipface)), pointmark(dest(flipface)));
11438                   }
11439                   misseg = (badface *) misseglist->append(NULL);
11440                   misseg->ss = checkseg;
11441                   misseg->forg = sorg(checkseg);
11442                   misseg->fdest = sdest(checkseg);
11443                   // Detach all tets having this seg.
11444                   starttet = flipface;
11445                   adjustedgering(starttet, CCW);
11446                   fnextself(starttet);
11447                   spintet = starttet;
11448                   hitbdry = 0;
11449                   do {
11450                     tssdissolve1(spintet);
11451                     if (!fnextself(spintet)) {
11452                       hitbdry++;
11453                       if (hitbdry < 2) {
11454                         esym(starttet, spintet);
11455                         if (!fnextself(spintet)) {
11456                           hitbdry++;
11457                         }
11458                       }
11459                     }
11460                   } while ((apex(spintet) != apex(starttet)) && (hitbdry < 2));
11461                 }
11462               } // if (checksubfaces)
11463               flip32(&flipface, flipqueue);
11464             }
11465           } else {
11466             // Four points (a, b, d, e) are coplanar.
11467             fnext(flipface, symface);
11468             if (fnextself(symface)) {
11469               // Check for a 4-4 flip.
11470               fnextself(symface);
11471               if (apex(symface) == pe) {
11472                 if (checksubfaces) {
11473                   tsspivot(&flipface, &checkseg);
11474                   if (checkseg.sh != dummysh) {
11475                     // A subsegment is not flippable.
11476                     continue;
11477                   }
11478                 } else if (checksubsegs) {
11479                   tsspivot1(flipface, checkseg);
11480                   if (checkseg.sh != dummysh) {
11481                     if (b->verbose > 2) {
11482                       printf("    Queuing missing segment (%d, %d).\n",
11483                         pointmark(org(flipface)), pointmark(dest(flipface)));
11484                     }
11485                     misseg = (badface *) misseglist->append(NULL);
11486                     misseg->ss = checkseg;
11487                     misseg->forg = sorg(checkseg);
11488                     misseg->fdest = sdest(checkseg);
11489                     // Detach all tets having this seg.
11490                     starttet = flipface;
11491                     adjustedgering(starttet, CCW);
11492                     fnextself(starttet);
11493                     spintet = starttet;
11494                     hitbdry = 0;
11495                     do {
11496                       tssdissolve1(spintet);
11497                       if (!fnextself(spintet)) {
11498                         hitbdry++;
11499                         if (hitbdry < 2) {
11500                           esym(starttet, spintet);
11501                           if (!fnextself(spintet)) {
11502                             hitbdry++;
11503                           }
11504                         }
11505                       }
11506                     } while ((apex(spintet) != apex(starttet)) &&
11507                              (hitbdry < 2));
11508                   }
11509                 } // if (checksubfaces)
11510                 flip22(&flipface, flipqueue);
11511               }
11512             } else {
11513               // Check for a 2-2 flip.
11514               esym(flipface, symface);
11515               fnextself(symface);
11516               symself(symface);
11517               if (symface.tet == dummytet) {
11518                 if (checksubfaces) {
11519                   tsspivot(&flipface, &checkseg);
11520                   if (checkseg.sh != dummysh) {
11521                     // A subsegment is not flipable.
11522                     continue;
11523                   }
11524                 } else if (checksubsegs) {
11525                   tsspivot1(flipface, checkseg);
11526                   if (checkseg.sh != dummysh) {
11527                     if (b->verbose > 2) {
11528                       printf("    Queuing missing segment (%d, %d).\n",
11529                         pointmark(org(flipface)), pointmark(dest(flipface)));
11530                     }
11531                     misseg = (badface *) misseglist->append(NULL);
11532                     misseg->ss = checkseg;
11533                     misseg->forg = sorg(checkseg);
11534                     misseg->fdest = sdest(checkseg);
11535                     // Detach all tets having this seg.
11536                     starttet = flipface;
11537                     adjustedgering(starttet, CCW);
11538                     fnextself(starttet);
11539                     spintet = starttet;
11540                     hitbdry = 0;
11541                     do {
11542                       tssdissolve1(spintet);
11543                       if (!fnextself(spintet)) {
11544                         hitbdry++;
11545                         if (hitbdry < 2) {
11546                           esym(starttet, spintet);
11547                           if (!fnextself(spintet)) {
11548                             hitbdry++;
11549                           }
11550                         }
11551                       }
11552                     } while ((apex(spintet) != apex(starttet)) &&
11553                              (hitbdry < 2));
11554                   }
11555                 } // if (checksubfaces)
11556                 flip22(&flipface, flipqueue);
11557               }
11558             }
11559           } // if (ori > 0.0)
11560         } // if (sign > 0.0)
11561       }
11562     } // !isdead(&qface->tt)
11563   } // while (!flipqueue->empty())
11564 
11565   flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11566   if (b->verbose > 1) {
11567     printf("    %ld flips.\n", flipcount);
11568   }
11569   return flipcount;
11570 }
11571 
11573 //                                                                           //
11574 // undoflip()    Undo the most recent flip sequence induced by flip().       //
11575 //                                                                           //
11576 // 'lastflip' is the stack of recently flipped faces. Walks through the list //
11577 // of flips, in the reverse of the order in which they were done, and undoes //
11578 // them.                                                                     //
11579 //                                                                           //
11581 
11582 void tetgenmesh::undoflip(badface *lastflip)
11583 {
11584   enum fliptype fc;
11585 
11586   while (lastflip != (badface *) NULL) {
11587     // Get the right flipped face.
11588     findface(&lastflip->tt, lastflip->forg, lastflip->fdest, lastflip->fapex);
11589     fc = (enum fliptype) (int) lastflip->key;
11590     switch (fc) {
11591     case T23:
11592       // The reverse operation of T23 is T32.
11593       flip32(&lastflip->tt, NULL);
11594       break;
11595     case T32:
11596       // The reverse operation of T32 is T23.
11597       flip23(&lastflip->tt, NULL);
11598       break;
11599     case T22:
11600     case T44:
11601       // The reverse operation of T22 or T44 is again T22 or T44.
11602       flip22(&lastflip->tt, NULL);
11603       break;
11604     default: // To omit compile warnings.
11605       break;
11606     }
11607     // Go on and process the next transformation.
11608     lastflip = lastflip->previtem;
11609   }
11610 }
11611 
11613 //                                                                           //
11614 // flipsub()    Flip non-Delaunay edges in a queue of (coplanar) subfaces.   //
11615 //                                                                           //
11616 // Assumpation:  Current triangulation T contains non-Delaunay edges (after  //
11617 // inserting a point or performing a flip). Non-Delaunay edges are queued in //
11618 // 'facequeue'. Returns the total number of flips done during this call.     //
11619 //                                                                           //
11621 
11622 long tetgenmesh::flipsub(queue* flipqueue)
11623 {
11624   badface *qedge;
11625   face flipedge, symedge;
11626   face checkseg;
11627   point pa, pb, pc, pd;
11628   REAL vab[3], vac[3], vad[3];
11629   REAL dot1, dot2, lac, lad;
11630   REAL sign, ori;
11631   int edgeflips;
11632   int i;
11633 
11634   if (b->verbose > 1) {
11635     printf("  Start do edge queue: %ld edges.\n", flipqueue->len());
11636   }
11637 
11638   edgeflips = 0;
11639 
11640   while (!flipqueue->empty()) {
11641     qedge = (badface *) flipqueue->pop();
11642     flipedge = qedge->ss;
11643     if (flipedge.sh == dummysh) continue;
11644     if ((sorg(flipedge) != qedge->forg) ||
11645         (sdest(flipedge) != qedge->fdest)) continue;
11646     sspivot(flipedge, checkseg);
11647     if (checkseg.sh != dummysh) continue;  // Can't flip a subsegment.
11648     spivot(flipedge, symedge);
11649     if (symedge.sh == dummysh) continue; // Can't flip a hull edge.
11650     pa = sorg(flipedge);
11651     pb = sdest(flipedge);
11652     pc = sapex(flipedge);
11653     pd = sapex(symedge);
11654     // Choose the triangle abc or abd as the base depending on the angle1
11655     //   (Vac, Vab) and angle2 (Vad, Vab).
11656     for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
11657     for (i = 0; i < 3; i++) vac[i] = pc[i] - pa[i];
11658     for (i = 0; i < 3; i++) vad[i] = pd[i] - pa[i];
11659     dot1 = dot(vac, vab);
11660     dot2 = dot(vad, vab);
11661     dot1 *= dot1;
11662     dot2 *= dot2;
11663     lac = dot(vac, vac);
11664     lad = dot(vad, vad);
11665     if (lad * dot1 <= lac * dot2) {
11666       // angle1 is closer to 90 than angle2, choose abc (flipedge).
11667       abovepoint = facetabovepointarray[shellmark(flipedge)];
11668       if (abovepoint == (point) NULL) {
11669         getfacetabovepoint(&flipedge);
11670       }
11671       sign = insphere(pa, pb, pc, abovepoint, pd);
11672       ori = orient3d(pa, pb, pc, abovepoint);
11673     } else {
11674       // angle2 is closer to 90 than angle1, choose abd (symedge).
11675       abovepoint = facetabovepointarray[shellmark(symedge)];
11676       if (abovepoint == (point) NULL) {
11677         getfacetabovepoint(&symedge);
11678       }
11679       sign = insphere(pa, pb, pd, abovepoint, pc);
11680       ori = orient3d(pa, pb, pd, abovepoint);
11681     }
11682     // Correct the sign.
11683     sign = ori > 0.0 ? sign : -sign;
11684     if (sign > 0.0) {
11685       // Flip the non-Delaunay edge.
11686       flip22sub(&flipedge, flipqueue);
11687       edgeflips++;
11688     }
11689   }
11690 
11691   if (b->verbose > 1) {
11692     printf("  Total %d flips.\n", edgeflips);
11693   }
11694 
11695   return edgeflips;
11696 }
11697 
11699 //                                                                           //
11700 // removetetbypeeloff()    Remove a boundary tet by peeling it off.          //
11701 //                                                                           //
11702 // 'striptet' (abcd) is on boundary and can be removed by stripping it off.  //
11703 // Let abc and bad are the external boundary faces.                          //
11704 //                                                                           //
11705 // To strip 'abcd' from the mesh is to detach its two interal faces (dca and //
11706 // cdb) from their adjoining tets together with a 2-to-2 flip to transform   //
11707 // two subfaces (abc and bad) into another two (dca and cdb).                //
11708 //                                                                           //
11709 // In mesh optimization. It is possible that ab is a segment and abcd is a   //
11710 // sliver on the hull. Strip abcd will also delete the segment ab.           //
11711 //                                                                           //
11713 
11714 bool tetgenmesh::removetetbypeeloff(triface *striptet)
11715 {
11716   triface abcd, badc;
11717   triface dcacasing, cdbcasing;
11718   face abc, bad;
11719   face abseg;
11720   REAL ang;
11721 
11722   abcd = *striptet;
11723   adjustedgering(abcd, CCW);
11724   // Get the casing tets at the internal sides.
11725   enextfnext(abcd, cdbcasing);
11726   enext2fnext(abcd, dcacasing);
11727   symself(cdbcasing);
11728   symself(dcacasing);
11729   // Do the neighboring tets exist?  During optimization. It is possible
11730   //   that the neighboring tets are already dead.
11731   if ((cdbcasing.tet == dummytet) || (dcacasing.tet == dummytet)) {
11732     // Do not strip this tet.
11733     return false;
11734   }
11735 
11736   // Are there subfaces?
11737   if (checksubfaces) {
11738     // Get the external subfaces abc, bad.
11739     fnext(abcd, badc);
11740     esymself(badc);
11741     tspivot(abcd, abc);
11742     tspivot(badc, bad);
11743     if (abc.sh != dummysh) {
11744       assert(bad.sh != dummysh);
11745       findedge(&abc, org(abcd), dest(abcd));
11746       findedge(&bad, org(badc), dest(badc));
11747       // Is ab a segment?
11748       sspivot(abc, abseg);
11749       if (abseg.sh != dummysh) {
11750         // Does a segment allow to be removed?
11751         if ((b->optlevel > 3) && (b->nobisect == 0)) {
11752           // Only remove this segment if the dihedal angle at ab is between
11753           //   [b->maxdihedral-9, 180] (deg).  This avoids mistakely fliping
11754           //   ab when it has actually no big dihedral angle while cd has.
11755           ang = facedihedral(org(abcd), dest(abcd), apex(abcd), oppo(abcd));
11756           ang = ang * 180.0 / PI;
11757           if ((ang + 9.0) > b->maxdihedral) {
11758             if (b->verbose > 1) {
11759               printf("    Remove a segment during peeling.\n");
11760             }
11761             face prevseg, nextseg;
11762             // It is only shared by abc and bad (abcd is a tet).
11763             ssdissolve(abc);
11764             ssdissolve(bad);
11765             abseg.shver = 0;
11766             senext(abseg, nextseg);
11767             spivotself(nextseg);
11768             if (nextseg.sh != dummysh) {
11769               ssdissolve(nextseg);
11770             }
11771             senext2(abseg, prevseg);
11772             spivotself(prevseg);
11773             if (prevseg.sh != dummysh) {
11774               ssdissolve(prevseg);
11775             }
11776             shellfacedealloc(subsegs, abseg.sh);
11777             optcount[1]++;
11778           } else {
11779             return false;
11780           }
11781         } else {
11782           return false;
11783         }
11784       }
11785       // Do a 2-to-2 flip on abc and bad, transform abc->dca, bad->cdb.
11786       flip22sub(&abc, NULL);
11787       // The two internal faces become boundary faces.
11788       tsbond(cdbcasing, bad);
11789       tsbond(dcacasing, abc);
11790     }
11791   }
11792 
11793   // Detach abcd from the two internal faces.
11794   dissolve(cdbcasing);
11795   dissolve(dcacasing);
11796   // Delete abcd.
11797   tetrahedrondealloc(abcd.tet);
11798   return true;
11799 }
11800 
11802 //                                                                           //
11803 // removeedgebyflip22()    Remove an edge by a 2-to-2 (or 4-to-4) flip.      //
11804 //                                                                           //
11805 // 'abtetlist' contains n tets (n is 2 or 4) sharing edge ab,  abtetlist[0]  //
11806 // and abtetlist[1] are tets abec and abde, respectively (NOTE, both are in  //
11807 // CW edge ring), where a, b, c, and d are coplanar.  If n = 4, abtetlist[2] //
11808 // and abtetlist[3] are tets abfd and abcf, respectively.  This routine uses //
11809 // flip22() to replace edge ab with cd, the surrounding tets are rotated.    //
11810 //                                                                           //
11811 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
11812 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
11813 // is the maximum dihedral angle in the old tets.                            //
11814 //                                                                           //
11816 
11817 bool tetgenmesh::removeedgebyflip22(REAL *key, int n, triface *abtetlist,
11818   queue *flipque)
11819 {
11820   point pa, pb, pc, pd, pe, pf;
11821   REAL cosmaxd, d1, d2, d3;
11822   bool doflip;
11823 
11824   cosmaxd = 0.0;
11825   pf = apex(abtetlist[2]);
11826   doflip = true;
11827   adjustedgering(abtetlist[0], CW);
11828   pa = org(abtetlist[0]);
11829   pb = dest(abtetlist[0]);
11830   pe = apex(abtetlist[0]);
11831   pc = oppo(abtetlist[0]);
11832   pd = apex(abtetlist[1]);
11833   if (n == 4) {
11834     pf = apex(abtetlist[2]);
11835   }
11836   if (key && (*key > -1.0)) {
11837     tetalldihedral(pc, pd, pe, pa, NULL, &d1, NULL);
11838     tetalldihedral(pd, pc, pe, pb, NULL, &d2, NULL);
11839     cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11840     if (n == 4) {
11841       tetalldihedral(pd, pc, pf, pa, NULL, &d1, NULL);
11842       tetalldihedral(pc, pd, pf, pb, NULL, &d2, NULL);
11843       d3 = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11844       cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
11845     }
11846     doflip = (*key < cosmaxd); // Can local quality be improved?
11847   }
11848 
11849   if (doflip) {
11850     flip22(&abtetlist[0], NULL);
11851     // Return the improved quality value.
11852     if (key) *key = cosmaxd;
11853   }
11854 
11855   return doflip;
11856 }
11857 
11859 //                                                                           //
11860 // removefacebyflip23()    Remove a face by a 2-to-3 flip.                   //
11861 //                                                                           //
11862 // 'abctetlist' contains 2 tets sharing abc, which are [0]abcd and [1]bace.  //
11863 // This routine forms three new tets that abc is not a face anymore. Save    //
11864 // them in 'newtetlist': [0]edab, [1]edbc, and [2]edca.  Note that the new   //
11865 // tets may not valid if one of them get inverted. return false if so.       //
11866 //                                                                           //
11867 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
11868 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
11869 // is the maximum dihedral angle in the old tets.                            //
11870 //                                                                           //
11871 // If the face is flipped, 'newtetlist' returns the three new tets. The two  //
11872 // tets in 'abctetlist' are NOT deleted.  The caller has the right to either //
11873 // delete them or reverse the operation.                                     //
11874 //                                                                           //
11876 
11877 bool tetgenmesh::removefacebyflip23(REAL *key, triface *abctetlist,
11878   triface *newtetlist, queue *flipque)
11879 {
11880   triface edab, edbc, edca; // new configuration.
11881   triface newfront, oldfront, adjfront;
11882   face checksh;
11883   point pa, pb, pc, pd, pe;
11884   REAL ori, cosmaxd, d1, d2, d3;
11885   REAL attrib, volume;
11886   bool doflip;
11887   int i;
11888 
11889   cosmaxd = 0.0;
11890 
11891   adjustedgering(abctetlist[0], CCW);
11892   pa = org(abctetlist[0]);
11893   pb = dest(abctetlist[0]);
11894   pc = apex(abctetlist[0]);
11895   pd = oppo(abctetlist[0]);
11896   pe = oppo(abctetlist[1]);
11897 
11898   // Check if the flip creates valid new tets.
11899   ori = orient3d(pe, pd, pa, pb);
11900   if (ori < 0.0) {
11901     ori = orient3d(pe, pd, pb, pc);
11902     if (ori < 0.0) {
11903       ori = orient3d(pe, pd, pc, pa);
11904     }
11905   }
11906   doflip = (ori < 0.0); // Can abc be flipped away?
11907   if (doflip && (key != (REAL *) NULL)) {
11908     if (*key > -1.0) {
11909       // Test if the new tets reduce the maximal dihedral angle.
11910       tetalldihedral(pe, pd, pa, pb, NULL, &d1, NULL);
11911       tetalldihedral(pe, pd, pb, pc, NULL, &d2, NULL);
11912       tetalldihedral(pe, pd, pc, pa, NULL, &d3, NULL);
11913       cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
11914       cosmaxd = cosmaxd < d3 ? cosmaxd : d3; // Choose the bigger angle.
11915       doflip = (*key < cosmaxd); // Can local quality be improved?
11916     }
11917   }
11918 
11919   if (doflip) {
11920     // A valid (2-to-3) flip is found.
11921     flip23s++;
11922     // Create the new tets.
11923     maketetrahedron(&edab);
11924     setorg(edab, pe);
11925     setdest(edab, pd);
11926     setapex(edab, pa);
11927     setoppo(edab, pb);
11928     maketetrahedron(&edbc);
11929     setorg(edbc, pe);
11930     setdest(edbc, pd);
11931     setapex(edbc, pb);
11932     setoppo(edbc, pc);
11933     maketetrahedron(&edca);
11934     setorg(edca, pe);
11935     setdest(edca, pd);
11936     setapex(edca, pc);
11937     setoppo(edca, pa);
11938     // Transfer the element attributes.
11939     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
11940       attrib = elemattribute(abctetlist[0].tet, i);
11941       setelemattribute(edab.tet, i, attrib);
11942       setelemattribute(edbc.tet, i, attrib);
11943       setelemattribute(edca.tet, i, attrib);
11944     }
11945     // Transfer the volume constraints.
11946     if (b->varvolume && !b->refine) {
11947       volume = volumebound(abctetlist[0].tet);
11948       setvolumebound(edab.tet, volume);
11949       setvolumebound(edbc.tet, volume);
11950       setvolumebound(edca.tet, volume);
11951     }
11952     // Return two new tets.
11953     newtetlist[0] = edab;
11954     newtetlist[1] = edbc;
11955     newtetlist[2] = edca;
11956     // Glue the three new tets.
11957     for (i = 0; i < 3; i++) {
11958       fnext(newtetlist[i], newfront);
11959       bond(newfront, newtetlist[(i + 1) % 3]);
11960     }
11961     // Substitute the three new tets into the old cavity.
11962     for (i = 0; i < 3; i++) {
11963       fnext(abctetlist[0], oldfront);
11964       sym(oldfront, adjfront); // may be outside.
11965       enextfnext(newtetlist[i], newfront);
11966       bond(newfront, adjfront);
11967       if (checksubfaces) {
11968         tspivot(oldfront, checksh);
11969         if (checksh.sh != dummysh) {
11970           tsbond(newfront, checksh);
11971         }
11972       }
11973       if (flipque != (queue *) NULL) {
11974         enqueueflipface(newfront, flipque);
11975       }
11976       enextself(abctetlist[0]);
11977     }
11978     findedge(&(abctetlist[1]), pb, pa);
11979     for (i = 0; i < 3; i++) {
11980       fnext(abctetlist[1], oldfront);
11981       sym(oldfront, adjfront); // may be outside.
11982       enext2fnext(newtetlist[i], newfront);
11983       bond(newfront, adjfront);
11984       if (checksubfaces) {
11985         tspivot(oldfront, checksh);
11986         if (checksh.sh != dummysh) {
11987           tsbond(newfront, checksh);
11988         }
11989       }
11990       if (flipque != (queue *) NULL) {
11991         enqueueflipface(newfront, flipque);
11992       }
11993       enext2self(abctetlist[1]);
11994     }
11995     // Do not delete the old tets.
11996     // for (i = 0; i < 2; i++) {
11997     //   tetrahedrondealloc(abctetlist[i].tet);
11998     // }
11999     // Return the improved quality value.
12000     if (key != (REAL *) NULL) *key = cosmaxd;
12001     return true;
12002   }
12003 
12004   return false;
12005 }
12006 
12008 //                                                                           //
12009 // removeedgebyflip32()    Remove an edge by a 3-to-2 flip.                  //
12010 //                                                                           //
12011 // 'abtetlist' contains 3 tets sharing ab. Imaging that ab is perpendicular  //
12012 // to the screen, where a lies in front of and b lies behind it. The 3 tets  //
12013 // of the list are: [0]abce, [1]abdc, and [2]abed, respectively.             //
12014 //                                                                           //
12015 // This routine forms two new tets that ab is not an edge of them. Save them //
12016 // in 'newtetlist', [0]dcea, [1]cdeb. Note that the new tets may not valid   //
12017 // if one of them get inverted. return false if so.                          //
12018 //                                                                           //
12019 // If 'key' != NULL.  The old tets are replaced by the new tets only if the  //
12020 // local mesh quality is improved. Current 'key' = cos(\theta), where \theta //
12021 // is the maximum dihedral angle in the old tets.                            //
12022 //                                                                           //
12023 // If the edge is flipped, 'newtetlist' returns the two new tets. The three  //
12024 // tets in 'abtetlist' are NOT deleted.  The caller has the right to either  //
12025 // delete them or reverse the operation.                                     //
12026 //                                                                           //
12028 
12029 bool tetgenmesh::removeedgebyflip32(REAL *key, triface *abtetlist,
12030   triface *newtetlist, queue *flipque)
12031 {
12032   triface dcea, cdeb; // new configuration.
12033   triface newfront, oldfront, adjfront;
12034   face checksh;
12035   point pa, pb, pc, pd, pe;
12036   REAL ori, cosmaxd, d1, d2;
12037   REAL attrib, volume;
12038   bool doflip;
12039   int i;
12040 
12041   pa = org(abtetlist[0]);
12042   pb = dest(abtetlist[0]);
12043   pc = apex(abtetlist[0]);
12044   pd = apex(abtetlist[1]);
12045   pe = apex(abtetlist[2]);
12046 
12047   ori = orient3d(pd, pc, pe, pa);
12048   if (ori < 0.0) {
12049     ori = orient3d(pc, pd, pe, pb);
12050   }
12051   doflip = (ori < 0.0); // Can ab be flipped away?
12052 
12053   // Does the caller ensure a valid configuration?
12054   if (doflip && (key != (REAL *) NULL)) {
12055     if (*key > -1.0) {
12056       // Test if the new tets reduce the maximal dihedral angle.
12057       tetalldihedral(pd, pc, pe, pa, NULL, &d1, NULL);
12058       tetalldihedral(pc, pd, pe, pb, NULL, &d2, NULL);
12059       cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
12060       doflip = (*key < cosmaxd); // Can local quality be improved?
12061       // Return the key
12062       *key = cosmaxd;
12063     }
12064   }
12065 
12066   if (doflip) {
12067     // Create the new tets.
12068     maketetrahedron(&dcea);
12069     setorg(dcea, pd);
12070     setdest(dcea, pc);
12071     setapex(dcea, pe);
12072     setoppo(dcea, pa);
12073     maketetrahedron(&cdeb);
12074     setorg(cdeb, pc);
12075     setdest(cdeb, pd);
12076     setapex(cdeb, pe);
12077     setoppo(cdeb, pb);
12078     // Transfer the element attributes.
12079     for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12080       attrib = elemattribute(abtetlist[0].tet, i);
12081       setelemattribute(dcea.tet, i, attrib);
12082       setelemattribute(cdeb.tet, i, attrib);
12083     }
12084     // Transfer the volume constraints.
12085     if (b->varvolume && !b->refine) {
12086       volume = volumebound(abtetlist[0].tet);
12087       setvolumebound(dcea.tet, volume);
12088       setvolumebound(cdeb.tet, volume);
12089     }
12090     // Return two new tets.
12091     newtetlist[0] = dcea;
12092     newtetlist[1] = cdeb;
12093     // Glue the two new tets.
12094     bond(dcea, cdeb);
12095     // Substitute the two new tets into the old three-tets cavity.
12096     for (i = 0; i < 3; i++) {
12097       fnext(dcea, newfront); // face dca, cea, eda.
12098       esym(abtetlist[(i + 1) % 3], oldfront);
12099       enextfnextself(oldfront);
12100       // Get the adjacent tet at the face (may be a dummytet).
12101       sym(oldfront, adjfront);
12102       bond(newfront, adjfront);
12103       if (checksubfaces) {
12104         tspivot(oldfront, checksh);
12105         if (checksh.sh != dummysh) {
12106           tsbond(newfront, checksh);
12107         }
12108       }
12109       if (flipque != (queue *) NULL) {
12110         enqueueflipface(newfront, flipque);
12111       }
12112       enext2self(dcea);
12113     }
12114     for (i = 0; i < 3; i++) {
12115       fnext(cdeb, newfront); // face cdb, deb, ecb.
12116       esym(abtetlist[(i + 1) % 3], oldfront);
12117       enext2fnextself(oldfront);
12118       // Get the adjacent tet at the face (may be a dummytet).
12119       sym(oldfront, adjfront);
12120       bond(newfront, adjfront);
12121       if (checksubfaces) {
12122         tspivot(oldfront, checksh);
12123         if (checksh.sh != dummysh) {
12124           tsbond(newfront, checksh);
12125         }
12126       }
12127       if (flipque != (queue *) NULL) {
12128         enqueueflipface(newfront, flipque);
12129       }
12130       enextself(cdeb);
12131     }
12132     // Do not delete the old tets.
12133     // for (i = 0; i < 3; i++) {
12134     //   tetrahedrondealloc(abtetlist[i].tet);
12135     // }
12136     return true;
12137   } // if (doflip)
12138 
12139   return false;
12140 }
12141 
12143 //                                                                           //
12144 // removeedgebytranNM()    Remove an edge by transforming n-to-m tets.       //
12145 //                                                                           //
12146 // This routine attempts to remove a given edge (ab) by transforming the set //
12147 // T of tets surrounding ab into another set T' of tets.  T and T' have the  //
12148 // same outer faces and ab is not an edge of T' anymore. Let |T|=n, and |T'| //
12149 // =m, it is actually a n-to-m flip for n > 3.  The relation between n and m //
12150 // depends on the method, ours is found below.                               //
12151 //                                                                           //
12152 // 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
12153 // to the screen, where a lies in front of and b lies behind it.  Let the    //
12154 // projections of the n apexes onto screen in clockwise order are: p_0, ...  //
12155 // p_n-1, respectively. The tets in the list are: [0]abp_0p_n-1,[1]abp_1p_0, //
12156 // ..., [n-1]abp_n-1p_n-2, respectively.                                     //
12157 //                                                                           //
12158 // The principle of the approach is: Recursively reduce the link of ab by    //
12159 // using flip23 until only three faces remain, hence a flip32 can be applied //
12160 // to remove ab. For a given face a.b.p_0, check a flip23 can be applied on  //
12161 // it, i.e, edge p_1.p_n-1 crosses it. NOTE*** We do the flip even p_1.p_n-1 //
12162 // intersects with a.b (they are coplanar). If so, a degenerate tet (a.b.p_1.//
12163 // p_n-1) is temporarily created, but it will be eventually removed by the   //
12164 // final flip32. This relaxation splits a flip44 into flip23 + flip32. *NOTE //
12165 // Now suppose a.b.p_0 gets flipped, p_0 is not on the link of ab anymore.   //
12166 // The link is then reduced (by 1). 2 of the 3 new tets, p_n-1.p_1.p_0.a and //
12167 // p_1.p_n-1.p_0.b, will be part of the new configuration.  The left new tet,//
12168 // a.b.p_1.p_n-1, goes into the new link of ab. A recurrence can be applied. //
12169 //                                                                           //
12170 // If 'e1' and 'e2' are not NULLs, they specify an wanted edge to appear in  //
12171 // the new tet configuration. In such case, only do flip23 if edge e1<->e2   //
12172 // can be recovered. It is used in removeedgebycombNM().                     //
12173 //                                                                           //
12174 // If ab gets removed. 'newtetlist' contains m new tets.  By using the above //
12175 // approach, the pairs (n, m) can be easily enumerated.  For example, (3, 2),//
12176 // (4, 4), (5, 6), (6, 8), (7, 10), (8, 12), (9, 14), (10, 16),  and so on.  //
12177 // It is easy to deduce, that m = (n - 2) * 2, when n >= 3.  The n tets in   //
12178 // 'abtetlist' are NOT deleted in this routine. The caller has the right to  //
12179 // either delete them or reverse this operation.                             //
12180 //                                                                           //
12182 
12183 bool tetgenmesh::removeedgebytranNM(REAL *key, int n, triface *abtetlist,
12184   triface *newtetlist, point e1, point e2, queue *flipque)
12185 {
12186   triface tmpabtetlist[9]; // Temporary max 9 tets configuration.
12187   triface newfront, oldfront, adjfront;
12188   face checksh;
12189   point pa, pb, p[10];
12190   REAL ori, cosmaxd, d1, d2;
12191   REAL tmpkey;
12192   REAL attrib, volume;
12193   bool doflip, copflag, success;
12194   int i, j, k;
12195 
12196   cosmaxd = 0.0;
12197   // Maximum 10 tets.
12198   assert(n <= 10);
12199   // Two points a and b are fixed.
12200   pa = org(abtetlist[0]);
12201   pb = dest(abtetlist[0]);
12202   // The points p_0, p_1, ..., p_n-1 are permuted in each new configuration.
12203   //   These permutations can be easily done in the following loop.
12204   // Loop through all the possible new tets configurations. Stop on finding
12205   //   a valid new tet configuration which also immproves the quality value.
12206   for (i = 0; i < n; i++) {
12207     // Get other n points for the current configuration.
12208     for (j = 0; j < n; j++) {
12209       p[j] = apex(abtetlist[(i + j) % n]);
12210     }
12211     // Is there a wanted edge?
12212     if ((e1 != (point) NULL) && (e2 != (point) NULL)) {
12213       // Yes. Skip this face if p[1]<->p[n-1] is not the edge.
12214       if (!(((p[1] == e1) && (p[n - 1] == e2)) ||
12215         ((p[1] == e2) && (p[n - 1] == e1)))) continue;
12216     }
12217     // Test if face a.b.p_0 can be flipped (by flip23), ie, to check if the
12218     //   edge p_n-1.p_1 crosses face a.b.p_0 properly.
12219     // Note. It is possible that face a.b.p_0 has type flip44, ie, a,b,p_1,
12220     //   and p_n-1 are coplanar. A trick is to split the flip44 into two
12221     //   steps: frist a flip23, then a flip32. The first step creates a
12222     //   degenerate tet (vol=0) which will be removed by the second flip.
12223     ori = orient3d(pa, pb, p[1], p[n - 1]);
12224     copflag = (ori == 0.0); // Are they coplanar?
12225     if (ori >= 0.0) {
12226       // Accept the coplanar case which supports flip44.
12227       ori = orient3d(pb, p[0], p[1], p[n - 1]);
12228       if (ori > 0.0) {
12229         ori = orient3d(p[0], pa, p[1], p[n - 1]);
12230       }
12231     }
12232     // Is face abc flipable?
12233     if (ori > 0.0) {
12234       // A valid (2-to-3) flip (or 4-to-4 flip) is found.
12235       copflag ? flip44s++ : flip23s++;
12236       doflip = true;
12237       if (key != (REAL *) NULL) {
12238         if (*key > -1.0) {
12239           // Test if the new tets reduce the maximal dihedral angle. Only 2
12240           //   tets, p_n-1.p_1.p_0.a and p_1.p_n-1.p_0.b, need to be tested
12241           //   The left one a.b.p_n-1.p_1 goes into the new link of ab.
12242           tetalldihedral(p[n - 1], p[1], p[0], pa, NULL, &d1, NULL);
12243           tetalldihedral(p[1], p[n - 1], p[0], pb, NULL, &d2, NULL);
12244           cosmaxd = d1 < d2 ? d1 : d2; // Choose the bigger angle.
12245           doflip = *key < cosmaxd; // Can the local quality be improved?
12246         }
12247       }
12248       if (doflip) {
12249         tmpkey = key != NULL ? *key : -1.0;
12250         // Create the two new tets.
12251         maketetrahedron(&(newtetlist[0]));
12252         setorg(newtetlist[0], p[n - 1]);
12253         setdest(newtetlist[0], p[1]);
12254         setapex(newtetlist[0], p[0]);
12255         setoppo(newtetlist[0], pa);
12256         maketetrahedron(&(newtetlist[1]));
12257         setorg(newtetlist[1], p[1]);
12258         setdest(newtetlist[1], p[n - 1]);
12259         setapex(newtetlist[1], p[0]);
12260         setoppo(newtetlist[1], pb);
12261         // Create the n - 1 temporary new tets (the new Star(ab)).
12262         maketetrahedron(&(tmpabtetlist[0]));
12263         setorg(tmpabtetlist[0], pa);
12264         setdest(tmpabtetlist[0], pb);
12265         setapex(tmpabtetlist[0], p[n - 1]);
12266         setoppo(tmpabtetlist[0], p[1]);
12267         for (j = 1; j < n - 1; j++) {
12268           maketetrahedron(&(tmpabtetlist[j]));
12269           setorg(tmpabtetlist[j], pa);
12270           setdest(tmpabtetlist[j], pb);
12271           setapex(tmpabtetlist[j], p[j]);
12272           setoppo(tmpabtetlist[j], p[j + 1]);
12273         }
12274         // Transfer the element attributes.
12275         for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12276           attrib = elemattribute(abtetlist[0].tet, j);
12277           setelemattribute(newtetlist[0].tet, j, attrib);
12278           setelemattribute(newtetlist[1].tet, j, attrib);
12279           for (k = 0; k < n - 1; k++) {
12280             setelemattribute(tmpabtetlist[k].tet, j, attrib);
12281           }
12282         }
12283         // Transfer the volume constraints.
12284         if (b->varvolume && !b->refine) {
12285           volume = volumebound(abtetlist[0].tet);
12286           setvolumebound(newtetlist[0].tet, volume);
12287           setvolumebound(newtetlist[1].tet, volume);
12288           for (k = 0; k < n - 1; k++) {
12289             setvolumebound(tmpabtetlist[k].tet, volume);
12290           }
12291         }
12292         // Glue the new tets at their internal faces: 2 + (n - 1).
12293         bond(newtetlist[0], newtetlist[1]); // p_n-1.p_1.p_0.
12294         fnext(newtetlist[0], newfront);
12295         enext2fnext(tmpabtetlist[0], adjfront);
12296         bond(newfront, adjfront); // p_n-1.p_1.a.
12297         fnext(newtetlist[1], newfront);
12298         enextfnext(tmpabtetlist[0], adjfront);
12299         bond(newfront, adjfront); // p_n-1.p_1.b.
12300         // Glue n - 1 internal faces around ab.
12301         for (j = 0; j < n - 1; j++) {
12302           fnext(tmpabtetlist[j], newfront);
12303           bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
12304         }
12305         // Substitute the old tets with the new tets by connecting the new
12306         //   tets to the adjacent tets in the mesh. There are n * 2 (outer)
12307         //   faces of the new tets need to be operated.
12308         // Note, after the substitution, the old tets still have pointers to
12309         //   their adjacent tets in the mesh.  These pointers can be re-used
12310         //   to inverse the substitution.
12311         for (j = 0; j < n; j++) {
12312           // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
12313           oldfront = abtetlist[(i + j) % n];
12314           esymself(oldfront);
12315           enextfnextself(oldfront);
12316           // Get an adjacent tet at face: [0]a.p_0.p_n-1 or [j]a.p_j.p_j-1.
12317           sym(oldfront, adjfront); // adjfront may be dummy.
12318           // Get the corresponding face from the new tets.
12319           if (j == 0) {
12320             enext2fnext(newtetlist[0], newfront); // a.p_0.n_n-1
12321           } else if (j == 1) {
12322             enextfnext(newtetlist[0], newfront); // a.p_1.p_0
12323           } else { // j >= 2.
12324             enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
12325           }
12326           bond(newfront, adjfront);
12327           if (checksubfaces) {
12328             tspivot(oldfront, checksh);
12329             if (checksh.sh != dummysh) {
12330               tsbond(newfront, checksh);
12331             }
12332           }
12333           if (flipque != (queue *) NULL) {
12334             // Only queue the faces of the two new tets.
12335             if (j < 2) enqueueflipface(newfront, flipque);
12336           }
12337         }
12338         for (j = 0; j < n; j++) {
12339           // Get an old tet: [0]a.b.p_0.p_n-1 or [j]a.b.p_j.p_j-1, (j > 0).
12340           oldfront = abtetlist[(i + j) % n];
12341           esymself(oldfront);
12342           enext2fnextself(oldfront);
12343           // Get an adjacent tet at face: [0]b.p_0.p_n-1 or [j]b.p_j.p_j-1.
12344           sym(oldfront, adjfront); // adjfront may be dummy.
12345           // Get the corresponding face from the new tets.
12346           if (j == 0) {
12347             enextfnext(newtetlist[1], newfront); // b.p_0.n_n-1
12348           } else if (j == 1) {
12349             enext2fnext(newtetlist[1], newfront); // b.p_1.p_0
12350           } else { // j >= 2.
12351             enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
12352           }
12353           bond(newfront, adjfront);
12354           if (checksubfaces) {
12355             tspivot(oldfront, checksh);
12356             if (checksh.sh != dummysh) {
12357               tsbond(newfront, checksh);
12358             }
12359           }
12360           if (flipque != (queue *) NULL) {
12361             // Only queue the faces of the two new tets.
12362             if (j < 2) enqueueflipface(newfront, flipque);
12363           }
12364         }
12365         // Adjust the faces in the temporary new tets at ab for recursively
12366         //   processing on the n-1 tets.(See the description at beginning)
12367         for (j = 0; j < n - 1; j++) {
12368           fnextself(tmpabtetlist[j]);
12369         }
12370         if (n > 4) {
12371           success = removeedgebytranNM(&tmpkey, n-1, tmpabtetlist,
12372             &(newtetlist[2]), NULL, NULL, flipque);
12373         } else { // assert(n == 4);
12374           success = removeedgebyflip32(&tmpkey, tmpabtetlist,
12375             &(newtetlist[2]), flipque);
12376         }
12377         // No matter it was success or not, delete the temporary tets.
12378         for (j = 0; j < n - 1; j++) {
12379           tetrahedrondealloc(tmpabtetlist[j].tet);
12380         }
12381         if (success) {
12382           // The new configuration is good.
12383           // Do not delete the old tets.
12384           // for (j = 0; j < n; j++) {
12385           //   tetrahedrondealloc(abtetlist[j].tet);
12386           // }
12387           // Save the minimal improved quality value.
12388           if (key != (REAL *) NULL) {
12389             *key = (tmpkey < cosmaxd ? tmpkey : cosmaxd);
12390           }
12391           return true;
12392         } else {
12393           // The new configuration is bad, substitue back the old tets.
12394           for (j = 0; j < n; j++) {
12395             oldfront = abtetlist[(i + j) % n];
12396             esymself(oldfront);
12397             enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
12398             sym(oldfront, adjfront); // adjfront may be dummy.
12399             bond(oldfront, adjfront);
12400             if (checksubfaces) {
12401               tspivot(oldfront, checksh);
12402               if (checksh.sh != dummysh) {
12403                 tsbond(oldfront, checksh);
12404               }
12405             }
12406           }
12407           for (j = 0; j < n; j++) {
12408             oldfront = abtetlist[(i + j) % n];
12409             esymself(oldfront);
12410             enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12411             sym(oldfront, adjfront); // adjfront may be dummy
12412             bond(oldfront, adjfront);
12413             if (checksubfaces) {
12414               tspivot(oldfront, checksh);
12415               if (checksh.sh != dummysh) {
12416                 tsbond(oldfront, checksh);
12417               }
12418             }
12419           }
12420           // Delete the new tets.
12421           tetrahedrondealloc(newtetlist[0].tet);
12422           tetrahedrondealloc(newtetlist[1].tet);
12423           // If tmpkey has been modified, then the failure was not due to
12424           //   unflipable configuration, but the non-improvement.
12425           if (key && (tmpkey < *key)) {
12426             *key = tmpkey;
12427             return false;
12428           }
12429         } // if (success)
12430       } // if (doflip)
12431     } // if (ori > 0.0)
12432   } // for (i = 0; i < n; i++)
12433 
12434   return false;
12435 }
12436 
12438 //                                                                           //
12439 // removeedgebycombNM()    Remove an edge by combining two flipNMs.          //
12440 //                                                                           //
12441 // Given a set T of tets surrounding edge ab. The premise is that ab can not //
12442 // be removed by a flipNM. This routine attempts to remove ab by two flipNMs,//
12443 // i.e., first find and flip an edge af (or bf) by flipNM, then flip ab by   //
12444 // flipNM. If it succeeds, two sets T(ab) and T(af) of tets are replaced by  //
12445 // a new set T' and both ab and af are not edges in T' anymore.              //
12446 //                                                                           //
12447 // 'abtetlist' contains n tets sharing ab. Imaging that ab is perpendicular  //
12448 // to the screen, such that a lies in front of and b lies behind it. Let the //
12449 // projections of the n apexes on the screen in clockwise order are: p_0,...,//
12450 // p_n-1, respectively. So the list of tets are: [0]abp_0p_n-1, [1]abp_1p_0, //
12451 // ..., [n-1]abp_n-1p_n-2, respectively.                                     //
12452 //                                                                           //
12453 // The principle of the approach is: for a face a.b.p_0, check if edge b.p_0 //
12454 // is of type N32 (or N44). If it is, then try to do a flipNM on it. If the  //
12455 // flip is successful, then try to do another flipNM on a.b.  If one of the  //
12456 // two flipNMs fails, restore the old tets as they have never been flipped.  //
12457 // Then try the next face a.b.p_1.  The process can be looped for all faces  //
12458 // having ab. Stop if ab is removed or all faces have been visited. Note in  //
12459 // the above description only b.p_0 is considered, a.p_0 is done by swapping //
12460 // the position of a and b.                                                  //
12461 //                                                                           //
12462 // Similar operations have been described in [Joe,1995].  My approach checks //
12463 // more cases for finding flips than Joe's.  For instance, the cases (1)-(7) //
12464 // of Joe only consider abf for finding a flip (T23/T32).  My approach looks //
12465 // all faces at ab for finding flips. Moreover, the flipNM can flip an edge  //
12466 // whose star may have more than 3 tets while Joe's only works on 3-tet case.//
12467 //                                                                           //
12468 // If ab is removed, 'newtetlist' contains the new tets. Two sets 'abtetlist'//
12469 // (n tets) and 'bftetlist' (n1 tets) have been replaced.  The number of new //
12470 // tets can be calculated by follows: the 1st flip transforms n1 tets into   //
12471 // (n1 - 2) * 2 new tets, however,one of the new tets goes into the new link //
12472 // of ab, i.e., the reduced tet number in Star(ab) is n - 1;  the 2nd flip   //
12473 // transforms n - 1 tets into (n - 3) * 2 new tets. Hence the number of new  //
12474 // tets are: m = ((n1 - 2) * 2 - 1) + (n - 3) * 2.  The old tets are NOT del-//
12475 // eted. The caller has the right to delete them or reverse the operation.   //
12476 //                                                                           //
12478 
12479 bool tetgenmesh::removeedgebycombNM(REAL *key, int n, triface *abtetlist,
12480   int *n1, triface *bftetlist, triface *newtetlist, queue *flipque)
12481 {
12482   triface tmpabtetlist[11];
12483   triface newfront, oldfront, adjfront;
12484   face checksh;
12485   point pa, pb, p[10];
12486   REAL ori, tmpkey, tmpkey2;
12487   REAL attrib, volume;
12488   bool doflip, success;
12489   int twice, count;
12490   int i, j, k, m;
12491 
12492   // Maximal 10 tets in Star(ab).
12493   assert(n <= 10);
12494 
12495   // Do the following procedure twice, one for flipping edge b.p_0 and the
12496   //   other for p_0.a which is symmetric to the first.
12497   twice = 0;
12498   do {
12499     // Two points a and b are fixed.
12500     pa = org(abtetlist[0]);
12501     pb = dest(abtetlist[0]);
12502     // The points p_0, ..., p_n-1 are permuted in the following loop.
12503     for (i = 0; i < n; i++) {
12504       // Get the n points for the current configuration.
12505       for (j = 0; j < n; j++) {
12506         p[j] = apex(abtetlist[(i + j) % n]);
12507       }
12508       // Check if b.p_0 is of type N32 or N44.
12509       ori = orient3d(pb, p[0], p[1], p[n - 1]);
12510       if ((ori > 0) && (key != (REAL *) NULL)) {
12511         // b.p_0 is not N32. However, it is possible that the tet b.p_0.p_1.
12512         //   p_n-1 has worse quality value than the key. In such case, also
12513         //   try to flip b.p_0.
12514         tetalldihedral(pb, p[0], p[n - 1], p[1], NULL, &tmpkey, NULL);
12515         if (tmpkey < *key) ori = 0.0;
12516       }
12517       if (ori <= 0.0) {
12518         // b.p_0 is either N32 or N44. Try the 1st flipNM.
12519         bftetlist[0] = abtetlist[i];
12520         enextself(bftetlist[0]);// go to edge b.p_0.
12521         adjustedgering(bftetlist[0], CW); // edge p_0.b.
12522         assert(apex(bftetlist[0]) == pa);
12523         // Form Star(b.p_0).
12524         doflip = true;
12525         *n1 = 0;
12526         do {
12527           // Is the list full?
12528           if (*n1 == 10) break;
12529           if (checksubfaces) {
12530             // Stop if a subface appears.
12531             tspivot(bftetlist[*n1], checksh);
12532             if (checksh.sh != dummysh) {
12533               doflip = false; break;
12534             }
12535           }
12536           // Get the next tet at p_0.b.
12537           fnext(bftetlist[*n1], bftetlist[(*n1) + 1]);
12538           (*n1)++;
12539         } while (apex(bftetlist[*n1]) != pa);
12540         // 2 <= n1 <= 10.
12541         if (doflip) {
12542           success = false;
12543           tmpkey = -1.0;  // = acos(pi).
12544           if (key != (REAL *) NULL) tmpkey = *key;
12545           m = 0;
12546           if (*n1 == 3) {
12547             // Three tets case. Try flip32.
12548             success = removeedgebyflip32(&tmpkey,bftetlist,newtetlist,flipque);
12549             m = 2;
12550           } else if ((*n1 > 3) && (*n1 < 7)) {
12551             // Four or more tets case. Try flipNM.
12552             success = removeedgebytranNM(&tmpkey, *n1, bftetlist, newtetlist,
12553                                          p[1], p[n - 1], flipque);
12554             // If success, the number of new tets.
12555             m = ((*n1) - 2) * 2;
12556           } else {
12557             if (b->verbose > 1) {
12558               printf("  !! Unhandled case: n1 = %d.\n", *n1);
12559             }
12560           }
12561           if (success) {
12562             // b.p_0 is flipped. The link of ab is reduced (by 1), i.e., p_0
12563             //   is not on the link of ab. Two old tets a.b.p_0.p_n-1 and
12564             //   a.b.p_1.p_0 have been removed from the Star(ab) and one new
12565             //   tet t = a.b.p_1.p_n-1 belongs to Star(ab).
12566             // Find t in the 'newtetlist' and remove it from the list.
12567             setpointmark(pa, -pointmark(pa) - 1);
12568             setpointmark(pb, -pointmark(pb) - 1);
12569             assert(m > 0);
12570             for (j = 0; j < m; j++) {
12571               tmpabtetlist[0] = newtetlist[j];
12572               // Does it has ab?
12573               count = 0;
12574               for (k = 0; k < 4; k++) {
12575                 if (pointmark((point)(tmpabtetlist[0].tet[4+k])) < 0) count++;
12576               }
12577               if (count == 2) {
12578                 // It is. Adjust t to be the edge ab.
12579                 for (tmpabtetlist[0].loc = 0; tmpabtetlist[0].loc < 4;
12580                      tmpabtetlist[0].loc++) {
12581                   if ((oppo(tmpabtetlist[0]) != pa) &&
12582                       (oppo(tmpabtetlist[0]) != pb)) break;
12583                 }
12584                 // The face of t must contain ab.
12585                 assert(tmpabtetlist[0].loc < 4);
12586                 findedge(&(tmpabtetlist[0]), pa, pb);
12587                 break;
12588               }
12589             }
12590             assert(j < m); // The tet must exist.
12591             // Remove t from list. Fill t's position by the last tet.
12592             newtetlist[j] = newtetlist[m - 1];
12593             setpointmark(pa, -(pointmark(pa) + 1));
12594             setpointmark(pb, -(pointmark(pb) + 1));
12595             // Create the temporary Star(ab) for the next flipNM.
12596             adjustedgering(tmpabtetlist[0], CCW);
12597             if (org(tmpabtetlist[0]) != pa) {
12598               fnextself(tmpabtetlist[0]);
12599               esymself(tmpabtetlist[0]);
12600             }
12601 #ifdef SELF_CHECK
12602             // Make sure current edge is a->b.
12603             assert(org(tmpabtetlist[0]) == pa);
12604             assert(dest(tmpabtetlist[0]) == pb);
12605             assert(apex(tmpabtetlist[0]) == p[n - 1]);
12606             assert(oppo(tmpabtetlist[0]) == p[1]);
12607 #endif // SELF_CHECK
12608             // There are n - 2 left temporary tets.
12609             for (j = 1; j < n - 1; j++) {
12610               maketetrahedron(&(tmpabtetlist[j]));
12611               setorg(tmpabtetlist[j], pa);
12612               setdest(tmpabtetlist[j], pb);
12613               setapex(tmpabtetlist[j], p[j]);
12614               setoppo(tmpabtetlist[j], p[j + 1]);
12615             }
12616             // Transfer the element attributes.
12617             for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12618               attrib = elemattribute(abtetlist[0].tet, j);
12619               for (k = 0; k < n - 1; k++) {
12620                 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12621               }
12622             }
12623             // Transfer the volume constraints.
12624             if (b->varvolume && !b->refine) {
12625               volume = volumebound(abtetlist[0].tet);
12626               for (k = 0; k < n - 1; k++) {
12627                 setvolumebound(tmpabtetlist[k].tet, volume);
12628               }
12629             }
12630             // Glue n - 1 internal faces of Star(ab).
12631             for (j = 0; j < n - 1; j++) {
12632               fnext(tmpabtetlist[j], newfront);
12633               bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]); // a.b.p_j+1
12634             }
12635             // Substitute the old tets with the new tets by connecting the
12636             //   new tets to the adjacent tets in the mesh. There are (n-2)
12637             //   * 2 (outer) faces of the new tets need to be operated.
12638             // Note that the old tets still have the pointers to their
12639             //   adjacent tets in the mesh.  These pointers can be re-used
12640             //   to inverse the substitution.
12641             for (j = 2; j < n; j++) {
12642               // Get an old tet: [j]a.b.p_j.p_j-1, (j > 1).
12643               oldfront = abtetlist[(i + j) % n];
12644               esymself(oldfront);
12645               enextfnextself(oldfront);
12646               // Get an adjacent tet at face: [j]a.p_j.p_j-1.
12647               sym(oldfront, adjfront); // adjfront may be dummy.
12648               // Get the corresponding face from the new tets.
12649               // j >= 2.
12650               enext2fnext(tmpabtetlist[j - 1], newfront); // a.p_j.p_j-1
12651               bond(newfront, adjfront);
12652               if (checksubfaces) {
12653                 tspivot(oldfront, checksh);
12654                 if (checksh.sh != dummysh) {
12655                   tsbond(newfront, checksh);
12656                 }
12657               }
12658             }
12659             for (j = 2; j < n; j++) {
12660               // Get an old tet: [j]a.b.p_j.p_j-1, (j > 2).
12661               oldfront = abtetlist[(i + j) % n];
12662               esymself(oldfront);
12663               enext2fnextself(oldfront);
12664               // Get an adjacent tet at face: [j]b.p_j.p_j-1.
12665               sym(oldfront, adjfront); // adjfront may be dummy.
12666               // Get the corresponding face from the new tets.
12667               // j >= 2.
12668               enextfnext(tmpabtetlist[j - 1], newfront); // b.p_j.p_j-1
12669               bond(newfront, adjfront);
12670               if (checksubfaces) {
12671                 tspivot(oldfront, checksh);
12672                 if (checksh.sh != dummysh) {
12673                   tsbond(newfront, checksh);
12674                 }
12675               }
12676             }
12677             // Adjust the faces in the temporary new tets at ab for
12678             //   recursively processing on the n-1 tets.
12679             for (j = 0; j < n - 1; j++) {
12680               fnextself(tmpabtetlist[j]);
12681             }
12682             tmpkey2 = -1;
12683             if (key) tmpkey2 = *key;
12684             if ((n - 1) == 3) {
12685               success = removeedgebyflip32(&tmpkey2, tmpabtetlist,
12686                 &(newtetlist[m - 1]), flipque);
12687             } else { // assert((n - 1) >= 4);
12688               success = removeedgebytranNM(&tmpkey2, n - 1, tmpabtetlist,
12689                 &(newtetlist[m - 1]), NULL, NULL, flipque);
12690             }
12691             // No matter it was success or not, delete the temporary tets.
12692             for (j = 0; j < n - 1; j++) {
12693               tetrahedrondealloc(tmpabtetlist[j].tet);
12694             }
12695             if (success) {
12696               // The new configuration is good.
12697               // Do not delete the old tets.
12698               // for (j = 0; j < n; j++) {
12699               //   tetrahedrondealloc(abtetlist[j].tet);
12700               // }
12701               // Return the bigger dihedral in the two sets of new tets.
12702               if (key != (REAL *) NULL) {
12703                 *key = tmpkey2 < tmpkey ? tmpkey2 : tmpkey;
12704               }
12705               return true;
12706             } else {
12707               // The new configuration is bad, substitue back the old tets.
12708               for (j = 0; j < n; j++) {
12709                 oldfront = abtetlist[(i + j) % n];
12710                 esymself(oldfront);
12711                 enextfnextself(oldfront); // [0]a.p_0.p_n-1, [j]a.p_j.p_j-1.
12712                 sym(oldfront, adjfront); // adjfront may be dummy.
12713                 bond(oldfront, adjfront);
12714                 if (checksubfaces) {
12715                   tspivot(oldfront, checksh);
12716                   if (checksh.sh != dummysh) {
12717                     tsbond(oldfront, checksh);
12718                   }
12719                 }
12720               }
12721               for (j = 0; j < n; j++) {
12722                 oldfront = abtetlist[(i + j) % n];
12723                 esymself(oldfront);
12724                 enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12725                 sym(oldfront, adjfront); // adjfront may be dummy
12726                 bond(oldfront, adjfront);
12727                 if (checksubfaces) {
12728                   tspivot(oldfront, checksh);
12729                   if (checksh.sh != dummysh) {
12730                     tsbond(oldfront, checksh);
12731                   }
12732                 }
12733               }
12734               // Substitute back the old tets of the first flip.
12735               for (j = 0; j < *n1; j++) {
12736                 oldfront = bftetlist[j];
12737                 esymself(oldfront);
12738                 enextfnextself(oldfront);
12739                 sym(oldfront, adjfront); // adjfront may be dummy.
12740                 bond(oldfront, adjfront);
12741                 if (checksubfaces) {
12742                   tspivot(oldfront, checksh);
12743                   if (checksh.sh != dummysh) {
12744                     tsbond(oldfront, checksh);
12745                   }
12746                 }
12747               }
12748               for (j = 0; j < *n1; j++) {
12749                 oldfront = bftetlist[j];
12750                 esymself(oldfront);
12751                 enext2fnextself(oldfront); // [0]b.p_0.p_n-1, [j]b.p_j.p_j-1.
12752                 sym(oldfront, adjfront); // adjfront may be dummy
12753                 bond(oldfront, adjfront);
12754                 if (checksubfaces) {
12755                   tspivot(oldfront, checksh);
12756                   if (checksh.sh != dummysh) {
12757                     tsbond(oldfront, checksh);
12758                   }
12759                 }
12760               }
12761               // Delete the new tets of the first flip. Note that one new
12762               //   tet has already been removed from the list.
12763               for (j = 0; j < m - 1; j++) {
12764                 tetrahedrondealloc(newtetlist[j].tet);
12765               }
12766             } // if (success)
12767           } // if (success)
12768         } // if (doflip)
12769       } // if (ori <= 0.0)
12770     } // for (i = 0; i < n; i++)
12771     // Inverse a and b and the tets configuration.
12772     for (i = 0; i < n; i++) newtetlist[i] = abtetlist[i];
12773     for (i = 0; i < n; i++) {
12774       oldfront = newtetlist[n - i - 1];
12775       esymself(oldfront);
12776       fnextself(oldfront);
12777       abtetlist[i] = oldfront;
12778     }
12779     twice++;
12780   } while (twice < 2);
12781 
12782   return false;
12783 }
12784 
12786 //                                                                           //
12787 // splittetrahedron()    Insert a point into a tetrahedron, split it into    //
12788 //                       four tetrahedra.