00001
00007 #ifndef UNUSED_OPT
00008 #ifdef NDEBUG
00009 #define UNUSED_OPT(var) var=var
00010 #else //NDEBUG
00011 #define UNUSED_OPT(var)
00012 #endif //NDEBUG
00013 #endif //UNUSED_OPT
00014
00015
00016 #include "predicates.hpp"
00017
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00039
00041
00042
00043
00044
00045
00047
00048 #include "tetgen.h"
00049 namespace tetgen
00050 {
00051
00053
00054
00055
00057
00058 void terminatetetgen(int x)
00059 {
00060 #ifdef TETLIBRARY
00061 throw x;
00062 #else
00063 exit(x);
00064 #endif // #ifdef TETLIBRARY
00065 }
00066
00067
00068
00069
00070
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00083
00084 void tetgenio::initialize()
00085 {
00086 firstnumber = 0;
00087 mesh_dim = 3;
00088 useindex = true;
00089
00090 pointlist = (REAL *) NULL;
00091 pointattributelist = (REAL *) NULL;
00092 pointmtrlist = (REAL *) NULL;
00093 pointmarkerlist = (int *) NULL;
00094 numberofpoints = 0;
00095 numberofpointattributes = 0;
00096 numberofpointmtrs = 0;
00097
00098 tetrahedronlist = (int *) NULL;
00099 tetrahedronattributelist = (REAL *) NULL;
00100 tetrahedronvolumelist = (REAL *) NULL;
00101 neighborlist = (int *) NULL;
00102 numberoftetrahedra = 0;
00103 numberofcorners = 4;
00104 numberoftetrahedronattributes = 0;
00105
00106 trifacelist = (int *) NULL;
00107 adjtetlist = (int *) NULL;
00108 trifacemarkerlist = (int *) NULL;
00109 numberoftrifaces = 0;
00110
00111 facetlist = (facet *) NULL;
00112 facetmarkerlist = (int *) NULL;
00113 numberoffacets = 0;
00114
00115 edgelist = (int *) NULL;
00116 edgemarkerlist = (int *) NULL;
00117 numberofedges = 0;
00118
00119 holelist = (REAL *) NULL;
00120 numberofholes = 0;
00121
00122 regionlist = (REAL *) NULL;
00123 numberofregions = 0;
00124
00125 facetconstraintlist = (REAL *) NULL;
00126 numberoffacetconstraints = 0;
00127 segmentconstraintlist = (REAL *) NULL;
00128 numberofsegmentconstraints = 0;
00129
00130 pbcgrouplist = (pbcgroup *) NULL;
00131 numberofpbcgroups = 0;
00132
00133 vpointlist = (REAL *) NULL;
00134 vedgelist = (voroedge *) NULL;
00135 vfacetlist = (vorofacet *) NULL;
00136 vcelllist = (int **) NULL;
00137 numberofvpoints = 0;
00138 numberofvedges = 0;
00139 numberofvfacets = 0;
00140 numberofvcells = 0;
00141 }
00142
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00157
00158 void tetgenio::deinitialize()
00159 {
00160 facet *f;
00161 polygon *p;
00162 pbcgroup *pg;
00163 int i, j;
00164
00165 if (pointlist != (REAL *) NULL) {
00166 delete [] pointlist;
00167 }
00168 if (pointattributelist != (REAL *) NULL) {
00169 delete [] pointattributelist;
00170 }
00171 if (pointmtrlist != (REAL *) NULL) {
00172 delete [] pointmtrlist;
00173 }
00174 if (pointmarkerlist != (int *) NULL) {
00175 delete [] pointmarkerlist;
00176 }
00177
00178 if (tetrahedronlist != (int *) NULL) {
00179 delete [] tetrahedronlist;
00180 }
00181 if (tetrahedronattributelist != (REAL *) NULL) {
00182 delete [] tetrahedronattributelist;
00183 }
00184 if (tetrahedronvolumelist != (REAL *) NULL) {
00185 delete [] tetrahedronvolumelist;
00186 }
00187 if (neighborlist != (int *) NULL) {
00188 delete [] neighborlist;
00189 }
00190
00191 if (trifacelist != (int *) NULL) {
00192 delete [] trifacelist;
00193 }
00194 if (adjtetlist != (int *) NULL) {
00195 delete [] adjtetlist;
00196 }
00197 if (trifacemarkerlist != (int *) NULL) {
00198 delete [] trifacemarkerlist;
00199 }
00200
00201 if (edgelist != (int *) NULL) {
00202 delete [] edgelist;
00203 }
00204 if (edgemarkerlist != (int *) NULL) {
00205 delete [] edgemarkerlist;
00206 }
00207
00208 if (facetlist != (facet *) NULL) {
00209 for (i = 0; i < numberoffacets; i++) {
00210 f = &facetlist[i];
00211 for (j = 0; j < f->numberofpolygons; j++) {
00212 p = &f->polygonlist[j];
00213 delete [] p->vertexlist;
00214 }
00215 delete [] f->polygonlist;
00216 if (f->holelist != (REAL *) NULL) {
00217 delete [] f->holelist;
00218 }
00219 }
00220 delete [] facetlist;
00221 }
00222 if (facetmarkerlist != (int *) NULL) {
00223 delete [] facetmarkerlist;
00224 }
00225
00226 if (holelist != (REAL *) NULL) {
00227 delete [] holelist;
00228 }
00229 if (regionlist != (REAL *) NULL) {
00230 delete [] regionlist;
00231 }
00232 if (facetconstraintlist != (REAL *) NULL) {
00233 delete [] facetconstraintlist;
00234 }
00235 if (segmentconstraintlist != (REAL *) NULL) {
00236 delete [] segmentconstraintlist;
00237 }
00238 if (pbcgrouplist != (pbcgroup *) NULL) {
00239 for (i = 0; i < numberofpbcgroups; i++) {
00240 pg = &(pbcgrouplist[i]);
00241 if (pg->pointpairlist != (int *) NULL) {
00242 delete [] pg->pointpairlist;
00243 }
00244 }
00245 delete [] pbcgrouplist;
00246 }
00247 if (vpointlist != (REAL *) NULL) {
00248 delete [] vpointlist;
00249 }
00250 if (vedgelist != (voroedge *) NULL) {
00251 delete [] vedgelist;
00252 }
00253 if (vfacetlist != (vorofacet *) NULL) {
00254 for (i = 0; i < numberofvfacets; i++) {
00255 delete [] vfacetlist[i].elist;
00256 }
00257 delete [] vfacetlist;
00258 }
00259 if (vcelllist != (int **) NULL) {
00260 for (i = 0; i < numberofvcells; i++) {
00261 delete [] vcelllist[i];
00262 }
00263 delete [] vcelllist;
00264 }
00265 }
00266
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00281
00282 bool tetgenio::load_node_call(FILE* infile, int markers, char* infilename)
00283 {
00284 char inputline[INPUTLINESIZE];
00285 char *stringptr;
00286 REAL x, y, z, attrib;
00287 int firstnode, currentmarker;
00288 int index, attribindex;
00289 int i, j;
00290
00291
00292 pointlist = new REAL[numberofpoints * 3];
00293 if (pointlist == (REAL *) NULL) {
00294 printf("Error: Out of memory.\n");
00295 terminatetetgen(1);
00296 }
00297 if (numberofpointattributes > 0) {
00298 pointattributelist = new REAL[numberofpoints * numberofpointattributes];
00299 if (pointattributelist == (REAL *) NULL) {
00300 printf("Error: Out of memory.\n");
00301 terminatetetgen(1);
00302 }
00303 }
00304 if (markers) {
00305 pointmarkerlist = new int[numberofpoints];
00306 if (pointmarkerlist == (int *) NULL) {
00307 printf("Error: Out of memory.\n");
00308 terminatetetgen(1);
00309 }
00310 }
00311
00312
00313 index = 0;
00314 attribindex = 0;
00315 for (i = 0; i < numberofpoints; i++) {
00316 stringptr = readnumberline(inputline, infile, infilename);
00317 if (useindex) {
00318 if (i == 0) {
00319 firstnode = (int) strtol (stringptr, &stringptr, 0);
00320 if ((firstnode == 0) || (firstnode == 1)) {
00321 firstnumber = firstnode;
00322 }
00323 }
00324 stringptr = findnextnumber(stringptr);
00325 }
00326 if (*stringptr == '\0') {
00327 printf("Error: Point %d has no x coordinate.\n", firstnumber + i);
00328 break;
00329 }
00330 x = (REAL) strtod(stringptr, &stringptr);
00331 stringptr = findnextnumber(stringptr);
00332 if (*stringptr == '\0') {
00333 printf("Error: Point %d has no y coordinate.\n", firstnumber + i);
00334 break;
00335 }
00336 y = (REAL) strtod(stringptr, &stringptr);
00337 if (mesh_dim == 3) {
00338 stringptr = findnextnumber(stringptr);
00339 if (*stringptr == '\0') {
00340 printf("Error: Point %d has no z coordinate.\n", firstnumber + i);
00341 break;
00342 }
00343 z = (REAL) strtod(stringptr, &stringptr);
00344 } else {
00345 z = 0.0;
00346 }
00347 pointlist[index++] = x;
00348 pointlist[index++] = y;
00349 pointlist[index++] = z;
00350
00351 for (j = 0; j < numberofpointattributes; j++) {
00352 stringptr = findnextnumber(stringptr);
00353 if (*stringptr == '\0') {
00354 attrib = 0.0;
00355 } else {
00356 attrib = (REAL) strtod(stringptr, &stringptr);
00357 }
00358 pointattributelist[attribindex++] = attrib;
00359 }
00360 if (markers) {
00361
00362 stringptr = findnextnumber(stringptr);
00363 if (*stringptr == '\0') {
00364 currentmarker = 0;
00365 } else {
00366 currentmarker = (int) strtol (stringptr, &stringptr, 0);
00367 }
00368 pointmarkerlist[i] = currentmarker;
00369 }
00370 }
00371 if (i < numberofpoints) {
00372
00373 delete [] pointlist;
00374 pointlist = (REAL *) NULL;
00375 if (markers) {
00376 delete [] pointmarkerlist;
00377 pointmarkerlist = (int *) NULL;
00378 }
00379 if (numberofpointattributes > 0) {
00380 delete [] pointattributelist;
00381 pointattributelist = (REAL *) NULL;
00382 }
00383 numberofpoints = 0;
00384 return false;
00385 }
00386 return true;
00387 }
00388
00390
00391
00392
00393
00394
00395
00397
00398 bool tetgenio::load_node(char* filename)
00399 {
00400 FILE *infile;
00401 char innodefilename[FILENAMESIZE];
00402 char inputline[INPUTLINESIZE];
00403 char *stringptr;
00404 int markers;
00405
00406 markers = 0;
00407
00408 strcpy(innodefilename, filename);
00409 strcat(innodefilename, ".node");
00410
00411
00412 infile = fopen(innodefilename, "r");
00413 if (infile == (FILE *) NULL) {
00414 printf("File I/O Error: Cannot access file %s.\n", innodefilename);
00415 return false;
00416 }
00417 printf("Opening %s.\n", innodefilename);
00418
00419 stringptr = readnumberline(inputline, infile, innodefilename);
00420
00421 stringptr = strstr(inputline, "rbox");
00422 if (stringptr == NULL) {
00423
00424
00425 stringptr = inputline;
00426 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00427 stringptr = findnextnumber(stringptr);
00428 if (*stringptr == '\0') {
00429 mesh_dim = 3;
00430 } else {
00431 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00432 }
00433 stringptr = findnextnumber(stringptr);
00434 if (*stringptr == '\0') {
00435 numberofpointattributes = 0;
00436 } else {
00437 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00438 }
00439 stringptr = findnextnumber(stringptr);
00440 if (*stringptr == '\0') {
00441 markers = 0;
00442 } else {
00443 markers = (int) strtol (stringptr, &stringptr, 0);
00444 }
00445 } else {
00446
00447 stringptr = inputline;
00448
00449 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00450
00451 stringptr = readnumberline(inputline, infile, innodefilename);
00452 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00453
00454 useindex = 0;
00455 }
00456
00457
00458
00459
00460
00461
00462 if (numberofpoints < (mesh_dim + 1)) {
00463 printf("Input error: TetGen needs at least %d points.\n", mesh_dim + 1);
00464 fclose(infile);
00465 return false;
00466 }
00467
00468
00469 if (!load_node_call(infile, markers, innodefilename)) {
00470 fclose(infile);
00471 return false;
00472 }
00473 fclose(infile);
00474 return true;
00475 }
00476
00478
00479
00480
00481
00482
00483
00484
00485
00487
00488 bool tetgenio::load_pbc(char* filename)
00489 {
00490 FILE *infile;
00491 char pbcfilename[FILENAMESIZE];
00492 char inputline[INPUTLINESIZE];
00493 char *stringptr;
00494 pbcgroup *pg;
00495 int index, p1, p2;
00496 int i, j, k;
00497
00498
00499 strcpy(pbcfilename, filename);
00500 strcat(pbcfilename, ".pbc");
00501 infile = fopen(pbcfilename, "r");
00502 if (infile != (FILE *) NULL) {
00503 printf("Opening %s.\n", pbcfilename);
00504 } else {
00505
00506 return false;
00507 }
00508
00509
00510 stringptr = readnumberline(inputline, infile, pbcfilename);
00511 numberofpbcgroups = (int) strtol (stringptr, &stringptr, 0);
00512 if (numberofpbcgroups == 0) {
00513
00514 fclose(infile);
00515 return false;
00516 }
00517
00518 pbcgrouplist = new pbcgroup[numberofpbcgroups];
00519
00520
00521 for (i = 0; i < numberofpbcgroups; i++) {
00522 pg = &(pbcgrouplist[i]);
00523
00524 pg->numberofpointpairs = 0;
00525 pg->pointpairlist = (int *) NULL;
00526
00527 stringptr = readnumberline(inputline, infile, pbcfilename);
00528 if (*stringptr == '\0') break;
00529 pg->fmark1 = (int) strtol(stringptr, &stringptr, 0);
00530 stringptr = findnextnumber(stringptr);
00531 if (*stringptr == '\0') break;
00532 pg->fmark2 = (int) strtol(stringptr, &stringptr, 0);
00533
00534 do {
00535 stringptr = readline(inputline, infile, NULL);
00536 } while ((*stringptr != '[') && (*stringptr != '\0'));
00537 if (*stringptr == '\0') break;
00538 for (j = 0; j < 4; j++) {
00539 for (k = 0; k < 4; k++) {
00540
00541 stringptr = findnextnumber(stringptr);
00542 if (*stringptr == '\0') {
00543
00544 stringptr = readnumberline(inputline, infile, pbcfilename);
00545 if (*stringptr == '\0') break;
00546 }
00547 pg->transmat[j][k] = (REAL) strtod(stringptr, &stringptr);
00548 }
00549 if (k < 4) break;
00550 }
00551 if (j < 4) break;
00552
00553 stringptr = readnumberline(inputline, infile, pbcfilename);
00554 if (*stringptr == '\0') break;
00555 pg->numberofpointpairs = (int) strtol(stringptr, &stringptr, 0);
00556 if (pg->numberofpointpairs > 0) {
00557 pg->pointpairlist = new int[pg->numberofpointpairs * 2];
00558
00559 index = 0;
00560 for (j = 0; j < pg->numberofpointpairs; j++) {
00561 stringptr = readnumberline(inputline, infile, pbcfilename);
00562 p1 = (int) strtol(stringptr, &stringptr, 0);
00563 stringptr = findnextnumber(stringptr);
00564 p2 = (int) strtol(stringptr, &stringptr, 0);
00565 pg->pointpairlist[index++] = p1;
00566 pg->pointpairlist[index++] = p2;
00567 }
00568 }
00569 }
00570 fclose(infile);
00571
00572 if (i < numberofpbcgroups) {
00573
00574 delete [] pbcgrouplist;
00575 pbcgrouplist = (pbcgroup *) NULL;
00576 numberofpbcgroups = 0;
00577 return false;
00578 }
00579 return true;
00580 }
00581
00583
00584
00585
00586
00587
00588
00590
00591 bool tetgenio::load_var(char* filename)
00592 {
00593 FILE *infile;
00594 char varfilename[FILENAMESIZE];
00595 char inputline[INPUTLINESIZE];
00596 char *stringptr;
00597 int index;
00598 int i;
00599
00600
00601 strcpy(varfilename, filename);
00602 strcat(varfilename, ".var");
00603 infile = fopen(varfilename, "r");
00604 if (infile != (FILE *) NULL) {
00605 printf("Opening %s.\n", varfilename);
00606 } else {
00607
00608 return false;
00609 }
00610
00611
00612 stringptr = readnumberline(inputline, infile, varfilename);
00613 if (*stringptr != '\0') {
00614 numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0);
00615 } else {
00616 numberoffacetconstraints = 0;
00617 }
00618 if (numberoffacetconstraints > 0) {
00619
00620 facetconstraintlist = new REAL[numberoffacetconstraints * 2];
00621 index = 0;
00622 for (i = 0; i < numberoffacetconstraints; i++) {
00623 stringptr = readnumberline(inputline, infile, varfilename);
00624 stringptr = findnextnumber(stringptr);
00625 if (*stringptr == '\0') {
00626 printf("Error: facet constraint %d has no facet marker.\n",
00627 firstnumber + i);
00628 break;
00629 } else {
00630 facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00631 }
00632 stringptr = findnextnumber(stringptr);
00633 if (*stringptr == '\0') {
00634 printf("Error: facet constraint %d has no maximum area bound.\n",
00635 firstnumber + i);
00636 break;
00637 } else {
00638 facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00639 }
00640 }
00641 if (i < numberoffacetconstraints) {
00642
00643 fclose(infile);
00644 return false;
00645 }
00646 }
00647
00648
00649 stringptr = readnumberline(inputline, infile, varfilename);
00650 if (*stringptr != '\0') {
00651 numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0);
00652 } else {
00653 numberofsegmentconstraints = 0;
00654 }
00655 if (numberofsegmentconstraints > 0) {
00656
00657 segmentconstraintlist = new REAL[numberofsegmentconstraints * 3];
00658 index = 0;
00659 for (i = 0; i < numberofsegmentconstraints; i++) {
00660 stringptr = readnumberline(inputline, infile, varfilename);
00661 stringptr = findnextnumber(stringptr);
00662 if (*stringptr == '\0') {
00663 printf("Error: segment constraint %d has no frist endpoint.\n",
00664 firstnumber + i);
00665 break;
00666 } else {
00667 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00668 }
00669 stringptr = findnextnumber(stringptr);
00670 if (*stringptr == '\0') {
00671 printf("Error: segment constraint %d has no second endpoint.\n",
00672 firstnumber + i);
00673 break;
00674 } else {
00675 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00676 }
00677 stringptr = findnextnumber(stringptr);
00678 if (*stringptr == '\0') {
00679 printf("Error: segment constraint %d has no maximum length bound.\n",
00680 firstnumber + i);
00681 break;
00682 } else {
00683 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00684 }
00685 }
00686 if (i < numberofsegmentconstraints) {
00687
00688 fclose(infile);
00689 return false;
00690 }
00691 }
00692
00693 fclose(infile);
00694 return true;
00695 }
00696
00698
00699
00700
00701
00702
00703
00705
00706 bool tetgenio::load_mtr(char* filename)
00707 {
00708 FILE *infile;
00709 char mtrfilename[FILENAMESIZE];
00710 char inputline[INPUTLINESIZE];
00711 char *stringptr;
00712 REAL mtr;
00713 int mtrindex;
00714 int i, j;
00715
00716 strcpy(mtrfilename, filename);
00717 strcat(mtrfilename, ".mtr");
00718 infile = fopen(mtrfilename, "r");
00719 if (infile != (FILE *) NULL) {
00720 printf("Opening %s.\n", mtrfilename);
00721 } else {
00722
00723 return false;
00724 }
00725
00726
00727 stringptr = readnumberline(inputline, infile, mtrfilename);
00728 stringptr = findnextnumber(stringptr);
00729 if (*stringptr != '\0') {
00730 numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0);
00731 }
00732 if (numberofpointmtrs == 0) {
00733
00734 numberofpointmtrs = 1;
00735 }
00736
00737
00738 pointmtrlist = new REAL[numberofpoints * numberofpointmtrs];
00739 if (pointmtrlist == (REAL *) NULL) {
00740 printf("Error: Out of memory.\n");
00741 terminatetetgen(1);
00742 }
00743 mtrindex = 0;
00744 for (i = 0; i < numberofpoints; i++) {
00745
00746 stringptr = readnumberline(inputline, infile, mtrfilename);
00747 for (j = 0; j < numberofpointmtrs; j++) {
00748 if (*stringptr == '\0') {
00749 printf("Error: Metric %d is missing value #%d in %s.\n",
00750 i + firstnumber, j + 1, mtrfilename);
00751 terminatetetgen(1);
00752 }
00753 mtr = (REAL) strtod(stringptr, &stringptr);
00754 pointmtrlist[mtrindex++] = mtr;
00755 stringptr = findnextnumber(stringptr);
00756 }
00757 }
00758
00759 fclose(infile);
00760 return true;
00761 }
00762
00764
00765
00766
00767
00768
00769
00770
00772
00773 bool tetgenio::load_poly(char* filename)
00774 {
00775 FILE *infile, *polyfile;
00776 char innodefilename[FILENAMESIZE];
00777 char inpolyfilename[FILENAMESIZE];
00778 char insmeshfilename[FILENAMESIZE];
00779 char inputline[INPUTLINESIZE];
00780 char *stringptr, *infilename;
00781 int smesh, markers, currentmarker;
00782 int readnodefile, index;
00783 int i, j, k;
00784
00785
00786 strcpy(innodefilename, filename);
00787 strcpy(inpolyfilename, filename);
00788 strcpy(insmeshfilename, filename);
00789 strcat(innodefilename, ".node");
00790 strcat(inpolyfilename, ".poly");
00791 strcat(insmeshfilename, ".smesh");
00792
00793
00794 smesh = 0;
00795
00796 polyfile = fopen(inpolyfilename, "r");
00797 if (polyfile == (FILE *) NULL) {
00798
00799 polyfile = fopen(insmeshfilename, "r");
00800 if (polyfile == (FILE *) NULL) {
00801 printf("File I/O Error: Cannot access file %s and %s.\n",
00802 inpolyfilename, insmeshfilename);
00803 return false;
00804 } else {
00805 printf("Opening %s.\n", insmeshfilename);
00806 }
00807 smesh = 1;
00808 } else {
00809 printf("Opening %s.\n", inpolyfilename);
00810 }
00811
00812 mesh_dim = 3;
00813 numberofpointattributes = 0;
00814 markers = 0;
00815
00816
00817 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00818 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00819 stringptr = findnextnumber(stringptr);
00820 if (*stringptr != '\0') {
00821 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00822 }
00823 stringptr = findnextnumber(stringptr);
00824 if (*stringptr != '\0') {
00825 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00826 }
00827 stringptr = findnextnumber(stringptr);
00828 if (*stringptr != '\0') {
00829 markers = (int) strtol (stringptr, &stringptr, 0);
00830 }
00831 if (numberofpoints > 0) {
00832 readnodefile = 0;
00833 if (smesh) {
00834 infilename = insmeshfilename;
00835 } else {
00836 infilename = inpolyfilename;
00837 }
00838 infile = polyfile;
00839 } else {
00840
00841
00842 readnodefile = 1;
00843 infilename = innodefilename;
00844 }
00845
00846 if (readnodefile) {
00847
00848 printf("Opening %s.\n", innodefilename);
00849 infile = fopen(innodefilename, "r");
00850 if (infile == (FILE *) NULL) {
00851 printf("File I/O Error: Cannot access file %s.\n", innodefilename);
00852 return false;
00853 }
00854
00855 mesh_dim = 3;
00856 numberofpointattributes = 0;
00857 markers = 0;
00858
00859
00860 stringptr = readnumberline(inputline, infile, innodefilename);
00861 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00862 stringptr = findnextnumber(stringptr);
00863 if (*stringptr != '\0') {
00864 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00865 }
00866 stringptr = findnextnumber(stringptr);
00867 if (*stringptr != '\0') {
00868 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00869 }
00870 stringptr = findnextnumber(stringptr);
00871 if (*stringptr != '\0') {
00872 markers = (int) strtol (stringptr, &stringptr, 0);
00873 }
00874 }
00875
00876 if ((mesh_dim != 3) && (mesh_dim != 2)) {
00877 printf("Input error: TetGen only works for 2D & 3D point sets.\n");
00878 fclose(infile);
00879 return false;
00880 }
00881 if (numberofpoints < (mesh_dim + 1)) {
00882 printf("Input error: TetGen needs at least %d points.\n", mesh_dim + 1);
00883 fclose(infile);
00884 return false;
00885 }
00886
00887
00888 if (!load_node_call(infile, markers, infilename)) {
00889 fclose(infile);
00890 return false;
00891 }
00892
00893 if (readnodefile) {
00894 fclose(infile);
00895 }
00896
00897 facet *f;
00898 polygon *p;
00899
00900 if (mesh_dim == 3) {
00901
00902
00903 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00904 numberoffacets = (int) strtol (stringptr, &stringptr, 0);
00905 if (numberoffacets <= 0) {
00906
00907 fclose(polyfile);
00908 return true;
00909 }
00910 stringptr = findnextnumber(stringptr);
00911 if (*stringptr == '\0') {
00912 markers = 0;
00913 } else {
00914 markers = (int) strtol (stringptr, &stringptr, 0);
00915 }
00916
00917
00918 facetlist = new facet[numberoffacets];
00919 if (markers == 1) {
00920 facetmarkerlist = new int[numberoffacets];
00921 }
00922
00923
00924 if (smesh == 0) {
00925
00926 for (i = 1; i <= numberoffacets; i++) {
00927 f = &(facetlist[i - 1]);
00928 init(f);
00929 f->numberofholes = 0;
00930 currentmarker = 0;
00931
00932 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00933 f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
00934 stringptr = findnextnumber(stringptr);
00935 if (*stringptr != '\0') {
00936 f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
00937 if (markers == 1) {
00938 stringptr = findnextnumber(stringptr);
00939 if (*stringptr != '\0') {
00940 currentmarker = (int) strtol(stringptr, &stringptr, 0);
00941 }
00942 }
00943 }
00944
00945 if (markers == 1) {
00946 facetmarkerlist[i - 1] = currentmarker;
00947 }
00948
00949 if (f->numberofpolygons <= 0) {
00950 printf("Error: Wrong number of polygon in %d facet.\n", i);
00951 break;
00952 }
00953
00954 f->polygonlist = new polygon[f->numberofpolygons];
00955
00956 for (j = 1; j <= f->numberofpolygons; j++) {
00957 p = &(f->polygonlist[j - 1]);
00958 init(p);
00959
00960 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00961 p->numberofvertices = (int) strtol(stringptr, &stringptr, 0);
00962 if (p->numberofvertices < 1) {
00963 printf("Error: Wrong polygon %d in facet %d\n", j, i);
00964 break;
00965 }
00966
00967 p->vertexlist = new int[p->numberofvertices];
00968
00969 for (k = 1; k <= p->numberofvertices; k++) {
00970 stringptr = findnextnumber(stringptr);
00971 if (*stringptr == '\0') {
00972
00973
00974 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00975 if (*stringptr == '\0') {
00976 printf("Error: Missing %d endpoints of polygon %d in facet %d",
00977 p->numberofvertices - k, j, i);
00978 break;
00979 }
00980 }
00981 p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
00982 }
00983 }
00984 if (j <= f->numberofpolygons) {
00985
00986
00987 if (j == 1) {
00988
00989 delete [] f->polygonlist;
00990 }
00991 f->numberofpolygons = j - 1;
00992
00993 f->numberofholes = 0;
00994 break;
00995 }
00996
00997 if (f->numberofholes > 0) {
00998
00999 f->holelist = new REAL[f->numberofholes * 3];
01000
01001 index = 0;
01002 for (j = 1; j <= f->numberofholes; j++) {
01003 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01004 for (k = 1; k <= 3; k++) {
01005 stringptr = findnextnumber(stringptr);
01006 if (*stringptr == '\0') {
01007 printf("Error: Hole %d in facet %d has no coordinates", j, i);
01008 break;
01009 }
01010 f->holelist[index++] = (REAL) strtod (stringptr, &stringptr);
01011 }
01012 if (k <= 3) {
01013
01014 break;
01015 }
01016 }
01017 if (j <= f->numberofholes) {
01018
01019 break;
01020 }
01021 }
01022 }
01023 if (i <= numberoffacets) {
01024
01025 numberoffacets = i - 1;
01026 fclose(polyfile);
01027 return false;
01028 }
01029 } else {
01030
01031 for (i = 1; i <= numberoffacets; i++) {
01032 f = &(facetlist[i - 1]);
01033 init(f);
01034
01035
01036 f->numberofpolygons = 1;
01037 f->polygonlist = new polygon[f->numberofpolygons];
01038 p = &(f->polygonlist[0]);
01039 init(p);
01040
01041 stringptr = readnumberline(inputline, polyfile, insmeshfilename);
01042 p->numberofvertices = (int) strtol (stringptr, &stringptr, 0);
01043 if (p->numberofvertices < 1) {
01044 printf("Error: Wrong number of vertex in facet %d\n", i);
01045 break;
01046 }
01047
01048 p->vertexlist = new int[p->numberofvertices];
01049 for (k = 1; k <= p->numberofvertices; k++) {
01050 stringptr = findnextnumber(stringptr);
01051 if (*stringptr == '\0') {
01052
01053
01054 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01055 if (*stringptr == '\0') {
01056 printf("Error: Missing %d endpoints in facet %d",
01057 p->numberofvertices - k, i);
01058 break;
01059 }
01060 }
01061 p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
01062 }
01063 if (k <= p->numberofvertices) {
01064
01065 break;
01066 }
01067
01068 if (markers == 1) {
01069 stringptr = findnextnumber(stringptr);
01070 if (*stringptr == '\0') {
01071 currentmarker = 0;
01072 } else {
01073 currentmarker = (int) strtol(stringptr, &stringptr, 0);
01074 }
01075 facetmarkerlist[i - 1] = currentmarker;
01076 }
01077 }
01078 if (i <= numberoffacets) {
01079
01080 numberoffacets = i - 1;
01081 fclose(polyfile);
01082 return false;
01083 }
01084 }
01085
01086
01087 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01088 if (*stringptr != '\0') {
01089 numberofholes = (int) strtol (stringptr, &stringptr, 0);
01090 } else {
01091 numberofholes = 0;
01092 }
01093 if (numberofholes > 0) {
01094
01095 holelist = new REAL[numberofholes * 3];
01096 for (i = 0; i < 3 * numberofholes; i += 3) {
01097 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01098 stringptr = findnextnumber(stringptr);
01099 if (*stringptr == '\0') {
01100 printf("Error: Hole %d has no x coord.\n", firstnumber + (i / 3));
01101 break;
01102 } else {
01103 holelist[i] = (REAL) strtod(stringptr, &stringptr);
01104 }
01105 stringptr = findnextnumber(stringptr);
01106 if (*stringptr == '\0') {
01107 printf("Error: Hole %d has no y coord.\n", firstnumber + (i / 3));
01108 break;
01109 } else {
01110 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
01111 }
01112 stringptr = findnextnumber(stringptr);
01113 if (*stringptr == '\0') {
01114 printf("Error: Hole %d has no z coord.\n", firstnumber + (i / 3));
01115 break;
01116 } else {
01117 holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
01118 }
01119 }
01120 if (i < 3 * numberofholes) {
01121
01122 fclose(polyfile);
01123 return false;
01124 }
01125 }
01126
01127
01128
01129 stringptr = readnumberline(inputline, polyfile, NULL);
01130 if (stringptr != (char *) NULL && *stringptr != '\0') {
01131 numberofregions = (int) strtol (stringptr, &stringptr, 0);
01132 } else {
01133 numberofregions = 0;
01134 }
01135 if (numberofregions > 0) {
01136
01137 regionlist = new REAL[numberofregions * 5];
01138 index = 0;
01139 for (i = 0; i < numberofregions; i++) {
01140 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01141 stringptr = findnextnumber(stringptr);
01142 if (*stringptr == '\0') {
01143 printf("Error: Region %d has no x coordinate.\n", firstnumber + i);
01144 break;
01145 } else {
01146 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01147 }
01148 stringptr = findnextnumber(stringptr);
01149 if (*stringptr == '\0') {
01150 printf("Error: Region %d has no y coordinate.\n", firstnumber + i);
01151 break;
01152 } else {
01153 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01154 }
01155 stringptr = findnextnumber(stringptr);
01156 if (*stringptr == '\0') {
01157 printf("Error: Region %d has no z coordinate.\n", firstnumber + i);
01158 break;
01159 } else {
01160 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01161 }
01162 stringptr = findnextnumber(stringptr);
01163 if (*stringptr == '\0') {
01164 printf("Error: Region %d has no region attrib.\n", firstnumber + i);
01165 break;
01166 } else {
01167 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01168 }
01169 stringptr = findnextnumber(stringptr);
01170 if (*stringptr == '\0') {
01171 regionlist[index] = regionlist[index - 1];
01172 } else {
01173 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
01174 }
01175 index++;
01176 }
01177 if (i < numberofregions) {
01178
01179 fclose(polyfile);
01180 return false;
01181 }
01182 }
01183
01184 } else {
01185
01186
01187 assert(mesh_dim == 2);
01188
01189 numberoffacets = 1;
01190
01191 facetlist = new facet[numberoffacets];
01192 facetmarkerlist = (int *) NULL;
01193 f = &(facetlist[0]);
01194 init(f);
01195
01196 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01197
01198 f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
01199 if (f->numberofpolygons > 0) {
01200 f->polygonlist = new polygon[f->numberofpolygons];
01201 }
01202
01203 for (j = 0; j < f->numberofpolygons; j++) {
01204 p = &(f->polygonlist[j]);
01205 init(p);
01206
01207 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01208 stringptr = findnextnumber(stringptr);
01209 p->numberofvertices = 2;
01210 p->vertexlist = new int[p->numberofvertices];
01211 p->vertexlist[0] = (int) strtol (stringptr, &stringptr, 0);
01212 stringptr = findnextnumber(stringptr);
01213 p->vertexlist[1] = (int) strtol (stringptr, &stringptr, 0);
01214 }
01215
01216 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01217 f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
01218 if (f->numberofholes > 0) {
01219
01220 f->holelist = new REAL[f->numberofholes * 3];
01221
01222 for (j = 0; j < f->numberofholes; j++) {
01223
01224 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01225 stringptr = findnextnumber(stringptr);
01226 f->holelist[j * 3] = (REAL) strtod (stringptr, &stringptr);
01227 stringptr = findnextnumber(stringptr);
01228 f->holelist[j * 3 + 1] = (REAL) strtod (stringptr, &stringptr);
01229 f->holelist[j * 3 + 2] = 0.0;
01230 }
01231 }
01232
01233
01234 }
01235
01236
01237 fclose(polyfile);
01238
01239
01240 load_var(filename);
01241
01242 load_mtr(filename);
01243
01244 load_pbc(filename);
01245
01246 return true;
01247 }
01248
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01262
01263 bool tetgenio::load_off(char* filename)
01264 {
01265 FILE *fp;
01266 tetgenio::facet *f;
01267 tetgenio::polygon *p;
01268 char infilename[FILENAMESIZE];
01269 char buffer[INPUTLINESIZE];
01270 char *bufferp;
01271 double *coord;
01272 int nverts = 0, iverts = 0;
01273 int nfaces = 0, ifaces = 0;
01274 int nedges = 0;
01275 int line_count = 0, i;
01276
01277 strncpy(infilename, filename, 1024 - 1);
01278 infilename[FILENAMESIZE - 1] = '\0';
01279 if (infilename[0] == '\0') {
01280 printf("Error: No filename.\n");
01281 return false;
01282 }
01283 if (strcmp(&infilename[strlen(infilename) - 4], ".off") != 0) {
01284 strcat(infilename, ".off");
01285 }
01286
01287 if (!(fp = fopen(infilename, "r"))) {
01288 printf("File I/O Error: Unable to open file %s\n", infilename);
01289 return false;
01290 }
01291 printf("Opening %s.\n", infilename);
01292
01293
01294 firstnumber = 0;
01295
01296 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01297
01298 if (nverts == 0) {
01299
01300 bufferp = strstr(bufferp, "OFF");
01301 if (bufferp != NULL) {
01302
01303 bufferp = findnextnumber(bufferp);
01304 if (*bufferp == '\0') {
01305
01306 bufferp = readline(buffer, fp, &line_count);
01307 }
01308 if ((sscanf(bufferp, "%d%d%d", &nverts, &nfaces, &nedges) != 3)
01309 || (nverts == 0)) {
01310 printf("Syntax error reading header on line %d in file %s\n",
01311 line_count, infilename);
01312 fclose(fp);
01313 return false;
01314 }
01315
01316 if (nverts > 0) {
01317 numberofpoints = nverts;
01318 pointlist = new REAL[nverts * 3];
01319 }
01320 if (nfaces > 0) {
01321 numberoffacets = nfaces;
01322 facetlist = new tetgenio::facet[nfaces];
01323 }
01324 }
01325 } else if (iverts < nverts) {
01326
01327 coord = &pointlist[iverts * 3];
01328 for (i = 0; i < 3; i++) {
01329 if (*bufferp == '\0') {
01330 printf("Syntax error reading vertex coords on line %d in file %s\n",
01331 line_count, infilename);
01332 fclose(fp);
01333 return false;
01334 }
01335 coord[i] = (REAL) strtod(bufferp, &bufferp);
01336 bufferp = findnextnumber(bufferp);
01337 }
01338 iverts++;
01339 } else if (ifaces < nfaces) {
01340
01341 f = &facetlist[ifaces];
01342 init(f);
01343
01344 f->numberofpolygons = 1;
01345 f->polygonlist = new tetgenio::polygon[1];
01346 p = &f->polygonlist[0];
01347 init(p);
01348
01349 p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01350 if (p->numberofvertices == 0) {
01351 printf("Syntax error reading polygon on line %d in file %s\n",
01352 line_count, infilename);
01353 fclose(fp);
01354 return false;
01355 }
01356
01357 p->vertexlist = new int[p->numberofvertices];
01358 for (i = 0; i < p->numberofvertices; i++) {
01359 bufferp = findnextnumber(bufferp);
01360 if (*bufferp == '\0') {
01361 printf("Syntax error reading polygon on line %d in file %s\n",
01362 line_count, infilename);
01363 fclose(fp);
01364 return false;
01365 }
01366 p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01367 }
01368 ifaces++;
01369 } else {
01370
01371 printf("Found extra text starting at line %d in file %s\n", line_count,
01372 infilename);
01373 break;
01374 }
01375 }
01376
01377
01378 fclose(fp);
01379
01380
01381 if (iverts != nverts) {
01382 printf("Expected %d vertices, but read only %d vertices in file %s\n",
01383 nverts, iverts, infilename);
01384 return false;
01385 }
01386
01387
01388 if (ifaces != nfaces) {
01389 printf("Expected %d faces, but read only %d faces in file %s\n",
01390 nfaces, ifaces, infilename);
01391 return false;
01392 }
01393
01394 return true;
01395 }
01396
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01415
01416 bool tetgenio::load_ply(char* filename)
01417 {
01418 FILE *fp;
01419 tetgenio::facet *f;
01420 tetgenio::polygon *p;
01421 char infilename[FILENAMESIZE];
01422 char buffer[INPUTLINESIZE];
01423 char *bufferp, *str;
01424 double *coord;
01425 int endheader = 0, format = 0;
01426 int nverts = 0, iverts = 0;
01427 int nfaces = 0, ifaces = 0;
01428 int line_count = 0, i;
01429
01430 strncpy(infilename, filename, FILENAMESIZE - 1);
01431 infilename[FILENAMESIZE - 1] = '\0';
01432 if (infilename[0] == '\0') {
01433 printf("Error: No filename.\n");
01434 return false;
01435 }
01436 if (strcmp(&infilename[strlen(infilename) - 4], ".ply") != 0) {
01437 strcat(infilename, ".ply");
01438 }
01439
01440 if (!(fp = fopen(infilename, "r"))) {
01441 printf("Error: Unable to open file %s\n", infilename);
01442 return false;
01443 }
01444 printf("Opening %s.\n", infilename);
01445
01446
01447 firstnumber = 0;
01448
01449 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01450 if (!endheader) {
01451
01452 str = strstr(bufferp, "end_header");
01453
01454 if (!str) str = strstr(bufferp, "End_header");
01455 if (!str) str = strstr(bufferp, "End_Header");
01456 if (str) {
01457
01458 endheader = 1;
01459 continue;
01460 }
01461
01462 if (nverts == 0 || nfaces == 0) {
01463
01464 str = strstr(bufferp, "element");
01465 if (!str) str = strstr(bufferp, "Element");
01466 if (str) {
01467 bufferp = findnextfield(str);
01468 if (*bufferp == '\0') {
01469 printf("Syntax error reading element type on line%d in file %s\n",
01470 line_count, infilename);
01471 fclose(fp);
01472 return false;
01473 }
01474 if (nverts == 0) {
01475
01476 str = strstr(bufferp, "vertex");
01477 if (!str) str = strstr(bufferp, "Vertex");
01478 if (str) {
01479 bufferp = findnextnumber(str);
01480 if (*bufferp == '\0') {
01481 printf("Syntax error reading vertex number on line");
01482 printf(" %d in file %s\n", line_count, infilename);
01483 fclose(fp);
01484 return false;
01485 }
01486 nverts = (int) strtol(bufferp, &bufferp, 0);
01487
01488 if (nverts > 0) {
01489 numberofpoints = nverts;
01490 pointlist = new REAL[nverts * 3];
01491 }
01492 }
01493 }
01494 if (nfaces == 0) {
01495
01496 str = strstr(bufferp, "face");
01497 if (!str) str = strstr(bufferp, "Face");
01498 if (str) {
01499 bufferp = findnextnumber(str);
01500 if (*bufferp == '\0') {
01501 printf("Syntax error reading face number on line");
01502 printf(" %d in file %s\n", line_count, infilename);
01503 fclose(fp);
01504 return false;
01505 }
01506 nfaces = (int) strtol(bufferp, &bufferp, 0);
01507
01508 if (nfaces > 0) {
01509 numberoffacets = nfaces;
01510 facetlist = new tetgenio::facet[nfaces];
01511 }
01512 }
01513 }
01514 }
01515 }
01516 if (format == 0) {
01517
01518 str = strstr(bufferp, "format");
01519 if (!str) str = strstr(bufferp, "Format");
01520 if (str) {
01521 format = 1;
01522 bufferp = findnextfield(str);
01523
01524 str = strstr(bufferp, "ascii");
01525 if (!str) str = strstr(bufferp, "ASCII");
01526 if (!str) {
01527 printf("This routine only reads ascii format of ply files.\n");
01528 printf("Hint: You can convert the binary to ascii format by\n");
01529 printf(" using the provided ply tools:\n");
01530 printf(" ply2ascii < %s > ascii_%s\n", infilename, infilename);
01531 fclose(fp);
01532 return false;
01533 }
01534 }
01535 }
01536 } else if (iverts < nverts) {
01537
01538 coord = &pointlist[iverts * 3];
01539 for (i = 0; i < 3; i++) {
01540 if (*bufferp == '\0') {
01541 printf("Syntax error reading vertex coords on line %d in file %s\n",
01542 line_count, infilename);
01543 fclose(fp);
01544 return false;
01545 }
01546 coord[i] = (REAL) strtod(bufferp, &bufferp);
01547 bufferp = findnextnumber(bufferp);
01548 }
01549 iverts++;
01550 } else if (ifaces < nfaces) {
01551
01552 f = &facetlist[ifaces];
01553 init(f);
01554
01555 f->numberofpolygons = 1;
01556 f->polygonlist = new tetgenio::polygon[1];
01557 p = &f->polygonlist[0];
01558 init(p);
01559
01560 p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01561 if (p->numberofvertices == 0) {
01562 printf("Syntax error reading polygon on line %d in file %s\n",
01563 line_count, infilename);
01564 fclose(fp);
01565 return false;
01566 }
01567
01568 p->vertexlist = new int[p->numberofvertices];
01569 for (i = 0; i < p->numberofvertices; i++) {
01570 bufferp = findnextnumber(bufferp);
01571 if (*bufferp == '\0') {
01572 printf("Syntax error reading polygon on line %d in file %s\n",
01573 line_count, infilename);
01574 fclose(fp);
01575 return false;
01576 }
01577 p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01578 }
01579 ifaces++;
01580 } else {
01581
01582 printf("Found extra text starting at line %d in file %s\n", line_count,
01583 infilename);
01584 break;
01585 }
01586 }
01587
01588
01589 fclose(fp);
01590
01591
01592 if (iverts != nverts) {
01593 printf("Expected %d vertices, but read only %d vertices in file %s\n",
01594 nverts, iverts, infilename);
01595 return false;
01596 }
01597
01598
01599 if (ifaces != nfaces) {
01600 printf("Expected %d faces, but read only %d faces in file %s\n",
01601 nfaces, ifaces, infilename);
01602 return false;
01603 }
01604
01605 return true;
01606 }
01607
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01625
01626 bool tetgenio::load_stl(char* filename)
01627 {
01628 FILE *fp;
01629 tetgenmesh::list *plist;
01630 tetgenio::facet *f;
01631 tetgenio::polygon *p;
01632 char infilename[FILENAMESIZE];
01633 char buffer[INPUTLINESIZE];
01634 char *bufferp, *str;
01635 double *coord;
01636 int solid = 0;
01637 int nverts = 0, iverts = 0;
01638 int nfaces = 0;
01639 int line_count = 0, i;
01640
01641 strncpy(infilename, filename, FILENAMESIZE - 1);
01642 infilename[FILENAMESIZE - 1] = '\0';
01643 if (infilename[0] == '\0') {
01644 printf("Error: No filename.\n");
01645 return false;
01646 }
01647 if (strcmp(&infilename[strlen(infilename) - 4], ".stl") != 0) {
01648 strcat(infilename, ".stl");
01649 }
01650
01651 if (!(fp = fopen(infilename, "r"))) {
01652 printf("Error: Unable to open file %s\n", infilename);
01653 return false;
01654 }
01655 printf("Opening %s.\n", infilename);
01656
01657
01658 plist = new tetgenmesh::list(sizeof(double) * 3, NULL, 1024);
01659
01660 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01661
01662
01663 if (solid == 0) {
01664
01665 bufferp = strstr(bufferp, "solid");
01666 if (bufferp != NULL) {
01667 solid = 1;
01668 }
01669 } else {
01670
01671 str = bufferp;
01672
01673 bufferp = strstr(bufferp, "endsolid");
01674 if (bufferp != NULL) {
01675 solid = 0;
01676 } else {
01677
01678 bufferp = str;
01679 bufferp = strstr(bufferp, "vertex");
01680 if (bufferp != NULL) {
01681 coord = (double *) plist->append(NULL);
01682 for (i = 0; i < 3; i++) {
01683 bufferp = findnextnumber(bufferp);
01684 if (*bufferp == '\0') {
01685 printf("Syntax error reading vertex coords on line %d\n",
01686 line_count);
01687 delete plist;
01688 fclose(fp);
01689 return false;
01690 }
01691 coord[i] = (REAL) strtod(bufferp, &bufferp);
01692 }
01693 }
01694 }
01695 }
01696 }
01697 fclose(fp);
01698
01699 nverts = plist->len();
01700
01701 if (nverts == 0 || (nverts % 3 != 0)) {
01702 printf("Error: Wrong number of vertices in file %s.\n", infilename);
01703 delete plist;
01704 return false;
01705 }
01706 numberofpoints = nverts;
01707 pointlist = new REAL[nverts * 3];
01708 for (i = 0; i < nverts; i++) {
01709 coord = (double *) (* plist)[i];
01710 iverts = i * 3;
01711 pointlist[iverts] = (REAL) coord[0];
01712 pointlist[iverts + 1] = (REAL) coord[1];
01713 pointlist[iverts + 2] = (REAL) coord[2];
01714 }
01715
01716 nfaces = (int) (nverts / 3);
01717 numberoffacets = nfaces;
01718 facetlist = new tetgenio::facet[nfaces];
01719
01720
01721 firstnumber = 1;
01722 iverts = firstnumber;
01723 for (i = 0; i < nfaces; i++) {
01724 f = &facetlist[i];
01725 init(f);
01726
01727 f->numberofpolygons = 1;
01728 f->polygonlist = new tetgenio::polygon[1];
01729 p = &f->polygonlist[0];
01730 init(p);
01731
01732 p->numberofvertices = 3;
01733 p->vertexlist = new int[p->numberofvertices];
01734 p->vertexlist[0] = iverts;
01735 p->vertexlist[1] = iverts + 1;
01736 p->vertexlist[2] = iverts + 2;
01737 iverts += 3;
01738 }
01739
01740 delete plist;
01741 return true;
01742 }
01743
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01756
01757 bool tetgenio::load_medit(char* filename)
01758 {
01759 FILE *fp;
01760 tetgenio::facet *tmpflist, *f;
01761 tetgenio::polygon *p;
01762 char infilename[FILENAMESIZE];
01763 char buffer[INPUTLINESIZE];
01764 char *bufferp, *str;
01765 double *coord;
01766 int *tmpfmlist;
01767 int dimension = 0;
01768 int nverts = 0;
01769 int nfaces = 0;
01770 int line_count = 0;
01771 int corners = 0;
01772 int i, j;
01773
01774 strncpy(infilename, filename, FILENAMESIZE - 1);
01775 infilename[FILENAMESIZE - 1] = '\0';
01776 if (infilename[0] == '\0') {
01777 printf("Error: No filename.\n");
01778 return false;
01779 }
01780 if (strcmp(&infilename[strlen(infilename) - 5], ".mesh") != 0) {
01781 strcat(infilename, ".mesh");
01782 }
01783
01784 if (!(fp = fopen(infilename, "r"))) {
01785 printf("Error: Unable to open file %s\n", infilename);
01786 return false;
01787 }
01788 printf("Opening %s.\n", infilename);
01789
01790
01791 firstnumber = 1;
01792
01793 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01794 if (*bufferp == '#') continue;
01795 if (dimension == 0) {
01796
01797 str = strstr(bufferp, "Dimension");
01798 if (!str) str = strstr(bufferp, "dimension");
01799 if (!str) str = strstr(bufferp, "DIMENSION");
01800 if (str) {
01801
01802 bufferp = findnextnumber(str);
01803 if (*bufferp == '\0') {
01804
01805 bufferp = readline(buffer, fp, &line_count);
01806 }
01807 dimension = (int) strtol(bufferp, &bufferp, 0);
01808 if (dimension != 2 && dimension != 3) {
01809 printf("Unknown dimension in file on line %d in file %s\n",
01810 line_count, infilename);
01811 fclose(fp);
01812 return false;
01813 }
01814 mesh_dim = dimension;
01815 }
01816 }
01817 if (nverts == 0) {
01818
01819 str = strstr(bufferp, "Vertices");
01820 if (!str) str = strstr(bufferp, "vertices");
01821 if (!str) str = strstr(bufferp, "VERTICES");
01822 if (str) {
01823
01824 bufferp = findnextnumber(str);
01825 if (*bufferp == '\0') {
01826
01827 bufferp = readline(buffer, fp, &line_count);
01828 }
01829 nverts = (int) strtol(bufferp, &bufferp, 0);
01830
01831 if (nverts > 0) {
01832 numberofpoints = nverts;
01833 pointlist = new REAL[nverts * 3];
01834 }
01835
01836 for (i = 0; i < nverts; i++) {
01837 bufferp = readline(buffer, fp, &line_count);
01838 if (bufferp == NULL) {
01839 printf("Unexpected end of file on line %d in file %s\n",
01840 line_count, infilename);
01841 fclose(fp);
01842 return false;
01843 }
01844
01845 coord = &pointlist[i * 3];
01846 for (j = 0; j < 3; j++) {
01847 if (*bufferp == '\0') {
01848 printf("Syntax error reading vertex coords on line");
01849 printf(" %d in file %s\n", line_count, infilename);
01850 fclose(fp);
01851 return false;
01852 }
01853 if ((j < 2) || (dimension == 3)) {
01854 coord[j] = (REAL) strtod(bufferp, &bufferp);
01855 } else {
01856 assert((j == 2) && (dimension == 2));
01857 coord[j] = 0.0;
01858 }
01859 bufferp = findnextnumber(bufferp);
01860 }
01861 }
01862 continue;
01863 }
01864 }
01865 if (nfaces == 0) {
01866
01867 corners = 0;
01868 str = strstr(bufferp, "Triangles");
01869 if (!str) str = strstr(bufferp, "triangles");
01870 if (!str) str = strstr(bufferp, "TRIANGLES");
01871 if (str) {
01872 corners = 3;
01873 } else {
01874 str = strstr(bufferp, "Quadrilaterals");
01875 if (!str) str = strstr(bufferp, "quadrilaterals");
01876 if (!str) str = strstr(bufferp, "QUADRILATERALS");
01877 if (str) {
01878 corners = 4;
01879 }
01880 }
01881 if (corners == 3 || corners == 4) {
01882
01883 bufferp = findnextnumber(str);
01884 if (*bufferp == '\0') {
01885
01886 bufferp = readline(buffer, fp, &line_count);
01887 }
01888 nfaces = strtol(bufferp, &bufferp, 0);
01889
01890 if (nfaces > 0) {
01891 if (numberoffacets > 0) {
01892
01893 tmpflist = new tetgenio::facet[numberoffacets + nfaces];
01894 tmpfmlist = new int[numberoffacets + nfaces];
01895
01896 for (i = 0; i < numberoffacets; i++) {
01897 f = &(tmpflist[i]);
01898 tetgenio::init(f);
01899 *f = facetlist[i];
01900 tmpfmlist[i] = facetmarkerlist[i];
01901 }
01902
01903 delete [] facetlist;
01904 delete [] facetmarkerlist;
01905
01906 facetlist = tmpflist;
01907 facetmarkerlist = tmpfmlist;
01908 } else {
01909
01910 facetlist = new tetgenio::facet[nfaces];
01911 facetmarkerlist = new int[nfaces];
01912 }
01913 }
01914
01915 for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
01916 bufferp = readline(buffer, fp, &line_count);
01917 if (bufferp == NULL) {
01918 printf("Unexpected end of file on line %d in file %s\n",
01919 line_count, infilename);
01920 fclose(fp);
01921 return false;
01922 }
01923 f = &facetlist[i];
01924 tetgenio::init(f);
01925
01926 f->numberofpolygons = 1;
01927 f->polygonlist = new tetgenio::polygon[1];
01928 p = &f->polygonlist[0];
01929 tetgenio::init(p);
01930 p->numberofvertices = corners;
01931
01932 p->vertexlist = new int[p->numberofvertices];
01933
01934 for (j = 0; j < corners; j++) {
01935 if (*bufferp == '\0') {
01936 printf("Syntax error reading face on line %d in file %s\n",
01937 line_count, infilename);
01938 fclose(fp);
01939 return false;
01940 }
01941 p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0);
01942 if (firstnumber == 1) {
01943
01944 if (p->vertexlist[j] == 0) {
01945
01946 firstnumber = 0;
01947 }
01948 }
01949 bufferp = findnextnumber(bufferp);
01950 }
01951
01952 facetmarkerlist[i] = 0;
01953 if (*bufferp != '\0') {
01954 facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
01955 }
01956 }
01957
01958 numberoffacets += nfaces;
01959 nfaces = 0;
01960 }
01961 }
01962
01963 }
01964
01965
01966 fclose(fp);
01967
01968 return true;
01969 }
01970
01972
01973
01974
01975
01976
01977
01978
01980
01981 bool tetgenio::load_plc(char* filename, int object)
01982 {
01983 enum tetgenbehavior::objecttype type;
01984
01985 type = (enum tetgenbehavior::objecttype) object;
01986 switch (type) {
01987 case tetgenbehavior::NODES:
01988 return load_node(filename);
01989 case tetgenbehavior::POLY:
01990 return load_poly(filename);
01991 case tetgenbehavior::OFF:
01992 return load_off(filename);
01993 case tetgenbehavior::PLY:
01994 return load_ply(filename);
01995 case tetgenbehavior::STL:
01996 return load_stl(filename);
01997 case tetgenbehavior::MEDIT:
01998 return load_medit(filename);
01999 default:
02000 return load_poly(filename);
02001 }
02002 }
02003
02005
02006
02007
02008
02009
02010
02011
02013
02014 bool tetgenio::load_tetmesh(char* filename)
02015 {
02016 FILE *infile;
02017 char innodefilename[FILENAMESIZE];
02018 char inelefilename[FILENAMESIZE];
02019 char infacefilename[FILENAMESIZE];
02020 char inedgefilename[FILENAMESIZE];
02021 char involfilename[FILENAMESIZE];
02022 char inputline[INPUTLINESIZE];
02023 char *stringptr, *infilename;
02024 REAL attrib, volume;
02025 int volelements;
02026 int markers, corner;
02027 int index, attribindex;
02028 int i, j;
02029
02030 markers = 0;
02031
02032
02033 strcpy(innodefilename, filename);
02034 strcpy(inelefilename, filename);
02035 strcpy(infacefilename, filename);
02036 strcpy(inedgefilename, filename);
02037 strcpy(involfilename, filename);
02038 strcat(innodefilename, ".node");
02039 strcat(inelefilename, ".ele");
02040 strcat(infacefilename, ".face");
02041 strcat(inedgefilename, ".edge");
02042 strcat(involfilename, ".vol");
02043
02044
02045 infilename = innodefilename;
02046 printf("Opening %s.\n", infilename);
02047 infile = fopen(infilename, "r");
02048 if (infile == (FILE *) NULL) {
02049 printf("File I/O Error: Cannot access file %s.\n", infilename);
02050 return false;
02051 }
02052
02053 stringptr = readnumberline(inputline, infile, infilename);
02054
02055 stringptr = strstr(inputline, "rbox");
02056 if (stringptr == NULL) {
02057
02058
02059 stringptr = inputline;
02060 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02061 stringptr = findnextnumber(stringptr);
02062 if (*stringptr == '\0') {
02063 mesh_dim = 3;
02064 } else {
02065 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02066 }
02067 stringptr = findnextnumber(stringptr);
02068 if (*stringptr == '\0') {
02069 numberofpointattributes = 0;
02070 } else {
02071 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
02072 }
02073 stringptr = findnextnumber(stringptr);
02074 if (*stringptr == '\0') {
02075 markers = 0;
02076 } else {
02077 markers = (int) strtol (stringptr, &stringptr, 0);
02078 }
02079 } else {
02080
02081 stringptr = inputline;
02082
02083 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02084
02085 stringptr = readnumberline(inputline, infile, infilename);
02086 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02087
02088 useindex = 0;
02089 }
02090
02091
02092 if (!load_node_call(infile, markers, infilename)) {
02093 fclose(infile);
02094 return false;
02095 }
02096 fclose(infile);
02097
02098
02099 if (mesh_dim == 3) {
02100 infilename = inelefilename;
02101 infile = fopen(infilename, "r");
02102 if (infile != (FILE *) NULL) {
02103 printf("Opening %s.\n", infilename);
02104
02105
02106 stringptr = readnumberline(inputline, infile, infilename);
02107 numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0);
02108 stringptr = findnextnumber(stringptr);
02109 if (*stringptr == '\0') {
02110 numberofcorners = 4;
02111 } else {
02112 numberofcorners = (int) strtol(stringptr, &stringptr, 0);
02113 }
02114 stringptr = findnextnumber(stringptr);
02115 if (*stringptr == '\0') {
02116 numberoftetrahedronattributes = 0;
02117 } else {
02118 numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0);
02119 }
02120 if (numberofcorners != 4 && numberofcorners != 10) {
02121 printf("Error: Wrong number of corners %d (should be 4 or 10).\n",
02122 numberofcorners);
02123 fclose(infile);
02124 return false;
02125 }
02126
02127 if (numberoftetrahedra > 0) {
02128 tetrahedronlist = new int[numberoftetrahedra * numberofcorners];
02129 if (tetrahedronlist == (int *) NULL) {
02130 printf("Error: Out of memory.\n");
02131 terminatetetgen(1);
02132 }
02133
02134 if (numberoftetrahedronattributes > 0) {
02135 tetrahedronattributelist = new REAL[numberoftetrahedra *
02136 numberoftetrahedronattributes];
02137 if (tetrahedronattributelist == (REAL *) NULL) {
02138 printf("Error: Out of memory.\n");
02139 terminatetetgen(1);
02140 }
02141 }
02142 }
02143
02144 index = 0;
02145 attribindex = 0;
02146 for (i = 0; i < numberoftetrahedra; i++) {
02147
02148 stringptr = readnumberline(inputline, infile, infilename);
02149 for (j = 0; j < numberofcorners; j++) {
02150 stringptr = findnextnumber(stringptr);
02151 if (*stringptr == '\0') {
02152 printf("Error: Tetrahedron %d is missing vertex %d in %s.\n",
02153 i + firstnumber, j + 1, infilename);
02154 terminatetetgen(1);
02155 }
02156 corner = (int) strtol(stringptr, &stringptr, 0);
02157 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02158 printf("Error: Tetrahedron %d has an invalid vertex index.\n",
02159 i + firstnumber);
02160 terminatetetgen(1);
02161 }
02162 tetrahedronlist[index++] = corner;
02163 }
02164
02165 for (j = 0; j < numberoftetrahedronattributes; j++) {
02166 stringptr = findnextnumber(stringptr);
02167 if (*stringptr == '\0') {
02168 attrib = 0.0;
02169 } else {
02170 attrib = (REAL) strtod(stringptr, &stringptr);
02171 }
02172 tetrahedronattributelist[attribindex++] = attrib;
02173 }
02174 }
02175 fclose(infile);
02176 }
02177 }
02178
02179
02180 if (mesh_dim == 3) {
02181 infilename = infacefilename;
02182 } else {
02183 infilename = inelefilename;
02184 }
02185 infile = fopen(infilename, "r");
02186 if (infile != (FILE *) NULL) {
02187 printf("Opening %s.\n", infilename);
02188
02189 stringptr = readnumberline(inputline, infile, infilename);
02190 numberoftrifaces = (int) strtol (stringptr, &stringptr, 0);
02191 stringptr = findnextnumber(stringptr);
02192 if (mesh_dim == 2) {
02193
02194 stringptr = findnextnumber(stringptr);
02195 }
02196 if (*stringptr == '\0') {
02197 markers = 0;
02198 } else {
02199 markers = (int) strtol (stringptr, &stringptr, 0);
02200 }
02201 if (numberoftrifaces > 0) {
02202 trifacelist = new int[numberoftrifaces * 3];
02203 if (trifacelist == (int *) NULL) {
02204 printf("Error: Out of memory.\n");
02205 terminatetetgen(1);
02206 }
02207 if (markers) {
02208 trifacemarkerlist = new int[numberoftrifaces * 3];
02209 if (trifacemarkerlist == (int *) NULL) {
02210 printf("Error: Out of memory.\n");
02211 terminatetetgen(1);
02212 }
02213 }
02214 }
02215
02216 index = 0;
02217 for (i = 0; i < numberoftrifaces; i++) {
02218
02219 stringptr = readnumberline(inputline, infile, infilename);
02220 for (j = 0; j < 3; j++) {
02221 stringptr = findnextnumber(stringptr);
02222 if (*stringptr == '\0') {
02223 printf("Error: Face %d is missing vertex %d in %s.\n",
02224 i + firstnumber, j + 1, infilename);
02225 terminatetetgen(1);
02226 }
02227 corner = (int) strtol(stringptr, &stringptr, 0);
02228 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02229 printf("Error: Face %d has an invalid vertex index.\n",
02230 i + firstnumber);
02231 terminatetetgen(1);
02232 }
02233 trifacelist[index++] = corner;
02234 }
02235
02236 if (markers) {
02237 stringptr = findnextnumber(stringptr);
02238 if (*stringptr == '\0') {
02239 attrib = 0.0;
02240 } else {
02241 attrib = (REAL) strtod(stringptr, &stringptr);
02242 }
02243 trifacemarkerlist[i] = (int) attrib;
02244 }
02245 }
02246 fclose(infile);
02247 }
02248
02249
02250 infilename = inedgefilename;
02251 infile = fopen(infilename, "r");
02252 if (infile != (FILE *) NULL) {
02253 printf("Opening %s.\n", infilename);
02254
02255 stringptr = readnumberline(inputline, infile, infilename);
02256 numberofedges = (int) strtol (stringptr, &stringptr, 0);
02257 if (numberofedges > 0) {
02258 edgelist = new int[numberofedges * 2];
02259 if (edgelist == (int *) NULL) {
02260 printf("Error: Out of memory.\n");
02261 terminatetetgen(1);
02262 }
02263 }
02264
02265 index = 0;
02266 for (i = 0; i < numberofedges; i++) {
02267
02268 stringptr = readnumberline(inputline, infile, infilename);
02269 for (j = 0; j < 2; j++) {
02270 stringptr = findnextnumber(stringptr);
02271 if (*stringptr == '\0') {
02272 printf("Error: Edge %d is missing vertex %d in %s.\n",
02273 i + firstnumber, j + 1, infilename);
02274 terminatetetgen(1);
02275 }
02276 corner = (int) strtol(stringptr, &stringptr, 0);
02277 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02278 printf("Error: Edge %d has an invalid vertex index.\n",
02279 i + firstnumber);
02280 terminatetetgen(1);
02281 }
02282 edgelist[index++] = corner;
02283 }
02284 }
02285 fclose(infile);
02286 }
02287
02288
02289 infilename = involfilename;
02290 infile = fopen(infilename, "r");
02291 if (infile != (FILE *) NULL) {
02292 printf("Opening %s.\n", infilename);
02293
02294 stringptr = readnumberline(inputline, infile, infilename);
02295 volelements = (int) strtol (stringptr, &stringptr, 0);
02296 if (volelements != numberoftetrahedra) {
02297 printf("Warning: %s and %s disagree on number of tetrahedra.\n",
02298 inelefilename, involfilename);
02299 volelements = 0;
02300 }
02301 if (volelements > 0) {
02302 tetrahedronvolumelist = new REAL[volelements];
02303 if (tetrahedronvolumelist == (REAL *) NULL) {
02304 printf("Error: Out of memory.\n");
02305 terminatetetgen(1);
02306 }
02307 }
02308
02309 for (i = 0; i < volelements; i++) {
02310 stringptr = readnumberline(inputline, infile, infilename);
02311 stringptr = findnextnumber(stringptr);
02312 if (*stringptr == '\0') {
02313 volume = -1.0;
02314 } else {
02315 volume = (REAL) strtod(stringptr, &stringptr);
02316 }
02317 tetrahedronvolumelist[i] = volume;
02318 }
02319 fclose(infile);
02320 }
02321
02322
02323 load_mtr(filename);
02324
02325 load_pbc(filename);
02326
02327 return true;
02328 }
02329
02331
02332
02333
02334
02335
02336
02338
02339 bool tetgenio::load_voronoi(char* filename)
02340 {
02341 FILE *infile;
02342 char innodefilename[FILENAMESIZE];
02343 char inedgefilename[FILENAMESIZE];
02344 char inputline[INPUTLINESIZE];
02345 char *stringptr, *infilename;
02346 voroedge *vedge;
02347 REAL x, y, z;
02348 int firstnode, corner;
02349 int index;
02350 int i, j;
02351
02352
02353 strcpy(innodefilename, filename);
02354 strcpy(inedgefilename, filename);
02355 strcat(innodefilename, ".v.node");
02356 strcat(inedgefilename, ".v.edge");
02357
02358
02359 infilename = innodefilename;
02360 printf("Opening %s.\n", infilename);
02361 infile = fopen(infilename, "r");
02362 if (infile == (FILE *) NULL) {
02363 printf("File I/O Error: Cannot access file %s.\n", infilename);
02364 return false;
02365 }
02366
02367 stringptr = readnumberline(inputline, infile, infilename);
02368
02369 stringptr = strstr(inputline, "rbox");
02370 if (stringptr == NULL) {
02371
02372
02373 stringptr = inputline;
02374 numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02375 stringptr = findnextnumber(stringptr);
02376 if (*stringptr == '\0') {
02377 mesh_dim = 3;
02378 } else {
02379 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02380 }
02381 useindex = 1;
02382 } else {
02383
02384 stringptr = inputline;
02385
02386 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02387
02388 stringptr = readnumberline(inputline, infile, infilename);
02389 numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02390 useindex = 0;
02391 }
02392
02393 vpointlist = new REAL[numberofvpoints * 3];
02394 if (vpointlist == (REAL *) NULL) {
02395 printf("Error: Out of memory.\n");
02396 terminatetetgen(1);
02397 }
02398
02399 index = 0;
02400 for (i = 0; i < numberofvpoints; i++) {
02401 stringptr = readnumberline(inputline, infile, infilename);
02402 if (useindex) {
02403 if (i == 0) {
02404 firstnode = (int) strtol (stringptr, &stringptr, 0);
02405 if ((firstnode == 0) || (firstnode == 1)) {
02406 firstnumber = firstnode;
02407 }
02408 }
02409 stringptr = findnextnumber(stringptr);
02410 }
02411 if (*stringptr == '\0') {
02412 printf("Error: Point %d has no x coordinate.\n", firstnumber + i);
02413 terminatetetgen(1);
02414 }
02415 x = (REAL) strtod(stringptr, &stringptr);
02416 stringptr = findnextnumber(stringptr);
02417 if (*stringptr == '\0') {
02418 printf("Error: Point %d has no y coordinate.\n", firstnumber + i);
02419 terminatetetgen(1);
02420 }
02421 y = (REAL) strtod(stringptr, &stringptr);
02422 if (mesh_dim == 3) {
02423 stringptr = findnextnumber(stringptr);
02424 if (*stringptr == '\0') {
02425 printf("Error: Point %d has no z coordinate.\n", firstnumber + i);
02426 terminatetetgen(1);
02427 }
02428 z = (REAL) strtod(stringptr, &stringptr);
02429 } else {
02430 z = 0.0;
02431 }
02432 vpointlist[index++] = x;
02433 vpointlist[index++] = y;
02434 vpointlist[index++] = z;
02435 }
02436 fclose(infile);
02437
02438
02439 infilename = inedgefilename;
02440 infile = fopen(infilename, "r");
02441 if (infile != (FILE *) NULL) {
02442 printf("Opening %s.\n", infilename);
02443
02444 stringptr = readnumberline(inputline, infile, infilename);
02445 numberofvedges = (int) strtol (stringptr, &stringptr, 0);
02446 if (numberofvedges > 0) {
02447 vedgelist = new voroedge[numberofvedges];
02448 }
02449
02450 index = 0;
02451 for (i = 0; i < numberofvedges; i++) {
02452
02453 stringptr = readnumberline(inputline, infile, infilename);
02454 vedge = &(vedgelist[i]);
02455 for (j = 0; j < 2; j++) {
02456 stringptr = findnextnumber(stringptr);
02457 if (*stringptr == '\0') {
02458 printf("Error: Edge %d is missing vertex %d in %s.\n",
02459 i + firstnumber, j + 1, infilename);
02460 terminatetetgen(1);
02461 }
02462 corner = (int) strtol(stringptr, &stringptr, 0);
02463 j == 0 ? vedge->v1 = corner : vedge->v2 = corner;
02464 }
02465 if (vedge->v2 < 0) {
02466 for (j = 0; j < mesh_dim; j++) {
02467 stringptr = findnextnumber(stringptr);
02468 if (*stringptr == '\0') {
02469 printf("Error: Edge %d is missing normal in %s.\n",
02470 i + firstnumber, infilename);
02471 terminatetetgen(1);
02472 }
02473 vedge->vnormal[j] = (REAL) strtod(stringptr, &stringptr);
02474 }
02475 if (mesh_dim == 2) {
02476 vedge->vnormal[2] = 0.0;
02477 }
02478 } else {
02479 vedge->vnormal[0] = 0.0;
02480 vedge->vnormal[1] = 0.0;
02481 vedge->vnormal[2] = 0.0;
02482 }
02483 }
02484 fclose(infile);
02485 }
02486
02487 return true;
02488 }
02489
02491
02492
02493
02494
02495
02497
02498 void tetgenio::save_nodes(char* filename)
02499 {
02500 FILE *fout;
02501 char outnodefilename[FILENAMESIZE];
02502 char outmtrfilename[FILENAMESIZE];
02503 int i, j;
02504
02505 sprintf(outnodefilename, "%s.node", filename);
02506 printf("Saving nodes to %s\n", outnodefilename);
02507 fout = fopen(outnodefilename, "w");
02508 fprintf(fout, "%d %d %d %d\n", numberofpoints, mesh_dim,
02509 numberofpointattributes, pointmarkerlist != NULL ? 1 : 0);
02510 for (i = 0; i < numberofpoints; i++) {
02511 if (mesh_dim == 2) {
02512 fprintf(fout, "%d %.16g %.16g", i + firstnumber, pointlist[i * 2],
02513 pointlist[i * 2 + 1]);
02514 } else {
02515 fprintf(fout, "%d %.16g %.16g %.16g", i + firstnumber,
02516 pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
02517 }
02518 for (j = 0; j < numberofpointattributes; j++) {
02519 fprintf(fout, " %.16g",
02520 pointattributelist[i * numberofpointattributes + j]);
02521 }
02522 if (pointmarkerlist != NULL) {
02523 fprintf(fout, " %d", pointmarkerlist[i]);
02524 }
02525 fprintf(fout, "\n");
02526 }
02527 fclose(fout);
02528
02529
02530 if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
02531 sprintf(outmtrfilename, "%s.mtr", filename);
02532 printf("Saving metrics to %s\n", outmtrfilename);
02533 fout = fopen(outmtrfilename, "w");
02534 fprintf(fout, "%d %d\n", numberofpoints, numberofpointmtrs);
02535 for (i = 0; i < numberofpoints; i++) {
02536 for (j = 0; j < numberofpointmtrs; j++) {
02537 fprintf(fout, "%.16g ", pointmtrlist[i * numberofpointmtrs + j]);
02538 }
02539 fprintf(fout, "\n");
02540 }
02541 fclose(fout);
02542 }
02543 }
02544
02546
02547
02548
02549
02550
02552
02553 void tetgenio::save_elements(char* filename)
02554 {
02555 FILE *fout;
02556 char outelefilename[FILENAMESIZE];
02557 int i, j;
02558
02559 sprintf(outelefilename, "%s.ele", filename);
02560 printf("Saving elements to %s\n", outelefilename);
02561 fout = fopen(outelefilename, "w");
02562 fprintf(fout, "%d %d %d\n", numberoftetrahedra, numberofcorners,
02563 numberoftetrahedronattributes);
02564 for (i = 0; i < numberoftetrahedra; i++) {
02565 fprintf(fout, "%d", i + firstnumber);
02566 for (j = 0; j < numberofcorners; j++) {
02567 fprintf(fout, " %5d", tetrahedronlist[i * numberofcorners + j]);
02568 }
02569 for (j = 0; j < numberoftetrahedronattributes; j++) {
02570 fprintf(fout, " %g",
02571 tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
02572 }
02573 fprintf(fout, "\n");
02574 }
02575
02576 fclose(fout);
02577 }
02578
02580
02581
02582
02583
02584
02586
02587 void tetgenio::save_faces(char* filename)
02588 {
02589 FILE *fout;
02590 char outfacefilename[FILENAMESIZE];
02591 int i;
02592
02593 sprintf(outfacefilename, "%s.face", filename);
02594 printf("Saving faces to %s\n", outfacefilename);
02595 fout = fopen(outfacefilename, "w");
02596 fprintf(fout, "%d %d\n", numberoftrifaces,
02597 trifacemarkerlist != NULL ? 1 : 0);
02598 for (i = 0; i < numberoftrifaces; i++) {
02599 fprintf(fout, "%d %5d %5d %5d", i + firstnumber, trifacelist[i * 3],
02600 trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
02601 if (trifacemarkerlist != NULL) {
02602 fprintf(fout, " %d", trifacemarkerlist[i]);
02603 }
02604 fprintf(fout, "\n");
02605 }
02606
02607 fclose(fout);
02608 }
02609
02611
02612
02613
02614
02615
02617
02618 void tetgenio::save_edges(char* filename)
02619 {
02620 FILE *fout;
02621 char outedgefilename[FILENAMESIZE];
02622 int i;
02623
02624 sprintf(outedgefilename, "%s.edge", filename);
02625 printf("Saving edges to %s\n", outedgefilename);
02626 fout = fopen(outedgefilename, "w");
02627 fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02628 for (i = 0; i < numberofedges; i++) {
02629 fprintf(fout, "%d %4d %4d", i + firstnumber, edgelist[i * 2],
02630 edgelist[i * 2 + 1]);
02631 if (edgemarkerlist != NULL) {
02632 fprintf(fout, " %d", edgemarkerlist[i]);
02633 }
02634 fprintf(fout, "\n");
02635 }
02636
02637 fclose(fout);
02638 }
02639
02641
02642
02643
02644
02645
02647
02648 void tetgenio::save_neighbors(char* filename)
02649 {
02650 FILE *fout;
02651 char outneighborfilename[FILENAMESIZE];
02652 int i;
02653
02654 sprintf(outneighborfilename, "%s.neigh", filename);
02655 printf("Saving neighbors to %s\n", outneighborfilename);
02656 fout = fopen(outneighborfilename, "w");
02657 fprintf(fout, "%d %d\n", numberoftetrahedra, mesh_dim + 1);
02658 for (i = 0; i < numberoftetrahedra; i++) {
02659 if (mesh_dim == 2) {
02660 fprintf(fout, "%d %5d %5d %5d", i + firstnumber, neighborlist[i * 3],
02661 neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]);
02662 } else {
02663 fprintf(fout, "%d %5d %5d %5d %5d", i + firstnumber,
02664 neighborlist[i * 4], neighborlist[i * 4 + 1],
02665 neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]);
02666 }
02667 fprintf(fout, "\n");
02668 }
02669
02670 fclose(fout);
02671 }
02672
02674
02675
02676
02677
02678
02679
02680
02682
02683 void tetgenio::save_poly(char* filename)
02684 {
02685 FILE *fout;
02686 facet *f;
02687 polygon *p;
02688 char outpolyfilename[FILENAMESIZE];
02689 int i, j, k;
02690
02691 sprintf(outpolyfilename, "%s.poly", filename);
02692 printf("Saving poly to %s\n", outpolyfilename);
02693 fout = fopen(outpolyfilename, "w");
02694
02695
02696
02697
02698 fprintf(fout, "%d %d %d %d\n", 0, mesh_dim, numberofpointattributes,
02699 pointmarkerlist != NULL ? 1 : 0);
02700
02701
02702 if (mesh_dim == 2) {
02703
02704 fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02705 for (i = 0; i < numberofedges; i++) {
02706 fprintf(fout, "%d %4d %4d", i + firstnumber, edgelist[i * 2],
02707 edgelist[i * 2 + 1]);
02708 if (edgemarkerlist != NULL) {
02709 fprintf(fout, " %d", edgemarkerlist[i]);
02710 }
02711 fprintf(fout, "\n");
02712 }
02713 } else {
02714
02715 fprintf(fout, "%d %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0);
02716 for (i = 0; i < numberoffacets; i++) {
02717 f = &(facetlist[i]);
02718 fprintf(fout, "%d %d %d # %d\n", f->numberofpolygons,f->numberofholes,
02719 facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber);
02720
02721 for (j = 0; j < f->numberofpolygons; j++) {
02722 p = &(f->polygonlist[j]);
02723 fprintf(fout, "%d ", p->numberofvertices);
02724 for (k = 0; k < p->numberofvertices; k++) {
02725 if (((k + 1) % 10) == 0) {
02726 fprintf(fout, "\n ");
02727 }
02728 fprintf(fout, " %d", p->vertexlist[k]);
02729 }
02730 fprintf(fout, "\n");
02731 }
02732
02733 for (j = 0; j < f->numberofholes; j++) {
02734 fprintf(fout, "%d %.12g %.12g %.12g\n", j + firstnumber,
02735 f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]);
02736 }
02737 }
02738 }
02739
02740
02741 fprintf(fout, "%d\n", numberofholes);
02742 for (i = 0; i < numberofholes; i++) {
02743
02744 fprintf(fout, "%d %.12g %.12g", i + firstnumber, holelist[i * mesh_dim],
02745 holelist[i * mesh_dim + 1]);
02746 if (mesh_dim == 3) {
02747
02748 fprintf(fout, " %.12g", holelist[i * mesh_dim + 2]);
02749 }
02750 fprintf(fout, "\n");
02751 }
02752
02753
02754 fprintf(fout, "%d\n", numberofregions);
02755 for (i = 0; i < numberofregions; i++) {
02756 if (mesh_dim == 2) {
02757
02758
02759 fprintf(fout, "%d %.12g %.12g %.12g %.12g\n", i + firstnumber,
02760 regionlist[i * 4], regionlist[i * 4 + 1],
02761 regionlist[i * 4 + 2], regionlist[i * 4 + 3]);
02762 } else {
02763
02764
02765 fprintf(fout, "%d %.12g %.12g %.12g %.12g %.12g\n", i + firstnumber,
02766 regionlist[i * 5], regionlist[i * 5 + 1],
02767 regionlist[i * 5 + 2], regionlist[i * 5 + 3],
02768 regionlist[i * 5 + 4]);
02769 }
02770 }
02771
02772 fclose(fout);
02773 }
02774
02776
02777
02778
02779
02780
02781
02782
02783
02784
02786
02787 char* tetgenio::readline(char *string, FILE *infile, int *linenumber)
02788 {
02789 char *result;
02790
02791
02792 do {
02793 result = fgets(string, INPUTLINESIZE - 1, infile);
02794 if (linenumber) (*linenumber)++;
02795 if (result == (char *) NULL) {
02796 return (char *) NULL;
02797 }
02798
02799 while ((*result == ' ') || (*result == '\t')) result++;
02800
02801 } while (*result == '\0');
02802 return result;
02803 }
02804
02806
02807
02808
02809
02810
02811
02813
02814 char* tetgenio::findnextfield(char *string)
02815 {
02816 char *result;
02817
02818 result = string;
02819
02820 while ((*result != '\0') && (*result != ' ') && (*result != '\t') &&
02821 (*result != ',') && (*result != ';')) {
02822 result++;
02823 }
02824
02825
02826 while ((*result == ' ') || (*result == '\t') || (*result == ',') ||
02827 (*result == ';')) {
02828 result++;
02829 }
02830 return result;
02831 }
02832
02834
02835
02836
02837
02838
02839
02841
02842 char* tetgenio::readnumberline(char *string, FILE *infile, char *infilename)
02843 {
02844 char *result;
02845
02846
02847 do {
02848 result = fgets(string, INPUTLINESIZE, infile);
02849 if (result == (char *) NULL) {
02850 if (infilename != (char *) NULL) {
02851 printf(" Error: Unexpected end of file in %s.\n", infilename);
02852 terminatetetgen(1);
02853 }
02854 return result;
02855 }
02856
02857
02858 while ((*result != '\0') && (*result != '#')
02859 && (*result != '.') && (*result != '+') && (*result != '-')
02860 && ((*result < '0') || (*result > '9'))) {
02861 result++;
02862 }
02863
02864 } while ((*result == '#') || (*result == '\0'));
02865 return result;
02866 }
02867
02869
02870
02871
02872
02873
02874
02875
02877
02878 char* tetgenio::findnextnumber(char *string)
02879 {
02880 char *result;
02881
02882 result = string;
02883
02884 while ((*result != '\0') && (*result != '#') && (*result != ' ') &&
02885 (*result != '\t') && (*result != ',')) {
02886 result++;
02887 }
02888
02889
02890 while ((*result != '\0') && (*result != '#')
02891 && (*result != '.') && (*result != '+') && (*result != '-')
02892 && ((*result < '0') || (*result > '9'))) {
02893 result++;
02894 }
02895
02896 if (*result == '#') {
02897 *result = '\0';
02898 }
02899 return result;
02900 }
02901
02902
02903
02904
02905
02906 static REAL PI = 3.14159265358979323846264338327950288419716939937510582;
02907
02908
02909
02910
02911
02913
02914
02915
02917
02918 tetgenbehavior::tetgenbehavior()
02919 {
02920
02921 plc = 0;
02922 quality = 0;
02923 refine = 0;
02924 coarse = 0;
02925 metric = 0;
02926 minratio = 2.0;
02927 goodratio = 0.0;
02928 minangle = 20.0;
02929 goodangle = 0.0;
02930 maxdihedral = 165.0;
02931 mindihedral = 5.0;
02932 varvolume = 0;
02933 fixedvolume = 0;
02934 maxvolume = -1.0;
02935 regionattrib = 0;
02936 insertaddpoints = 0;
02937 diagnose = 0;
02938 offcenter = 0;
02939 conformdel = 0;
02940 alpha1 = sqrt(2.0);
02941 alpha2 = 1.0;
02942 alpha3 = 0.6;
02943 zeroindex = 0;
02944 facesout = 0;
02945 edgesout = 0;
02946 neighout = 0;
02947 voroout = 0;
02948 meditview = 0;
02949 gidview = 0;
02950 geomview = 0;
02951 optlevel = 3;
02952 optpasses = 3;
02953 order = 1;
02954 nojettison = 0;
02955 nobound = 0;
02956 nonodewritten = 0;
02957 noelewritten = 0;
02958 nofacewritten = 0;
02959 noiterationnum = 0;
02960 nobisect = 0;
02961 noflip = 0;
02962 steiner = -1;
02963 fliprepair = 1;
02964 nomerge = 0;
02965 docheck = 0;
02966 quiet = 0;
02967 verbose = 0;
02968 useshelles = 0;
02969 epsilon = 1.0e-8;
02970 epsilon2 = 1.0e-5;
02971 object = NONE;
02972
02973 commandline[0] = '\0';
02974 infilename[0] = '\0';
02975 outfilename[0] = '\0';
02976 addinfilename[0] = '\0';
02977 bgmeshfilename[0] = '\0';
02978 }
02979
02981
02982
02983
02985
02986 void tetgenbehavior::versioninfo()
02987 {
02988 printf("Version 1.4.2 (April 16, 2007).\n");
02989 printf("\n");
02990 printf("Copyright (C) 2002 - 2007\n");
02991 printf("Hang Si\n");
02992 printf("Mohrenstr. 39, 10117 Berlin, Germany\n");
02993 printf("si@wias-berlin.de\n");
02994 }
02995
02997
02998
02999
03001
03002 void tetgenbehavior::syntax()
03003 {
03004 printf(" tetgen [-prq_Ra_AiMYS_T_dzo_fenvgGOJBNEFICQVh] input_file\n");
03005 printf(" -p Tetrahedralizes a piecewise linear complex (PLC).\n");
03006 printf(" -r Reconstructs a previously generated mesh.\n");
03007 printf(" -q Quality mesh generation (adding new mesh points to ");
03008 printf("improve mesh quality).\n");
03009 printf(" -R Mesh coarsening (deleting redundant mesh points).\n");
03010 printf(" -a Applies a maximum tetrahedron volume constraint.\n");
03011 printf(" -A Assigns attributes to identify tetrahedra in different ");
03012 printf("regions.\n");
03013 printf(" -i Inserts a list of additional points into mesh.\n");
03014 printf(" -M Does not merge coplanar facets.\n");
03015 printf(" -Y Suppresses boundary facets/segments splitting.\n");
03016 printf(" -S Specifies maximum number of added points.\n");
03017 printf(" -T Sets a tolerance for coplanar test (default 1e-8).\n");
03018 printf(" -d Detects self-intersections of facets of the PLC.\n");
03019 printf(" -z Numbers all output items starting from zero.\n");
03020 printf(" -o2 Generates second-order subparametric elements.\n");
03021 printf(" -f Outputs all faces to .face file.");
03022 printf("file.\n");
03023 printf(" -e Outputs all edges to .edge file.\n");
03024 printf(" -n Outputs tetrahedra neighbors to .neigh file.\n");
03025 printf(" -v Outputs Voronoi diagram to files.\n");
03026 printf(" -g Outputs mesh to .mesh file for viewing by Medit.\n");
03027 printf(" -G Outputs mesh to .msh file for viewing by Gid.\n");
03028 printf(" -O Outputs mesh to .off file for viewing by Geomview.\n");
03029 printf(" -J No jettison of unused vertices from output .node file.\n");
03030 printf(" -B Suppresses output of boundary information.\n");
03031 printf(" -N Suppresses output of .node file.\n");
03032 printf(" -E Suppresses output of .ele file.\n");
03033 printf(" -F Suppresses output of .face file.\n");
03034 printf(" -I Suppresses mesh iteration numbers.\n");
03035 printf(" -C Checks the consistency of the final mesh.\n");
03036 printf(" -Q Quiet: No terminal output except errors.\n");
03037 printf(" -V Verbose: Detailed information, more terminal output.\n");
03038 printf(" -h Help: A brief instruction for using TetGen.\n");
03039 }
03040
03042
03043
03044
03046
03047 void tetgenbehavior::usage()
03048 {
03049 printf("TetGen\n");
03050 printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
03051 printf("Triangulator\n");
03052 versioninfo();
03053 printf("\n");
03054 printf("What Can TetGen Do?\n");
03055 printf("\n");
03056 printf(" TetGen generates exact Delaunay tetrahedralizations, exact\n");
03057 printf(" constrained Delaunay tetrahedralizations, and quality ");
03058 printf("tetrahedral\n meshes. The latter are nicely graded and whose ");
03059 printf("tetrahedra have\n radius-edge ratio bounded, thus are suitable ");
03060 printf("for finite element and\n finite volume analysis.\n");
03061 printf("\n");
03062 printf("Command Line Syntax:\n");
03063 printf("\n");
03064 printf(" Below is the command line syntax of TetGen with a list of ");
03065 printf("short\n");
03066 printf(" descriptions. Underscores indicate that numbers may optionally\n");
03067 printf(" follow certain switches. Do not leave any space between a ");
03068 printf("switch\n");
03069 printf(" and its numeric parameter. \'input_file\' contains input data\n");
03070 printf(" depending on the switches you supplied which may be a ");
03071 printf(" piecewise\n");
03072 printf(" linear complex or a list of nodes. File formats and detailed\n");
03073 printf(" description of command line switches are found in user's ");
03074 printf("manual.\n");
03075 printf("\n");
03076 syntax();
03077 printf("\n");
03078 printf("Examples of How to Use TetGen:\n");
03079 printf("\n");
03080 printf(" \'tetgen object\' reads vertices from object.node, and writes ");
03081 printf("their\n Delaunay tetrahedralization to object.1.node and ");
03082 printf("object.1.ele.\n");
03083 printf("\n");
03084 printf(" \'tetgen -p object\' reads a PLC from object.poly or object.");
03085 printf("smesh (and\n possibly object.node) and writes its constrained ");
03086 printf("Delaunay\n tetrahedralization to object.1.node, object.1.ele and ");
03087 printf("object.1.face.\n");
03088 printf("\n");
03089 printf(" \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
03090 printf(" object.smesh (and possibly object.node), generates a mesh ");
03091 printf("whose\n tetrahedra have radius-edge ratio smaller than 1.414 and ");
03092 printf("have volume\n of 0.1 or less, and writes the mesh to ");
03093 printf("object.1.node, object.1.ele\n and object.1.face.\n");
03094 printf("\n");
03095 printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
03096 }
03097
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116
03117
03118
03119
03121
03122 bool tetgenbehavior::parse_commandline(int argc, char **argv)
03123 {
03124 int startindex;
03125 int increment;
03126 int meshnumber;
03127 int scount;
03128 int i, j, k;
03129 char workstring[1024];
03130
03131
03132 if (argc == 0) {
03133 startindex = 0;
03134 argc = 1;
03135 commandline[0] = '\0';
03136 } else {
03137 startindex = 1;
03138 strcpy(commandline, argv[0]);
03139 strcat(commandline, " ");
03140 }
03141
03142
03143 scount = 0;
03144
03145 for (i = startindex; i < argc; i++) {
03146
03147 strcat(commandline, argv[i]);
03148 strcat(commandline, " ");
03149 if (startindex == 1) {
03150
03151 if (argv[i][0] != '-') {
03152 strncpy(infilename, argv[i], 1024 - 1);
03153 infilename[1024 - 1] = '\0';
03154
03155 continue;
03156 }
03157 }
03158
03159 for (j = startindex; argv[i][j] != '\0'; j++) {
03160 if (argv[i][j] == 'p') {
03161 plc = 1;
03162 } else if (argv[i][j] == 'r') {
03163 refine = 1;
03164 } else if (argv[i][j] == 'R') {
03165 coarse = 1;
03166 } else if (argv[i][j] == 'q') {
03167 quality++;
03168 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03169 (argv[i][j + 1] == '.')) {
03170 k = 0;
03171 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03172 (argv[i][j + 1] == '.')) {
03173 j++;
03174 workstring[k] = argv[i][j];
03175 k++;
03176 }
03177 workstring[k] = '\0';
03178 if (quality == 1) {
03179 minratio = (REAL) strtod(workstring, (char **) NULL);
03180 } else if (quality == 2) {
03181 mindihedral = (REAL) strtod(workstring, (char **) NULL);
03182 } else if (quality == 3) {
03183 maxdihedral = (REAL) strtod(workstring, (char **) NULL);
03184 } else if (quality == 4) {
03185 alpha2 = (REAL) strtod(workstring, (char **) NULL);
03186 } else if (quality == 5) {
03187 alpha1 = (REAL) strtod(workstring, (char **) NULL);
03188 }
03189 }
03190 } else if (argv[i][j] == 'm') {
03191 metric++;
03192 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03193 (argv[i][j + 1] == '.')) {
03194 k = 0;
03195 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03196 (argv[i][j + 1] == '.')) {
03197 j++;
03198 workstring[k] = argv[i][j];
03199 k++;
03200 }
03201 workstring[k] = '\0';
03202 if (metric == 1) {
03203 alpha1 = (REAL) strtod(workstring, (char **) NULL);
03204 } else if (metric == 2) {
03205 alpha2 = (REAL) strtod(workstring, (char **) NULL);
03206 }
03207 }
03208 } else if (argv[i][j] == 'a') {
03209 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03210 (argv[i][j + 1] == '.')) {
03211 fixedvolume = 1;
03212 k = 0;
03213 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03214 (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03215 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03216 j++;
03217 workstring[k] = argv[i][j];
03218 k++;
03219 }
03220 workstring[k] = '\0';
03221 maxvolume = (REAL) strtod(workstring, (char **) NULL);
03222 } else {
03223 varvolume = 1;
03224 }
03225 } else if (argv[i][j] == 'A') {
03226 regionattrib++;
03227 } else if (argv[i][j] == 'i') {
03228 insertaddpoints = 1;
03229 } else if (argv[i][j] == 'd') {
03230 diagnose = 1;
03231 } else if (argv[i][j] == 'z') {
03232 zeroindex = 1;
03233 } else if (argv[i][j] == 'f') {
03234 facesout = 1;
03235 } else if (argv[i][j] == 'e') {
03236 edgesout++;
03237 } else if (argv[i][j] == 'n') {
03238 neighout++;
03239 } else if (argv[i][j] == 'v') {
03240 voroout = 1;
03241 } else if (argv[i][j] == 'g') {
03242 meditview = 1;
03243 } else if (argv[i][j] == 'G') {
03244 gidview = 1;
03245 } else if (argv[i][j] == 'O') {
03246 geomview = 1;
03247 } else if (argv[i][j] == 'M') {
03248 nomerge = 1;
03249 } else if (argv[i][j] == 'Y') {
03250 nobisect++;
03251 } else if (argv[i][j] == 'J') {
03252 nojettison = 1;
03253 } else if (argv[i][j] == 'B') {
03254 nobound = 1;
03255 } else if (argv[i][j] == 'N') {
03256 nonodewritten = 1;
03257 } else if (argv[i][j] == 'E') {
03258 noelewritten = 1;
03259 } else if (argv[i][j] == 'F') {
03260 nofacewritten = 1;
03261 } else if (argv[i][j] == 'I') {
03262 noiterationnum = 1;
03263 } else if (argv[i][j] == 'o') {
03264 if (argv[i][j + 1] == '2') {
03265 j++;
03266 order = 2;
03267 }
03268 } else if (argv[i][j] == 'S') {
03269 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03270 (argv[i][j + 1] == '.')) {
03271 k = 0;
03272 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03273 (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03274 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03275 j++;
03276 workstring[k] = argv[i][j];
03277 k++;
03278 }
03279 workstring[k] = '\0';
03280 steiner = (int) strtol(workstring, (char **) NULL, 0);
03281 }
03282 } else if (argv[i][j] == 's') {
03283 scount++;
03284 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03285 (argv[i][j + 1] == '.')) {
03286 k = 0;
03287 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03288 (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03289 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03290 j++;
03291 workstring[k] = argv[i][j];
03292 k++;
03293 }
03294 workstring[k] = '\0';
03295 if (scount == 1) {
03296 optlevel = (int) strtol(workstring, (char **) NULL, 0);
03297 } else if (scount == 2) {
03298 optpasses = (int) strtol(workstring, (char **) NULL, 0);
03299 }
03300 }
03301 } else if (argv[i][j] == 'D') {
03302 conformdel++;
03303 } else if (argv[i][j] == 'T') {
03304 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03305 (argv[i][j + 1] == '.')) {
03306 k = 0;
03307 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03308 (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03309 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03310 j++;
03311 workstring[k] = argv[i][j];
03312 k++;
03313 }
03314 workstring[k] = '\0';
03315 epsilon = (REAL) strtod(workstring, (char **) NULL);
03316 }
03317 } else if (argv[i][j] == 'C') {
03318 docheck++;
03319 } else if (argv[i][j] == 'X') {
03320 fliprepair = 0;
03321 } else if (argv[i][j] == 'Q') {
03322 quiet = 1;
03323 } else if (argv[i][j] == 'V') {
03324 verbose++;
03325
03326
03327
03328 } else if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
03329 (argv[i][j] == '?')) {
03330 usage();
03331 terminatetetgen(0);
03332 } else {
03333 printf("Warning: Unknown switch -%c.\n", argv[i][j]);
03334 }
03335 }
03336 }
03337
03338 if (startindex == 0) {
03339
03340 strcpy(infilename, "tetgen-tmpfile");
03341 } else {
03342 if (infilename[0] == '\0') {
03343
03344 syntax();
03345 terminatetetgen(0);
03346 }
03347
03348 if (!strcmp(&infilename[strlen(infilename) - 5], ".node")) {
03349 infilename[strlen(infilename) - 5] = '\0';
03350 object = NODES;
03351 } else if (!strcmp(&infilename[strlen(infilename) - 5], ".poly")) {
03352 infilename[strlen(infilename) - 5] = '\0';
03353 object = POLY;
03354 plc = 1;
03355 } else if (!strcmp(&infilename[strlen(infilename) - 6], ".smesh")) {
03356 infilename[strlen(infilename) - 6] = '\0';
03357 object = POLY;
03358 plc = 1;
03359 } else if (!strcmp(&infilename[strlen(infilename) - 4], ".off")) {
03360 infilename[strlen(infilename) - 4] = '\0';
03361 object = OFF;
03362 plc = 1;
03363 } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ply")) {
03364 infilename[strlen(infilename) - 4] = '\0';
03365 object = PLY;
03366 plc = 1;
03367 } else if (!strcmp(&infilename[strlen(infilename) - 4], ".stl")) {
03368 infilename[strlen(infilename) - 4] = '\0';
03369 object = STL;
03370 plc = 1;
03371 } else if (!strcmp(&infilename[strlen(infilename) - 5], ".mesh")) {
03372 infilename[strlen(infilename) - 5] = '\0';
03373 object = MEDIT;
03374 plc = 1;
03375 } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ele")) {
03376 infilename[strlen(infilename) - 4] = '\0';
03377 object = MESH;
03378 refine = 1;
03379 }
03380 }
03381 plc = plc || diagnose;
03382 useshelles = plc || refine || coarse || quality;
03383 goodratio = minratio;
03384 goodratio *= goodratio;
03385
03386
03387 if (plc && refine) {
03388 printf("Error: Switch -r cannot use together with -p.\n");
03389 return false;
03390 }
03391 if (refine && (plc || noiterationnum)) {
03392 printf("Error: Switches %s cannot use together with -r.\n",
03393 "-p, -d, and -I");
03394 return false;
03395 }
03396 if (diagnose && (quality || insertaddpoints || (order == 2) || neighout
03397 || docheck)) {
03398 printf("Error: Switches %s cannot use together with -d.\n",
03399 "-q, -i, -o2, -n, and -C");
03400 return false;
03401 }
03402
03403
03404
03405 if (!refine && !plc) {
03406 varvolume = 0;
03407 }
03408
03409
03410 if (refine || !plc) {
03411 regionattrib = 0;
03412 }
03413
03414 if (fixedvolume || varvolume) {
03415 if (quality == 0) {
03416 quality = 1;
03417 }
03418 }
03419
03420 goodangle = cos(minangle * PI / 180.0);
03421 goodangle *= goodangle;
03422
03423 increment = 0;
03424 strcpy(workstring, infilename);
03425 j = 1;
03426 while (workstring[j] != '\0') {
03427 if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
03428 increment = j + 1;
03429 }
03430 j++;
03431 }
03432 meshnumber = 0;
03433 if (increment > 0) {
03434 j = increment;
03435 do {
03436 if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
03437 meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
03438 } else {
03439 increment = 0;
03440 }
03441 j++;
03442 } while (workstring[j] != '\0');
03443 }
03444 if (noiterationnum) {
03445 strcpy(outfilename, infilename);
03446 } else if (increment == 0) {
03447 strcpy(outfilename, infilename);
03448 strcat(outfilename, ".1");
03449 } else {
03450 workstring[increment] = '%';
03451 workstring[increment + 1] = 'd';
03452 workstring[increment + 2] = '\0';
03453 sprintf(outfilename, workstring, meshnumber + 1);
03454 }
03455
03456 strcpy(addinfilename, infilename);
03457 strcat(addinfilename, ".a");
03458
03459 strcpy(bgmeshfilename, infilename);
03460 strcat(bgmeshfilename, ".b");
03461
03462 return true;
03463 }
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483 int tetgenmesh::compare_2_ints(const void* x, const void* y) {
03484 if (* (int *) x < * (int *) y) {
03485 return -1;
03486 } else if (* (int *) x > * (int *) y) {
03487 return 1;
03488 } else {
03489 return 0;
03490 }
03491 }
03492
03493
03494
03495 int tetgenmesh::compare_2_longs(const void* x, const void* y) {
03496 if (* (long *) x < * (long *) y) {
03497 return -1;
03498 } else if (* (long *) x > * (long *) y) {
03499 return 1;
03500 } else {
03501 return 0;
03502 }
03503 }
03504
03505
03506 int tetgenmesh::compare_2_unsignedlongs(const void* x, const void* y) {
03507 if (* (unsigned long *) x < * (unsigned long *) y) {
03508 return -1;
03509 } else if (* (unsigned long *) x > * (unsigned long *) y) {
03510 return 1;
03511 } else {
03512 return 0;
03513 }
03514 }
03515
03517
03518
03519
03520
03521
03522
03523
03524
03525
03526
03527
03528
03530
03531 void tetgenmesh::set_compfunc(char* str, int* itbytes, compfunc* pcomp)
03532 {
03533
03534 if (str[strlen(str) - 1] == '*') {
03535 *itbytes = sizeof(unsigned long);
03536 *pcomp = &compare_2_unsignedlongs;
03537 return;
03538 }
03539
03540 if (strcmp(str, "int") == 0) {
03541 *itbytes = sizeof(int);
03542 *pcomp = &compare_2_ints;
03543 } else if (strcmp(str, "long") == 0) {
03544 *itbytes = sizeof(long);
03545 *pcomp = &compare_2_longs;
03546 } else if (strcmp(str, "unsigned long") == 0) {
03547 *itbytes = sizeof(unsigned long);
03548 *pcomp = &compare_2_unsignedlongs;
03549 } else {
03550
03551 printf("Error in set_compfunc(): unknown type %s.\n", str);
03552 terminatetetgen(1);
03553 }
03554 }
03555
03557
03558
03559
03560
03561
03562
03563
03565
03566 void tetgenmesh::list::
03567 listinit(int itbytes, compfunc pcomp, int mitems,int exsize)
03568 {
03569 #ifdef SELF_CHECK
03570 assert(itbytes > 0 && mitems > 0 && exsize > 0);
03571 #endif
03572 itembytes = itbytes;
03573 comp = pcomp;
03574 maxitems = mitems;
03575 expandsize = exsize;
03576 base = (char *) malloc(maxitems * itembytes);
03577 if (base == (char *) NULL) {
03578 printf("Error: Out of memory.\n");
03579 terminatetetgen(1);
03580 }
03581 items = 0;
03582 }
03583
03585
03586
03587
03588
03589
03590
03591
03592
03594
03595 void* tetgenmesh::list::append(void *appitem)
03596 {
03597
03598 if (items == maxitems) {
03599 char* newbase = (char *) realloc(base, (maxitems + expandsize) *
03600 itembytes);
03601 if (newbase == (char *) NULL) {
03602 printf("Error: Out of memory.\n");
03603 terminatetetgen(1);
03604 }
03605 base = newbase;
03606 maxitems += expandsize;
03607 }
03608 if (appitem != (void *) NULL) {
03609 memcpy(base + items * itembytes, appitem, itembytes);
03610 }
03611 items++;
03612 return (void *) (base + (items - 1) * itembytes);
03613 }
03614
03616
03617
03618
03619
03620
03621
03622
03623
03625
03626 void* tetgenmesh::list::insert(int pos, void* insitem)
03627 {
03628 if (pos >= items) {
03629 return append(insitem);
03630 }
03631
03632 if (items == maxitems) {
03633 char* newbase = (char *) realloc(base, (maxitems + expandsize) *
03634 itembytes);
03635 if (newbase == (char *) NULL) {
03636 printf("Error: Out of memory.\n");
03637 terminatetetgen(1);
03638 }
03639 base = newbase;
03640 maxitems += expandsize;
03641 }
03642
03643 memmove(base + (pos + 1) * itembytes,
03644 base + pos * itembytes,
03645 (items - pos) * itembytes);
03646
03647 if (insitem != (void *) NULL) {
03648 memcpy(base + pos * itembytes, insitem, itembytes);
03649 }
03650 items++;
03651 return (void *) (base + pos * itembytes);
03652 }
03653
03655
03656
03657
03658
03659
03660
03661
03662
03664
03665 void tetgenmesh::list::del(int pos, int order)
03666 {
03667
03668 if (pos >= 0 && pos < items - 1) {
03669 if (order == 1) {
03670
03671 memmove(base + pos * itembytes,
03672 base + (pos + 1) * itembytes,
03673 (items - pos - 1) * itembytes);
03674 } else {
03675
03676 memcpy(base + pos * itembytes,
03677 base + (items - 1) * itembytes,
03678 itembytes);
03679 }
03680 }
03681 if (items > 0) {
03682 items--;
03683 }
03684 }
03685
03687
03688
03689
03690
03691
03692
03693
03695
03696 int tetgenmesh::list::hasitem(void* checkitem)
03697 {
03698 int i;
03699
03700 for (i = 0; i < items; i++) {
03701 if (comp != (compfunc) NULL) {
03702 if ((* comp)((void *)(base + i * itembytes), checkitem) == 0) {
03703 return i;
03704 }
03705 }
03706 }
03707 return -1;
03708 }
03709
03711
03712
03713
03714
03715
03717
03718 void tetgenmesh::list::sort()
03719 {
03720 qsort((void *) base, (size_t) items, (size_t) itembytes, comp);
03721 }
03722
03724
03725
03726
03728
03729 tetgenmesh::memorypool::memorypool()
03730 {
03731 firstblock = nowblock = (void **) NULL;
03732 nextitem = (void *) NULL;
03733 deaditemstack = (void *) NULL;
03734 pathblock = (void **) NULL;
03735 pathitem = (void *) NULL;
03736 itemwordtype = POINTER;
03737 alignbytes = 0;
03738 itembytes = itemwords = 0;
03739 itemsperblock = 0;
03740 items = maxitems = 0l;
03741 unallocateditems = 0;
03742 pathitemsleft = 0;
03743 }
03744
03745 tetgenmesh::memorypool::
03746 memorypool(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03747 {
03748 poolinit(bytecount, itemcount, wtype, alignment);
03749 }
03750
03752
03753
03754
03756
03757 tetgenmesh::memorypool::~memorypool()
03758 {
03759 while (firstblock != (void **) NULL) {
03760 nowblock = (void **) *(firstblock);
03761 free(firstblock);
03762 firstblock = nowblock;
03763 }
03764 }
03765
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778
03779
03781
03782 void tetgenmesh::memorypool::
03783 poolinit(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03784 {
03785 int wordsize;
03786
03787
03788 itemwordtype = wtype;
03789 wordsize = (itemwordtype == POINTER) ? sizeof(void *) : sizeof(REAL);
03790
03791
03792
03793
03794
03795 if (alignment > wordsize) {
03796 alignbytes = alignment;
03797 } else {
03798 alignbytes = wordsize;
03799 }
03800 if ((int) sizeof(void *) > alignbytes) {
03801 alignbytes = (int) sizeof(void *);
03802 }
03803 itemwords = ((bytecount + alignbytes - 1) / alignbytes)
03804 * (alignbytes / wordsize);
03805 itembytes = itemwords * wordsize;
03806 itemsperblock = itemcount;
03807
03808
03809
03810
03811 firstblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *)
03812 + alignbytes);
03813 if (firstblock == (void **) NULL) {
03814 printf("Error: Out of memory.\n");
03815 terminatetetgen(1);
03816 }
03817
03818 *(firstblock) = (void *) NULL;
03819 restart();
03820 }
03821
03823
03824
03825
03826
03827
03828
03829
03831
03832 void tetgenmesh::memorypool::restart()
03833 {
03834 unsigned long alignptr;
03835
03836 items = 0;
03837 maxitems = 0;
03838
03839
03840 nowblock = firstblock;
03841
03842 alignptr = (unsigned long) (nowblock + 1);
03843
03844 nextitem = (void *)
03845 (alignptr + (unsigned long) alignbytes -
03846 (alignptr % (unsigned long) alignbytes));
03847
03848 unallocateditems = itemsperblock;
03849
03850 deaditemstack = (void *) NULL;
03851 }
03852
03854
03855
03856
03858
03859 void* tetgenmesh::memorypool::alloc()
03860 {
03861 void *newitem;
03862 void **newblock;
03863 unsigned long alignptr;
03864
03865
03866
03867 if (deaditemstack != (void *) NULL) {
03868 newitem = deaditemstack;
03869 deaditemstack = * (void **) deaditemstack;
03870 } else {
03871
03872 if (unallocateditems == 0) {
03873
03874 if (*nowblock == (void *) NULL) {
03875
03876 newblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *)
03877 + alignbytes);
03878 if (newblock == (void **) NULL) {
03879 printf("Error: Out of memory.\n");
03880 terminatetetgen(1);
03881 }
03882 *nowblock = (void *) newblock;
03883
03884 *newblock = (void *) NULL;
03885 }
03886
03887 nowblock = (void **) *nowblock;
03888
03889
03890 alignptr = (unsigned long) (nowblock + 1);
03891
03892 nextitem = (void *)
03893 (alignptr + (unsigned long) alignbytes -
03894 (alignptr % (unsigned long) alignbytes));
03895
03896 unallocateditems = itemsperblock;
03897 }
03898
03899 newitem = nextitem;
03900
03901 if (itemwordtype == POINTER) {
03902 nextitem = (void *) ((void **) nextitem + itemwords);
03903 } else {
03904 nextitem = (void *) ((REAL *) nextitem + itemwords);
03905 }
03906 unallocateditems--;
03907 maxitems++;
03908 }
03909 items++;
03910 return newitem;
03911 }
03912
03914
03915
03916
03917
03918
03920
03921 void tetgenmesh::memorypool::dealloc(void *dyingitem)
03922 {
03923
03924 *((void **) dyingitem) = deaditemstack;
03925 deaditemstack = dyingitem;
03926 items--;
03927 }
03928
03930
03931
03932
03933
03934
03936
03937 void tetgenmesh::memorypool::traversalinit()
03938 {
03939 unsigned long alignptr;
03940
03941
03942 pathblock = firstblock;
03943
03944 alignptr = (unsigned long) (pathblock + 1);
03945
03946 pathitem = (void *)
03947 (alignptr + (unsigned long) alignbytes -
03948 (alignptr % (unsigned long) alignbytes));
03949
03950 pathitemsleft = itemsperblock;
03951 }
03952
03954
03955
03956
03957
03958
03959
03960
03961
03962
03964
03965 void* tetgenmesh::memorypool::traverse()
03966 {
03967 void *newitem;
03968 unsigned long alignptr;
03969
03970
03971 if (pathitem == nextitem) {
03972 return (void *) NULL;
03973 }
03974
03975 if (pathitemsleft == 0) {
03976
03977 pathblock = (void **) *pathblock;
03978
03979 alignptr = (unsigned long) (pathblock + 1);
03980
03981 pathitem = (void *)
03982 (alignptr + (unsigned long) alignbytes -
03983 (alignptr % (unsigned long) alignbytes));
03984
03985 pathitemsleft = itemsperblock;
03986 }
03987 newitem = pathitem;
03988
03989 if (itemwordtype == POINTER) {
03990 pathitem = (void *) ((void **) pathitem + itemwords);
03991 } else {
03992 pathitem = (void *) ((REAL *) pathitem + itemwords);
03993 }
03994 pathitemsleft--;
03995 return newitem;
03996 }
03997
03999
04000
04001
04002
04003
04004
04006
04007 void tetgenmesh::link::linkinit(int bytecount, compfunc pcomp, int itemcount)
04008 {
04009 #ifdef SELF_CHECK
04010 assert(bytecount > 0 && itemcount > 0);
04011 #endif
04012
04013 linkitembytes = bytecount;
04014
04015 comp = pcomp;
04016
04017
04018
04019
04020
04021 poolinit(bytecount + 2 * sizeof(void **), itemcount + 2, POINTER, 0);
04022
04023
04024 head = (void **) alloc();
04025 tail = (void **) alloc();
04026 *head = (void *) tail;
04027 *(head + 1) = NULL;
04028 *tail = NULL;
04029 *(tail + 1) = (void *) head;
04030 nextlinkitem = *head;
04031 curpos = 1;
04032 linkitems = 0;
04033 }
04034
04036
04037
04038
04039
04040
04041
04042
04044
04045 void tetgenmesh::link::clear()
04046 {
04047
04048 restart();
04049
04050
04051 head = (void **) alloc();
04052 tail = (void **) alloc();
04053 *head = (void *) tail;
04054 *(head + 1) = NULL;
04055 *tail = NULL;
04056 *(tail + 1) = (void *) head;
04057 nextlinkitem = *head;
04058 curpos = 1;
04059 linkitems = 0;
04060 }
04061
04063
04064
04065
04066
04067
04068
04069
04070
04072
04073 bool tetgenmesh::link::move(int numberofnodes)
04074 {
04075 void **nownode;
04076 int i;
04077
04078 nownode = (void **) nextlinkitem;
04079 if (numberofnodes > 0) {
04080
04081 i = 0;
04082 while ((i < numberofnodes) && *nownode) {
04083 nownode = (void **) *nownode;
04084 i++;
04085 }
04086 if (*nownode == NULL) return false;
04087 nextlinkitem = (void *) nownode;
04088 curpos += numberofnodes;
04089 } else if (numberofnodes < 0) {
04090
04091 i = 0;
04092 numberofnodes = -numberofnodes;
04093 while ((i < numberofnodes) && *(nownode + 1)) {
04094 nownode = (void **) *(nownode + 1);
04095 i++;
04096 }
04097 if (*(nownode + 1) == NULL) return false;
04098 nextlinkitem = (void *) nownode;
04099 curpos -= numberofnodes;
04100 }
04101 return true;
04102 }
04103
04105
04106
04107
04108
04109
04110
04111
04112
04113
04115
04116 bool tetgenmesh::link::locate(int pos)
04117 {
04118 int headdist, taildist, curdist;
04119 int abscurdist, mindist;
04120
04121 if (pos < 1 || pos > linkitems) return false;
04122
04123 headdist = pos - 1;
04124 taildist = linkitems - pos;
04125 curdist = pos - curpos;
04126 abscurdist = curdist >= 0 ? curdist : -curdist;
04127
04128 if (headdist > taildist) {
04129 if (taildist > abscurdist) {
04130 mindist = curdist;
04131 } else {
04132
04133 mindist = -taildist;
04134 goend();
04135 }
04136 } else {
04137
04138 if (headdist > abscurdist) {
04139 mindist = curdist;
04140 } else {
04141
04142 mindist = headdist;
04143 rewind();
04144 }
04145 }
04146
04147 return move(mindist);
04148 }
04149
04151
04152
04153
04154
04155
04156
04157
04159
04160 void* tetgenmesh::link::add(void* newitem)
04161 {
04162 void **newnode = tail;
04163 if (newitem != (void *) NULL) {
04164 memcpy((void *)(newnode + 2), newitem, linkitembytes);
04165 }
04166 tail = (void **) alloc();
04167 *tail = NULL;
04168 *newnode = (void*) tail;
04169 *(tail + 1) = (void*) newnode;
04170 linkitems++;
04171 return (void *)(newnode + 2);
04172 }
04173
04175
04176
04177
04178
04179
04180
04181
04182
04183
04185
04186 void* tetgenmesh::link::insert(int pos, void* insitem)
04187 {
04188 if (!locate(pos)) {
04189 return add(insitem);
04190 }
04191
04192 void **nownode = (void **) nextlinkitem;
04193
04194
04195 void **newnode = (void **) alloc();
04196 if (insitem != (void *) NULL) {
04197 memcpy((void *)(newnode + 2), insitem, linkitembytes);
04198 }
04199
04200 *(void **)(*(nownode + 1)) = (void *) newnode;
04201 *newnode = (void *) nownode;
04202 *(newnode + 1) = *(nownode + 1);
04203 *(nownode + 1) = (void *) newnode;
04204
04205 linkitems++;
04206
04207 nextlinkitem = (void *) newnode;
04208 return (void *)(newnode + 2);
04209 }
04210
04212
04213
04214
04215
04216
04217
04219
04220 void* tetgenmesh::link::deletenode(void** deadnode)
04221 {
04222 void **nextnode = (void **) *deadnode;
04223 void **prevnode = (void **) *(deadnode + 1);
04224 *prevnode = (void *) nextnode;
04225 *(nextnode + 1) = (void *) prevnode;
04226
04227 dealloc((void *) deadnode);
04228 linkitems--;
04229
04230 nextlinkitem = (void *) nextnode;
04231 return (void *)(deadnode + 2);
04232 }
04233
04235
04236
04237
04238
04239
04240
04241
04243
04244 void* tetgenmesh::link::del(int pos)
04245 {
04246 if (!locate(pos) || (linkitems == 0)) {
04247 return (void *) NULL;
04248 }
04249 return deletenode((void **) nextlinkitem);
04250 }
04251
04253
04254
04255
04256
04257
04258
04259
04261
04262 void* tetgenmesh::link::getitem()
04263 {
04264 if (nextlinkitem == (void *) tail) return NULL;
04265 void **nownode = (void **) nextlinkitem;
04266 nextlinkitem = *nownode;
04267 curpos += 1;
04268 return (void *)(nownode + 2);
04269 }
04270
04272
04273
04274
04275
04276
04277
04279
04280 void* tetgenmesh::link::getnitem(int pos)
04281 {
04282 if (!locate(pos)) return NULL;
04283 return (void *)((void **) nextlinkitem + 2);
04284 }
04285
04287
04288
04289
04290
04291
04292
04293
04295
04296 int tetgenmesh::link::hasitem(void* checkitem)
04297 {
04298 void *pathitem;
04299 int count;
04300
04301 rewind();
04302 pathitem = getitem();
04303 count = 0;
04304 while (pathitem) {
04305 count ++;
04306 if (comp) {
04307 if ((* comp)(pathitem, checkitem) == 0) {
04308 return count;
04309 }
04310 }
04311 pathitem = getitem();
04312 }
04313 return -1;
04314 }
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329
04330 int tetgenmesh::plus1mod3[3] = {1, 2, 0};
04331 int tetgenmesh::minus1mod3[3] = {2, 0, 1};
04332
04333
04334
04335
04336 int tetgenmesh::ve[6] = { 2, 5, 4, 1, 0, 3 };
04337
04338
04339
04340
04341 int tetgenmesh::vo[6] = { 0, 1, 1, 2, 2, 0 };
04342 int tetgenmesh::vd[6] = { 1, 0, 2, 1, 0, 2 };
04343 int tetgenmesh::va[6] = { 2, 2, 0, 0, 1, 1 };
04344
04345
04346
04347
04348
04349
04350 int tetgenmesh::locver2org[4][6] = {
04351 {0, 1, 1, 2, 2, 0},
04352 {0, 3, 3, 1, 1, 0},
04353 {1, 3, 3, 2, 2, 1},
04354 {2, 3, 3, 0, 0, 2}
04355 };
04356 int tetgenmesh::locver2dest[4][6] = {
04357 {1, 0, 2, 1, 0, 2},
04358 {3, 0, 1, 3, 0, 1},
04359 {3, 1, 2, 3, 1, 2},
04360 {3, 2, 0, 3, 2, 0}
04361 };
04362 int tetgenmesh::locver2apex[4][6] = {
04363 {2, 2, 0, 0, 1, 1},
04364 {1, 1, 0, 0, 3, 3},
04365 {2, 2, 1, 1, 3, 3},
04366 {0, 0, 2, 2, 3, 3}
04367 };
04368
04369
04370
04371 int tetgenmesh::loc2oppo[4] = { 3, 2, 0, 1 };
04372
04373
04374
04375
04376
04377 int tetgenmesh::locver2nextf[4][6][2] = {
04378 { {1, 5}, {-1, -1}, {2, 5}, {-1, -1}, {3, 5}, {-1, -1} },
04379 { {3, 3}, {-1, -1}, {2, 1}, {-1, -1}, {0, 1}, {-1, -1} },
04380 { {1, 3}, {-1, -1}, {3, 1}, {-1, -1}, {0, 3}, {-1, -1} },
04381 { {2, 3}, {-1, -1}, {1, 1}, {-1, -1}, {0, 5}, {-1, -1} }
04382 };
04383
04384
04385
04386
04387
04388 int tetgenmesh::locver2edge[4][6] = {
04389 {0, 0, 1, 1, 2, 2},
04390 {3, 3, 4, 4, 0, 0},
04391 {4, 4, 5, 5, 1, 1},
04392 {5, 5, 3, 3, 2, 2}
04393 };
04394
04395 int tetgenmesh::edge2locver[6][2] = {
04396 {0, 0},
04397 {0, 2},
04398 {0, 4},
04399 {1, 0},
04400 {1, 2},
04401 {2, 2}
04402 };
04403
04404
04405
04406
04407
04408
04409
04410 #define Div2 >> 1
04411 #define Mod2 & 01
04412
04413
04414
04415
04416
04417 #define Orient(V) ((V) Div2)
04418
04419
04420
04421 #define EdgeRing(V) ((V) Mod2)
04422
04423
04424
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435
04436 inline void tetgenmesh::decode(tetrahedron ptr, triface& t) {
04437 t.loc = (int) ((unsigned long) (ptr) & (unsigned long) 3l);
04438 t.tet = (tetrahedron *) ((unsigned long) (ptr) & ~(unsigned long) 7l);
04439 }
04440
04441 inline tetgenmesh::tetrahedron tetgenmesh::encode(triface& t) {
04442 return (tetrahedron) ((unsigned long) t.tet | (unsigned long) t.loc);
04443 }
04444
04445
04446
04447 inline void tetgenmesh::sym(triface& t1, triface& t2) {
04448 tetrahedron ptr = t1.tet[t1.loc];
04449 decode(ptr, t2);
04450 }
04451
04452 inline void tetgenmesh::symself(triface& t) {
04453 tetrahedron ptr = t.tet[t.loc];
04454 decode(ptr, t);
04455 }
04456
04457
04458
04459 inline void tetgenmesh::bond(triface& t1, triface& t2) {
04460 t1.tet[t1.loc] = encode(t2);
04461 t2.tet[t2.loc] = encode(t1);
04462 }
04463
04464
04465
04466
04467
04468
04469 inline void tetgenmesh::dissolve(triface& t) {
04470 t.tet[t.loc] = (tetrahedron) dummytet;
04471 }
04472
04473
04474
04475
04476 inline tetgenmesh::point tetgenmesh::org(triface& t) {
04477 return (point) t.tet[locver2org[t.loc][t.ver] + 4];
04478 }
04479
04480 inline tetgenmesh::point tetgenmesh::dest(triface& t) {
04481 return (point) t.tet[locver2dest[t.loc][t.ver] + 4];
04482 }
04483
04484 inline tetgenmesh::point tetgenmesh::apex(triface& t) {
04485 return (point) t.tet[locver2apex[t.loc][t.ver] + 4];
04486 }
04487
04488 inline tetgenmesh::point tetgenmesh::oppo(triface& t) {
04489 return (point) t.tet[loc2oppo[t.loc] + 4];
04490 }
04491
04492 inline void tetgenmesh::setorg(triface& t, point pointptr) {
04493 t.tet[locver2org[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04494 }
04495
04496 inline void tetgenmesh::setdest(triface& t, point pointptr) {
04497 t.tet[locver2dest[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04498 }
04499
04500 inline void tetgenmesh::setapex(triface& t, point pointptr) {
04501 t.tet[locver2apex[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04502 }
04503
04504 inline void tetgenmesh::setoppo(triface& t, point pointptr) {
04505 t.tet[loc2oppo[t.loc] + 4] = (tetrahedron) pointptr;
04506 }
04507
04508
04509
04510
04511
04512
04513
04514
04515 inline void tetgenmesh::esym(triface& t1, triface& t2) {
04516 t2.tet = t1.tet;
04517 t2.loc = t1.loc;
04518 t2.ver = t1.ver + (EdgeRing(t1.ver) ? -1 : 1);
04519 }
04520
04521 inline void tetgenmesh::esymself(triface& t) {
04522 t.ver += (EdgeRing(t.ver) ? -1 : 1);
04523 }
04524
04525
04526
04527 inline void tetgenmesh::enext(triface& t1, triface& t2) {
04528 t2.tet = t1.tet;
04529 t2.loc = t1.loc;
04530 t2.ver = ve[t1.ver];
04531 }
04532
04533 inline void tetgenmesh::enextself(triface& t) {
04534 t.ver = ve[t.ver];
04535 }
04536
04537
04538
04539 inline void tetgenmesh::enext2(triface& t1, triface& t2) {
04540 t2.tet = t1.tet;
04541 t2.loc = t1.loc;
04542 t2.ver = ve[ve[t1.ver]];
04543 }
04544
04545 inline void tetgenmesh::enext2self(triface& t) {
04546 t.ver = ve[ve[t.ver]];
04547 }
04548
04549
04550
04551
04552
04553 inline bool tetgenmesh::fnext(triface& t1, triface& t2)
04554 {
04555
04556 t2.loc = locver2nextf[t1.loc][t1.ver][0];
04557
04558 if (t2.loc != -1) {
04559
04560 t2.ver = locver2nextf[t1.loc][t1.ver][1];
04561 t2.tet = t1.tet;
04562 } else {
04563
04564 sym(t1, t2);
04565 if (t2.tet != dummytet) {
04566
04567 point torg;
04568 int tloc, tver, i;
04569 t2.ver = 0;
04570 torg = org(t1);
04571 for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04572 enextself(t2);
04573 }
04574
04575 tloc = t2.loc;
04576 tver = t2.ver;
04577 t2.loc = locver2nextf[tloc][tver][0];
04578 t2.ver = locver2nextf[tloc][tver][1];
04579 }
04580 }
04581 return t2.tet != dummytet;
04582 }
04583
04584 inline bool tetgenmesh::fnextself(triface& t1)
04585 {
04586 triface t2;
04587
04588
04589 t2.loc = locver2nextf[t1.loc][t1.ver][0];
04590
04591 if (t2.loc != -1) {
04592
04593 t2.ver = locver2nextf[t1.loc][t1.ver][1];
04594 t1.loc = t2.loc;
04595 t1.ver = t2.ver;
04596 } else {
04597
04598 sym(t1, t2);
04599 if (t2.tet != dummytet) {
04600
04601 point torg;
04602 int i;
04603 t2.ver = 0;
04604 torg = org(t1);
04605 for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04606 enextself(t2);
04607 }
04608 t1.loc = locver2nextf[t2.loc][t2.ver][0];
04609 t1.ver = locver2nextf[t2.loc][t2.ver][1];
04610 t1.tet = t2.tet;
04611 }
04612 }
04613 return t2.tet != dummytet;
04614 }
04615
04616
04617
04618
04619 inline void tetgenmesh::enextfnext(triface& t1, triface& t2) {
04620 enext(t1, t2);
04621 fnextself(t2);
04622 }
04623
04624 inline void tetgenmesh::enextfnextself(triface& t) {
04625 enextself(t);
04626 fnextself(t);
04627 }
04628
04629 inline void tetgenmesh::enext2fnext(triface& t1, triface& t2) {
04630 enext2(t1, t2);
04631 fnextself(t2);
04632 }
04633
04634 inline void tetgenmesh::enext2fnextself(triface& t) {
04635 enext2self(t);
04636 fnextself(t);
04637 }
04638
04639
04640
04641
04642
04643 inline void tetgenmesh::infect(triface& t) {
04644 t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] | (unsigned long) 4l);
04645 }
04646
04647 inline void tetgenmesh::uninfect(triface& t) {
04648 t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] & ~ (unsigned long) 4l);
04649 }
04650
04651
04652
04653 inline bool tetgenmesh::infected(triface& t) {
04654 return (((unsigned long) t.tet[0] & (unsigned long) 4l) != 0);
04655 }
04656
04657
04658
04659 inline REAL tetgenmesh::elemattribute(tetrahedron* ptr, int attnum) {
04660 return ((REAL *) (ptr))[elemattribindex + attnum];
04661 }
04662
04663 inline void tetgenmesh::
04664 setelemattribute(tetrahedron* ptr, int attnum, REAL value){
04665 ((REAL *) (ptr))[elemattribindex + attnum] = value;
04666 }
04667
04668
04669
04670 inline REAL tetgenmesh::volumebound(tetrahedron* ptr) {
04671 return ((REAL *) (ptr))[volumeboundindex];
04672 }
04673
04674 inline void tetgenmesh::setvolumebound(tetrahedron* ptr, REAL value) {
04675 ((REAL *) (ptr))[volumeboundindex] = value;
04676 }
04677
04678
04679
04680
04681
04682
04683
04684
04685
04686
04687
04688
04689
04690
04691
04692
04693
04694 inline void tetgenmesh::sdecode(shellface sptr, face& s) {
04695 s.shver = (int) ((unsigned long) (sptr) & (unsigned long) 7l);
04696 s.sh = (shellface *) ((unsigned long) (sptr) & ~ (unsigned long) 7l);
04697 }
04698
04699 inline tetgenmesh::shellface tetgenmesh::sencode(face& s) {
04700 return (shellface) ((unsigned long) s.sh | (unsigned long) s.shver);
04701 }
04702
04703
04704
04705
04706 inline void tetgenmesh::spivot(face& s1, face& s2) {
04707 shellface sptr = s1.sh[Orient(s1.shver)];
04708 sdecode(sptr, s2);
04709 }
04710
04711 inline void tetgenmesh::spivotself(face& s) {
04712 shellface sptr = s.sh[Orient(s.shver)];
04713 sdecode(sptr, s);
04714 }
04715
04716
04717
04718
04719 inline void tetgenmesh::sbond(face& s1, face& s2) {
04720 s1.sh[Orient(s1.shver)] = sencode(s2);
04721 s2.sh[Orient(s2.shver)] = sencode(s1);
04722 }
04723
04724
04725
04726
04727 inline void tetgenmesh::sbond1(face& s1, face& s2) {
04728 s1.sh[Orient(s1.shver)] = sencode(s2);
04729 }
04730
04731
04732
04733
04734 inline void tetgenmesh::sdissolve(face& s) {
04735 s.sh[Orient(s.shver)] = (shellface) dummysh;
04736 }
04737
04738
04739
04740
04741 inline tetgenmesh::point tetgenmesh::sorg(face& s) {
04742 return (point) s.sh[3 + vo[s.shver]];
04743 }
04744
04745 inline tetgenmesh::point tetgenmesh::sdest(face& s) {
04746 return (point) s.sh[3 + vd[s.shver]];
04747 }
04748
04749 inline tetgenmesh::point tetgenmesh::sapex(face& s) {
04750 return (point) s.sh[3 + va[s.shver]];
04751 }
04752
04753 inline void tetgenmesh::setsorg(face& s, point pointptr) {
04754 s.sh[3 + vo[s.shver]] = (shellface) pointptr;
04755 }
04756
04757 inline void tetgenmesh::setsdest(face& s, point pointptr) {
04758 s.sh[3 + vd[s.shver]] = (shellface) pointptr;
04759 }
04760
04761 inline void tetgenmesh::setsapex(face& s, point pointptr) {
04762 s.sh[3 + va[s.shver]] = (shellface) pointptr;
04763 }
04764
04765
04766
04767
04768 inline void tetgenmesh::sesym(face& s1, face& s2) {
04769 s2.sh = s1.sh;
04770 s2.shver = s1.shver + (EdgeRing(s1.shver) ? -1 : 1);
04771 }
04772
04773 inline void tetgenmesh::sesymself(face& s) {
04774 s.shver += (EdgeRing(s.shver) ? -1 : 1);
04775 }
04776
04777 inline void tetgenmesh::senext(face& s1, face& s2) {
04778 s2.sh = s1.sh;
04779 s2.shver = ve[s1.shver];
04780 }
04781
04782 inline void tetgenmesh::senextself(face& s) {
04783 s.shver = ve[s.shver];
04784 }
04785
04786 inline void tetgenmesh::senext2(face& s1, face& s2) {
04787 s2.sh = s1.sh;
04788 s2.shver = ve[ve[s1.shver]];
04789 }
04790
04791 inline void tetgenmesh::senext2self(face& s) {
04792 s.shver = ve[ve[s.shver]];
04793 }
04794
04795
04796
04797 inline void tetgenmesh::sfnext(face& s1, face& s2) {
04798 getnextsface(&s1, &s2);
04799 }
04800
04801 inline void tetgenmesh::sfnextself(face& s) {
04802 getnextsface(&s, NULL);
04803 }
04804
04805
04806
04807
04808 inline tetgenmesh::badface* tetgenmesh::shell2badface(face& s) {
04809 return (badface*) s.sh[11];
04810 }
04811
04812 inline void tetgenmesh::setshell2badface(face& s, badface* value) {
04813 s.sh[11] = (shellface) value;
04814 }
04815
04816
04817
04818 inline REAL tetgenmesh::areabound(face& s) {
04819 return ((REAL *) (s.sh))[areaboundindex];
04820 }
04821
04822 inline void tetgenmesh::setareabound(face& s, REAL value) {
04823 ((REAL *) (s.sh))[areaboundindex] = value;
04824 }
04825
04826
04827
04828
04829 inline int tetgenmesh::shellmark(face& s) {
04830 return ((int *) (s.sh))[shmarkindex];
04831 }
04832
04833 inline void tetgenmesh::setshellmark(face& s, int value) {
04834 ((int *) (s.sh))[shmarkindex] = value;
04835 }
04836
04837
04838
04839 inline enum tetgenmesh::shestype tetgenmesh::shelltype(face& s) {
04840 return (enum shestype) ((int *) (s.sh))[shmarkindex + 1];
04841 }
04842
04843 inline void tetgenmesh::setshelltype(face& s, enum shestype value) {
04844 ((int *) (s.sh))[shmarkindex + 1] = (int) value;
04845 }
04846
04847
04848
04849 inline int tetgenmesh::shellpbcgroup(face& s) {
04850 return ((int *) (s.sh))[shmarkindex + 2];
04851 }
04852
04853 inline void tetgenmesh::setshellpbcgroup(face& s, int value) {
04854 ((int *) (s.sh))[shmarkindex + 2] = value;
04855 }
04856
04857
04858
04859
04860 inline void tetgenmesh::sinfect(face& s) {
04861 s.sh[6] = (shellface) ((unsigned long) s.sh[6] | (unsigned long) 4l);
04862 }
04863
04864 inline void tetgenmesh::suninfect(face& s) {
04865 s.sh[6] = (shellface)((unsigned long) s.sh[6] & ~(unsigned long) 4l);
04866 }
04867
04868
04869
04870 inline bool tetgenmesh::sinfected(face& s) {
04871 return (((unsigned long) s.sh[6] & (unsigned long) 4l) != 0);
04872 }
04873
04874
04875
04876
04877
04878
04879
04880
04881
04882
04883
04884 inline void tetgenmesh::tspivot(triface& t, face& s) {
04885 shellface sptr = (shellface) t.tet[8 + t.loc];
04886 sdecode(sptr, s);
04887 }
04888
04889
04890
04891 inline void tetgenmesh::stpivot(face& s, triface& t) {
04892 tetrahedron ptr = (tetrahedron) s.sh[6 + EdgeRing(s.shver)];
04893 decode(ptr, t);
04894 }
04895
04896
04897
04898 inline void tetgenmesh::tsbond(triface& t, face& s) {
04899 t.tet[8 + t.loc] = (tetrahedron) sencode(s);
04900 s.sh[6 + EdgeRing(s.shver)] = (shellface) encode(t);
04901 }
04902
04903
04904
04905 inline void tetgenmesh::tsdissolve(triface& t) {
04906 t.tet[8 + t.loc] = (tetrahedron) dummysh;
04907 }
04908
04909
04910
04911 inline void tetgenmesh::stdissolve(face& s) {
04912 s.sh[6 + EdgeRing(s.shver)] = (shellface) dummytet;
04913 }
04914
04915
04916
04917
04918
04919
04920
04921
04922
04923
04924
04925 inline void tetgenmesh::sspivot(face& s, face& edge) {
04926 shellface sptr = (shellface) s.sh[8 + Orient(s.shver)];
04927 sdecode(sptr, edge);
04928 }
04929
04930
04931
04932 inline void tetgenmesh::ssbond(face& s, face& edge) {
04933 s.sh[8 + Orient(s.shver)] = sencode(edge);
04934 edge.sh[0] = sencode(s);
04935 }
04936
04937
04938
04939 inline void tetgenmesh::ssdissolve(face& s) {
04940 s.sh[8 + Orient(s.shver)] = (shellface) dummysh;
04941 }
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951 inline void tetgenmesh::tsspivot1(triface& t, face& seg)
04952 {
04953 shellface sptr = (shellface) t.tet[8 + locver2edge[t.loc][t.ver]];
04954 sdecode(sptr, seg);
04955 }
04956
04957
04958
04959 inline void tetgenmesh::tssbond1(triface& t, face& seg)
04960 {
04961 t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) sencode(seg);
04962 }
04963
04964 inline void tetgenmesh::tssdissolve1(triface& t)
04965 {
04966 t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) dummysh;
04967 }
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977 inline int tetgenmesh::pointmark(point pt) {
04978 return ((int *) (pt))[pointmarkindex];
04979 }
04980
04981 inline void tetgenmesh::setpointmark(point pt, int value) {
04982 ((int *) (pt))[pointmarkindex] = value;
04983 }
04984
04985
04986
04987 inline enum tetgenmesh::verttype tetgenmesh::pointtype(point pt) {
04988 return (enum verttype) ((int *) (pt))[pointmarkindex + 1];
04989 }
04990
04991 inline void tetgenmesh::setpointtype(point pt, enum verttype value) {
04992 ((int *) (pt))[pointmarkindex + 1] = (int) value;
04993 }
04994
04995
04996
04997
04998 inline tetgenmesh::tetrahedron tetgenmesh::point2tet(point pt) {
04999 return ((tetrahedron *) (pt))[point2simindex];
05000 }
05001
05002 inline void tetgenmesh::setpoint2tet(point pt, tetrahedron value) {
05003 ((tetrahedron *) (pt))[point2simindex] = value;
05004 }
05005
05006 inline tetgenmesh::shellface tetgenmesh::point2sh(point pt) {
05007 return (shellface) ((tetrahedron *) (pt))[point2simindex + 1];
05008 }
05009
05010 inline void tetgenmesh::setpoint2sh(point pt, shellface value) {
05011 ((tetrahedron *) (pt))[point2simindex + 1] = (tetrahedron) value;
05012 }
05013
05014 inline tetgenmesh::point tetgenmesh::point2ppt(point pt) {
05015 return (point) ((tetrahedron *) (pt))[point2simindex + 2];
05016 }
05017
05018 inline void tetgenmesh::setpoint2ppt(point pt, point value) {
05019 ((tetrahedron *) (pt))[point2simindex + 2] = (tetrahedron) value;
05020 }
05021
05022 inline tetgenmesh::tetrahedron tetgenmesh::point2bgmtet(point pt) {
05023 return ((tetrahedron *) (pt))[point2simindex + 3];
05024 }
05025
05026 inline void tetgenmesh::setpoint2bgmtet(point pt, tetrahedron value) {
05027 ((tetrahedron *) (pt))[point2simindex + 3] = value;
05028 }
05029
05030
05031
05032 inline tetgenmesh::point tetgenmesh::point2pbcpt(point pt) {
05033 return (point) ((tetrahedron *) (pt))[point2pbcptindex];
05034 }
05035
05036 inline void tetgenmesh::setpoint2pbcpt(point pt, point value) {
05037 ((tetrahedron *) (pt))[point2pbcptindex] = (tetrahedron) value;
05038 }
05039
05040
05041
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052 inline void tetgenmesh::adjustedgering(triface& t, int direction) {
05053 if (EdgeRing(t.ver) != direction) {
05054 esymself(t);
05055 }
05056 }
05057
05058 inline void tetgenmesh::adjustedgering(face& s, int direction) {
05059 if (EdgeRing(s.shver) != direction) {
05060 sesymself(s);
05061 }
05062 }
05063
05064
05065
05066 inline bool tetgenmesh::isdead(triface* t) {
05067 if (t->tet == (tetrahedron *) NULL) return true;
05068 else return t->tet[4] == (tetrahedron) NULL;
05069 }
05070
05071 inline bool tetgenmesh::isdead(face* s) {
05072 if (s->sh == (shellface *) NULL) return true;
05073 else return s->sh[3] == (shellface) NULL;
05074 }
05075
05076
05077
05078
05079 inline bool tetgenmesh::isfacehaspoint(triface* t, point testpoint) {
05080 return ((org(*t) == testpoint) || (dest(*t) == testpoint) ||
05081 (apex(*t) == testpoint));
05082 }
05083
05084 inline bool tetgenmesh::isfacehaspoint(face* s, point testpoint) {
05085 return (s->sh[3] == (shellface) testpoint) ||
05086 (s->sh[4] == (shellface) testpoint) ||
05087 (s->sh[5] == (shellface) testpoint);
05088 }
05089
05090
05091
05092
05093 inline bool tetgenmesh::isfacehasedge(face* s, point tend1, point tend2) {
05094 return (isfacehaspoint(s, tend1) && isfacehaspoint(s, tend2));
05095 }
05096
05097
05098
05099 inline bool tetgenmesh::issymexist(triface* t) {
05100 tetrahedron *ptr = (tetrahedron *)
05101 ((unsigned long)(t->tet[t->loc]) & ~(unsigned long)7l);
05102 return ptr != dummytet;
05103 }
05104
05106
05107
05108
05109
05110
05111
05112
05114
05115 void tetgenmesh::getnextsface(face* s1, face* s2)
05116 {
05117 face neighsh, spinsh;
05118 face testseg;
05119
05120 sspivot(*s1, testseg);
05121 if (testseg.sh != dummysh) {
05122 testseg.shver = 0;
05123 if (sorg(testseg) == sorg(*s1)) {
05124 spivot(*s1, neighsh);
05125 } else {
05126 spinsh = *s1;
05127 do {
05128 neighsh = spinsh;
05129 spivotself(spinsh);
05130 } while (spinsh.sh != s1->sh);
05131 }
05132 } else {
05133 spivot(*s1, neighsh);
05134 }
05135 if (sorg(neighsh) != sorg(*s1)) {
05136 sesymself(neighsh);
05137 }
05138 if (s2 != (face *) NULL) {
05139 *s2 = neighsh;
05140 } else {
05141 *s1 = neighsh;
05142 }
05143 }
05144
05146
05147
05148
05149
05150
05151
05152
05153
05154
05155
05156
05157
05158
05160
05161 void tetgenmesh::tsspivot(triface* checkedge, face* checkseg)
05162 {
05163 triface spintet;
05164 face parentsh;
05165 point tapex;
05166 int hitbdry;
05167
05168 spintet = *checkedge;
05169 tapex = apex(*checkedge);
05170 hitbdry = 0;
05171 do {
05172 tspivot(spintet, parentsh);
05173
05174 if ((parentsh.sh != dummysh) && (sapex(parentsh) != NULL)) {
05175
05176 findedge(&parentsh, org(*checkedge), dest(*checkedge));
05177 sspivot(parentsh, *checkseg);
05178 if (checkseg->sh != dummysh) {
05179
05180 if (sorg(*checkseg) != org(*checkedge)) {
05181 sesymself(*checkseg);
05182 }
05183 }
05184 return;
05185 }
05186 if (!fnextself(spintet)) {
05187 hitbdry++;
05188 if (hitbdry < 2) {
05189 esym(*checkedge, spintet);
05190 if (!fnextself(spintet)) {
05191 hitbdry++;
05192 }
05193 }
05194 }
05195 } while ((apex(spintet) != tapex) && (hitbdry < 2));
05196
05197 checkseg->sh = dummysh;
05198 }
05199
05201
05202
05203
05204
05205
05206
05207
05208
05210
05211 void tetgenmesh::sstpivot(face* checkseg, triface* retedge)
05212 {
05213 face parentsh;
05214
05215
05216 sdecode(checkseg->sh[0], parentsh);
05217 #ifdef SELF_CHECK
05218 assert(parentsh.sh != dummysh);
05219 #endif
05220
05221 stpivot(parentsh, *retedge);
05222 if (retedge->tet == dummytet) {
05223 sesymself(parentsh);
05224 stpivot(parentsh, *retedge);
05225 #ifdef SELF_CHECK
05226 assert(retedge->tet != dummytet);
05227 #endif
05228 }
05229
05230 findedge(retedge, sorg(*checkseg), sdest(*checkseg));
05231 }
05232
05234
05235
05236
05237
05238
05239
05240
05242
05243 bool tetgenmesh::findorg(triface* tface, point dorg)
05244 {
05245 if (org(*tface) == dorg) {
05246 return true;
05247 } else {
05248 if (dest(*tface) == dorg) {
05249 enextself(*tface);
05250 return true;
05251 } else {
05252 if (apex(*tface) == dorg) {
05253 enext2self(*tface);
05254 return true;
05255 } else {
05256 if (oppo(*tface) == dorg) {
05257
05258 adjustedgering(*tface, CCW);
05259 fnextself(*tface);
05260 enext2self(*tface);
05261 return true;
05262 }
05263 }
05264 }
05265 }
05266 return false;
05267 }
05268
05269 bool tetgenmesh::findorg(face* sface, point dorg)
05270 {
05271 if (sorg(*sface) == dorg) {
05272 return true;
05273 } else {
05274 if (sdest(*sface) == dorg) {
05275 senextself(*sface);
05276 return true;
05277 } else {
05278 if (sapex(*sface) == dorg) {
05279 senext2self(*sface);
05280 return true;
05281 }
05282 }
05283 }
05284 return false;
05285 }
05286
05288
05289
05290
05291
05292
05293
05294
05296
05297 void tetgenmesh::findedge(triface* tface, point eorg, point edest)
05298 {
05299 int i;
05300
05301 for (i = 0; i < 3; i++) {
05302 if (org(*tface) == eorg) {
05303 if (dest(*tface) == edest) {
05304
05305 return;
05306 }
05307 } else {
05308 if (org(*tface) == edest) {
05309 if (dest(*tface) == eorg) {
05310
05311 esymself(*tface);
05312 return;
05313 }
05314 }
05315 }
05316 enextself(*tface);
05317 }
05318
05319 printf("Internalerror in findedge(): Unable to find an edge in tet.\n");
05320 internalerror();
05321 }
05322
05323 void tetgenmesh::findedge(face* sface, point eorg, point edest)
05324 {
05325 int i;
05326
05327 for (i = 0; i < 3; i++) {
05328 if (sorg(*sface) == eorg) {
05329 if (sdest(*sface) == edest) {
05330
05331 return;
05332 }
05333 } else {
05334 if (sorg(*sface) == edest) {
05335 if (sdest(*sface) == eorg) {
05336
05337 sesymself(*sface);
05338 return;
05339 }
05340 }
05341 }
05342 senextself(*sface);
05343 }
05344 printf("Internalerror in findedge(): Unable to find an edge in subface.\n");
05345 internalerror();
05346 }
05347
05349
05350
05351
05352
05353
05354
05355
05357
05358 void tetgenmesh::findface(triface *fface, point forg, point fdest, point fapex)
05359 {
05360 triface spintet;
05361 enum finddirectionresult collinear;
05362 int hitbdry;
05363
05364 if (!isdead(fface)) {
05365
05366 if (org(*fface) == forg && dest(*fface) == fdest &&
05367 apex(*fface) == fapex) return;
05368 } else {
05369
05370 if (!isdead(&recenttet)) *fface = recenttet;
05371 }
05372
05373 if (!isdead(fface)) {
05374 if (!findorg(fface, forg)) {
05375
05376 preciselocate(forg, fface, tetrahedrons->items);
05377 }
05378
05379 if (org(*fface) == forg) {
05380 collinear = finddirection(fface, fdest, tetrahedrons->items);
05381 if (collinear == RIGHTCOLLINEAR) {
05382
05383 } else if (collinear == LEFTCOLLINEAR) {
05384 enext2self(*fface);
05385 esymself(*fface);
05386 } else if (collinear == TOPCOLLINEAR) {
05387 fnextself(*fface);
05388 enext2self(*fface);
05389 esymself(*fface);
05390 }
05391 }
05392
05393 if ((org(*fface) == forg) && (dest(*fface) == fdest)) {
05394
05395 spintet = *fface;
05396 hitbdry = 0;
05397 do {
05398 if (apex(spintet) == fapex) {
05399
05400
05401 if (org(spintet) != org(*fface)) {
05402 esymself(spintet);
05403 }
05404 *fface = spintet;
05405 return;
05406 }
05407 if (!fnextself(spintet)) {
05408 hitbdry ++;
05409 if (hitbdry < 2) {
05410 esym(*fface, spintet);
05411 if (!fnextself(spintet)) {
05412 hitbdry ++;
05413 }
05414 }
05415 }
05416 } while (hitbdry < 2 && apex(spintet) != apex(*fface));
05417
05418 }
05419 }
05420
05421 if (isdead(fface) || (org(*fface) != forg) || (dest(*fface) != fdest) ||
05422 (apex(*fface) != fapex)) {
05423
05424
05425
05426 if (b->verbose > 1) {
05427 printf("Warning in findface(): Perform a brute-force searching.\n");
05428 }
05429 enum verttype forgty, fdestty, fapexty;
05430 int share, i;
05431 forgty = pointtype(forg);
05432 fdestty = pointtype(fdest);
05433 fapexty = pointtype(fapex);
05434 setpointtype(forg, DEADVERTEX);
05435 setpointtype(fdest, DEADVERTEX);
05436 setpointtype(fapex, DEADVERTEX);
05437 tetrahedrons->traversalinit();
05438 fface->tet = tetrahedrontraverse();
05439 while (fface->tet != (tetrahedron *) NULL) {
05440 share = 0;
05441 for (i = 0; i < 4; i++) {
05442 if (pointtype((point) fface->tet[4 + i]) == DEADVERTEX) share ++;
05443 }
05444 if (share == 3) {
05445
05446 if (pointtype((point) fface->tet[4]) != DEADVERTEX) {
05447 fface->loc = 2;
05448 } else if (pointtype((point) fface->tet[5]) != DEADVERTEX) {
05449 fface->loc = 3;
05450 } else if (pointtype((point) fface->tet[6]) != DEADVERTEX) {
05451 fface->loc = 1;
05452 } else {
05453 fface->loc = 0;
05454 }
05455 findedge(fface, forg, fdest);
05456 break;
05457 }
05458 fface->tet = tetrahedrontraverse();
05459 }
05460 setpointtype(forg, forgty);
05461 setpointtype(fdest, fdestty);
05462 setpointtype(fapex, fapexty);
05463 if (fface->tet == (tetrahedron *) NULL) {
05464
05465 printf("Internal error: Fail to find the indicated face.\n");
05466 internalerror();
05467 }
05468 }
05469 }
05470
05472
05473
05474
05475
05476
05477
05479
05480 void tetgenmesh::getonextseg(face* s, face* lseg)
05481 {
05482 face checksh, checkseg;
05483 point forg;
05484
05485 forg = sorg(*s);
05486 checksh = *s;
05487 do {
05488
05489 senext2self(checksh);
05490
05491 sspivot(checksh, checkseg);
05492 if (checkseg.sh != dummysh) break;
05493
05494 spivotself(checksh);
05495 #ifdef SELF_CHECK
05496
05497 assert(checksh.sh != s->sh);
05498 #endif
05499 if (sorg(checksh) != forg) {
05500 sesymself(checksh);
05501 #ifdef SELF_CHECK
05502 assert(sorg(checksh) == forg);
05503 #endif
05504 }
05505 } while (true);
05506 if (sorg(checkseg) != forg) sesymself(checkseg);
05507 *lseg = checkseg;
05508 }
05509
05511
05512
05513
05514
05515
05516
05517
05519
05520 void tetgenmesh::getseghasorg(face* sseg, point dorg)
05521 {
05522 face nextseg;
05523 point checkpt;
05524
05525 nextseg = *sseg;
05526 checkpt = sorg(nextseg);
05527 while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05528
05529 senext2self(nextseg);
05530 spivotself(nextseg);
05531 nextseg.shver = 0;
05532 if (sdest(nextseg) != checkpt) sesymself(nextseg);
05533 checkpt = sorg(nextseg);
05534 }
05535 if (checkpt == dorg) {
05536 *sseg = nextseg;
05537 return;
05538 }
05539 nextseg = *sseg;
05540 checkpt = sdest(nextseg);
05541 while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05542
05543 senextself(nextseg);
05544 spivotself(nextseg);
05545 nextseg.shver = 0;
05546 if (sorg(nextseg) != checkpt) sesymself(nextseg);
05547 checkpt = sdest(nextseg);
05548 }
05549 if (checkpt == dorg) {
05550 sesym(nextseg, *sseg);
05551 return;
05552 }
05553
05554 printf("Internalerror in getseghasorg(): Unable to find the subseg.\n");
05555 internalerror();
05556 }
05557
05559
05560
05561
05563
05564 tetgenmesh::point tetgenmesh::getsubsegfarorg(face* sseg)
05565 {
05566 face prevseg;
05567 point checkpt;
05568
05569 checkpt = sorg(*sseg);
05570 senext2(*sseg, prevseg);
05571 spivotself(prevseg);
05572
05573 while (prevseg.sh != dummysh) {
05574 prevseg.shver = 0;
05575 if (sdest(prevseg) != checkpt) sesymself(prevseg);
05576 checkpt = sorg(prevseg);
05577 senext2self(prevseg);
05578 spivotself(prevseg);
05579 }
05580 return checkpt;
05581 }
05582
05584
05585
05586
05588
05589 tetgenmesh::point tetgenmesh::getsubsegfardest(face* sseg)
05590 {
05591 face nextseg;
05592 point checkpt;
05593
05594 checkpt = sdest(*sseg);
05595 senext(*sseg, nextseg);
05596 spivotself(nextseg);
05597
05598 while (nextseg.sh != dummysh) {
05599 nextseg.shver = 0;
05600 if (sorg(nextseg) != checkpt) sesymself(nextseg);
05601 checkpt = sdest(nextseg);
05602 senextself(nextseg);
05603 spivotself(nextseg);
05604 }
05605 return checkpt;
05606 }
05607
05609
05610
05611
05612
05613
05615
05616 void tetgenmesh::printtet(triface* tface)
05617 {
05618 triface tmpface, prtface;
05619 point tmppt;
05620 face tmpsh;
05621 int facecount;
05622
05623 printf("Tetra x%lx with loc(%i) and ver(%i):",
05624 (unsigned long)(tface->tet), tface->loc, tface->ver);
05625 if (infected(*tface)) {
05626 printf(" (infected)");
05627 }
05628 printf("\n");
05629
05630 tmpface = *tface;
05631 facecount = 0;
05632 while(facecount < 4) {
05633 tmpface.loc = facecount;
05634 sym(tmpface, prtface);
05635 if(prtface.tet == dummytet) {
05636 printf(" [%i] Outer space.\n", facecount);
05637 } else {
05638 printf(" [%i] x%lx loc(%i).", facecount,
05639 (unsigned long)(prtface.tet), prtface.loc);
05640 if (infected(prtface)) {
05641 printf(" (infected)");
05642 }
05643 printf("\n");
05644 }
05645 facecount ++;
05646 }
05647
05648 tmppt = org(*tface);
05649 if(tmppt == (point) NULL) {
05650 printf(" Org [%i] NULL\n", locver2org[tface->loc][tface->ver]);
05651 } else {
05652 printf(" Org [%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05653 locver2org[tface->loc][tface->ver], (unsigned long)(tmppt),
05654 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05655 }
05656 tmppt = dest(*tface);
05657 if(tmppt == (point) NULL) {
05658 printf(" Dest[%i] NULL\n", locver2dest[tface->loc][tface->ver]);
05659 } else {
05660 printf(" Dest[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05661 locver2dest[tface->loc][tface->ver], (unsigned long)(tmppt),
05662 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05663 }
05664 tmppt = apex(*tface);
05665 if(tmppt == (point) NULL) {
05666 printf(" Apex[%i] NULL\n", locver2apex[tface->loc][tface->ver]);
05667 } else {
05668 printf(" Apex[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05669 locver2apex[tface->loc][tface->ver], (unsigned long)(tmppt),
05670 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05671 }
05672 tmppt = oppo(*tface);
05673 if(tmppt == (point) NULL) {
05674 printf(" Oppo[%i] NULL\n", loc2oppo[tface->loc]);
05675 } else {
05676 printf(" Oppo[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05677 loc2oppo[tface->loc], (unsigned long)(tmppt),
05678 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05679 }
05680
05681 if (b->useshelles) {
05682 tmpface = *tface;
05683 facecount = 0;
05684 while(facecount < 6) {
05685 tmpface.loc = facecount;
05686 tspivot(tmpface, tmpsh);
05687 if(tmpsh.sh != dummysh) {
05688 printf(" [%i] x%lx ID(%i) ", facecount,
05689 (unsigned long)(tmpsh.sh), shellmark(tmpsh));
05690 if (sorg(tmpsh) == (point) NULL) {
05691 printf("(fake)");
05692 }
05693 printf("\n");
05694 }
05695 facecount ++;
05696 }
05697 }
05698 }
05699
05701
05702
05703
05704
05705
05707
05708 void tetgenmesh::printsh(face* sface)
05709 {
05710 face prtsh;
05711 triface prttet;
05712 point printpoint;
05713
05714 if (sapex(*sface) != NULL) {
05715 printf("subface x%lx, ver %d, mark %d:",
05716 (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05717 } else {
05718 printf("Subsegment x%lx, ver %d, mark %d:",
05719 (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05720 }
05721 if (sinfected(*sface)) {
05722 printf(" (infected)");
05723 }
05724 if (shell2badface(*sface)) {
05725 printf(" (queued)");
05726 }
05727 if (sapex(*sface) != NULL) {
05728 if (shelltype(*sface) == SHARP) {
05729 printf(" (sharp)");
05730 }
05731 } else {
05732 if (shelltype(*sface) == SHARP) {
05733 printf(" (sharp)");
05734 }
05735 }
05736 if (checkpbcs) {
05737 if (shellpbcgroup(*sface) >= 0) {
05738 printf(" (pbc %d)", shellpbcgroup(*sface));
05739 }
05740 }
05741 printf("\n");
05742
05743 sdecode(sface->sh[0], prtsh);
05744 if (prtsh.sh == dummysh) {
05745 printf(" [0] = No shell\n");
05746 } else {
05747 printf(" [0] = x%lx %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05748 }
05749 sdecode(sface->sh[1], prtsh);
05750 if (prtsh.sh == dummysh) {
05751 printf(" [1] = No shell\n");
05752 } else {
05753 printf(" [1] = x%lx %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05754 }
05755 sdecode(sface->sh[2], prtsh);
05756 if (prtsh.sh == dummysh) {
05757 printf(" [2] = No shell\n");
05758 } else {
05759 printf(" [2] = x%lx %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05760 }
05761
05762 printpoint = sorg(*sface);
05763 if (printpoint == (point) NULL)
05764 printf(" Org [%d] = NULL\n", vo[sface->shver]);
05765 else
05766 printf(" Org [%d] = x%lx (%.12g,%.12g,%.12g) %d\n",
05767 vo[sface->shver], (unsigned long)(printpoint), printpoint[0],
05768 printpoint[1], printpoint[2], pointmark(printpoint));
05769 printpoint = sdest(*sface);
05770 if (printpoint == (point) NULL)
05771 printf(" Dest[%d] = NULL\n", vd[sface->shver]);
05772 else
05773 printf(" Dest[%d] = x%lx (%.12g,%.12g,%.12g) %d\n",
05774 vd[sface->shver], (unsigned long)(printpoint), printpoint[0],
05775 printpoint[1], printpoint[2], pointmark(printpoint));
05776
05777 if (sapex(*sface) != NULL) {
05778 printpoint = sapex(*sface);
05779 if (printpoint == (point) NULL)
05780 printf(" Apex[%d] = NULL\n", va[sface->shver]);
05781 else
05782 printf(" Apex[%d] = x%lx (%.12g,%.12g,%.12g) %d\n",
05783 va[sface->shver], (unsigned long)(printpoint), printpoint[0],
05784 printpoint[1], printpoint[2], pointmark(printpoint));
05785
05786 decode(sface->sh[6], prttet);
05787 if (prttet.tet == dummytet) {
05788 printf(" [6] = Outer space\n");
05789 } else {
05790 printf(" [6] = x%lx %d\n",
05791 (unsigned long)(prttet.tet), prttet.loc);
05792 }
05793 decode(sface->sh[7], prttet);
05794 if (prttet.tet == dummytet) {
05795 printf(" [7] = Outer space\n");
05796 } else {
05797 printf(" [7] = x%lx %d\n",
05798 (unsigned long)(prttet.tet), prttet.loc);
05799 }
05800
05801 sdecode(sface->sh[8], prtsh);
05802 if (prtsh.sh == dummysh) {
05803 printf(" [8] = No subsegment\n");
05804 } else {
05805 printf(" [8] = x%lx %d\n",
05806 (unsigned long)(prtsh.sh), prtsh.shver);
05807 }
05808 sdecode(sface->sh[9], prtsh);
05809 if (prtsh.sh == dummysh) {
05810 printf(" [9] = No subsegment\n");
05811 } else {
05812 printf(" [9] = x%lx %d\n",
05813 (unsigned long)(prtsh.sh), prtsh.shver);
05814 }
05815 sdecode(sface->sh[10], prtsh);
05816 if (prtsh.sh == dummysh) {
05817 printf(" [10]= No subsegment\n");
05818 } else {
05819 printf(" [10]= x%lx %d\n",
05820 (unsigned long)(prtsh.sh), prtsh.shver);
05821 }
05822 }
05823 }
05824
05825
05826
05827
05828
05829
05830
05831
05832
05833
05834
05835
05836
05838
05839
05840
05841
05842
05843
05844
05845
05847
05848 void tetgenmesh::makepoint2tetmap()
05849 {
05850 triface tetloop;
05851 point pointptr;
05852
05853 if (b->verbose > 0) {
05854 printf(" Constructing mapping from points to tetrahedra.\n");
05855 }
05856
05857
05858 points->traversalinit();
05859 pointptr = pointtraverse();
05860 while (pointptr != (point) NULL) {
05861 setpoint2tet(pointptr, (tetrahedron) NULL);
05862 pointptr = pointtraverse();
05863 }
05864
05865 tetrahedrons->traversalinit();
05866 tetloop.tet = tetrahedrontraverse();
05867 while (tetloop.tet != (tetrahedron *) NULL) {
05868
05869 tetloop.loc = 0;
05870 pointptr = org(tetloop);
05871 setpoint2tet(pointptr, encode(tetloop));
05872 pointptr = dest(tetloop);
05873 setpoint2tet(pointptr, encode(tetloop));
05874 pointptr = apex(tetloop);
05875 setpoint2tet(pointptr, encode(tetloop));
05876 pointptr = oppo(tetloop);
05877 setpoint2tet(pointptr, encode(tetloop));
05878
05879 tetloop.tet = tetrahedrontraverse();
05880 }
05881 }
05882
05884
05885
05886
05887
05888
05889
05890
05891
05893
05894 void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
05895 {
05896 point pointloop;
05897 int idx;
05898
05899 if (b->verbose > 0) {
05900 printf(" Constructing mapping from indices to points.\n");
05901 }
05902
05903 idx2verlist = new point[points->items];
05904
05905 points->traversalinit();
05906 pointloop = pointtraverse();
05907 idx = 0;
05908 while (pointloop != (point) NULL) {
05909 idx2verlist[idx] = pointloop;
05910 idx++;
05911 pointloop = pointtraverse();
05912 }
05913 }
05914
05916
05917
05918
05919
05920
05921
05922
05923
05924
05925
05926
05927
05928
05929
05930
05932
05933 void tetgenmesh::makesegmentmap(int*& idx2seglist, shellface**& segsperverlist)
05934 {
05935 shellface *shloop;
05936 int i, j, k;
05937
05938 if (b->verbose > 0) {
05939 printf(" Constructing mapping from points to segments.\n");
05940 }
05941
05942
05943 idx2seglist = new int[points->items + 1];
05944 for (i = 0; i < points->items + 1; i++) idx2seglist[i] = 0;
05945
05946
05947
05948 subsegs->traversalinit();
05949 shloop = shellfacetraverse(subsegs);
05950 while (shloop != (shellface *) NULL) {
05951
05952 for (i = 0; i < 2; i++) {
05953 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05954 idx2seglist[j]++;
05955 }
05956 shloop = shellfacetraverse(subsegs);
05957 }
05958
05959
05960 j = idx2seglist[0];
05961 idx2seglist[0] = 0;
05962 for (i = 0; i < points->items; i++) {
05963 k = idx2seglist[i + 1];
05964 idx2seglist[i + 1] = idx2seglist[i] + j;
05965 j = k;
05966 }
05967
05968 segsperverlist = new shellface*[idx2seglist[i]];
05969
05970 subsegs->traversalinit();
05971 shloop = shellfacetraverse(subsegs);
05972 while (shloop != (shellface *) NULL) {
05973 for (i = 0; i < 2; i++) {
05974 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05975 segsperverlist[idx2seglist[j]] = shloop;
05976 idx2seglist[j]++;
05977 }
05978 shloop = shellfacetraverse(subsegs);
05979 }
05980
05981 for (i = points->items - 1; i >= 0; i--) {
05982 idx2seglist[i + 1] = idx2seglist[i];
05983 }
05984 idx2seglist[0] = 0;
05985 }
05986
05988
05989
05990
05991
05992
05993
05994
05995
05996
05997
05998
05999
06000
06001
06002
06004
06005 void tetgenmesh::
06006 makesubfacemap(int*& idx2facelist, shellface**& facesperverlist)
06007 {
06008 shellface *shloop;
06009 int i, j, k;
06010
06011 if (b->verbose > 0) {
06012 printf(" Constructing mapping from points to subfaces.\n");
06013 }
06014
06015
06016 idx2facelist = new int[points->items + 1];
06017 for (i = 0; i < points->items + 1; i++) idx2facelist[i] = 0;
06018
06019
06020
06021 subfaces->traversalinit();
06022 shloop = shellfacetraverse(subfaces);
06023 while (shloop != (shellface *) NULL) {
06024
06025 for (i = 0; i < 3; i++) {
06026 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06027 idx2facelist[j]++;
06028 }
06029 shloop = shellfacetraverse(subfaces);
06030 }
06031
06032
06033 j = idx2facelist[0];
06034 idx2facelist[0] = 0;
06035 for (i = 0; i < points->items; i++) {
06036 k = idx2facelist[i + 1];
06037 idx2facelist[i + 1] = idx2facelist[i] + j;
06038 j = k;
06039 }
06040
06041 facesperverlist = new shellface*[idx2facelist[i]];
06042
06043 subfaces->traversalinit();
06044 shloop = shellfacetraverse(subfaces);
06045 while (shloop != (shellface *) NULL) {
06046 for (i = 0; i < 3; i++) {
06047 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06048 facesperverlist[idx2facelist[j]] = shloop;
06049 idx2facelist[j]++;
06050 }
06051 shloop = shellfacetraverse(subfaces);
06052 }
06053
06054 for (i = points->items - 1; i >= 0; i--) {
06055 idx2facelist[i + 1] = idx2facelist[i];
06056 }
06057 idx2facelist[0] = 0;
06058 }
06059
06061
06062
06063
06064
06065
06066
06067
06068
06069
06070
06071
06072
06073
06074
06075
06077
06078 void tetgenmesh::
06079 maketetrahedronmap(int*& idx2tetlist, tetrahedron**& tetsperverlist)
06080 {
06081 tetrahedron *tetloop;
06082 int i, j, k;
06083
06084 if (b->verbose > 0) {
06085 printf(" Constructing mapping from points to tetrahedra.\n");
06086 }
06087
06088
06089 idx2tetlist = new int[points->items + 1];
06090 for (i = 0; i < points->items + 1; i++) idx2tetlist[i] = 0;
06091
06092
06093
06094 tetrahedrons->traversalinit();
06095 tetloop = tetrahedrontraverse();
06096 while (tetloop != (tetrahedron *) NULL) {
06097
06098 for (i = 0; i < 4; i++) {
06099 j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06100 idx2tetlist[j]++;
06101 }
06102 tetloop = tetrahedrontraverse();
06103 }
06104
06105
06106 j = idx2tetlist[0];
06107 idx2tetlist[0] = 0;
06108 for (i = 0; i < points->items; i++) {
06109 k = idx2tetlist[i + 1];
06110 idx2tetlist[i + 1] = idx2tetlist[i] + j;
06111 j = k;
06112 }
06113
06114 tetsperverlist = new tetrahedron*[idx2tetlist[i]];
06115
06116 tetrahedrons->traversalinit();
06117 tetloop = tetrahedrontraverse();
06118 while (tetloop != (tetrahedron *) NULL) {
06119 for (i = 0; i < 4; i++) {
06120 j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06121 tetsperverlist[idx2tetlist[j]] = tetloop;
06122 idx2tetlist[j]++;
06123 }
06124 tetloop = tetrahedrontraverse();
06125 }
06126
06127 for (i = points->items - 1; i >= 0; i--) {
06128 idx2tetlist[i + 1] = idx2tetlist[i];
06129 }
06130 idx2tetlist[0] = 0;
06131 }
06132
06133
06134
06135
06136
06137
06138
06139
06140
06141
06142
06143 inline REAL tetgenmesh::dot(REAL* v1, REAL* v2)
06144 {
06145 return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
06146 }
06147
06148
06149
06150 inline void tetgenmesh::cross(REAL* v1, REAL* v2, REAL* n)
06151 {
06152 n[0] = v1[1] * v2[2] - v2[1] * v1[2];
06153 n[1] = -(v1[0] * v2[2] - v2[0] * v1[2]);
06154 n[2] = v1[0] * v2[1] - v2[0] * v1[1];
06155 }
06156
06157
06158 static void initm44(REAL a00, REAL a01, REAL a02, REAL a03,
06159 REAL a10, REAL a11, REAL a12, REAL a13,
06160 REAL a20, REAL a21, REAL a22, REAL a23,
06161 REAL a30, REAL a31, REAL a32, REAL a33,
06162 REAL M[4][4])
06163 {
06164 M[0][0] = a00; M[0][1] = a01; M[0][2] = a02; M[0][3] = a03;
06165 M[1][0] = a10; M[1][1] = a11; M[1][2] = a12; M[1][3] = a13;
06166 M[2][0] = a20; M[2][1] = a21; M[2][2] = a22; M[2][3] = a23;
06167 M[3][0] = a30; M[3][1] = a31; M[3][2] = a32; M[3][3] = a33;
06168 }
06169
06170
06171 static void m4xm4(REAL m1[4][4], REAL m2[4][4])
06172 {
06173 REAL tmp[4];
06174 int i, j;
06175
06176 for (i = 0; i < 4; i++) {
06177 for (j = 0; j < 4; j++) {
06178 tmp[j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j]
06179 + m1[i][2] * m2[2][j] + m1[i][3] * m2[3][j];
06180 }
06181 for (j = 0; j < 4; j++)
06182 m1[i][j] = tmp[j];
06183 }
06184 }
06185
06186
06187 static void m4xv4(REAL v2[4], REAL m[4][4], REAL v1[4])
06188 {
06189 v2[0] = m[0][0]*v1[0] + m[0][1]*v1[1] + m[0][2]*v1[2] + m[0][3]*v1[3];
06190 v2[1] = m[1][0]*v1[0] + m[1][1]*v1[1] + m[1][2]*v1[2] + m[1][3]*v1[3];
06191 v2[2] = m[2][0]*v1[0] + m[2][1]*v1[1] + m[2][2]*v1[2] + m[2][3]*v1[3];
06192 v2[3] = m[3][0]*v1[0] + m[3][1]*v1[1] + m[3][2]*v1[2] + m[3][3]*v1[3];
06193 }
06194
06196
06197
06198
06199
06200
06201
06202
06203
06204
06205
06206
06207
06208
06209
06210
06211
06212
06213
06214
06215
06216
06218
06219 bool tetgenmesh::lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N)
06220 {
06221 REAL scales[4];
06222 REAL pivot, biggest, mult, tempf;
06223 int pivotindex = 0;
06224 int i, j, k;
06225
06226 *d = 1.0;
06227
06228 for (i = N; i < n + N; i++) {
06229
06230 biggest = 0.0;
06231 for (j = N; j < n + N; j++)
06232 if (biggest < (tempf = fabs(lu[i][j])))
06233 biggest = tempf;
06234 if (biggest != 0.0)
06235 scales[i] = 1.0 / biggest;
06236 else {
06237 scales[i] = 0.0;
06238 return false;
06239 }
06240 ps[i] = i;
06241 }
06242
06243 for (k = N; k < n + N - 1; k++) {
06244
06245 biggest = 0.0;
06246 for (i = k; i < n + N; i++) {
06247 if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
06248 biggest = tempf;
06249 pivotindex = i;
06250 }
06251 }
06252 if (biggest == 0.0) {
06253 return false;
06254 }
06255 if (pivotindex != k) {
06256 j = ps[k];
06257 ps[k] = ps[pivotindex];
06258 ps[pivotindex] = j;
06259 *d = -(*d);
06260 }
06261
06262
06263 pivot = lu[ps[k]][k];
06264 for (i = k + 1; i < n + N; i++) {
06265 lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
06266 if (mult != 0.0) {
06267 for (j = k + 1; j < n + N; j++)
06268 lu[ps[i]][j] -= mult * lu[ps[k]][j];
06269 }
06270 }
06271 }
06272
06273
06274 return lu[ps[n + N - 1]][n + N - 1] != 0.0;
06275 }
06276
06278
06279
06280
06281
06282
06283
06284
06285
06286
06287
06288
06289
06291
06292 void tetgenmesh::lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N)
06293 {
06294 int i, j;
06295 REAL X[4], dot;
06296
06297 for (i = N; i < n + N; i++) X[i] = 0.0;
06298
06299
06300 for (i = N; i < n + N; i++) {
06301 dot = 0.0;
06302 for (j = N; j < i + N; j++)
06303 dot += lu[ps[i]][j] * X[j];
06304 X[i] = b[ps[i]] - dot;
06305 }
06306
06307
06308 for (i = n + N - 1; i >= N; i--) {
06309 dot = 0.0;
06310 for (j = i + 1; j < n + N; j++)
06311 dot += lu[ps[i]][j] * X[j];
06312 X[i] = (X[i] - dot) / lu[ps[i]][i];
06313 }
06314
06315 for (i = N; i < n + N; i++) b[i] = X[i];
06316 }
06317
06318
06319
06320
06321
06322
06323
06324
06325
06326
06327
06328
06329
06330
06332
06333
06334
06335
06336
06337
06338
06339
06340
06341
06342
06343
06345
06346 enum tetgenmesh::interresult tetgenmesh::edge_vert_col_inter(REAL* A, REAL* B,
06347 REAL* P)
06348 {
06349 int i = 0;
06350 do {
06351 if (A[i] < B[i]) {
06352 if (P[i] < A[i]) {
06353 return DISJOINT;
06354 } else if (P[i] > A[i]) {
06355 if (P[i] < B[i]) {
06356 return INTERSECT;
06357 } else if (P[i] > B[i]) {
06358 return DISJOINT;
06359 } else {
06360
06361 return SHAREVERTEX;
06362 }
06363 } else {
06364
06365 return SHAREVERTEX;
06366 }
06367 } else if (A[i] > B[i]) {
06368 if (P[i] < B[i]) {
06369 return DISJOINT;
06370 } else if (P[i] > B[i]) {
06371 if (P[i] < A[i]) {
06372 return INTERSECT;
06373 } else if (P[i] > A[i]) {
06374 return DISJOINT;
06375 } else {
06376
06377 return SHAREVERTEX;
06378 }
06379 } else {
06380
06381 return SHAREVERTEX;
06382 }
06383 }
06384
06385 i++;
06386 } while (i < 3);
06387
06388 return DISJOINT;
06389 }
06390
06392
06393
06394
06395
06396
06397
06398
06399
06400
06401
06402
06403
06404
06405
06406
06408
06409 enum tetgenmesh::interresult tetgenmesh:: edge_edge_cop_inter(REAL* A, REAL* B,
06410 REAL* P, REAL* Q, REAL* R)
06411 {
06412 REAL s1, s2, s3, s4;
06413
06414 #ifdef SELF_CHECK
06415 assert(R != NULL);
06416 #endif
06417 s1 = orient3d(A, B, R, P);
06418 s2 = orient3d(A, B, R, Q);
06419 if (s1 * s2 > 0.0) {
06420
06421 return DISJOINT;
06422 }
06423 s3 = orient3d(P, Q, R, A);
06424 s4 = orient3d(P, Q, R, B);
06425 if (s3 * s4 > 0.0) {
06426
06427 return DISJOINT;
06428 }
06429
06430
06431
06432
06433
06434 enum interresult abp, abq;
06435 enum interresult pqa, pqb;
06436
06437 if (s1 == 0.0) {
06438
06439 abp = edge_vert_col_inter(A, B, P);
06440 if (abp == INTERSECT) {
06441
06442 return INTERSECT;
06443 }
06444 if (s2 == 0.0) {
06445
06446 abq = edge_vert_col_inter(A, B, Q);
06447 if (abq == INTERSECT) {
06448
06449 return INTERSECT;
06450 }
06451 if (abp == SHAREVERTEX && abq == SHAREVERTEX) {
06452
06453 return SHAREEDGE;
06454 }
06455 pqa = edge_vert_col_inter(P, Q, A);
06456 if (pqa == INTERSECT) {
06457
06458 return INTERSECT;
06459 }
06460 pqb = edge_vert_col_inter(P, Q, B);
06461 if (pqb == INTERSECT) {
06462
06463 return INTERSECT;
06464 }
06465 if (abp == SHAREVERTEX || abq == SHAREVERTEX) {
06466
06467 #ifdef SELF_CHECK
06468
06469 assert(abp ^ abq);
06470 #endif
06471 return SHAREVERTEX;
06472 }
06473
06474 #ifdef SELF_CHECK
06475 assert((abp == DISJOINT) && (abp == abq && abq == pqa && pqa == pqb));
06476 #endif
06477 return DISJOINT;
06478 } else {
06479
06480 #ifdef SELF_CHECK
06481 assert(abp == SHAREVERTEX || abp == DISJOINT);
06482 #endif
06483 return abp;
06484 }
06485 }
06486
06487 if (s2 == 0.0) {
06488
06489 abq = edge_vert_col_inter(A, B, Q);
06490 #ifdef SELF_CHECK
06491 assert(abq == SHAREVERTEX || abq == DISJOINT || abq == INTERSECT);
06492 #endif
06493 return abq;
06494 }
06495
06496
06497
06498 if (s3 == 0.0) {
06499
06500 #ifdef SELF_CHECK
06501 assert(s4 != 0.0);
06502 #endif
06503 pqa = edge_vert_col_inter(P, Q, A);
06504 #ifdef SELF_CHECK
06505
06506 assert(pqa != SHAREVERTEX);
06507 assert(pqa == INTERSECT || pqa == DISJOINT);
06508 #endif
06509 return pqa;
06510 }
06511 if (s4 == 0.0) {
06512
06513 #ifdef SELF_CHECK
06514 assert(s3 != 0.0);
06515 #endif
06516 pqb = edge_vert_col_inter(P, Q, B);
06517 #ifdef SELF_CHECK
06518
06519 assert(pqb != SHAREVERTEX);
06520 assert(pqb == INTERSECT || pqb == DISJOINT);
06521 #endif
06522 return pqb;
06523 }
06524
06525
06526 return INTERSECT;
06527 }
06528
06530
06531
06532
06533
06534
06535
06536
06537
06538
06540
06542
06543
06544
06545
06546
06547
06548
06549
06550
06551
06552
06553
06554
06555
06557
06558 enum tetgenmesh::interresult tetgenmesh::tri_vert_cop_inter(REAL* A, REAL* B,
06559 REAL* C, REAL* P, REAL* R)
06560 {
06561 REAL s1, s2, s3;
06562 int sign;
06563
06564 #ifdef SELF_CHECK
06565 assert(R != (REAL *) NULL);
06566 #endif
06567
06568
06569 s1 = orient3d(A, B, C, R);
06570 #ifdef SELF_CHECK
06571 assert(s1 != 0.0);
06572 #endif
06573 sign = s1 < 0.0 ? 1 : -1;
06574
06575
06576 s1 = orient3d(A, B, R, P) * sign;
06577 if (s1 < 0.0) {
06578
06579 return DISJOINT;
06580 }
06581 s2 = orient3d(B, C, R, P) * sign;
06582 if (s2 < 0.0) {
06583
06584 return DISJOINT;
06585 }
06586 s3 = orient3d(C, A, R, P) * sign;
06587 if (s3 < 0.0) {
06588
06589 return DISJOINT;
06590 }
06591 if (s1 == 0.0) {
06592
06593 if (s2 == 0.0) {
06594
06595 #ifdef SELF_CHECK
06596 assert(s3 > 0.0);
06597 #endif
06598
06599 return SHAREVERTEX;
06600 }
06601 if (s3 == 0.0) {
06602
06603
06604 return SHAREVERTEX;
06605 }
06606
06607 return INTERSECT;
06608 }
06609
06610 if (s2 == 0.0) {
06611
06612 if (s3 == 0.0) {
06613
06614
06615 return SHAREVERTEX;
06616 }
06617
06618 return INTERSECT;
06619 }
06620 if (s3 == 0.0) {
06621
06622
06623 return INTERSECT;
06624 }
06625
06626
06627 return INTERSECT;
06628 }
06629
06631
06632
06633
06634
06635
06636
06637
06638
06639
06640
06641
06643
06644 enum tetgenmesh::interresult tetgenmesh::tri_edge_cop_inter(REAL* A, REAL* B,
06645 REAL* C, REAL* P, REAL* Q, REAL* R)
06646 {
06647 enum interresult abpq, bcpq, capq;
06648 enum interresult abcp, abcq;
06649
06650
06651 abpq = edge_edge_cop_inter(A, B, P, Q, R);
06652 if (abpq == INTERSECT || abpq == SHAREEDGE) {
06653 return abpq;
06654 }
06655 bcpq = edge_edge_cop_inter(B, C, P, Q, R);
06656 if (bcpq == INTERSECT || bcpq == SHAREEDGE) {
06657 return bcpq;
06658 }
06659 capq = edge_edge_cop_inter(C, A, P, Q, R);
06660 if (capq == INTERSECT || capq == SHAREEDGE) {
06661 return capq;
06662 }
06663
06664
06665 abcp = tri_vert_cop_inter(A, B, C, P, R);
06666 if (abcp == INTERSECT) {
06667 return INTERSECT;
06668 }
06669 abcq = tri_vert_cop_inter(A, B, C, Q, R);
06670 if (abcq == INTERSECT) {
06671 return INTERSECT;
06672 }
06673
06674
06675
06676 if (abpq == SHAREVERTEX) {
06677
06678 #ifdef SELF_CHECK
06679 assert(abcp ^ abcq);
06680 #endif
06681 return SHAREVERTEX;
06682 }
06683 if (bcpq == SHAREVERTEX) {
06684
06685 #ifdef SELF_CHECK
06686 assert(abcp ^ abcq);
06687 #endif
06688 return SHAREVERTEX;
06689 }
06690 if (capq == SHAREVERTEX) {
06691
06692 #ifdef SELF_CHECK
06693 assert(abcp ^ abcq);
06694 #endif
06695 return SHAREVERTEX;
06696 }
06697
06698
06699 return DISJOINT;
06700 }
06701
06703
06704
06705
06706
06707
06708
06709
06710
06711
06712
06713
06715
06716 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter_tail(REAL* A, REAL* B,
06717 REAL* C, REAL* P, REAL* Q, REAL s1, REAL s2)
06718 {
06719 REAL s3, s4, s5;
06720 int sign;
06721
06722 if (s1 * s2 > 0.0) {
06723
06724 return DISJOINT;
06725 }
06726
06727 if (s1 * s2 < 0.0) {
06728
06729
06730
06731 sign = s1 < 0.0 ? 1 : -1;
06732 s3 = orient3d(A, B, P, Q) * sign;
06733 if (s3 < 0.0) {
06734
06735 return DISJOINT;
06736 }
06737 s4 = orient3d(B, C, P, Q) * sign;
06738 if (s4 < 0.0) {
06739
06740 return DISJOINT;
06741 }
06742 s5 = orient3d(C, A, P, Q) * sign;
06743 if (s5 < 0.0) {
06744
06745 return DISJOINT;
06746 }
06747 if (s3 == 0.0) {
06748
06749 if (s4 == 0.0) {
06750
06751 #ifdef SELF_CHECK
06752 assert(s5 > 0.0);
06753 #endif
06754
06755 return SHAREVERTEX;
06756 }
06757 if (s5 == 0.0) {
06758
06759
06760 return SHAREVERTEX;
06761 }
06762
06763
06764 return INTERSECT;
06765 }
06766
06767 if (s4 == 0.0) {
06768
06769 if (s5 == 0.0) {
06770
06771
06772 return SHAREVERTEX;
06773 }
06774
06775 return INTERSECT;
06776 }
06777
06778 if (s5 == 0.0) {
06779
06780
06781 return INTERSECT;
06782 }
06783
06784
06785 return INTERSECT;
06786 }
06787
06788 if (s1 != 0.0 || s2 != 0.0) {
06789
06790 if (s1 == 0.0) {
06791
06792 #ifdef SELF_CHECK
06793 assert(s2 != 0.0);
06794 #endif
06795 return tri_vert_cop_inter(A, B, C, P, Q);
06796 } else {
06797
06798 #ifdef SELF_CHECK
06799 assert(s2 == 0.0);
06800 #endif
06801 return tri_vert_cop_inter(A, B, C, Q, P);
06802 }
06803 }
06804
06805
06806
06807 REAL R[3], N[3];
06808 REAL ax, ay, az, bx, by, bz;
06809
06810 ax = A[0] - B[0];
06811 ay = A[1] - B[1];
06812 az = A[2] - B[2];
06813 bx = A[0] - C[0];
06814 by = A[1] - C[1];
06815 bz = A[2] - C[2];
06816 N[0] = ay * bz - by * az;
06817 N[1] = az * bx - bz * ax;
06818 N[2] = ax * by - bx * ay;
06819
06820 #ifdef SELF_CHECK
06821 assert((fabs(N[0]) + fabs(N[1]) + fabs(N[2])) > 0.0);
06822 #endif
06823
06824
06825 R[0] = N[0] + A[0];
06826 R[1] = N[1] + A[1];
06827 R[2] = N[2] + A[2];
06828
06829
06830
06831 if (R[0] == A[0] && R[1] == A[1] && R[2] == A[2]) {
06832 int i, j;
06833 for (i = 0; i < 3; i++) {
06834 #ifdef SELF_CHECK
06835 assert (R[i] == A[i]);
06836 #endif
06837 j = 2;
06838 do {
06839 if (N[i] > 0.0) {
06840 N[i] += (j * macheps);
06841 } else {
06842 N[i] -= (j * macheps);
06843 }
06844 R[i] = N[i] + A[i];
06845 j *= 2;
06846 } while (R[i] == A[i]);
06847 }
06848 }
06849
06850 return tri_edge_cop_inter(A, B, C, P, Q, R);
06851 }
06852
06854
06855
06856
06857
06858
06859
06860
06862
06863 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter(REAL* A, REAL* B,
06864 REAL* C, REAL* P, REAL* Q)
06865 {
06866 REAL s1, s2;
06867
06868
06869 s1 = orient3d(A, B, C, P);
06870 s2 = orient3d(A, B, C, Q);
06871
06872 return tri_edge_inter_tail(A, B, C, P, Q, s1, s2);
06873 }
06874
06876
06877
06878
06879
06880
06881
06882
06884
06885 enum tetgenmesh::interresult tetgenmesh::tri_tri_inter(REAL* A, REAL* B,
06886 REAL* C, REAL* O, REAL* P, REAL* Q)
06887 {
06888 REAL s_o, s_p, s_q;
06889 REAL s_a, s_b, s_c;
06890
06891 s_o = orient3d(A, B, C, O);
06892 s_p = orient3d(A, B, C, P);
06893 s_q = orient3d(A, B, C, Q);
06894 if ((s_o * s_p > 0.0) && (s_o * s_q > 0.0)) {
06895
06896 return DISJOINT;
06897 }
06898
06899 s_a = orient3d(O, P, Q, A);
06900 s_b = orient3d(O, P, Q, B);
06901 s_c = orient3d(O, P, Q, C);
06902 if ((s_a * s_b > 0.0) && (s_a * s_c > 0.0)) {
06903
06904 return DISJOINT;
06905 }
06906
06907 enum interresult abcop, abcpq, abcqo;
06908 int shareedge = 0;
06909
06910 abcop = tri_edge_inter_tail(A, B, C, O, P, s_o, s_p);
06911 if (abcop == INTERSECT) {
06912 return INTERSECT;
06913 } else if (abcop == SHAREEDGE) {
06914 shareedge++;
06915 }
06916 abcpq = tri_edge_inter_tail(A, B, C, P, Q, s_p, s_q);
06917 if (abcpq == INTERSECT) {
06918 return INTERSECT;
06919 } else if (abcpq == SHAREEDGE) {
06920 shareedge++;
06921 }
06922 abcqo = tri_edge_inter_tail(A, B, C, Q, O, s_q, s_o);
06923 if (abcqo == INTERSECT) {
06924 return INTERSECT;
06925 } else if (abcqo == SHAREEDGE) {
06926 shareedge++;
06927 }
06928 if (shareedge == 3) {
06929
06930 return SHAREFACE;
06931 }
06932 #ifdef SELF_CHECK
06933
06934 assert(shareedge == 0 || shareedge == 1);
06935 #endif
06936
06937
06938 enum interresult opqab, opqbc, opqca;
06939
06940 opqab = tri_edge_inter_tail(O, P, Q, A, B, s_a, s_b);
06941 if (opqab == INTERSECT) {
06942 return INTERSECT;
06943 }
06944 opqbc = tri_edge_inter_tail(O, P, Q, B, C, s_b, s_c);
06945 if (opqbc == INTERSECT) {
06946 return INTERSECT;
06947 }
06948 opqca = tri_edge_inter_tail(O, P, Q, C, A, s_c, s_a);
06949 if (opqca == INTERSECT) {
06950 return INTERSECT;
06951 }
06952
06953
06954
06955 if (abcop == SHAREEDGE) {
06956 #ifdef SELF_CHECK
06957 assert(abcpq == SHAREVERTEX && abcqo == SHAREVERTEX);
06958 #endif
06959
06960 return SHAREEDGE;
06961 }
06962 if (abcpq == SHAREEDGE) {
06963 #ifdef SELF_CHECK
06964 assert(abcop == SHAREVERTEX && abcqo == SHAREVERTEX);
06965 #endif
06966
06967 return SHAREEDGE;
06968 }
06969 if (abcqo == SHAREEDGE) {
06970 #ifdef SELF_CHECK
06971 assert(abcop == SHAREVERTEX && abcpq == SHAREVERTEX);
06972 #endif
06973
06974 return SHAREEDGE;
06975 }
06976
06977
06978 if (abcop == SHAREVERTEX) {
06979
06980 if (abcpq == SHAREVERTEX) {
06981
06982 #ifdef SELF_CHECK
06983 assert(abcqo != SHAREVERTEX);
06984 #endif
06985 } else {
06986
06987 #ifdef SELF_CHECK
06988 assert(abcqo == SHAREVERTEX);
06989 #endif
06990 }
06991 return SHAREVERTEX;
06992 }
06993 if (abcpq == SHAREVERTEX) {
06994
06995 #ifdef SELF_CHECK
06996 assert(abcqo == SHAREVERTEX);
06997 #endif
06998 return SHAREVERTEX;
06999 }
07000
07001
07002 return DISJOINT;
07003 }
07004
07006
07007
07008
07009
07010
07011
07012
07013
07014
07015
07017
07018 REAL tetgenmesh::insphere_sos(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
07019 int ia, int ib, int ic, int id, int ie)
07020 {
07021 REAL det;
07022
07023 det = insphere(pa, pb, pc, pd, pe);
07024 if (det != 0.0) {
07025 return det;
07026 }
07027
07028
07029 REAL *p[5], *tmpp;
07030 REAL sign, det_c, det_d;
07031 int idx[5], perm, tmp;
07032 int n, i, j;
07033
07034 p[0] = pa; idx[0] = ia;
07035 p[1] = pb; idx[1] = ib;
07036 p[2] = pc; idx[2] = ic;
07037 p[3] = pd; idx[3] = id;
07038 p[4] = pe; idx[4] = ie;
07039
07040
07041 n = 5;
07042 perm = 0;
07043 for (i = 0; i < n - 1; i++) {
07044 for (j = 0; j < n - 1 - i; j++) {
07045 if (idx[j + 1] < idx[j]) {
07046 tmp = idx[j];
07047 idx[j] = idx[j + 1];
07048 idx[j + 1] = tmp;
07049 tmpp = p[j];
07050 p[j] = p[j + 1];
07051 p[j + 1] = tmpp;
07052 perm++;
07053 }
07054 }
07055 }
07056
07057 sign = (perm % 2 == 0) ? 1.0 : -1.0;
07058 det_c = orient3d(p[1], p[2], p[3], p[4]);
07059 if (det_c != 0.0) {
07060 return sign * det_c;
07061 }
07062 det_d = orient3d(p[0], p[2], p[3], p[4]);
07063 return -sign * det_d;
07064 }
07065
07067
07068
07069
07070
07071
07072
07073
07075
07076 bool tetgenmesh::iscollinear(REAL* A, REAL* B, REAL* C, REAL eps)
07077 {
07078 REAL abx, aby, abz;
07079 REAL acx, acy, acz;
07080 REAL Lv, Lw, dd;
07081 REAL d, q;
07082
07083
07084 q = longest * eps;
07085 q *= q;
07086
07087 abx = A[0] - B[0];
07088 aby = A[1] - B[1];
07089 abz = A[2] - B[2];
07090 acx = A[0] - C[0];
07091 acy = A[1] - C[1];
07092 acz = A[2] - C[2];
07093 Lv = abx * abx + aby * aby + abz * abz;
07094
07095 if (Lv < q) return true;
07096 Lw = acx * acx + acy * acy + acz * acz;
07097
07098 if (Lw < q) return true;
07099 dd = abx * acx + aby * acy + abz * acz;
07100
07101 d = (dd * dd) / (Lv * Lw);
07102 if (d > 1.0) d = 1.0;
07103 q = 1.0 - sqrt(d);
07104
07105 return q <= eps;
07106 }
07107
07109
07110
07111
07112
07113
07114
07115
07116
07118
07119 bool tetgenmesh::
07120 iscoplanar(REAL* k, REAL* l, REAL* m, REAL* n, REAL vol6, REAL eps)
07121 {
07122 REAL L, q;
07123 REAL x, y, z;
07124
07125 if (vol6 == 0.0) return true;
07126
07127 x = k[0] - l[0];
07128 y = k[1] - l[1];
07129 z = k[2] - l[2];
07130 L = sqrt(x * x + y * y + z * z);
07131 x = l[0] - m[0];
07132 y = l[1] - m[1];
07133 z = l[2] - m[2];
07134 L += sqrt(x * x + y * y + z * z);
07135 x = m[0] - k[0];
07136 y = m[1] - k[1];
07137 z = m[2] - k[2];
07138 L += sqrt(x * x + y * y + z * z);
07139 x = k[0] - n[0];
07140 y = k[1] - n[1];
07141 z = k[2] - n[2];
07142 L += sqrt(x * x + y * y + z * z);
07143 x = l[0] - n[0];
07144 y = l[1] - n[1];
07145 z = l[2] - n[2];
07146 L += sqrt(x * x + y * y + z * z);
07147 x = m[0] - n[0];
07148 y = m[1] - n[1];
07149 z = m[2] - n[2];
07150 L += sqrt(x * x + y * y + z * z);
07151 #ifdef SELF_CHECK
07152 assert(L > 0.0);
07153 #endif
07154 L /= 6.0;
07155 q = fabs(vol6) / (L * L * L);
07156
07157 return q <= eps;
07158 }
07159
07161
07162
07163
07164
07165
07166
07167
07168
07170
07171 bool tetgenmesh::
07172 iscospheric(REAL* k, REAL* l, REAL* m, REAL* n, REAL* o, REAL vol24, REAL eps)
07173 {
07174 REAL L, q;
07175
07176
07177 L = distance(k, l);
07178 L += distance(l, m);
07179 L += distance(m, k);
07180 L += distance(k, n);
07181 L += distance(l, n);
07182 L += distance(m, n);
07183 L += distance(k, o);
07184 L += distance(l, o);
07185 L += distance(m, o);
07186 L += distance(n, o);
07187 #ifdef SELF_CHECK
07188 assert(L > 0.0);
07189 #endif
07190 L /= 10.0;
07191 q = fabs(vol24) / (L * L * L * L);
07192
07193 return q < eps;
07194 }
07195
07196
07197
07198
07199
07200
07201
07202
07203
07204
07205 inline REAL tetgenmesh::distance(REAL* p1, REAL* p2)
07206 {
07207 return sqrt((p2[0] - p1[0]) * (p2[0] - p1[0]) +
07208 (p2[1] - p1[1]) * (p2[1] - p1[1]) +
07209 (p2[2] - p1[2]) * (p2[2] - p1[2]));
07210 }
07211
07213
07214
07215
07216
07217
07218
07219
07220
07221
07222
07223
07225
07226 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2)
07227 {
07228 REAL v1[3], v2[3];
07229 REAL len, l_p;
07230
07231 v1[0] = e2[0] - e1[0];
07232 v1[1] = e2[1] - e1[1];
07233 v1[2] = e2[2] - e1[2];
07234 v2[0] = p[0] - e1[0];
07235 v2[1] = p[1] - e1[1];
07236 v2[2] = p[2] - e1[2];
07237
07238 len = sqrt(dot(v1, v1));
07239 #ifdef SELF_CHECK
07240 assert(len != 0.0);
07241 #endif
07242 v1[0] /= len;
07243 v1[1] /= len;
07244 v1[2] /= len;
07245 l_p = dot(v1, v2);
07246
07247 return sqrt(dot(v2, v2) - l_p * l_p);
07248 }
07249
07251
07252
07253
07255
07256 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2, REAL* e3)
07257 {
07258 REAL prj[3];
07259
07260 projpt2face(p, e1, e2, e3, prj);
07261 return distance(p, prj);
07262 }
07263
07265
07266
07267
07268
07269
07270
07271
07272
07273
07274
07276
07277 REAL tetgenmesh::interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n)
07278 {
07279 REAL v1[3], v2[3], np[3];
07280 REAL theta, costheta, lenlen;
07281 REAL ori, len1, len2;
07282
07283
07284 v1[0] = p1[0] - o[0];
07285 v1[1] = p1[1] - o[1];
07286 v1[2] = p1[2] - o[2];
07287 v2[0] = p2[0] - o[0];
07288 v2[1] = p2[1] - o[1];
07289 v2[2] = p2[2] - o[2];
07290 len1 = sqrt(dot(v1, v1));
07291 len2 = sqrt(dot(v2, v2));
07292 lenlen = len1 * len2;
07293 #ifdef SELF_CHECK
07294 assert(lenlen != 0.0);
07295 #endif
07296 costheta = dot(v1, v2) / lenlen;
07297 if (costheta > 1.0) {
07298 costheta = 1.0;
07299 } else if (costheta < -1.0) {
07300 costheta = -1.0;
07301 }
07302 theta = acos(costheta);
07303 if (n != NULL) {
07304
07305 np[0] = o[0] + n[0];
07306 np[1] = o[1] + n[1];
07307 np[2] = o[2] + n[2];
07308
07309 ori = orient3d(p1, o, np, p2);
07310 if (ori > 0.0) {
07311 theta = 2 * PI - theta;
07312 }
07313 }
07314
07315 return theta;
07316 }
07317
07319
07320
07321
07323
07324 void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj)
07325 {
07326 REAL v1[3], v2[3];
07327 REAL len, l_p;
07328
07329 v1[0] = e2[0] - e1[0];
07330 v1[1] = e2[1] - e1[1];
07331 v1[2] = e2[2] - e1[2];
07332 v2[0] = p[0] - e1[0];
07333 v2[1] = p[1] - e1[1];
07334 v2[2] = p[2] - e1[2];
07335
07336 len = sqrt(dot(v1, v1));
07337 #ifdef SELF_CHECK
07338 assert(len != 0.0);
07339 #endif
07340 v1[0] /= len;
07341 v1[1] /= len;
07342 v1[2] /= len;
07343 l_p = dot(v1, v2);
07344
07345 prj[0] = e1[0] + l_p * v1[0];
07346 prj[1] = e1[1] + l_p * v1[1];
07347 prj[2] = e1[2] + l_p * v1[2];
07348 }
07349
07351
07352
07353
07355
07356 void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj)
07357 {
07358 REAL fnormal[3], v1[3];
07359 REAL len, dist;
07360
07361
07362 facenormal(f1, f2, f3, fnormal, &len);
07363 #ifdef SELF_CHECK
07364 assert(len > 0.0);
07365 #endif
07366 fnormal[0] /= len;
07367 fnormal[1] /= len;
07368 fnormal[2] /= len;
07369
07370 v1[0] = p[0] - f1[0];
07371 v1[1] = p[1] - f1[1];
07372 v1[2] = p[2] - f1[2];
07373
07374 dist = dot(fnormal, v1);
07375
07376
07377 prj[0] = p[0] - dist * fnormal[0];
07378 prj[1] = p[1] - dist * fnormal[1];
07379 prj[2] = p[2] - dist * fnormal[2];
07380 }
07381
07383
07384
07385
07386
07387
07388
07389
07390
07392
07393 void tetgenmesh::facenormal(REAL* pa, REAL* pb, REAL* pc, REAL* n, REAL* nlen)
07394 {
07395 REAL v1[3], v2[3];
07396
07397 v1[0] = pb[0] - pa[0];
07398 v1[1] = pb[1] - pa[1];
07399 v1[2] = pb[2] - pa[2];
07400 v2[0] = pc[0] - pa[0];
07401 v2[1] = pc[1] - pa[1];
07402 v2[2] = pc[2] - pa[2];
07403
07404 cross(v1, v2, n);
07405 if (nlen != (REAL *) NULL) {
07406 *nlen = sqrt(dot(n, n));
07407 }
07408 }
07409
07411
07412
07413
07414
07415
07416
07417
07418
07419
07420
07421
07422
07423
07425
07426 void tetgenmesh::edgeorthonormal(REAL* e1, REAL* e2, REAL* op, REAL* n)
07427 {
07428 REAL v1[3], v2[3], fn[3];
07429 REAL len;
07430
07431
07432 v1[0] = e2[0] - e1[0];
07433 v1[1] = e2[1] - e1[1];
07434 v1[2] = e2[2] - e1[2];
07435
07436 v2[0] = op[0] - e1[0];
07437 v2[1] = op[1] - e1[1];
07438 v2[2] = op[2] - e1[2];
07439
07440 cross(v1, v2, fn);
07441
07442 cross(fn, v1, n);
07443
07444 len = sqrt(dot(n, n));
07445 n[0] /= len;
07446 n[1] /= len;
07447 n[2] /= len;
07448 }
07449
07451
07452
07453
07454
07455
07456
07457
07458
07460
07461 REAL tetgenmesh::facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2)
07462 {
07463 REAL n1[3], n2[3];
07464 REAL n1len, n2len;
07465 REAL costheta, ori;
07466 REAL theta;
07467
07468 facenormal(pa, pb, pc1, n1, &n1len);
07469 facenormal(pa, pb, pc2, n2, &n2len);
07470 costheta = dot(n1, n2) / (n1len * n2len);
07471
07472 if (costheta > 1.0) {
07473 costheta = 1.0;
07474 } else if (costheta < -1.0) {
07475 costheta = -1.0;
07476 }
07477 theta = acos(costheta);
07478 ori = orient3d(pa, pb, pc1, pc2);
07479 if (ori > 0.0) {
07480 theta = 2 * PI - theta;
07481 }
07482
07483 return theta;
07484 }
07485
07487
07488
07489
07490
07491
07492
07493
07494
07496
07497 void tetgenmesh::tetalldihedral(point pa, point pb, point pc, point pd,
07498 REAL* cosdd, REAL* cosmaxd, REAL* cosmind)
07499 {
07500 REAL N[4][3], cosd, len;
07501 int f1, f2, i, j;
07502
07503 f1=0;
07504 f2=0;
07505
07506
07507 tetallnormal(pa, pb, pc, pd, N, NULL);
07508
07509 for (i = 0; i < 4; i++) {
07510 len = sqrt(dot(N[i], N[i]));
07511 if (len != 0.0) {
07512 for (j = 0; j < 3; j++) N[i][j] /= len;
07513 }
07514 }
07515
07516 for (i = 0; i < 6; i++) {
07517 switch (i) {
07518 case 0: f1 = 2; f2 = 3; break;
07519 case 1: f1 = 0; f2 = 3; break;
07520 case 2: f1 = 1; f2 = 3; break;
07521 case 3: f1 = 1; f2 = 2; break;
07522 case 4: f1 = 2; f2 = 0; break;
07523 case 5: f1 = 0; f2 = 1; break;
07524 }
07525 cosd = -dot(N[f1], N[f2]);
07526 if (cosdd) cosdd[i] = cosd;
07527 if (i == 0) {
07528 if (cosmaxd) *cosmaxd = cosd;
07529 if (cosmind) *cosmind = cosd;
07530 } else {
07531 if (cosmaxd) *cosmaxd = cosd < *cosmaxd ? cosd : *cosmaxd;
07532 if (cosmind) *cosmind = cosd > *cosmind ? cosd : *cosmind;
07533 }
07534 }
07535 }
07536
07538
07539
07540
07541
07542
07543
07545
07546 void tetgenmesh::tetallnormal(point pa, point pb, point pc, point pd,
07547 REAL N[4][3], REAL* volume)
07548 {
07549 REAL A[4][4], rhs[4], D;
07550 int indx[4];
07551 int i, j;
07552
07553
07554 for (i = 0; i < 3; i++) A[0][i] = pa[i] - pd[i];
07555 for (i = 0; i < 3; i++) A[1][i] = pb[i] - pd[i];
07556 for (i = 0; i < 3; i++) A[2][i] = pc[i] - pd[i];
07557
07558 lu_decmp(A, 3, indx, &D, 0);
07559 if (volume != NULL) {
07560
07561 *volume = fabs((A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2])) / 6.0;
07562 }
07563 for (j = 0; j < 3; j++) {
07564 for (i = 0; i < 3; i++) rhs[i] = 0.0;
07565 rhs[j] = 1.0;
07566 lu_solve(A, 3, indx, rhs, 0);
07567 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07568 }
07569
07570 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07571 }
07572
07574
07575
07576
07577
07578
07579
07581
07582 REAL tetgenmesh::tetaspectratio(point pa, point pb, point pc, point pd)
07583 {
07584 REAL vda[3], vdb[3], vdc[3];
07585 REAL N[4][3], A[4][4], rhs[4], D;
07586 REAL H[4], volume, radius2, minheightinv;
07587 int indx[4];
07588 int i, j;
07589
07590
07591 for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
07592 for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
07593 for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
07594
07595 lu_decmp(A, 3, indx, &D, 0);
07596
07597 volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
07598
07599 if (volume == 0.0) return 1.0e+200;
07600
07601
07602 rhs[0] = 0.5 * dot(vda, vda);
07603 rhs[1] = 0.5 * dot(vdb, vdb);
07604 rhs[2] = 0.5 * dot(vdc, vdc);
07605 lu_solve(A, 3, indx, rhs, 0);
07606
07607
07608
07609 radius2 = dot(rhs, rhs);
07610
07611
07612 for (j = 0; j < 3; j++) {
07613 for (i = 0; i < 3; i++) rhs[i] = 0.0;
07614 rhs[j] = 1.0;
07615 lu_solve(A, 3, indx, rhs, 0);
07616 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07617 }
07618
07619 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07620
07621 for (i = 0; i < 4; i++) {
07622
07623 H[i] = sqrt(dot(N[i], N[i]));
07624
07625
07626
07627 }
07628
07629
07630
07631 minheightinv = H[0];
07632 for (i = 1; i < 3; i++) {
07633 if (H[i] > minheightinv) minheightinv = H[i];
07634 }
07635
07636 return sqrt(radius2) * minheightinv;
07637 }
07638
07640
07641
07642
07643
07644
07645
07646
07647
07648
07649
07650
07651
07653
07654 bool tetgenmesh::
07655 circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* cent, REAL* radius)
07656 {
07657 REAL A[4][4], rhs[4], D;
07658 int indx[4];
07659
07660
07661 A[0][0] = pb[0] - pa[0];
07662 A[0][1] = pb[1] - pa[1];
07663 A[0][2] = pb[2] - pa[2];
07664 A[1][0] = pc[0] - pa[0];
07665 A[1][1] = pc[1] - pa[1];
07666 A[1][2] = pc[2] - pa[2];
07667 if (pd != NULL) {
07668 A[2][0] = pd[0] - pa[0];
07669 A[2][1] = pd[1] - pa[1];
07670 A[2][2] = pd[2] - pa[2];
07671 } else {
07672 cross(A[0], A[1], A[2]);
07673 }
07674
07675
07676 rhs[0] = 0.5 * dot(A[0], A[0]);
07677 rhs[1] = 0.5 * dot(A[1], A[1]);
07678 if (pd != NULL) {
07679 rhs[2] = 0.5 * dot(A[2], A[2]);
07680 } else {
07681 rhs[2] = 0.0;
07682 }
07683
07684
07685
07686 if (!lu_decmp(A, 3, indx, &D, 0)) {
07687 if (radius != (REAL *) NULL) *radius = 0.0;
07688 return false;
07689 }
07690 lu_solve(A, 3, indx, rhs, 0);
07691 if (cent != (REAL *) NULL) {
07692 cent[0] = pa[0] + rhs[0];
07693 cent[1] = pa[1] + rhs[1];
07694 cent[2] = pa[2] + rhs[2];
07695 }
07696 if (radius != (REAL *) NULL) {
07697 *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
07698 }
07699 return true;
07700 }
07701
07703
07704
07705
07706
07707
07708
07709
07710
07711
07712
07713
07714
07715
07716
07717
07718
07719
07720
07721
07722
07724
07725 void tetgenmesh::inscribedsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
07726 REAL* cent, REAL* radius)
07727 {
07728 REAL N[4][3], H[4];
07729 REAL rd;
07730 int i;
07731
07732
07733 tetallnormal(pa, pb, pc, pd, N, NULL);
07734 for (i = 0; i < 4; i++) {
07735
07736 H[i] = sqrt(dot(N[i], N[i]));
07737 }
07738
07739 rd = 1.0 / (H[0] + H[1] + H[2] + H[3]);
07740 if (radius != (REAL*) NULL) *radius = rd;
07741 if (cent != (REAL*) NULL) {
07742
07743 cent[0] = rd * (H[0] * pa[0] + H[1] * pb[0] + H[2] * pc[0] + H[3] * pd[0]);
07744 cent[1] = rd * (H[0] * pa[1] + H[1] * pb[1] + H[2] * pc[1] + H[3] * pd[1]);
07745 cent[2] = rd * (H[0] * pa[2] + H[1] * pb[2] + H[2] * pc[2] + H[3] * pd[2]);
07746 }
07747 }
07748
07750
07751
07752
07753
07754
07755
07756
07757
07758
07759
07760
07761
07762
07763
07764
07765
07766
07767
07768
07769
07771
07772 void tetgenmesh::rotatepoint(REAL* p, REAL rotangle, REAL* p1, REAL* p2)
07773 {
07774 REAL T[4][4], pp0[4], p0t[4], p2t[4];
07775 REAL roty, rotx, alphaR, projlen;
07776 REAL dx, dy, dz;
07777
07778 initm44(1, 0, 0, -p1[0],
07779 0, 1, 0, -p1[1],
07780 0, 0, 1, -p1[2],
07781 0, 0, 0, 1, T);
07782 pp0[0] = p[0]; pp0[1] = p[1]; pp0[2] = p[2]; pp0[3] = 1.0;
07783 m4xv4(p0t, T, pp0);
07784 pp0[0] = p2[0]; pp0[1] = p2[1]; pp0[2] = p2[2]; pp0[3] = 1.0;
07785 m4xv4(p2t, T, pp0);
07786
07787
07788 dx = p2t[0];
07789 dz = p2t[2];
07790 projlen = sqrt(dx * dx + dz * dz);
07791 if (projlen <= (b->epsilon * 1e-2) * longest) {
07792 roty = 0;
07793 } else {
07794 roty = acos(dz / projlen);
07795 if (dx < 0) {
07796 roty = -roty;
07797 }
07798 }
07799
07800 initm44(cos(-roty), 0, sin(-roty), 0,
07801 0, 1, 0, 0,
07802 -sin(-roty), 0, cos(-roty), 0,
07803 0, 0, 0, 1, T);
07804 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07805 m4xv4(p0t, T, pp0);
07806 pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
07807 m4xv4(p2t, T, pp0);
07808
07809
07810 dy = p2t[1];
07811 dz = p2t[2];
07812 projlen = sqrt(dy * dy + dz * dz);
07813 if (projlen <= (b->epsilon * 1e-2) * longest) {
07814 rotx = 0;
07815 } else {
07816 rotx = acos(dz / projlen);
07817 if (dy < 0) {
07818 rotx = -rotx;
07819 }
07820 }
07821
07822 initm44(1, 0, 0, 0,
07823 0, cos(rotx), -sin(rotx), 0,
07824 0, sin(rotx), cos(rotx), 0,
07825 0, 0, 0, 1, T);
07826 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07827 m4xv4(p0t, T, pp0);
07828
07829
07830
07831 alphaR = rotangle;
07832 initm44(cos(alphaR), -sin(alphaR), 0, 0,
07833 sin(alphaR), cos(alphaR), 0, 0,
07834 0, 0, 1, 0,
07835 0, 0, 0, 1, T);
07836 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07837 m4xv4(p0t, T, pp0);
07838
07839 initm44(1, 0, 0, 0,
07840 0, cos(-rotx), -sin(-rotx), 0,
07841 0, sin(-rotx), cos(-rotx), 0,
07842 0, 0, 0, 1, T);
07843 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07844 m4xv4(p0t, T, pp0);
07845
07846 initm44(cos(roty), 0, sin(roty), 0,
07847 0, 1, 0, 0,
07848 -sin(roty), 0, cos(roty), 0,
07849 0, 0, 0, 1, T);
07850 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07851 m4xv4(p0t, T, pp0);
07852
07853 initm44(1, 0, 0, p1[0],
07854 0, 1, 0, p1[1],
07855 0, 0, 1, p1[2],
07856 0, 0, 0, 1, T);
07857 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07858 m4xv4(p0t, T, pp0);
07859
07860 p[0] = p0t[0];
07861 p[1] = p0t[1];
07862 p[2] = p0t[2];
07863 }
07864
07866
07867
07868
07869
07870
07871
07872
07873
07874
07875
07877
07878 void tetgenmesh::spherelineint(REAL* p1, REAL* p2, REAL* C, REAL R, REAL p[7])
07879 {
07880 REAL x1, y1, z1;
07881 REAL x2, y2, z2;
07882 REAL x3, y3, z3, r;
07883 REAL a, b, c, mu, i ;
07884
07885 x1 = p1[0]; y1 = p1[1]; z1 = p1[2];
07886 x2 = p2[0]; y2 = p2[1]; z2 = p2[2];
07887 x3 = C[0]; y3 = C[1]; z3 = C[2];
07888 r = R;
07889
07890 a = (x2 - x1) * (x2 - x1)
07891 + (y2 - y1) * (y2 - y1)
07892 + (z2 - z1) * (z2 - z1);
07893 b = 2 * ( (x2 - x1) * (x1 - x3)
07894 + (y2 - y1) * (y1 - y3)
07895 + (z2 - z1) * (z1 - z3) ) ;
07896 c = (x3 * x3) + (y3 * y3) + (z3 * z3)
07897 + (x1 * x1) + (y1 * y1) + (z1 * z1)
07898 - 2 * (x3 * x1 + y3 * y1 + z3 * z1) - (r * r) ;
07899 i = b * b - 4 * a * c ;
07900
07901 if (i < 0.0) {
07902
07903 p[0] = 0.0;
07904 } else if (i == 0.0) {
07905
07906 p[0] = 1.0;
07907 mu = -b / (2 * a) ;
07908 p[1] = x1 + mu * (x2 - x1);
07909 p[2] = y1 + mu * (y2 - y1);
07910 p[3] = z1 + mu * (z2 - z1);
07911 } else {
07912
07913 p[0] = 2.0;
07914
07915 mu = (-b + sqrt((b * b) - 4 * a * c)) / (2 * a);
07916 p[1] = x1 + mu * (x2 - x1);
07917 p[2] = y1 + mu * (y2 - y1);
07918 p[3] = z1 + mu * (z2 - z1);
07919
07920 mu = (-b - sqrt((b * b) - 4 * a * c)) / (2 * a);
07921 p[4] = x1 + mu * (x2 - x1);
07922 p[5] = y1 + mu * (y2 - y1);
07923 p[6] = z1 + mu * (z2 - z1);
07924 }
07925 }
07926
07928
07929
07930
07931
07932
07933
07934
07935
07936
07937
07938
07939
07940
07941
07942
07943
07944
07946
07947 void tetgenmesh::linelineint(REAL *p1,REAL *p2, REAL *p3, REAL *p4, REAL p[7])
07948 {
07949 REAL p13[3], p43[3], p21[3];
07950 REAL d1343, d4321, d1321, d4343, d2121;
07951 REAL numer, denom;
07952 REAL mua, mub;
07953
07954 p13[0] = p1[0] - p3[0];
07955 p13[1] = p1[1] - p3[1];
07956 p13[2] = p1[2] - p3[2];
07957 p43[0] = p4[0] - p3[0];
07958 p43[1] = p4[1] - p3[1];
07959 p43[2] = p4[2] - p3[2];
07960 if (p43[0] == 0.0 && p43[1] == 0.0 && p43[2] == 0.0) {
07961 p[0] = 0.0;
07962 return;
07963 }
07964
07965 p21[0] = p2[0] - p1[0];
07966 p21[1] = p2[1] - p1[1];
07967 p21[2] = p2[2] - p1[2];
07968 if (p21[0] == 0.0 && p21[1] == 0.0 && p21[2] == 0.0) {
07969 p[0] = 0.0;
07970 return;
07971 }
07972
07973 d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
07974 d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
07975 d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
07976 d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
07977 d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
07978
07979 denom = d2121 * d4343 - d4321 * d4321;
07980 if (denom == 0.0) {
07981 p[0] = 0.0;
07982 return;
07983 }
07984 numer = d1343 * d4321 - d1321 * d4343;
07985 mua = numer / denom;
07986 mub = (d1343 + d4321 * mua) / d4343;
07987
07988 p[0] = 1.0;
07989 p[1] = p1[0] + mua * p21[0];
07990 p[2] = p1[1] + mua * p21[1];
07991 p[3] = p1[2] + mua * p21[2];
07992 p[4] = p3[0] + mub * p43[0];
07993 p[5] = p3[1] + mub * p43[1];
07994 p[6] = p3[2] + mub * p43[2];
07995 }
07996
07998
07999
08000
08001
08002
08003
08004
08005
08006
08007
08008
08009
08010
08011
08012
08013
08014
08015
08016
08017
08019
08020 void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
08021 REAL* ip, REAL* u)
08022 {
08023 REAL n[3], det, det1;
08024
08025
08026 facenormal(pa, pb, pc, n, NULL);
08027
08028 det = n[0] * (e2[0] - e1[0]) + n[1] * (e2[1] - e1[1])
08029 + n[2] * (e2[2] - e1[2]);
08030 if (det != 0.0) {
08031
08032 det1 = n[0] * (pa[0] - e1[0]) + n[1] * (pa[1] - e1[1])
08033 + n[2] * (pa[2] - e1[2]);
08034 *u = det1 / det;
08035 ip[0] = e1[0] + *u * (e2[0] - e1[0]);
08036 ip[1] = e1[1] + *u * (e2[1] - e1[1]);
08037 ip[2] = e1[2] + *u * (e2[2] - e1[2]);
08038 } else {
08039 *u = 0.0;
08040 }
08041 }
08042
08043
08044
08045
08046
08047
08048
08049
08050
08052
08053
08054
08055
08056
08057
08058
08059
08060
08061
08062
08063
08064
08066
08067 void tetgenmesh::dummyinit(int tetwords, int shwords)
08068 {
08069 unsigned long alignptr;
08070
08071
08072 dummytetbase = (tetrahedron *) new char[tetwords * sizeof(tetrahedron)
08073 + tetrahedrons->alignbytes];
08074
08075 alignptr = (unsigned long) dummytetbase;
08076 dummytet = (tetrahedron *)
08077 (alignptr + (unsigned long) tetrahedrons->alignbytes
08078 - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08079
08080
08081
08082
08083 dummytet[0] = (tetrahedron) dummytet;
08084 dummytet[1] = (tetrahedron) dummytet;
08085 dummytet[2] = (tetrahedron) dummytet;
08086 dummytet[3] = (tetrahedron) dummytet;
08087
08088 dummytet[4] = (tetrahedron) NULL;
08089 dummytet[5] = (tetrahedron) NULL;
08090 dummytet[6] = (tetrahedron) NULL;
08091 dummytet[7] = (tetrahedron) NULL;
08092
08093 if (b->useshelles) {
08094
08095
08096
08097 dummyshbase = (shellface *) new char[shwords * sizeof(shellface)
08098 + subfaces->alignbytes];
08099
08100 alignptr = (unsigned long) dummyshbase;
08101 dummysh = (shellface *)
08102 (alignptr + (unsigned long) subfaces->alignbytes
08103 - (alignptr % (unsigned long) subfaces->alignbytes));
08104
08105
08106
08107
08108 dummysh[0] = (shellface) dummysh;
08109 dummysh[1] = (shellface) dummysh;
08110 dummysh[2] = (shellface) dummysh;
08111
08112 dummysh[3] = (shellface) NULL;
08113 dummysh[4] = (shellface) NULL;
08114 dummysh[5] = (shellface) NULL;
08115
08116 dummysh[6] = (shellface) dummytet;
08117 dummysh[7] = (shellface) dummytet;
08118
08119 dummysh[8] = (shellface) dummysh;
08120 dummysh[9] = (shellface) dummysh;
08121 dummysh[10] = (shellface) dummysh;
08122
08123 dummysh[11] = (shellface) NULL;
08124
08125
08126 dummytet[8 ] = (tetrahedron) dummysh;
08127 dummytet[9 ] = (tetrahedron) dummysh;
08128 dummytet[10] = (tetrahedron) dummysh;
08129 dummytet[11] = (tetrahedron) dummysh;
08130 }
08131 }
08132
08134
08135
08136
08137
08138
08139
08140
08141
08142
08143
08144
08145
08146
08147
08148
08150
08151 void tetgenmesh::initializepools()
08152 {
08153 enum wordtype wtype;
08154 int pointsize, elesize, shsize;
08155
08156
08157 if ((b->plc || b->refine) && (in->pbcgrouplist != NULL)) {
08158 checkpbcs = 1;
08159 }
08160
08161 if (in->segmentconstraintlist || in->facetconstraintlist) {
08162 varconstraint = 1;
08163 }
08164
08165
08166
08167 pointmtrindex = 3 + in->numberofpointattributes;
08168
08169 if (b->metric) {
08170
08171 if (bgm != (tetgenmesh *) NULL) {
08172
08173 sizeoftensor = (bgm->in != (tetgenio *) NULL) ?
08174 bgm->in->numberofpointmtrs : in->numberofpointmtrs;
08175 } else {
08176
08177 sizeoftensor = in->numberofpointmtrs;
08178 }
08179
08180 sizeoftensor = (sizeoftensor > 0) ? sizeoftensor : 1;
08181 } else {
08182
08183 sizeoftensor = b->quality ? 1 : 0;
08184 }
08185
08186
08187
08188 point2simindex = ((pointmtrindex + sizeoftensor) * sizeof(REAL)
08189 + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08190 if (b->plc || b->refine) {
08191
08192
08193
08194
08195 if (b->metric) {
08196
08197 pointsize = (point2simindex + 4) * sizeof(tetrahedron);
08198 } else {
08199 pointsize = (point2simindex + 3) * sizeof(tetrahedron);
08200 }
08201
08202 point2pbcptindex = (pointsize + sizeof(tetrahedron) - 1)
08203 / sizeof(tetrahedron);
08204 if (checkpbcs) {
08205
08206
08207 pointsize = (point2pbcptindex + 1) * sizeof(tetrahedron);
08208 }
08209 } else {
08210 pointsize = point2simindex * sizeof(tetrahedron);
08211 }
08212
08213
08214 pointmarkindex = (pointsize + sizeof(int) - 1) / sizeof(int);
08215
08216
08217
08218 pointsize = (pointmarkindex + 2) * sizeof(int);
08219
08220 wtype = (sizeof(REAL) >= sizeof(tetrahedron)) ? FLOATINGPOINT : POINTER;
08221
08222 points = new memorypool(pointsize, VERPERBLOCK, wtype, 0);
08223
08224
08225
08226
08227 elesize = (8 + b->useshelles * 6) * sizeof(tetrahedron);
08228
08229 if (b->voroout && (b->useshelles == 0)) {
08230 elesize = (8 + 4) * sizeof(tetrahedron);
08231 }
08232
08233
08234 elemattribindex = (elesize + sizeof(REAL) - 1) / sizeof(REAL);
08235
08236
08237
08238 volumeboundindex = elemattribindex + in->numberoftetrahedronattributes
08239 + (b->regionattrib > 0);
08240
08241
08242 if (b->varvolume) {
08243 elesize = (volumeboundindex + 1) * sizeof(REAL);
08244 } else if (in->numberoftetrahedronattributes + b->regionattrib > 0) {
08245 elesize = volumeboundindex * sizeof(REAL);
08246 }
08247
08248
08249 elemmarkerindex = (elesize + sizeof(int) - 1) / sizeof(int);
08250 if (b->neighout || b->voroout) {
08251 elesize = (elemmarkerindex + 1) * sizeof(int);
08252 }
08253
08254
08255 highorderindex = (elesize + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08256 if (b->order == 2) {
08257 elesize = (highorderindex + 1) * sizeof(tetrahedron);
08258 }
08259
08260 tetrahedrons = new memorypool(elesize, ELEPERBLOCK, POINTER, 8);
08261
08262 if (b->useshelles) {
08263
08264
08265
08266 shsize = 12 * sizeof(shellface);
08267
08268
08269 areaboundindex = (shsize + sizeof(REAL) - 1) / sizeof(REAL);
08270
08271
08272 if (b->quality && varconstraint) {
08273 shsize = (areaboundindex + 1) * sizeof(REAL);
08274 } else {
08275 shsize = areaboundindex * sizeof(REAL);
08276 }
08277
08278
08279 shmarkindex = (shsize + sizeof(int) - 1) / sizeof(int);
08280
08281
08282 shsize = (shmarkindex + 2 + checkpbcs) * sizeof(int);
08283
08284
08285
08286 subfaces = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08287
08288
08289 subsegs = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08290
08291 dummyinit(tetrahedrons->itemwords, subfaces->itemwords);
08292 } else {
08293
08294 dummyinit(tetrahedrons->itemwords, 0);
08295 }
08296 }
08297
08299
08300
08301
08303
08304 void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
08305 {
08306
08307
08308 dyingtetrahedron[4] = (tetrahedron) NULL;
08309 dyingtetrahedron[5] = (tetrahedron) NULL;
08310 dyingtetrahedron[6] = (tetrahedron) NULL;
08311 dyingtetrahedron[7] = (tetrahedron) NULL;
08312 tetrahedrons->dealloc((void *) dyingtetrahedron);
08313 }
08314
08316
08317
08318
08320
08321 tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse()
08322 {
08323 tetrahedron *newtetrahedron;
08324
08325 do {
08326 newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
08327 if (newtetrahedron == (tetrahedron *) NULL) {
08328 return (tetrahedron *) NULL;
08329 }
08330 } while (newtetrahedron[7] == (tetrahedron) NULL);
08331 return newtetrahedron;
08332 }
08333
08335
08336
08337
08338
08340
08341 void tetgenmesh::shellfacedealloc(memorypool *pool, shellface *dyingsh)
08342 {
08343
08344
08345 dyingsh[3] = (shellface) NULL;
08346 dyingsh[4] = (shellface) NULL;
08347 dyingsh[5] = (shellface) NULL;
08348 pool->dealloc((void *) dyingsh);
08349 }
08350
08352
08353
08354
08355
08357
08358 tetgenmesh::shellface* tetgenmesh::shellfacetraverse(memorypool *pool)
08359 {
08360 shellface *newshellface;
08361
08362 do {
08363 newshellface = (shellface *) pool->traverse();
08364 if (newshellface == (shellface *) NULL) {
08365 return (shellface *) NULL;
08366 }
08367 } while (newshellface[3] == (shellface) NULL);
08368 return newshellface;
08369 }
08370
08372
08373
08374
08376
08377 void tetgenmesh::badfacedealloc(memorypool *pool, badface *dying)
08378 {
08379
08380
08381 dying->forg = (point) NULL;
08382 pool->dealloc((void *) dying);
08383 }
08384
08386
08387
08388
08390
08391 tetgenmesh::badface* tetgenmesh::badfacetraverse(memorypool *pool)
08392 {
08393 badface *newsh;
08394
08395 do {
08396 newsh = (badface *) pool->traverse();
08397 if (newsh == (badface *) NULL) {
08398 return (badface *) NULL;
08399 }
08400 } while (newsh->forg == (point) NULL);
08401 return newsh;
08402 }
08403
08405
08406
08407
08409
08410 void tetgenmesh::pointdealloc(point dyingpoint)
08411 {
08412
08413
08414 setpointtype(dyingpoint, DEADVERTEX);
08415 points->dealloc((void *) dyingpoint);
08416 }
08417
08419
08420
08421
08423
08424 tetgenmesh::point tetgenmesh::pointtraverse()
08425 {
08426 point newpoint;
08427
08428 do {
08429 newpoint = (point) points->traverse();
08430 if (newpoint == (point) NULL) {
08431 return (point) NULL;
08432 }
08433 } while (pointtype(newpoint) == DEADVERTEX);
08434 return newpoint;
08435 }
08436
08438
08439
08440
08442
08443 void tetgenmesh::maketetrahedron(triface *newtet)
08444 {
08445 newtet->tet = (tetrahedron *) tetrahedrons->alloc();
08446
08447 newtet->tet[0] = (tetrahedron) dummytet;
08448 newtet->tet[1] = (tetrahedron) dummytet;
08449 newtet->tet[2] = (tetrahedron) dummytet;
08450 newtet->tet[3] = (tetrahedron) dummytet;
08451
08452 newtet->tet[4] = (tetrahedron) NULL;
08453 newtet->tet[5] = (tetrahedron) NULL;
08454 newtet->tet[6] = (tetrahedron) NULL;
08455 newtet->tet[7] = (tetrahedron) NULL;
08456
08457 if (b->useshelles) {
08458 newtet->tet[8 ] = (tetrahedron) dummysh;
08459 newtet->tet[9 ] = (tetrahedron) dummysh;
08460 newtet->tet[10] = (tetrahedron) dummysh;
08461 newtet->tet[11] = (tetrahedron) dummysh;
08462 newtet->tet[12] = (tetrahedron) dummysh;
08463 newtet->tet[13] = (tetrahedron) dummysh;
08464 }
08465 for (int i = 0; i < in->numberoftetrahedronattributes; i++) {
08466 setelemattribute(newtet->tet, i, 0.0);
08467 }
08468 if (b->varvolume) {
08469 setvolumebound(newtet->tet, -1.0);
08470 }
08471
08472 newtet->loc = 0;
08473 newtet->ver = 0;
08474 }
08475
08477
08478
08479
08480
08482
08483 void tetgenmesh::makeshellface(memorypool *pool, face *newface)
08484 {
08485 newface->sh = (shellface *) pool->alloc();
08486
08487 newface->sh[0] = (shellface) dummysh;
08488 newface->sh[1] = (shellface) dummysh;
08489 newface->sh[2] = (shellface) dummysh;
08490
08491 newface->sh[3] = (shellface) NULL;
08492 newface->sh[4] = (shellface) NULL;
08493 newface->sh[5] = (shellface) NULL;
08494
08495 newface->sh[6] = (shellface) dummytet;
08496 newface->sh[7] = (shellface) dummytet;
08497
08498
08499 newface->sh [8] = (shellface) dummysh;
08500 newface->sh [9] = (shellface) dummysh;
08501 newface->sh[10] = (shellface) dummysh;
08502
08503 newface->sh[11] = (shellface) NULL;
08504 if (b->quality && varconstraint) {
08505
08506 setareabound(*newface, 0.0);
08507 }
08508
08509 setshellmark(*newface, 0);
08510
08511 setshelltype(*newface, NSHARP);
08512 if (checkpbcs) {
08513
08514 setshellpbcgroup(*newface, -1);
08515 }
08516
08517 newface->shver = 0;
08518 }
08519
08521
08522
08523
08525
08526 void tetgenmesh::makepoint(point* pnewpoint)
08527 {
08528 int ptmark, i;
08529
08530 *pnewpoint = (point) points->alloc();
08531
08532 (*pnewpoint)[0] = 0.0;
08533 (*pnewpoint)[1] = 0.0;
08534 (*pnewpoint)[2] = 0.0;
08535
08536 for (i = 0; i < in->numberofpointattributes; i++) {
08537 (*pnewpoint)[3 + i] = 0.0;
08538 }
08539
08540 for (i = 0; i < sizeoftensor; i++) {
08541 (*pnewpoint)[pointmtrindex + i] = 0.0;
08542 }
08543 if (b->plc || b->refine) {
08544
08545 setpoint2tet(*pnewpoint, NULL);
08546 setpoint2sh(*pnewpoint, NULL);
08547 setpoint2ppt(*pnewpoint, NULL);
08548 if (b->metric) {
08549 setpoint2bgmtet(*pnewpoint, NULL);
08550 }
08551 if (checkpbcs) {
08552
08553 setpoint2pbcpt(*pnewpoint, NULL);
08554 }
08555 }
08556
08557 ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
08558 setpointmark(*pnewpoint, ptmark);
08559
08560 setpointtype(*pnewpoint, UNUSEDVERTEX);
08561 }
08562
08563
08564
08565
08566
08567
08568
08569
08570
08572
08573
08574
08576
08577 unsigned long tetgenmesh::randomnation(unsigned int choices)
08578 {
08579 unsigned long newrandom;
08580
08581 if (choices >= 714025l) {
08582 newrandom = (randomseed * 1366l + 150889l) % 714025l;
08583 randomseed = (newrandom * 1366l + 150889l) % 714025l;
08584 newrandom = newrandom * (choices / 714025l) + randomseed;
08585 if (newrandom >= choices) {
08586 return newrandom - choices;
08587 } else {
08588 return newrandom;
08589 }
08590 } else {
08591 randomseed = (randomseed * 1366l + 150889l) % 714025l;
08592 return randomseed % choices;
08593 }
08594
08595
08596
08597 }
08598
08600
08601
08602
08604
08605 REAL tetgenmesh::distance2(tetrahedron* tetptr, point p)
08606 {
08607 point p1, p2, p3, p4;
08608 REAL dx, dy, dz;
08609
08610 p1 = (point) tetptr[4];
08611 p2 = (point) tetptr[5];
08612 p3 = (point) tetptr[6];
08613 p4 = (point) tetptr[7];
08614
08615 dx = p[0] - 0.25 * (p1[0] + p2[0] + p3[0] + p4[0]);
08616 dy = p[1] - 0.25 * (p1[1] + p2[1] + p3[1] + p4[1]);
08617 dz = p[2] - 0.25 * (p1[2] + p2[2] + p3[2] + p4[2]);
08618
08619 return dx * dx + dy * dy + dz * dz;
08620 }
08621
08623
08624
08625
08626
08627
08628
08629
08630
08631
08632
08633
08634
08635
08636
08637
08638
08639
08640
08641
08642
08643
08644
08645
08646
08647
08648
08649
08651
08652 enum tetgenmesh::locateresult tetgenmesh::preciselocate(point searchpt,
08653 triface* searchtet, long maxtetnumber)
08654 {
08655 triface backtracetet;
08656 triface walkthroface;
08657 point forg, fdest, fapex, toppo;
08658 REAL ori1, ori2, ori3, ori4;
08659 long tetnumber;
08660 int side;
08661
08662 if (isdead(searchtet)) searchtet->tet = dummytet;
08663 if (searchtet->tet == dummytet) {
08664 searchtet->loc = 0;
08665 symself(*searchtet);
08666 }
08667
08668 #ifdef SELF_CHECK
08669
08670 #endif
08671 if (isdead(searchtet)) {
08672 printf("Warning: Point location failed.\n");
08673 return OUTSIDE;
08674 }
08675
08676 searchtet->ver = 0;
08677
08678
08679 for (searchtet->loc = 0; searchtet->loc < 4; searchtet->loc++) {
08680 forg = org(*searchtet);
08681 fdest = dest(*searchtet);
08682 fapex = apex(*searchtet);
08683 ori1 = orient3d(forg, fdest, fapex, searchpt);
08684 if (ori1 < 0.0) break;
08685 }
08686 #ifdef SELF_CHECK
08687 assert(searchtet->loc < 4);
08688 #endif
08689
08690
08691 tetnumber = 0l;
08692 while ((maxtetnumber > 0l) && (tetnumber <= maxtetnumber)) {
08693
08694 if (searchtet->tet == dummytet) {
08695 *searchtet = backtracetet;
08696 return OUTSIDE;
08697 }
08698
08699 walkthroface.tet = (tetrahedron *) NULL;
08700
08701 searchtet->ver = 0;
08702
08703 toppo = oppo(*searchtet);
08704
08705
08706 for (side = 0; side < 3; side++) {
08707 forg = org(*searchtet);
08708 fdest = dest(*searchtet);
08709 ori2 = orient3d(forg, fdest, toppo, searchpt);
08710 if (ori2 == 0.0) {
08711
08712
08713 fapex = apex(*searchtet);
08714 ori3 = orient3d(fdest, fapex, toppo, searchpt);
08715 if (ori3 < 0.0) {
08716
08717 enextself(*searchtet);
08718 fnext(*searchtet, walkthroface);
08719 break;
08720 }
08721 ori4 = orient3d(fapex, forg, toppo, searchpt);
08722 if (ori4 < 0.0) {
08723
08724 enext2self(*searchtet);
08725 fnext(*searchtet, walkthroface);
08726 break;
08727 }
08728
08729
08730 #ifdef SELF_CHECK
08731 assert(ori1 < 0.0);
08732 #endif
08733
08734
08735
08736
08737
08738 fnextself(*searchtet);
08739 if (ori3 == 0.0) {
08740 if (ori4 == 0.0) {
08741
08742 enext2self(*searchtet);
08743 return ONVERTEX;
08744 } else {
08745
08746 enextself(*searchtet);
08747 return ONEDGE;
08748 }
08749 }
08750 if (ori4 == 0.0) {
08751
08752 enext2self(*searchtet);
08753 return ONEDGE;
08754 }
08755
08756 return ONFACE;
08757 } else if (ori2 < 0.0) {
08758
08759 fnext(*searchtet, walkthroface);
08760 break;
08761 }
08762
08763 enextself(*searchtet);
08764 }
08765 if (side >= 3) {
08766
08767 return INTETRAHEDRON;
08768 }
08769
08770 #ifdef SELF_CHECK
08771 assert(walkthroface.tet != (tetrahedron *) NULL);
08772 #endif
08773
08774
08775
08776 backtracetet = walkthroface;
08777 sym(walkthroface, *searchtet);
08778 tetnumber++;
08779 }
08780
08781
08782
08783
08784 return OUTSIDE;
08785 }
08786
08788
08789
08790
08791
08792
08793
08794
08795
08796
08797
08798
08799
08800
08801
08802
08803
08804
08805
08806
08808
08809 enum tetgenmesh::locateresult tetgenmesh::locate(point searchpt,
08810 triface *searchtet)
08811 {
08812 tetrahedron *firsttet, *tetptr;
08813 void **sampleblock;
08814 long sampleblocks, samplesperblock, samplenum;
08815 long tetblocks, i, j;
08816 unsigned long alignptr;
08817 REAL searchdist, dist;
08818
08819
08820 if (isdead(searchtet)) {
08821 searchtet->tet = dummytet;
08822 }
08823 if (searchtet->tet == dummytet) {
08824
08825 searchtet->loc = 0;
08826 symself(*searchtet);
08827 }
08828 #ifdef SELF_CHECK
08829
08830 #endif
08831 if (isdead(searchtet)) {
08832 printf("Warning: Point location failed.\n");
08833 return OUTSIDE;
08834 }
08835
08836
08837 searchdist = distance2(searchtet->tet, searchpt);
08838
08839
08840
08841 if (!isdead(&recenttet) && (recenttet.tet != searchtet->tet)) {
08842 dist = distance2(recenttet.tet, searchpt);
08843 if (dist < searchdist) {
08844 *searchtet = recenttet;
08845 searchdist = dist;
08846 }
08847 }
08848
08849
08850
08851
08852
08853 while (SAMPLEFACTOR * samples * samples * samples * samples <
08854 tetrahedrons->items) {
08855 samples++;
08856 }
08857
08858 tetblocks = (tetrahedrons->maxitems + ELEPERBLOCK - 1) / ELEPERBLOCK;
08859
08860 samplesperblock = 1 + (samples / tetblocks);
08861 sampleblocks = samples / samplesperblock;
08862 sampleblock = tetrahedrons->firstblock;
08863 for (i = 0; i < sampleblocks; i++) {
08864 alignptr = (unsigned long) (sampleblock + 1);
08865 firsttet = (tetrahedron *)
08866 (alignptr + (unsigned long) tetrahedrons->alignbytes
08867 - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08868 for (j = 0; j < samplesperblock; j++) {
08869 if (i == tetblocks - 1) {
08870
08871 samplenum = randomnation((int)
08872 (tetrahedrons->maxitems - (i * ELEPERBLOCK)));
08873 } else {
08874 samplenum = randomnation(ELEPERBLOCK);
08875 }
08876 tetptr = (tetrahedron *)
08877 (firsttet + (samplenum * tetrahedrons->itemwords));
08878 if (tetptr[4] != (tetrahedron) NULL) {
08879 dist = distance2(tetptr, searchpt);
08880 if (dist < searchdist) {
08881 searchtet->tet = tetptr;
08882 searchdist = dist;
08883 }
08884 }
08885 }
08886 sampleblock = (void **) *sampleblock;
08887 }
08888
08889
08890 return preciselocate(searchpt, searchtet, tetrahedrons->items);
08891 }
08892
08894
08895
08896
08897
08898
08899
08900
08901
08902
08903
08904
08905
08906
08907
08908
08909
08910
08911
08912
08913
08915
08916 enum tetgenmesh::locateresult tetgenmesh::adjustlocate(point searchpt,
08917 triface* searchtet, enum locateresult precise, REAL epspp)
08918 {
08919 point torg, tdest, tapex, toppo;
08920 REAL s1, s2, s3, s4;
08921
08922
08923
08924
08925
08926
08927 adjustedgering(*searchtet, CCW);
08928 torg = org(*searchtet);
08929 tdest = dest(*searchtet);
08930 tapex = apex(*searchtet);
08931 toppo = oppo(*searchtet);
08932
08933 switch (precise) {
08934 case ONVERTEX:
08935
08936 return ONVERTEX;
08937 case ONEDGE:
08938
08939 s1 = 0.0;
08940 s2 = 0.0;
08941 break;
08942 case ONFACE:
08943
08944 s1 = 0.0;
08945 s2 = orient3d(torg, tdest, toppo, searchpt);
08946 break;
08947 default:
08948 s1 = orient3d(tdest, torg, tapex, searchpt);
08949 s2 = orient3d(torg, tdest, toppo, searchpt);
08950 }
08951
08952 if (s1 != 0.0) {
08953 if (iscoplanar(tdest, torg, tapex, searchpt, s1, epspp)) {
08954 s1 = 0.0;
08955 }
08956 }
08957 if (s1 < 0.0) {
08958 return OUTSIDE;
08959 }
08960
08961 if (s2 != 0.0) {
08962 if (iscoplanar(torg, tdest, toppo, searchpt, s2, epspp)) {
08963 s2 = 0.0;
08964 }
08965 }
08966 if (s2 < 0.0) {
08967 fnextself(*searchtet);
08968 return OUTSIDE;
08969 }
08970
08971 s3 = orient3d(tdest, tapex, toppo, searchpt);
08972 if (s3 != 0.0) {
08973 if (iscoplanar(tdest, tapex, toppo, searchpt, s3, epspp)) {
08974 s3 = 0.0;
08975 }
08976 }
08977 if (s3 < 0.0) {
08978 enextfnextself(*searchtet);
08979 return OUTSIDE;
08980 }
08981
08982 s4 = orient3d(tapex, torg, toppo, searchpt);
08983 if (s4 != 0.0) {
08984 if (iscoplanar(tapex, torg, toppo, searchpt, s4, epspp)) {
08985 s4 = 0.0;
08986 }
08987 }
08988 if (s4 < 0.0) {
08989 enext2fnextself(*searchtet);
08990 return OUTSIDE;
08991 }
08992
08993
08994 if (s1 == 0.0) {
08995 if (s2 == 0.0) {
08996 if (s3 == 0.0) {
08997
08998 enextself(*searchtet);
08999 return ONVERTEX;
09000 }
09001 if (s4 == 0.0) {
09002
09003 return ONVERTEX;
09004 }
09005
09006 return ONEDGE;
09007 }
09008 if (s3 == 0.0) {
09009 if (s4 == 0.0) {
09010
09011 enext2self(*searchtet);
09012 return ONVERTEX;
09013 }
09014
09015 enextself(*searchtet);
09016 return ONEDGE;
09017 }
09018 if (s4 == 0.0) {
09019
09020 enext2self(*searchtet);
09021 return ONEDGE;
09022 }
09023
09024 return ONFACE;
09025 }
09026 if (s2 == 0.0) {
09027 fnextself(*searchtet);
09028 if (s3 == 0.0) {
09029 if (s4 == 0.0) {
09030
09031 enext2self(*searchtet);
09032 return ONVERTEX;
09033 }
09034
09035 enextself(*searchtet);
09036 return ONEDGE;
09037 }
09038 if (s4 == 0.0) {
09039
09040 enext2self(*searchtet);
09041 return ONEDGE;
09042 }
09043
09044 return ONFACE;
09045 }
09046 if (s3 == 0.0) {
09047 enextfnextself(*searchtet);
09048 if (s4 == 0.0) {
09049
09050 enextself(*searchtet);
09051 return ONEDGE;
09052 }
09053
09054 return ONFACE;
09055 }
09056 if (s4 == 0.0) {
09057 enext2fnextself(*searchtet);
09058
09059 return ONFACE;
09060 }
09061
09062
09063 return INTETRAHEDRON;
09064 }
09065
09067
09068
09069
09071
09072 enum tetgenmesh::locateresult tetgenmesh::hullwalk(point searchpt,
09073 triface *hulltet)
09074 {
09075 list* travtetlist;
09076 triface travtet, neightet;
09077 point pa, pb, pc;
09078 enum locateresult loc;
09079 REAL ori;
09080 int i;
09081
09082 travtetlist = new list(sizeof(triface), NULL, 256);
09083 travtet = *hulltet;
09084 infect(travtet);
09085 travtetlist->append(&travtet);
09086
09087 loc = OUTSIDE;
09088 for (i = 0; i < travtetlist->len(); i++) {
09089 travtet = * (triface *)(* travtetlist)[i];
09090
09091 travtet.ver = 0;
09092
09093 for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09094 pa = org(travtet);
09095 pb = dest(travtet);
09096 pc = apex(travtet);
09097 ori = orient3d(pa, pb, pc, searchpt);
09098 if (ori > 0.0) break;
09099 }
09100
09101 if (travtet.loc == 4) {
09102 hulltet->tet = travtet.tet;
09103 loc = adjustlocate(searchpt, hulltet, INTETRAHEDRON, b->epsilon);
09104 assert(loc != OUTSIDE);
09105 } else {
09106
09107 sym(travtet, neightet);
09108 if (neightet.tet == dummytet) {
09109
09110 loc = adjustlocate(searchpt, &travtet, OUTSIDE, b->epsilon);
09111 }
09112 if (loc == OUTSIDE) {
09113
09114 for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09115 sym(travtet, neightet);
09116 if ((neightet.tet != dummytet) && !infected(neightet)) {
09117
09118 infect(neightet);
09119 travtetlist->append(&neightet);
09120 }
09121 }
09122 }
09123 }
09124 if (loc != OUTSIDE) break;
09125 }
09126
09127
09128 for (i = 0; i < travtetlist->len(); i++) {
09129 travtet = * (triface *)(* travtetlist)[i];
09130 uninfect(travtet);
09131 }
09132
09133 delete travtetlist;
09134 return loc;
09135 }
09136
09138
09139
09140
09141
09142
09143
09144
09145
09146
09147
09148
09149
09150
09151
09152
09153
09154
09155
09156
09157
09158
09160
09161 enum tetgenmesh::locateresult tetgenmesh::locatesub(point searchpt,
09162 face* searchsh, int stopatseg, REAL epspp)
09163 {
09164 face backtracksh, spinsh, checkedge;
09165 point forg, fdest, fapex;
09166 REAL orgori, destori;
09167 REAL ori, sign;
09168 int moveleft, i;
09169
09170 if (searchsh->sh == dummysh) {
09171 searchsh->shver = 0;
09172 spivotself(*searchsh);
09173 #ifdef SELF_CHECK
09174 assert(searchsh->sh != dummysh);
09175 #endif
09176 }
09177
09178 adjustedgering(*searchsh, CCW);
09179 forg = sorg(*searchsh);
09180 fdest = sdest(*searchsh);
09181 fapex = sapex(*searchsh);
09182 ori = orient3d(forg, fdest, fapex, abovepoint);
09183 sign = ori > 0.0 ? -1 : 1;
09184
09185
09186
09187
09188 for (i = 0; i < 3; i++) {
09189 forg = sorg(*searchsh);
09190 fdest = sdest(*searchsh);
09191 ori = orient3d(forg, fdest, abovepoint, searchpt) * sign;
09192 if (ori > 0.0) break;
09193 senextself(*searchsh);
09194 }
09195 #ifdef SELF_CHECK
09196 assert(i < 3);
09197 #endif
09198
09199 while (1) {
09200 fapex = sapex(*searchsh);
09201
09202 if (fapex[0] == searchpt[0] && fapex[1] == searchpt[1] &&
09203 fapex[2] == searchpt[2]) {
09204 senext2self(*searchsh);
09205 return ONVERTEX;
09206 }
09207
09208
09209 destori = orient3d(forg, fapex, abovepoint, searchpt) * sign;
09210 if (epspp > 0.0) {
09211 if (iscoplanar(forg, fapex, abovepoint, searchpt, destori, epspp)) {
09212 destori = 0.0;
09213 }
09214 }
09215
09216
09217 orgori = orient3d(fapex, fdest, abovepoint, searchpt) * sign;
09218 if (epspp > 0.0) {
09219 if (iscoplanar(fapex, fdest, abovepoint, searchpt, orgori, epspp)) {
09220 orgori = 0.0;
09221 }
09222 }
09223 if (destori > 0.0) {
09224 moveleft = 1;
09225 } else {
09226 if (orgori > 0.0) {
09227 moveleft = 0;
09228 } else {
09229
09230 if (destori == 0.0) {
09231 senext2self(*searchsh);
09232 return ONEDGE;
09233 }
09234 if (orgori == 0.0) {
09235 senextself(*searchsh);
09236 return ONEDGE;
09237 }
09238 return ONFACE;
09239 }
09240 }
09241
09242
09243 if (moveleft) {
09244 senext2(*searchsh, backtracksh);
09245 fdest = fapex;
09246 } else {
09247 senext(*searchsh, backtracksh);
09248 forg = fapex;
09249 }
09250
09251 sspivot(backtracksh, checkedge);
09252 if (checkedge.sh != dummysh) {
09253 if (stopatseg) {
09254
09255 *searchsh = backtracksh;
09256 return OUTSIDE;
09257 }
09258
09259
09260 spinsh = backtracksh;
09261 do {
09262 spivotself(spinsh);
09263 if (spinsh.sh == backtracksh.sh) {
09264
09265 break;
09266 }
09267
09268 if (shellmark(spinsh) == shellmark(backtracksh)) {
09269
09270 *searchsh = spinsh;
09271 break;
09272 }
09273
09274 ori = orient3d(forg, fdest, sapex(backtracksh), sapex(spinsh));
09275 if (iscoplanar(forg, fdest, sapex(backtracksh), sapex(spinsh), ori,
09276 b->epsilon)) {
09277
09278 *searchsh = spinsh;
09279 break;
09280 }
09281 } while (spinsh.sh != backtracksh.sh);
09282 } else {
09283 spivot(backtracksh, *searchsh);
09284 }
09285
09286 if ((searchsh->sh == dummysh) || (searchsh->sh == backtracksh.sh)) {
09287
09288 *searchsh = backtracksh;
09289 return OUTSIDE;
09290 }
09291
09292 if (sorg(*searchsh) != forg) sesymself(*searchsh);
09293 #ifdef SELF_CHECK
09294 assert((sorg(*searchsh) == forg) && (sdest(*searchsh) == fdest));
09295 #endif
09296 }
09297 }
09298
09300
09301
09302
09303
09304
09305
09306
09307
09308
09309
09310
09311
09312
09313
09314
09315
09316
09317
09318
09319
09320
09322
09323 enum tetgenmesh::locateresult tetgenmesh::
09324 adjustlocatesub(point searchpt, face* searchsh, enum locateresult precise,
09325 REAL epspp)
09326 {
09327 point pa, pb, pc;
09328 bool s1, s2, s3;
09329
09330 pa = sorg(*searchsh);
09331 pb = sdest(*searchsh);
09332 pc = sapex(*searchsh);
09333
09334 if (precise == ONEDGE) {
09335 s1 = true;
09336 } else {
09337 s1 = iscollinear(pa, pb, searchpt, epspp);
09338 }
09339 s2 = iscollinear(pb, pc, searchpt, epspp);
09340 s3 = iscollinear(pc, pa, searchpt, epspp);
09341 if (s1) {
09342 if (s2) {
09343
09344 #ifdef SELF_CHECK
09345 assert(!s3);
09346 #endif
09347 senextself(*searchsh);
09348 return ONVERTEX;
09349 } else if (s3) {
09350
09351 return ONVERTEX;
09352 } else {
09353
09354 return ONEDGE;
09355 }
09356 } else if (s2) {
09357 if (s3) {
09358
09359 senext2self(*searchsh);
09360 return ONVERTEX;
09361 } else {
09362
09363 senextself(*searchsh);
09364 return ONEDGE;
09365 }
09366 } else if (s3) {
09367
09368 senext2self(*searchsh);
09369 return ONEDGE;
09370 } else {
09371 return precise;
09372 }
09373 }
09374
09376
09377
09378
09379
09380
09381
09382
09383
09384
09385
09386
09387
09389
09390 enum tetgenmesh::locateresult tetgenmesh::
09391 locateseg(point searchpt, face* searchseg)
09392 {
09393 face backtraceseg;
09394 point pa, pb;
09395 REAL dx, dy, dz;
09396 int moveleft;
09397 int i;
09398
09399 moveleft = 0;
09400 while (1) {
09401 searchseg->shver = 0;
09402 pa = sorg(*searchseg);
09403 pb = sdest(*searchseg);
09404
09405 dx = fabs(pb[0] - pa[0]);
09406 dy = fabs(pb[1] - pa[1]);
09407 dz = fabs(pb[2] - pa[2]);
09408 if (dx > dy) {
09409 if (dx > dz) {
09410 i = 0;
09411 } else {
09412 i = 2;
09413 }
09414 } else {
09415 if (dy > dz) {
09416 i = 1;
09417 } else {
09418 i = 2;
09419 }
09420 }
09421 if (pa[i] < pb[i]) {
09422 if (searchpt[i] < pa[i]) {
09423 moveleft = 1;
09424 } else if (searchpt[i] > pa[i]) {
09425 if (searchpt[i] < pb[i]) {
09426 return ONEDGE;
09427 } else if (searchpt[i] > pb[i]) {
09428 moveleft = 0;
09429 } else {
09430 #ifdef SELF_CHECK
09431 assert(searchpt[i] == pb[i]);
09432 #endif
09433 sesymself(*searchseg);
09434 return ONVERTEX;
09435 }
09436 } else {
09437 #ifdef SELF_CHECK
09438 assert(searchpt[i] == pa[i]);
09439 #endif
09440 return ONVERTEX;
09441 }
09442 } else if (pa[i] > pb[i]) {
09443 if (searchpt[i] < pb[i]) {
09444 moveleft = 0;
09445 } else if (searchpt[i] > pb[i]) {
09446 if (searchpt[i] < pa[i]) {
09447 return ONEDGE;
09448 } else if (searchpt[i] > pa[i]) {
09449 moveleft = 1;
09450 } else {
09451 #ifdef SELF_CHECK
09452 assert(searchpt[i] == pa[i]);
09453 #endif
09454 return ONVERTEX;
09455 }
09456 } else {
09457 #ifdef SELF_CHECK
09458 assert(searchpt[i] == pb[i]);
09459 #endif
09460 sesymself(*searchseg);
09461 return ONVERTEX;
09462 }
09463 }
09464 backtraceseg = *searchseg;
09465 if (moveleft) {
09466 senext2self(*searchseg);
09467 } else {
09468 senextself(*searchseg);
09469 }
09470 spivotself(*searchseg);
09471 if (searchseg->sh == dummysh) {
09472 *searchseg = backtraceseg;
09473 break;
09474 }
09475 }
09476
09477 return OUTSIDE;
09478 }
09479
09481
09482
09483
09484
09485
09486
09487
09489
09490 enum tetgenmesh::locateresult tetgenmesh::
09491 adjustlocateseg(point searchpt, face* searchseg, enum locateresult precise,
09492 REAL epspp)
09493 {
09494 point pa, pb;
09495 REAL L, d, r;
09496
09497 pa = sorg(*searchseg);
09498 pb = sdest(*searchseg);
09499 L = distance(pa, pb);
09500
09501
09502 d = distance(pa, searchpt);
09503 r = d / L;
09504 if (r <= epspp) {
09505 return ONVERTEX;
09506 }
09507
09508 d = distance(pb, searchpt);
09509 r = d / L;
09510 if (r <= epspp) {
09511 sesymself(*searchseg);
09512 return ONVERTEX;
09513 }
09514
09515 return precise;
09516 }
09517
09518
09519
09520
09521
09522
09523
09524
09525
09527
09528
09529
09530
09531
09532
09533
09534
09535
09536
09537
09538
09539
09540
09541
09542
09543
09544
09545
09546
09547
09548
09549
09550
09551
09552
09553
09554
09555
09556
09558
09560
09561
09562
09563
09564
09565
09566
09567
09568
09569
09570
09571
09572
09573
09574
09575
09576
09577
09578
09579
09580
09581
09582
09583
09584
09585
09586
09587
09589
09590 enum tetgenmesh::fliptype tetgenmesh::categorizeface(triface& horiz)
09591 {
09592 triface symhoriz, casing;
09593 face checksh, checkseg;
09594 face cassh1, cassh2;
09595 point pa, pb, pc, pd, pe, pf, pg;
09596 point abdoppo, bcdoppo, cadoppo;
09597 REAL ori1, ori2, ori3;
09598 int adjtet;
09599
09600 sym(horiz, symhoriz);
09601 if (symhoriz.tet == dummytet) {
09602
09603 return N40;
09604 }
09605
09606 adjustedgering(horiz, CCW);
09607 findedge(&symhoriz, dest(horiz), org(horiz));
09608 pa = org(horiz);
09609 pb = dest(horiz);
09610 pc = apex(horiz);
09611 pd = oppo(horiz);
09612 pe = oppo(symhoriz);
09613
09614
09615
09616 abdoppo = bcdoppo = cadoppo = (point) NULL;
09617 adjtet = 0;
09618 fnext(horiz, casing);
09619 symself(casing);
09620 if (casing.tet != dummytet) {
09621 abdoppo = oppo(casing);
09622 if (abdoppo == pe) adjtet++;
09623 }
09624 enextfnext(horiz, casing);
09625 symself(casing);
09626 if (casing.tet != dummytet) {
09627 bcdoppo = oppo(casing);
09628 if (bcdoppo == pe) adjtet++;
09629 }
09630 enext2fnext(horiz, casing);
09631 symself(casing);
09632 if (casing.tet != dummytet) {
09633 cadoppo = oppo(casing);
09634 if (cadoppo == pe) adjtet++;
09635 }
09636
09637 if (adjtet == 0) {
09638
09639 ori1 = orient3d(pa, pb, pd, pe);
09640 if (checksubfaces && ori1 != 0.0) {
09641
09642 fnext(horiz, casing);
09643 tspivot(casing, cassh1);
09644 fnext(symhoriz, casing);
09645 tspivot(casing, cassh2);
09646 if ((cassh1.sh != dummysh) && (cassh2.sh != dummysh)) {
09647
09648 findedge(&cassh1, pa, pb);
09649 sspivot(cassh1, checkseg);
09650 if (checkseg.sh == dummysh) {
09651
09652
09653 ori1 = 0.0;
09654 } else {
09655
09656
09657
09658
09659
09660 if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09661 }
09662 } else {
09663
09664
09665 if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon)) ori1 = 0.0;
09666 }
09667 }
09668 if (ori1 < 0.0) {
09669
09670 #ifdef SELF_CHECK
09671 if (!nonconvex) {
09672
09673 fnext(horiz, casing);
09674 symself(casing);
09675 assert(casing.tet != dummytet);
09676 fnext(symhoriz, casing);
09677 symself(casing);
09678 assert(casing.tet != dummytet);
09679 }
09680 #endif
09681 if (checksubfaces) {
09682
09683 tsspivot(&horiz, &checkseg);
09684 if (checkseg.sh != dummysh) {
09685 return FORBIDDENEDGE;
09686 }
09687 }
09688 return N32;
09689 }
09690 ori2 = orient3d(pb, pc, pd, pe);
09691 if (checksubfaces && ori2 != 0.0) {
09692
09693 enextfnext(horiz, casing);
09694 tspivot(casing, cassh1);
09695 enext2fnext(symhoriz, casing);
09696 tspivot(casing, cassh2);
09697 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09698
09699 findedge(&cassh1, pb, pc);
09700 sspivot(cassh1, checkseg);
09701 if (checkseg.sh == dummysh) {
09702
09703
09704 ori2 = 0.0;
09705 } else {
09706 if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09707 }
09708 } else {
09709
09710
09711 if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon)) ori2 = 0.0;
09712 }
09713 }
09714 if (ori2 < 0.0) {
09715
09716 #ifdef SELF_CHECK
09717 if (!nonconvex) {
09718
09719 enextfnext(horiz, casing);
09720 symself(casing);
09721 assert(casing.tet != dummytet);
09722 enext2fnext(symhoriz, casing);
09723 symself(casing);
09724 assert(casing.tet != dummytet);
09725 }
09726 #endif
09727 enextself(horiz);
09728 if (checksubfaces) {
09729
09730 tsspivot(&horiz, &checkseg);
09731 if (checkseg.sh != dummysh) {
09732 return FORBIDDENEDGE;
09733 }
09734 }
09735 return N32;
09736 }
09737 ori3 = orient3d(pc, pa, pd, pe);
09738 if (checksubfaces && ori3 != 0.0) {
09739
09740 enext2fnext(horiz, casing);
09741 tspivot(casing, cassh1);
09742 enextfnext(symhoriz, casing);
09743 tspivot(casing, cassh2);
09744 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09745
09746 findedge(&cassh1, pc, pa);
09747 sspivot(cassh1, checkseg);
09748 if (checkseg.sh == dummysh) {
09749
09750
09751 ori3 = 0.0;
09752 } else {
09753
09754
09755
09756 if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon * 1e+2)) ori3 = 0.0;
09757 }
09758 } else {
09759
09760
09761 if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon)) ori3 = 0.0;
09762 }
09763 }
09764 if (ori3 < 0.0) {
09765
09766 #ifdef SELF_CHECK
09767 if (!nonconvex) {
09768
09769 enext2fnext(horiz, casing);
09770 symself(casing);
09771 assert(casing.tet != dummytet);
09772 enextfnext(symhoriz, casing);
09773 symself(casing);
09774 assert(casing.tet != dummytet);
09775 }
09776 #endif
09777 enext2self(horiz);
09778 if (checksubfaces) {
09779
09780 tsspivot(&horiz, &checkseg);
09781 if (checkseg.sh != dummysh) {
09782 return FORBIDDENEDGE;
09783 }
09784 }
09785 return N32;
09786 }
09787 if (ori1 == 0.0) {
09788
09789 if (ori2 * ori3 == 0.0) {
09790
09791
09792
09793
09794 return N40;
09795 }
09796 } else if (ori2 == 0.0) {
09797
09798 if (ori1 * ori3 == 0.0) {
09799
09800
09801
09802
09803 return N40;
09804 }
09805
09806 enextself(horiz);
09807 enext2self(symhoriz);
09808 } else if (ori3 == 0.0) {
09809
09810 if (ori1 * ori2 == 0.0) {
09811
09812
09813
09814
09815 return N40;
09816 }
09817
09818 enext2self(horiz);
09819 enextself(symhoriz);
09820 } else {
09821
09822 if (checksubfaces) {
09823 tspivot(horiz, checksh);
09824 if (checksh.sh != dummysh) {
09825
09826 return FORBIDDENFACE;
09827 }
09828 }
09829 return T23;
09830 }
09831
09832 if (checksubfaces) {
09833 tsspivot(&horiz, &checkseg);
09834 if (checkseg.sh != dummysh) {
09835
09836 return FORBIDDENEDGE;
09837 }
09838 tspivot(horiz, checksh);
09839 if (checksh.sh != dummysh) {
09840
09841 return FORBIDDENFACE;
09842 }
09843 }
09844
09845
09846
09847
09848 pf = pg = (point) NULL;
09849 fnext(horiz, casing);
09850 symself(casing);
09851 if (casing.tet != dummytet) {
09852 pf = oppo(casing);
09853 }
09854 fnext(symhoriz, casing);
09855 symself(casing);
09856 if (casing.tet != dummytet) {
09857 pg = oppo(casing);
09858 }
09859 if (pf == pg) {
09860
09861 if (checksubfaces) {
09862
09863 pa = org(horiz);
09864 pb = dest(horiz);
09865 pc = apex(horiz);
09866
09867 ori1 = orient3d(pc, pd, pe, pa);
09868 if (ori1 <= 0) return N40;
09869 ori1 = orient3d(pd, pc, pe, pb);
09870 if (ori1 <= 0) return N40;
09871 if (pf != (point) NULL) {
09872 ori1 = orient3d(pd, pf, pe, pa);
09873 if (ori1 <= 0) return N40;
09874 ori1 = orient3d(pf, pd, pe, pb);
09875 if (ori1 <= 0) return N40;
09876 }
09877 }
09878 if (pf == (point) NULL) {
09879
09880 return T22;
09881 } else {
09882
09883 #ifdef SELF_CHECK
09884 assert(pf != (point) NULL);
09885 #endif
09886 return T44;
09887 }
09888 } else {
09889
09890 return N32;
09891 }
09892 } else if (adjtet == 1) {
09893
09894
09895 if (bcdoppo == pe) {
09896
09897 enextself(horiz);
09898 enext2self(symhoriz);
09899 pa = org(horiz);
09900 pb = dest(horiz);
09901 pc = apex(horiz);
09902 } else if (cadoppo == pe) {
09903
09904 enext2self(horiz);
09905 enextself(symhoriz);
09906 pa = org(horiz);
09907 pb = dest(horiz);
09908 pc = apex(horiz);
09909 } else {
09910
09911 #ifdef SELF_CHECK
09912 assert(abdoppo == pe);
09913 #endif
09914 }
09915
09916 ori1 = orient3d(pc, pd, pe, pa);
09917 if (checksubfaces && ori1 != 0.0) {
09918
09919 enext2fnext(horiz, casing);
09920 tspivot(casing, cassh1);
09921 enextfnext(symhoriz, casing);
09922 tspivot(casing, cassh2);
09923 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09924
09925 findedge(&cassh1, pc, pa);
09926 sspivot(cassh1, checkseg);
09927 if (checkseg.sh == dummysh) {
09928
09929
09930 ori1 = 0.0;
09931 } else {
09932
09933
09934
09935
09936 if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09937 }
09938 } else {
09939
09940 if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon)) ori1 = 0.0;
09941 }
09942 }
09943 if (ori1 <= 0.0) {
09944
09945 return N40;
09946 }
09947 ori2 = orient3d(pd, pc, pe, pb);
09948 if (checksubfaces && ori2 != 0.0) {
09949
09950 enextfnext(horiz, casing);
09951 tspivot(casing, cassh1);
09952 enext2fnext(symhoriz, casing);
09953 tspivot(casing, cassh2);
09954 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09955
09956 findedge(&cassh1, pb, pc);
09957 sspivot(cassh1, checkseg);
09958 if (checkseg.sh == dummysh) {
09959
09960
09961 ori2 = 0.0;
09962 } else {
09963
09964
09965
09966
09967 if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09968 }
09969 } else {
09970
09971 if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon)) ori2 = 0.0;
09972 }
09973 }
09974 if (ori2 <= 0.0) {
09975
09976 return N40;
09977 }
09978
09979 if (checksubfaces) {
09980
09981
09982 tsspivot(&horiz, &checkseg);
09983 if (checkseg.sh != dummysh) {
09984
09985 return FORBIDDENEDGE;
09986 }
09987
09988
09989
09990
09991 fnext(horiz, casing);
09992 tspivot(casing, cassh1);
09993 fnext(symhoriz, casing);
09994 tspivot(casing, cassh2);
09995 if (cassh1.sh != dummysh || cassh2.sh != dummysh) {
09996 if (!b->quiet) {
09997
09998 printf("Warning: A tetrahedron spans two subfaces of a facet.\n");
09999 }
10000
10001 return N32;
10002 }
10003 }
10004 return T32;
10005 } else {
10006
10007
10008 return N40;
10009 }
10010 }
10011
10013
10014
10015
10016
10017
10018
10019
10020
10022
10023 void tetgenmesh::enqueueflipface(triface& checkface, queue* flipqueue)
10024 {
10025 badface *queface;
10026 triface symface;
10027
10028 sym(checkface, symface);
10029 if (symface.tet != dummytet) {
10030 queface = (badface *) flipqueue->push((void *) NULL);
10031 queface->tt = checkface;
10032 queface->foppo = oppo(symface);
10033 }
10034 }
10035
10036 void tetgenmesh::enqueueflipedge(face& checkedge, queue* flipqueue)
10037 {
10038 badface *queface;
10039
10040 queface = (badface *) flipqueue->push((void *) NULL);
10041 queface->ss = checkedge;
10042 queface->forg = sorg(checkedge);
10043 queface->fdest = sdest(checkedge);
10044 }
10045
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059
10061
10062 void tetgenmesh::flip23(triface* flipface, queue* flipqueue)
10063 {
10064 triface abcd, bace;
10065 triface oldabd, oldbcd, oldcad;
10066 triface abdcasing, bcdcasing, cadcasing;
10067 triface oldbae, oldcbe, oldace;
10068 triface baecasing, cbecasing, acecasing;
10069 triface worktet;
10070 face abdsh, bcdsh, cadsh;
10071 face baesh, cbesh, acesh;
10072 face abseg, bcseg, caseg;
10073 face adseg, bdseg, cdseg;
10074 face aeseg, beseg, ceseg;
10075 triface edab, edbc, edca;
10076 point pa, pb, pc, pd, pe;
10077 REAL attrib, volume;
10078 int i;
10079
10080 abcd = *flipface;
10081 adjustedgering(abcd, CCW);
10082 pa = org(abcd);
10083 pb = dest(abcd);
10084 pc = apex(abcd);
10085 pd = oppo(abcd);
10086
10087
10088 sym(abcd, bace);
10089 bace.ver = 0;
10090 for (i = 0; (i < 3) && (org(bace) != pb); i++) {
10091 enextself(bace);
10092 }
10093 pe = oppo(bace);
10094
10095 if (b->verbose > 2) {
10096 printf(" Do T23 on face (%d, %d, %d) %d, %d.\n", pointmark(pa),
10097 pointmark(pb), pointmark(pc), pointmark(pd), pointmark(pe));
10098 }
10099 flip23s++;
10100
10101
10102 fnext(abcd, oldabd);
10103 enextfnext(abcd, oldbcd);
10104 enext2fnext(abcd, oldcad);
10105 fnext(bace, oldbae);
10106 enext2fnext(bace, oldcbe);
10107 enextfnext(bace, oldace);
10108 sym(oldabd, abdcasing);
10109 sym(oldbcd, bcdcasing);
10110 sym(oldcad, cadcasing);
10111 sym(oldbae, baecasing);
10112 sym(oldcbe, cbecasing);
10113 sym(oldace, acecasing);
10114 if (checksubfaces) {
10115 tspivot(oldabd, abdsh);
10116 tspivot(oldbcd, bcdsh);
10117 tspivot(oldcad, cadsh);
10118 tspivot(oldbae, baesh);
10119 tspivot(oldcbe, cbesh);
10120 tspivot(oldace, acesh);
10121 } else if (checksubsegs) {
10122 tsspivot1(abcd, abseg);
10123 enext(abcd, worktet);
10124 tsspivot1(worktet, bcseg);
10125 enext2(abcd, worktet);
10126 tsspivot1(worktet, caseg);
10127 enext2(oldabd, worktet);
10128 tsspivot1(worktet, adseg);
10129 enext2(oldbcd, worktet);
10130 tsspivot1(worktet, bdseg);
10131 enext2(oldcad, worktet);
10132 tsspivot1(worktet, cdseg);
10133 enext(oldbae, worktet);
10134 tsspivot1(worktet, aeseg);
10135 enext(oldcbe, worktet);
10136 tsspivot1(worktet, beseg);
10137 enext(oldace, worktet);
10138 tsspivot1(worktet, ceseg);
10139 }
10140
10141
10142 edab.tet = abcd.tet;
10143 setorg (edab, pe);
10144 setdest(edab, pd);
10145 setapex(edab, pa);
10146 setoppo(edab, pb);
10147 edbc.tet = bace.tet;
10148 setorg (edbc, pe);
10149 setdest(edbc, pd);
10150 setapex(edbc, pb);
10151 setoppo(edbc, pc);
10152 maketetrahedron(&edca);
10153 setorg (edca, pe);
10154 setdest(edca, pd);
10155 setapex(edca, pc);
10156 setoppo(edca, pa);
10157
10158 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
10159 attrib = elemattribute(abcd.tet, i);
10160 setelemattribute(edca.tet, i, attrib);
10161 }
10162
10163
10164
10165 if (b->varvolume && !b->refine) {
10166 volume = volumebound(abcd.tet);
10167 setvolumebound(edca.tet, volume);
10168 }
10169
10170
10171 for (i = 0; i < 4; i ++) {
10172 edab.tet[i] = (tetrahedron) dummytet;
10173 }
10174 for (i = 0; i < 4; i ++) {
10175 edbc.tet[i] = (tetrahedron) dummytet;
10176 }
10177
10178 edab.loc = 0;
10179 edca.loc = 1;
10180 bond(edab, edca);
10181 edab.loc = 1;
10182 edbc.loc = 0;
10183 bond(edab, edbc);
10184 edbc.loc = 1;
10185 edca.loc = 0;
10186 bond(edbc, edca);
10187
10188 edab.loc = 2;
10189 bond(edab, abdcasing);
10190 edab.loc = 3;
10191 bond(edab, baecasing);
10192 edbc.loc = 2;
10193 bond(edbc, bcdcasing);
10194 edbc.loc = 3;
10195 bond(edbc, cbecasing);
10196 edca.loc = 2;
10197 bond(edca, cadcasing);
10198 edca.loc = 3;
10199 bond(edca, acecasing);
10200
10201 if (checksubfaces) {
10202
10203 for (i = 0; i < 4; i ++) {
10204 edab.loc = i;
10205 tsdissolve(edab);
10206 edbc.loc = i;
10207 tsdissolve(edbc);
10208 }
10209 if (abdsh.sh != dummysh) {
10210 edab.loc = 2;
10211 tsbond(edab, abdsh);
10212 }
10213 if (baesh.sh != dummysh) {
10214 edab.loc = 3;
10215 tsbond(edab, baesh);
10216 }
10217 if (bcdsh.sh != dummysh) {
10218 edbc.loc = 2;
10219 tsbond(edbc, bcdsh);
10220 }
10221 if (cbesh.sh != dummysh) {
10222 edbc.loc = 3;
10223 tsbond(edbc, cbesh);
10224 }
10225 if (cadsh.sh != dummysh) {
10226 edca.loc = 2;
10227 tsbond(edca, cadsh);
10228 }
10229 if (acesh.sh != dummysh) {
10230 edca.loc = 3;
10231 tsbond(edca, acesh);
10232 }
10233 } else if (checksubsegs) {
10234 for (i = 0; i < 6; i++) {
10235 edab.tet[8 + i] = (tetrahedron) dummysh;
10236 }
10237 for (i = 0; i < 6; i++) {
10238 edbc.tet[8 + i] = (tetrahedron) dummysh;
10239 }
10240 edab.loc = edab.ver = 0;
10241 edbc.loc = edab.ver = 0;
10242 edca.loc = edab.ver = 0;
10243
10244 enext(edab, worktet);
10245 tssbond1(worktet, adseg);
10246 enext2(edab, worktet);
10247 tssbond1(worktet, aeseg);
10248 fnext(edab, worktet);
10249 enextself(worktet);
10250 tssbond1(worktet, bdseg);
10251 enextself(worktet);
10252 tssbond1(worktet, beseg);
10253 enextfnext(edab, worktet);
10254 enextself(worktet);
10255 tssbond1(worktet, abseg);
10256
10257 enext(edbc, worktet);
10258 tssbond1(worktet, bdseg);
10259 enext2(edbc, worktet);
10260 tssbond1(worktet, beseg);
10261 fnext(edbc, worktet);
10262 enextself(worktet);
10263 tssbond1(worktet, cdseg);
10264 enextself(worktet);
10265 tssbond1(worktet, ceseg);
10266 enextfnext(edbc, worktet);
10267 enextself(worktet);
10268 tssbond1(worktet, bcseg);
10269
10270 enext(edca, worktet);
10271 tssbond1(worktet, cdseg);
10272 enext2(edca, worktet);
10273 tssbond1(worktet, ceseg);
10274 fnext(edca, worktet);
10275 enextself(worktet);
10276 tssbond1(worktet, adseg);
10277 enextself(worktet);
10278 tssbond1(worktet, aeseg);
10279 enextfnext(edca, worktet);
10280 enextself(worktet);
10281 tssbond1(worktet, caseg);
10282 }
10283
10284 edab.loc = 0;
10285 edbc.loc = 0;
10286 edca.loc = 0;
10287 if (b->verbose > 3) {
10288 printf(" Updating edab ");
10289 printtet(&edab);
10290 printf(" Updating edbc ");
10291 printtet(&edbc);
10292 printf(" Creating edca ");
10293 printtet(&edca);
10294 }
10295
10296 if (flipqueue != (queue *) NULL) {
10297 enextfnext(edab, abdcasing);
10298 enqueueflipface(abdcasing, flipqueue);
10299 enext2fnext(edab, baecasing);
10300 enqueueflipface(baecasing, flipqueue);
10301 enextfnext(edbc, bcdcasing);
10302 enqueueflipface(bcdcasing, flipqueue);
10303 enext2fnext(edbc, cbecasing);
10304 enqueueflipface(cbecasing, flipqueue);
10305 enextfnext(edca, cadcasing);
10306 enqueueflipface(cadcasing, flipqueue);
10307 enext2fnext(edca, acecasing);
10308 enqueueflipface(acecasing, flipqueue);
10309 }
10310
10311
10312 recenttet = edbc;
10313
10314 *flipface = edab;
10315 }
10316
10318
10319
10320
10321
10322
10323
10324
10325
10326
10327
10328
10329
10330
10331
10333
10334 void tetgenmesh::flip32(triface* flipface, queue* flipqueue)
10335 {
10336 triface edab, edbc, edca;
10337 triface oldabd, oldbcd, oldcad;
10338 triface abdcasing, bcdcasing, cadcasing;
10339 triface oldbae, oldcbe, oldace;
10340 triface baecasing, cbecasing, acecasing;
10341 triface worktet;
10342 face abdsh, bcdsh, cadsh;
10343 face baesh, cbesh, acesh;
10344 face abseg, bcseg, caseg;
10345 face adseg, bdseg, cdseg;
10346 face aeseg, beseg, ceseg;
10347 triface abcd, bace;
10348 point pa, pb, pc, pd, pe;
10349 int i;
10350
10351 edab = *flipface;
10352 adjustedgering(edab, CCW);
10353 pa = apex(edab);
10354 pb = oppo(edab);
10355 pd = dest(edab);
10356 pe = org(edab);
10357 fnext(edab, edbc);
10358 symself(edbc);
10359 edbc.ver = 0;
10360 for (i = 0; (i < 3) && (org(edbc) != pe); i++) {
10361 enextself(edbc);
10362 }
10363 pc = oppo(edbc);
10364 fnext(edbc, edca);
10365 symself(edca);
10366 edca.ver = 0;
10367 for (i = 0; (i < 3) && (org(edca) != pe); i++) {
10368 enextself(edca);
10369 }
10370
10371 if (b->verbose > 2) {
10372 printf(" Do T32 on edge (%d, %d) %d, %d, %d.\n", pointmark(pe),
10373 pointmark(pd), pointmark(pa), pointmark(pb), pointmark(pc));
10374 }
10375 flip32s++;
10376
10377
10378 enextfnext(edab, oldabd);
10379 enext2fnext(edab, oldbae);
10380 enextfnext(edbc, oldbcd);
10381 enext2fnext(edbc, oldcbe);
10382 enextfnext(edca, oldcad);
10383 enext2fnext(edca, oldace);
10384 sym(oldabd, abdcasing);
10385 sym(oldbcd, bcdcasing);
10386 sym(oldcad, cadcasing);
10387 sym(oldbae, baecasing);
10388 sym(oldcbe, cbecasing);
10389 sym(oldace, acecasing);
10390 if (checksubfaces) {
10391 tspivot(oldabd, abdsh);
10392 tspivot(oldbcd, bcdsh);
10393 tspivot(oldcad, cadsh);
10394 tspivot(oldbae, baesh);
10395 tspivot(oldcbe, cbesh);
10396 tspivot(oldace, acesh);
10397 } else if (checksubsegs) {
10398 enext(edab, worktet);
10399 tsspivot1(worktet, adseg);
10400 enext2(edab, worktet);
10401 tsspivot1(worktet, aeseg);
10402 enext(edbc, worktet);
10403 tsspivot1(worktet, bdseg);
10404 enext2(edbc, worktet);
10405 tsspivot1(worktet, beseg);
10406 enext(edca, worktet);
10407 tsspivot1(worktet, cdseg);
10408 enext2(edca, worktet);
10409 tsspivot1(worktet, ceseg);
10410 enextfnext(edab, worktet);
10411 enextself(worktet);
10412 tsspivot1(worktet, abseg);
10413 enextfnext(edbc, worktet);
10414 enextself(worktet);
10415 tsspivot1(worktet, bcseg);
10416 enextfnext(edca, worktet);
10417 enextself(worktet);
10418 tsspivot1(worktet, caseg);
10419 }
10420
10421
10422 abcd.tet = edab.tet;
10423 setorg (abcd, pa);
10424 setdest(abcd, pb);
10425 setapex(abcd, pc);
10426 setoppo(abcd, pd);
10427 bace.tet = edbc.tet;
10428 setorg (bace, pb);
10429 setdest(bace, pa);
10430 setapex(bace, pc);
10431 setoppo(bace, pe);
10432
10433 tetrahedrondealloc(edca.tet);
10434
10435
10436 for (i = 0; i < 4; i ++) {
10437 abcd.tet[i] = (tetrahedron) dummytet;
10438 }
10439 for (i = 0; i < 4; i ++) {
10440 bace.tet[i] = (tetrahedron) dummytet;
10441 }
10442
10443 abcd.loc = 0;
10444 bace.loc = 0;
10445 bond(abcd, bace);
10446
10447 abcd.loc = 1;
10448 bond(abcd, abdcasing);
10449 abcd.loc = 2;
10450 bond(abcd, bcdcasing);
10451 abcd.loc = 3;
10452 bond(abcd, cadcasing);
10453 bace.loc = 1;
10454 bond(bace, baecasing);
10455 bace.loc = 3;
10456 bond(bace, cbecasing);
10457 bace.loc = 2;
10458 bond(bace, acecasing);
10459 if (checksubfaces) {
10460
10461 for (i = 0; i < 4; i ++) {
10462 abcd.tet[8 + i] = (tetrahedron) dummysh;
10463 }
10464 for (i = 0; i < 4; i ++) {
10465 bace.tet[8 + i] = (tetrahedron) dummysh;
10466 }
10467 if (abdsh.sh != dummysh) {
10468 abcd.loc = 1;
10469 tsbond(abcd, abdsh);
10470 }
10471 if (bcdsh.sh != dummysh) {
10472 abcd.loc = 2;
10473 tsbond(abcd, bcdsh);
10474 }
10475 if (cadsh.sh != dummysh) {
10476 abcd.loc = 3;
10477 tsbond(abcd, cadsh);
10478 }
10479 if (baesh.sh != dummysh) {
10480 bace.loc = 1;
10481 tsbond(bace, baesh);
10482 }
10483 if (cbesh.sh != dummysh) {
10484 bace.loc = 3;
10485 tsbond(bace, cbesh);
10486 }
10487 if (acesh.sh != dummysh) {
10488 bace.loc = 2;
10489 tsbond(bace, acesh);
10490 }
10491 } else if (checksubsegs) {
10492 for (i = 0; i < 6; i++) {
10493 abcd.tet[8 + i] = (tetrahedron) dummysh;
10494 }
10495 for (i = 0; i < 6; i++) {
10496 bace.tet[8 + i] = (tetrahedron) dummysh;
10497 }
10498 abcd.loc = abcd.ver = 0;
10499 bace.loc = bace.ver = 0;
10500 tssbond1(abcd, abseg);
10501 enext(abcd, worktet);
10502 tssbond1(worktet, bcseg);
10503 enext2(abcd, worktet);
10504 tssbond1(worktet, caseg);
10505 fnext(abcd, worktet);
10506 enext2self(worktet);
10507 tssbond1(worktet, adseg);
10508 enextfnext(abcd, worktet);
10509 enext2self(worktet);
10510 tssbond1(worktet, bdseg);
10511 enext2fnext(abcd, worktet);
10512 enext2self(worktet);
10513 tssbond1(worktet, cdseg);
10514 tssbond1(bace, abseg);
10515 enext2(bace, worktet);
10516 tssbond1(worktet, bcseg);
10517 enext(bace, worktet);
10518 tssbond1(worktet, caseg);
10519 fnext(bace, worktet);
10520 enextself(worktet);
10521 tssbond1(worktet, aeseg);
10522 enext2fnext(bace, worktet);
10523 enextself(worktet);
10524 tssbond1(worktet, beseg);
10525 enextfnext(bace, worktet);
10526 enextself(worktet);
10527 tssbond1(worktet, ceseg);
10528 }
10529
10530 abcd.loc = 0;
10531 bace.loc = 0;
10532 if (b->verbose > 3) {
10533 printf(" Updating abcd ");
10534 printtet(&abcd);
10535 printf(" Updating bace ");
10536 printtet(&bace);
10537 printf(" Deleting edca ");
10538
10539 }
10540
10541 if (flipqueue != (queue *) NULL) {
10542 fnext(abcd, abdcasing);
10543 enqueueflipface(abdcasing, flipqueue);
10544 fnext(bace, baecasing);
10545 enqueueflipface(baecasing, flipqueue);
10546 enextfnext(abcd, bcdcasing);
10547 enqueueflipface(bcdcasing, flipqueue);
10548 enextfnext(bace, cbecasing);
10549 enqueueflipface(cbecasing, flipqueue);
10550 enext2fnext(abcd, cadcasing);
10551 enqueueflipface(cadcasing, flipqueue);
10552 enext2fnext(bace, acecasing);
10553 enqueueflipface(acecasing, flipqueue);
10554 }
10555
10556
10557 recenttet = abcd;
10558
10559 *flipface = abcd;
10560 }
10561
10563
10564
10565
10566
10567
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581
10582
10583
10584
10585
10587
10588 void tetgenmesh::flip22(triface* flipface, queue* flipqueue)
10589 {
10590 triface abce, bade;
10591 triface oldbce, oldcae, oldade, olddbe;
10592 triface bcecasing, caecasing, adecasing, dbecasing;
10593 face bcesh, caesh, adesh, dbesh;
10594 triface bacf, abdf;
10595 triface oldacf, oldcbf, oldbdf, olddaf;
10596 triface acfcasing, cbfcasing, bdfcasing, dafcasing;
10597 triface worktet;
10598 face acfsh, cbfsh, bdfsh, dafsh;
10599 face abc, bad;
10600 face adseg, dbseg, bcseg, caseg;
10601 face aeseg, deseg, beseg, ceseg;
10602 face afseg, dfseg, bfseg, cfseg;
10603 point pa, pb, pc, pd;
10604 #ifdef SELF_CHECK
10605 point pe, pf;
10606 #endif
10607 int mirrorflag, i;
10608
10609 adjustedgering(*flipface, CCW);
10610 fnext(*flipface, abce);
10611 esymself(abce);
10612 adjustedgering(*flipface, CW);
10613 fnext(*flipface, bade);
10614 #ifdef SELF_CHECK
10615 assert(bade.tet != dummytet);
10616 #endif
10617 esymself(bade);
10618 pa = org(abce);
10619 pb = dest(abce);
10620 pc = apex(abce);
10621 pd = apex(bade);
10622 #ifdef SELF_CHECK
10623 pe = oppo(bade);
10624 assert(oppo(abce) == pe);
10625 #endif
10626 sym(abce, bacf);
10627 mirrorflag = bacf.tet != dummytet;
10628 if (mirrorflag) {
10629
10630 bacf.ver = 0;
10631 for (i = 0; (i < 3) && (org(bacf) != pb); i++) {
10632 enextself(bacf);
10633 }
10634 sym(bade, abdf);
10635 #ifdef SELF_CHECK
10636 assert(abdf.tet != dummytet);
10637 #endif
10638
10639 abdf.ver = 0;
10640 for (i = 0; (i < 3) && (org(abdf) != pa); i++) {
10641 enextself(abdf);
10642 }
10643
10644 #ifdef SELF_CHECK
10645 pf = oppo(bacf);
10646 assert(oppo(abdf) == pf);
10647 #endif
10648 }
10649
10650 if (b->verbose > 2) {
10651 printf(" Do %s on edge (%d, %d).\n", mirrorflag ? "T44" : "T22",
10652 pointmark(pa), pointmark(pb));
10653 }
10654 mirrorflag ? flip44s++ : flip22s++;
10655
10656
10657 enextfnext(abce, oldbce);
10658 enext2fnext(abce, oldcae);
10659 enextfnext(bade, oldade);
10660 enext2fnext(bade, olddbe);
10661 sym(oldbce, bcecasing);
10662 sym(oldcae, caecasing);
10663 sym(oldade, adecasing);
10664 sym(olddbe, dbecasing);
10665 if (checksubfaces) {
10666 tspivot(oldbce, bcesh);
10667 tspivot(oldcae, caesh);
10668 tspivot(oldade, adesh);
10669 tspivot(olddbe, dbesh);
10670 tspivot(abce, abc);
10671 tspivot(bade, bad);
10672 } else if (checksubsegs) {
10673
10674 enext(bade, worktet);
10675 tsspivot1(worktet, adseg);
10676 enext2(bade, worktet);
10677 tsspivot1(worktet, dbseg);
10678 enext(abce, worktet);
10679 tsspivot1(worktet, bcseg);
10680 enext2(abce, worktet);
10681 tsspivot1(worktet, caseg);
10682
10683 fnext(bade, worktet);
10684 enextself(worktet);
10685 tsspivot1(worktet, aeseg);
10686 enextfnext(bade, worktet);
10687 enextself(worktet);
10688 tsspivot1(worktet, deseg);
10689 enext2fnext(bade, worktet);
10690 enextself(worktet);
10691 tsspivot1(worktet, beseg);
10692 enextfnext(abce, worktet);
10693 enextself(worktet);
10694 tsspivot1(worktet, ceseg);
10695 }
10696 if (mirrorflag) {
10697 enextfnext(bacf, oldacf);
10698 enext2fnext(bacf, oldcbf);
10699 enextfnext(abdf, oldbdf);
10700 enext2fnext(abdf, olddaf);
10701 sym(oldacf, acfcasing);
10702 sym(oldcbf, cbfcasing);
10703 sym(oldbdf, bdfcasing);
10704 sym(olddaf, dafcasing);
10705 if (checksubfaces) {
10706 tspivot(oldacf, acfsh);
10707 tspivot(oldcbf, cbfsh);
10708 tspivot(oldbdf, bdfsh);
10709 tspivot(olddaf, dafsh);
10710 } else if (checksubsegs) {
10711
10712 fnext(abdf, worktet);
10713 enext2self(worktet);
10714 tsspivot1(worktet, afseg);
10715 enext2fnext(abdf, worktet);
10716 enext2self(worktet);
10717 tsspivot1(worktet, dfseg);
10718 enextfnext(abdf, worktet);
10719 enext2self(worktet);
10720 tsspivot1(worktet, bfseg);
10721 enextfnext(bacf, worktet);
10722 enextself(worktet);
10723 tsspivot1(worktet, cfseg);
10724 }
10725 }
10726
10727
10728 bond(oldbce, caecasing);
10729 bond(oldcae, adecasing);
10730 bond(oldade, dbecasing);
10731 bond(olddbe, bcecasing);
10732 if (checksubfaces) {
10733
10734 if (caesh.sh == dummysh) {
10735 tsdissolve(oldbce);
10736 } else {
10737 tsbond(oldbce, caesh);
10738 }
10739 if (adesh.sh == dummysh) {
10740 tsdissolve(oldcae);
10741 } else {
10742 tsbond(oldcae, adesh);
10743 }
10744 if (dbesh.sh == dummysh) {
10745 tsdissolve(oldade);
10746 } else {
10747 tsbond(oldade, dbesh);
10748 }
10749 if (bcesh.sh == dummysh) {
10750 tsdissolve(olddbe);
10751 } else {
10752 tsbond(olddbe, bcesh);
10753 }
10754 } else if (checksubsegs) {
10755
10756 enext(abce, worktet);
10757 if (caseg.sh == dummysh) {
10758 tssdissolve1(worktet);
10759 } else {
10760 tssbond1(worktet, caseg);
10761 }
10762 enext2(abce, worktet);
10763 if (adseg.sh == dummysh) {
10764 tssdissolve1(worktet);
10765 } else {
10766 tssbond1(worktet, adseg);
10767 }
10768 fnext(abce, worktet);
10769 enextself(worktet);
10770 if (ceseg.sh == dummysh) {
10771 tssdissolve1(worktet);
10772 } else {
10773 tssbond1(worktet, ceseg);
10774 }
10775 enextfnext(abce, worktet);
10776 enextself(worktet);
10777 if (aeseg.sh == dummysh) {
10778 tssdissolve1(worktet);
10779 } else {
10780 tssbond1(worktet, aeseg);
10781 }
10782 enext2fnext(abce, worktet);
10783 enextself(worktet);
10784 if (deseg.sh == dummysh) {
10785 tssdissolve1(worktet);
10786 } else {
10787 tssbond1(worktet, deseg);
10788 }
10789
10790 enext(bade, worktet);
10791 if (dbseg.sh == dummysh) {
10792 tssdissolve1(worktet);
10793 } else {
10794 tssbond1(worktet, dbseg);
10795 }
10796 enext2(bade, worktet);
10797 if (bcseg.sh == dummysh) {
10798 tssdissolve1(worktet);
10799 } else {
10800 tssbond1(worktet, bcseg);
10801 }
10802 fnext(bade, worktet);
10803 enextself(worktet);
10804 if (deseg.sh == dummysh) {
10805 tssdissolve1(worktet);
10806 } else {
10807 tssbond1(worktet, deseg);
10808 }
10809 enextfnext(bade, worktet);
10810 enextself(worktet);
10811 if (beseg.sh == dummysh) {
10812 tssdissolve1(worktet);
10813 } else {
10814 tssbond1(worktet, beseg);
10815 }
10816 enext2fnext(bade, worktet);
10817 enextself(worktet);
10818 if (ceseg.sh == dummysh) {
10819 tssdissolve1(worktet);
10820 } else {
10821 tssbond1(worktet, ceseg);
10822 }
10823 }
10824 if (mirrorflag) {
10825
10826 bond(oldcbf, acfcasing);
10827 bond(oldacf, dafcasing);
10828 bond(olddaf, bdfcasing);
10829 bond(oldbdf, cbfcasing);
10830 if (checksubfaces) {
10831
10832 if (acfsh.sh == dummysh) {
10833 tsdissolve(oldcbf);
10834 } else {
10835 tsbond(oldcbf, acfsh);
10836 }
10837 if (dafsh.sh == dummysh) {
10838 tsdissolve(oldacf);
10839 } else {
10840 tsbond(oldacf, dafsh);
10841 }
10842 if (bdfsh.sh == dummysh) {
10843 tsdissolve(olddaf);
10844 } else {
10845 tsbond(olddaf, bdfsh);
10846 }
10847 if (cbfsh.sh == dummysh) {
10848 tsdissolve(oldbdf);
10849 } else {
10850 tsbond(oldbdf, cbfsh);
10851 }
10852 } else if (checksubsegs) {
10853
10854 enext2(bacf, worktet);
10855 if (caseg.sh == dummysh) {
10856 tssdissolve1(worktet);
10857 } else {
10858 tssbond1(worktet, caseg);
10859 }
10860 enext(bacf, worktet);
10861 if (adseg.sh == dummysh) {
10862 tssdissolve1(worktet);
10863 } else {
10864 tssbond1(worktet, adseg);
10865 }
10866 fnext(bacf, worktet);
10867 enext2self(worktet);
10868 if (cfseg.sh == dummysh) {
10869 tssdissolve1(worktet);
10870 } else {
10871 tssbond1(worktet, cfseg);
10872 }
10873 enext2fnext(bacf, worktet);
10874 enext2self(worktet);
10875 if (afseg.sh == dummysh) {
10876 tssdissolve1(worktet);
10877 } else {
10878 tssbond1(worktet, afseg);
10879 }
10880 enextfnext(bacf, worktet);
10881 enext2self(worktet);
10882 if (dfseg.sh == dummysh) {
10883 tssdissolve1(worktet);
10884 } else {
10885 tssbond1(worktet, dfseg);
10886 }
10887
10888 enext2(abdf, worktet);
10889 if (dbseg.sh == dummysh) {
10890 tssdissolve1(worktet);
10891 } else {
10892 tssbond1(worktet, dbseg);
10893 }
10894 enext(abdf, worktet);
10895 if (bcseg.sh == dummysh) {
10896 tssdissolve1(worktet);
10897 } else {
10898 tssbond1(worktet, bcseg);
10899 }
10900 fnext(abdf, worktet);
10901 enext2self(worktet);
10902 if (dfseg.sh == dummysh) {
10903 tssdissolve1(worktet);
10904 } else {
10905 tssbond1(worktet, dfseg);
10906 }
10907 enext2fnext(abdf, worktet);
10908 enext2self(worktet);
10909 if (bfseg.sh == dummysh) {
10910 tssdissolve1(worktet);
10911 } else {
10912 tssbond1(worktet, bfseg);
10913 }
10914 enextfnext(abdf, worktet);
10915 enext2self(worktet);
10916 if (cfseg.sh == dummysh) {
10917 tssdissolve1(worktet);
10918 } else {
10919 tssbond1(worktet, cfseg);
10920 }
10921 }
10922 }
10923
10924
10925 setorg(abce, pd);
10926 setdest(abce, pc);
10927 setapex(abce, pa);
10928 setorg(bade, pc);
10929 setdest(bade, pd);
10930 setapex(bade, pb);
10931 if (mirrorflag) {
10932 setorg(bacf, pc);
10933 setdest(bacf, pd);
10934 setapex(bacf, pa);
10935 setorg(abdf, pd);
10936 setdest(abdf, pc);
10937 setapex(abdf, pb);
10938 }
10939
10940
10941 if (checksubfaces && abc.sh != dummysh) {
10942 #ifdef SELF_CHECK
10943 assert(bad.sh != dummysh);
10944 #endif
10945
10946
10947 findedge(&abc, pa, pb);
10948
10949 flip22sub(&abc, NULL);
10950 }
10951
10952 if (b->verbose > 3) {
10953 printf(" Updating abce ");
10954 printtet(&abce);
10955 printf(" Updating bade ");
10956 printtet(&bade);
10957 if (mirrorflag) {
10958 printf(" Updating bacf ");
10959 printtet(&bacf);
10960 printf(" Updating abdf ");
10961 printtet(&abdf);
10962 }
10963 }
10964
10965 if (flipqueue != (queue *) NULL) {
10966 enextfnext(abce, bcecasing);
10967 enqueueflipface(bcecasing, flipqueue);
10968 enext2fnext(abce, caecasing);
10969 enqueueflipface(caecasing, flipqueue);
10970 enextfnext(bade, adecasing);
10971 enqueueflipface(adecasing, flipqueue);
10972 enext2fnext(bade, dbecasing);
10973 enqueueflipface(dbecasing, flipqueue);
10974 if (mirrorflag) {
10975 enextfnext(bacf, acfcasing);
10976 enqueueflipface(acfcasing, flipqueue);
10977 enext2fnext(bacf, cbfcasing);
10978 enqueueflipface(cbfcasing, flipqueue);
10979 enextfnext(abdf, bdfcasing);
10980 enqueueflipface(bdfcasing, flipqueue);
10981 enext2fnext(abdf, dafcasing);
10982 enqueueflipface(dafcasing, flipqueue);
10983 }
10984
10985
10986
10987
10988
10989 enqueueflipface(abce, flipqueue);
10990 enqueueflipface(bade, flipqueue);
10991 }
10992
10993
10994 recenttet = abce;
10995 }
10996
10998
10999
11000
11001
11002
11003
11004
11005
11006
11007
11008
11009
11010
11011
11012
11013
11014
11015
11016
11017
11018
11019
11020
11021
11023
11024 void tetgenmesh::flip22sub(face* flipedge, queue* flipqueue)
11025 {
11026 face abc, bad;
11027 face oldbc, oldca, oldad, olddb;
11028 face bccasin, bccasout, cacasin, cacasout;
11029 face adcasin, adcasout, dbcasin, dbcasout;
11030 face bc, ca, ad, db;
11031 face spinsh;
11032 point pa, pb, pc, pd;
11033
11034 abc = *flipedge;
11035 spivot(abc, bad);
11036 if (sorg(bad) != sdest(abc)) {
11037 sesymself(bad);
11038 }
11039 pa = sorg(abc);
11040 pb = sdest(abc);
11041 pc = sapex(abc);
11042 pd = sapex(bad);
11043
11044 if (b->verbose > 2) {
11045 printf(" Flip sub edge (%d, %d).\n", pointmark(pa), pointmark(pb));
11046 }
11047
11048
11049 senext(abc, oldbc);
11050 senext2(abc, oldca);
11051 senext(bad, oldad);
11052 senext2(bad, olddb);
11053
11054
11055
11056 spivot(oldbc, bccasout);
11057 sspivot(oldbc, bc);
11058 if (bc.sh != dummysh) {
11059
11060 if (bccasout.sh != dummysh) {
11061 if (oldbc.sh != bccasout.sh) {
11062
11063 spinsh = bccasout;
11064 do {
11065 bccasin = spinsh;
11066 spivotself(spinsh);
11067 } while (spinsh.sh != oldbc.sh);
11068 } else {
11069 bccasout.sh = dummysh;
11070 }
11071 }
11072 ssdissolve(oldbc);
11073 }
11074 spivot(oldca, cacasout);
11075 sspivot(oldca, ca);
11076 if (ca.sh != dummysh) {
11077
11078 if (cacasout.sh != dummysh) {
11079 if (oldca.sh != cacasout.sh) {
11080
11081 spinsh = cacasout;
11082 do {
11083 cacasin = spinsh;
11084 spivotself(spinsh);
11085 } while (spinsh.sh != oldca.sh);
11086 } else {
11087 cacasout.sh = dummysh;
11088 }
11089 }
11090 ssdissolve(oldca);
11091 }
11092 spivot(oldad, adcasout);
11093 sspivot(oldad, ad);
11094 if (ad.sh != dummysh) {
11095
11096 if (adcasout.sh != dummysh) {
11097 if (oldad.sh != adcasout.sh) {
11098
11099 spinsh = adcasout;
11100 do {
11101 adcasin = spinsh;
11102 spivotself(spinsh);
11103 } while (spinsh.sh != oldad.sh);
11104 } else {
11105 adcasout.sh = dummysh;
11106 }
11107 }
11108 ssdissolve(oldad);
11109 }
11110 spivot(olddb, dbcasout);
11111 sspivot(olddb, db);
11112 if (db.sh != dummysh) {
11113
11114 if (dbcasout.sh != dummysh) {
11115 if (olddb.sh != dbcasout.sh) {
11116
11117 spinsh = dbcasout;
11118 do {
11119 dbcasin = spinsh;
11120 spivotself(spinsh);
11121 } while (spinsh.sh != olddb.sh);
11122 } else {
11123 dbcasout.sh = dummysh;
11124 }
11125 }
11126 ssdissolve(olddb);
11127 }
11128
11129
11130 if (ca.sh != dummysh) {
11131 if (cacasout.sh != dummysh) {
11132 sbond1(cacasin, oldbc);
11133 sbond1(oldbc, cacasout);
11134 } else {
11135
11136 sbond(oldbc, oldbc);
11137
11138 dummysh[0] = sencode(oldbc);
11139 }
11140 ssbond(oldbc, ca);
11141 } else {
11142 sbond(oldbc, cacasout);
11143 }
11144 if (ad.sh != dummysh) {
11145 if (adcasout.sh != dummysh) {
11146 sbond1(adcasin, oldca);
11147 sbond1(oldca, adcasout);
11148 } else {
11149
11150 sbond(oldca, oldca);
11151
11152 dummysh[0] = sencode(oldca);
11153 }
11154 ssbond(oldca, ad);
11155 } else {
11156 sbond(oldca, adcasout);
11157 }
11158 if (db.sh != dummysh) {
11159 if (dbcasout.sh != dummysh) {
11160 sbond1(dbcasin, oldad);
11161 sbond1(oldad, dbcasout);
11162 } else {
11163
11164 sbond(oldad, oldad);
11165
11166 dummysh[0] = sencode(oldad);
11167 }
11168 ssbond(oldad, db);
11169 } else {
11170 sbond(oldad, dbcasout);
11171 }
11172 if (bc.sh != dummysh) {
11173 if (bccasout.sh != dummysh) {
11174 sbond1(bccasin, olddb);
11175 sbond1(olddb, bccasout);
11176 } else {
11177
11178 sbond(olddb, olddb);
11179
11180 dummysh[0] = sencode(olddb);
11181 }
11182 ssbond(olddb, bc);
11183 } else {
11184 sbond(olddb, bccasout);
11185 }
11186
11187
11188 setsorg(abc, pd);
11189 setsdest(abc, pc);
11190 setsapex(abc, pa);
11191 setsorg(bad, pc);
11192 setsdest(bad, pd);
11193 setsapex(bad, pb);
11194
11195 if (flipqueue != (queue *) NULL) {
11196 enqueueflipedge(bccasout, flipqueue);
11197 enqueueflipedge(cacasout, flipqueue);
11198 enqueueflipedge(adcasout, flipqueue);
11199 enqueueflipedge(dbcasout, flipqueue);
11200 }
11201 }
11202
11204
11205
11206
11207
11208
11209
11210
11211
11212
11213
11214
11215
11216
11217
11219
11220 long tetgenmesh::flip(queue* flipqueue, badface **plastflip)
11221 {
11222 badface *qface, *newflip;
11223 triface flipface, symface;
11224 point pa, pb, pc, pd, pe;
11225 enum fliptype fc;
11226 REAL sign, bakepsilon;
11227 long flipcount;
11228 int epscount, fcount;
11229 int ia, ib, ic, id, ie;
11230
11231 if (b->verbose > 1) {
11232 printf(" Do flipface queue: %ld faces.\n", flipqueue->len());
11233 }
11234
11235 flipcount = flip23s + flip32s + flip22s + flip44s;
11236 if (checksubfaces) {
11237
11238 fcount = 0;
11239 }
11240
11241 if (plastflip != (badface **) NULL) {
11242
11243 flipstackers->restart();
11244 *plastflip = (badface *) NULL;
11245 }
11246
11247
11248 while (!flipqueue->empty()) {
11249 qface = (badface *) flipqueue->pop();
11250 flipface = qface->tt;
11251 if (isdead(&flipface)) continue;
11252 sym(flipface, symface);
11253
11254 if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11255
11256 adjustedgering(flipface, CW);
11257 pa = org(flipface);
11258 pb = dest(flipface);
11259 pc = apex(flipface);
11260 pd = oppo(flipface);
11261 pe = oppo(symface);
11262 if (symbolic) {
11263 ia = pointmark(pa);
11264 ib = pointmark(pb);
11265 ic = pointmark(pc);
11266 id = pointmark(pd);
11267 ie = pointmark(pe);
11268 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
11269 assert(sign != 0.0);
11270 } else {
11271 sign = insphere(pa, pb, pc, pd, pe);
11272 }
11273 } else {
11274 sign = -1.0;
11275 }
11276 if (sign > 0.0) {
11277
11278 if (checksubfaces) {
11279 fcount++;
11280 bakepsilon = b->epsilon;
11281 epscount = 0;
11282 while (epscount < 32) {
11283 fc = categorizeface(flipface);
11284 if (fc == N40) {
11285 b->epsilon *= 1e-1;
11286 epscount++;
11287 continue;
11288 }
11289 break;
11290 }
11291 b->epsilon = bakepsilon;
11292 if (epscount >= 32) {
11293 if (b->verbose > 0) {
11294 printf("Warning: Can't flip a degenerate tetrahedron.\n");
11295 }
11296 fc = N40;
11297 }
11298 } else {
11299 fc = categorizeface(flipface);
11300 #ifdef SELF_CHECK
11301 assert(fc != N40);
11302 #endif
11303 }
11304 switch (fc) {
11305
11306 case T44:
11307 case T22:
11308 flip22(&flipface, flipqueue);
11309 break;
11310 case T23:
11311 flip23(&flipface, flipqueue);
11312 break;
11313 case T32:
11314 flip32(&flipface, flipqueue);
11315 break;
11316
11317 case N32:
11318 break;
11319 case FORBIDDENFACE:
11320 break;
11321 case FORBIDDENEDGE:
11322 break;
11323
11324 case N40:
11325
11326 break;
11327 }
11328 if (plastflip != (badface **) NULL) {
11329 if ((fc == T44) || (fc == T22) || (fc == T23) || (fc == T32)) {
11330
11331 newflip = (badface *) flipstackers->alloc();
11332 newflip->tt = flipface;
11333 newflip->key = (REAL) fc;
11334 newflip->forg = org(flipface);
11335 newflip->fdest = dest(flipface);
11336 newflip->fapex = apex(flipface);
11337 newflip->previtem = *plastflip;
11338 *plastflip = newflip;
11339 }
11340 }
11341 }
11342 }
11343
11344 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11345 if (b->verbose > 1) {
11346 printf(" %ld flips.\n", flipcount);
11347 }
11348
11349 return flipcount;
11350 }
11351
11353
11354
11355
11357
11358 long tetgenmesh::lawson(list *misseglist, queue* flipqueue)
11359 {
11360 badface *qface, *misseg;
11361 triface flipface, symface;
11362 triface starttet, spintet;
11363 face checksh, checkseg;
11364 point pa, pb, pc, pd, pe;
11365 point swappt;
11366 REAL sign, ori;
11367 long flipcount;
11368 int ia, ib, ic, id, ie;
11369 int hitbdry, i;
11370
11371 if (b->verbose > 1) {
11372 printf(" Do flipface queue: %ld faces.\n", flipqueue->len());
11373 }
11374 flipcount = flip23s + flip32s + flip22s + flip44s;
11375
11376
11377
11378
11379 while (!flipqueue->empty()) {
11380 qface = (badface *) flipqueue->pop();
11381 flipface = qface->tt;
11382
11383 if (!isdead(&flipface)) {
11384 sym(flipface, symface);
11385
11386 if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11387 flipface.ver = 0;
11388 pa = org(flipface);
11389 pb = dest(flipface);
11390 pc = apex(flipface);
11391 pd = oppo(flipface);
11392 pe = oppo(symface);
11393 if (symbolic) {
11394 ia = pointmark(pa);
11395 ib = pointmark(pb);
11396 ic = pointmark(pc);
11397 id = pointmark(pd);
11398 ie = pointmark(pe);
11399 sign = insphere_sos(pb, pa, pc, pd, pe, ib, ia, ic, id, ie);
11400 } else {
11401 sign = insphere(pb, pa, pc, pd, pe);
11402 }
11403 if (sign > 0.0) {
11404 for (i = 0; i < 3; i++) {
11405 ori = orient3d(pa, pb, pd, pe);
11406 if (ori > 0.0) {
11407
11408 swappt = pa;
11409 pa = pb;
11410 pb = pc;
11411 pc = swappt;
11412 enextself(flipface);
11413 } else {
11414 break;
11415 }
11416 }
11417 if (ori > 0.0) {
11418
11419 if (checksubfaces) {
11420 tspivot(flipface, checksh);
11421 if (checksh.sh != dummysh) {
11422
11423 continue;
11424 }
11425 }
11426 flip23(&flipface, flipqueue);
11427 } else if (ori < 0.0) {
11428
11429 fnext(flipface, symface);
11430 symself(symface);
11431 if (oppo(symface) == pe) {
11432
11433 if (checksubfaces) {
11434 tsspivot(&flipface, &checkseg);
11435 if (checkseg.sh != dummysh) {
11436
11437 continue;
11438 }
11439 } else if (checksubsegs) {
11440 tsspivot1(flipface, checkseg);
11441 if (checkseg.sh != dummysh) {
11442 if (b->verbose > 2) {
11443 printf(" Queuing missing segment (%d, %d).\n",
11444 pointmark(org(flipface)), pointmark(dest(flipface)));
11445 }
11446 misseg = (badface *) misseglist->append(NULL);
11447 misseg->ss = checkseg;
11448 misseg->forg = sorg(checkseg);
11449 misseg->fdest = sdest(checkseg);
11450
11451 starttet = flipface;
11452 adjustedgering(starttet, CCW);
11453 fnextself(starttet);
11454 spintet = starttet;
11455 hitbdry = 0;
11456 do {
11457 tssdissolve1(spintet);
11458 if (!fnextself(spintet)) {
11459 hitbdry++;
11460 if (hitbdry < 2) {
11461 esym(starttet, spintet);
11462 if (!fnextself(spintet)) {
11463 hitbdry++;
11464 }
11465 }
11466 }
11467 } while ((apex(spintet) != apex(starttet)) && (hitbdry < 2));
11468 }
11469 }
11470 flip32(&flipface, flipqueue);
11471 }
11472 } else {
11473
11474 fnext(flipface, symface);
11475 if (fnextself(symface)) {
11476
11477 fnextself(symface);
11478 if (apex(symface) == pe) {
11479 if (checksubfaces) {
11480 tsspivot(&flipface, &checkseg);
11481 if (checkseg.sh != dummysh) {
11482
11483 continue;
11484 }
11485 } else if (checksubsegs) {
11486 tsspivot1(flipface, checkseg);
11487 if (checkseg.sh != dummysh) {
11488 if (b->verbose > 2) {
11489 printf(" Queuing missing segment (%d, %d).\n",
11490 pointmark(org(flipface)), pointmark(dest(flipface)));
11491 }
11492 misseg = (badface *) misseglist->append(NULL);
11493 misseg->ss = checkseg;
11494 misseg->forg = sorg(checkseg);
11495 misseg->fdest = sdest(checkseg);
11496
11497 starttet = flipface;
11498 adjustedgering(starttet, CCW);
11499 fnextself(starttet);
11500 spintet = starttet;
11501 hitbdry = 0;
11502 do {
11503 tssdissolve1(spintet);
11504 if (!fnextself(spintet)) {
11505 hitbdry++;
11506 if (hitbdry < 2) {
11507 esym(starttet, spintet);
11508 if (!fnextself(spintet)) {
11509 hitbdry++;
11510 }
11511 }
11512 }
11513 } while ((apex(spintet) != apex(starttet)) &&
11514 (hitbdry < 2));
11515 }
11516 }
11517 flip22(&flipface, flipqueue);
11518 }
11519 } else {
11520
11521 esym(flipface, symface);
11522 fnextself(symface);
11523 symself(symface);
11524 if (symface.tet == dummytet) {
11525 if (checksubfaces) {
11526 tsspivot(&flipface, &checkseg);
11527 if (checkseg.sh != dummysh) {
11528
11529 continue;
11530 }
11531 } else if (checksubsegs) {
11532 tsspivot1(flipface, checkseg);
11533 if (checkseg.sh != dummysh) {
11534 if (b->verbose > 2) {
11535 printf(" Queuing missing segment (%d, %d).\n",
11536 pointmark(org(flipface)), pointmark(dest(flipface)));
11537 }
11538 misseg = (badface *) misseglist->append(NULL);
11539 misseg->ss = checkseg;
11540 misseg->forg = sorg(checkseg);
11541 misseg->fdest = sdest(checkseg);
11542
11543 starttet = flipface;
11544 adjustedgering(starttet, CCW);
11545 fnextself(starttet);
11546 spintet = starttet;
11547 hitbdry = 0;
11548 do {
11549 tssdissolve1(spintet);
11550 if (!fnextself(spintet)) {
11551 hitbdry++;
11552 if (hitbdry < 2) {
11553 esym(starttet, spintet);
11554 if (!fnextself(spintet)) {
11555 hitbdry++;
11556 }
11557 }
11558 }
11559 } while ((apex(spintet) != apex(starttet)) &&
11560 (hitbdry < 2));
11561 }
11562 }
11563 flip22(&flipface, flipqueue);
11564 }
11565 }
11566 }
11567 }
11568 }
11569 }
11570 }
11571
11572 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11573 if (b->verbose > 1) {
11574 printf(" %ld flips.\n", flipcount);
11575 }
11576 return flipcount;
11577 }
11578
11580
11581
11582
11583
11584
11585
11586
11588
11589 void tetgenmesh::undoflip(badface *lastflip)
11590 {
11591 enum fliptype fc;
11592
11593 while (lastflip != (badface *) NULL) {
11594
11595 findface(&lastflip->tt, lastflip->forg, lastflip->fdest, lastflip->fapex);
11596 fc = (enum fliptype) (int) lastflip->key;
11597 switch (fc) {
11598 case T23:
11599
11600 flip32(&lastflip->tt, NULL);
11601 break;
11602 case T32:
11603
11604 flip23(&lastflip->tt, NULL);
11605 break;
11606 case T22:
11607 case T44:
11608
11609 flip22(&lastflip->tt, NULL);
11610 break;
11611 default:
11612 break;
11613 }
11614
11615 lastflip = lastflip->previtem;
11616 }
11617 }
11618
11620
11621
11622
11623
11624
11625
11626
11628
11629 long tetgenmesh::flipsub(queue* flipqueue)
11630 {
11631 badface *qedge;
11632 face flipedge, symedge;
11633 face checkseg;
11634 point pa, pb, pc, pd;
11635 REAL vab[3], vac[3], vad[3];
11636 REAL dot1, dot2, lac, lad;
11637 REAL sign, ori;
11638 int edgeflips;
11639 int i;
11640
11641 if (b->verbose > 1) {
11642 printf(" Start do edge queue: %ld edges.\n", flipqueue->len());
11643 }
11644
11645 edgeflips = 0;
11646
11647 while (!flipqueue->empty()) {
11648 qedge = (badface *) flipqueue->pop();
11649 flipedge = qedge->ss;
11650 if (flipedge.sh == dummysh) continue;
11651 if ((sorg(flipedge) != qedge->forg) ||
11652 (sdest(flipedge) != qedge->fdest)) continue;
11653 sspivot(flipedge, checkseg);
11654 if (checkseg.sh != dummysh) continue;
11655 spivot(flipedge, symedge);
11656 if (symedge.sh == dummysh) continue;
11657 pa = sorg(flipedge);
11658 pb = sdest(flipedge);
11659 pc = sapex(flipedge);
11660 pd = sapex(symedge);
11661
11662
11663 for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
11664 for (i = 0; i < 3; i++) vac[i] = pc[i] - pa[i];
11665 for (i = 0; i < 3; i++) vad[i] = pd[i] - pa[i];
11666 dot1 = dot(vac, vab);
11667 dot2 = dot(vad, vab);
11668 dot1 *= dot1;
11669 dot2 *= dot2;
11670 lac = dot(vac, vac);
11671 lad = dot(vad, vad);
11672 if (lad * dot1 <= lac * dot2) {
11673
11674 abovepoint = facetabovepointarray[shellmark(flipedge)];
11675 if (abovepoint == (point) NULL) {
11676 getfacetabovepoint(&flipedge);
11677 }
11678 sign = insphere(pa, pb, pc, abovepoint, pd);
11679 ori = orient3d(pa, pb, pc, abovepoint);
11680 } else {
11681
11682 abovepoint = facetabovepointarray[shellmark(symedge)];
11683 if (abovepoint == (point) NULL) {
11684 getfacetabovepoint(&symedge);
11685 }
11686 sign = insphere(pa, pb, pd, abovepoint, pc);
11687 ori = orient3d(pa, pb, pd, abovepoint);
11688 }
11689
11690 sign = ori > 0.0 ? sign : -sign;
11691 if (sign > 0.0) {
11692
11693 flip22sub(&flipedge, flipqueue);
11694 edgeflips++;
11695 }
11696 }
11697
11698 if (b->verbose > 1) {
11699 printf(" Total %d flips.\n", edgeflips);
11700 }
11701
11702 return edgeflips;
11703 }
11704
11706
11707
11708
11709
11710
11711
11712
11713
11714
11715
11716
11717
11718
11720
11721 bool tetgenmesh::removetetbypeeloff(triface *striptet)
11722 {
11723 triface abcd, badc;
11724 triface dcacasing, cdbcasing;
11725 face abc, bad;
11726 face abseg;
11727 REAL ang;
11728
11729 abcd = *striptet;
11730 adjustedgering(abcd, CCW);
11731
11732 enextfnext(abcd, cdbcasing);
11733 enext2fnext(abcd, dcacasing);
11734 symself(cdbcasing);
11735 symself(dcacasing);
11736
11737
11738 if ((cdbcasing.tet == dummytet) || (dcacasing.tet == dummytet)) {
11739
11740 return false;
11741 }
11742
11743
11744 if (checksubfaces) {
11745
11746 fnext(abcd, badc);
11747 esymself(badc);
11748 tspivot(abcd, abc);
11749 tspivot(badc, bad);
11750 if (abc.sh != dummysh) {
11751 assert(bad.sh != dummysh);
11752 findedge(&abc, org(abcd), dest(abcd));
11753 findedge(&bad, org(badc), dest(badc));
11754
11755 sspivot(abc, abseg);
11756 if (abseg.sh != dummysh) {
11757
11758 if ((b->optlevel > 3) && (b->nobisect == 0)) {
11759
11760
11761
11762 ang = facedihedral(org(abcd), dest(abcd), apex(abcd), oppo(abcd));
11763 ang = ang * 180.0 / PI;
11764 if ((ang + 9.0) > b->maxdihedral) {
11765 if (b->verbose > 1) {
11766 printf(" Remove a segment during peeling.\n");
11767 }
11768 face prevseg, nextseg;
11769
11770 ssdissolve(abc);
11771 ssdissolve(bad);
11772 abseg.shver = 0;
11773 senext(abseg, nextseg);
11774 spivotself(nextseg);
11775 if (nextseg.sh != dummysh) {
11776 ssdissolve(nextseg);
11777 }
11778 senext2(abseg, prevseg);
11779 spivotself(prevseg);
11780 if (prevseg.sh != dummysh) {
11781 ssdissolve(prevseg);
11782 }
11783 shellfacedealloc(subsegs, abseg.sh);
11784 optcount[1]++;
11785 } else {
11786 return false;
11787 }
11788 } else {
11789 return false;
11790 }
11791 }
11792
11793 flip22sub(&abc, NULL);
11794
11795 tsbond(cdbcasing, bad);
11796 tsbond(dcacasing, abc);
11797 }
11798 }
11799
11800
11801 dissolve(cdbcasing);
11802 dissolve(dcacasing);
11803
11804 tetrahedrondealloc(abcd.tet);
11805 return true;
11806 }
11807
11809
11810
11811
11812
11813
11814
11815
11816
11817
11818
11819
11820
11821
11823
11824 bool tetgenmesh::removeedgebyflip22(REAL *key, int n, triface *abtetlist,
11825 queue *flipque)
11826 {
11827 point pa, pb, pc, pd, pe, pf;
11828 REAL cosmaxd, d1, d2, d3;
11829 bool doflip;
11830
11831 cosmaxd = 0.0;
11832 pf = apex(abtetlist[2]);
11833 doflip = true;
11834 adjustedgering(abtetlist[0], CW);
11835 pa = org(abtetlist[0]);
11836 pb = dest(abtetlist[0]);
11837 pe = apex(abtetlist[0]);
11838 pc = oppo(abtetlist[0]);
11839 pd = apex(abtetlist[1]);
11840 if (n == 4) {
11841 pf = apex(abtetlist[2]);
11842 }
11843 if (key && (*key > -1.0)) {
11844 tetalldihedral(pc, pd, pe, pa, NULL, &d1, NULL);
11845 tetalldihedral(pd, pc, pe, pb, NULL, &d2, NULL);
11846 cosmaxd = d1 < d2 ? d1 : d2;
11847 if (n == 4) {
11848 tetalldihedral(pd, pc, pf, pa, NULL, &d1, NULL);
11849 tetalldihedral(pc, pd, pf, pb, NULL, &d2, NULL);
11850 d3 = d1 < d2 ? d1 : d2;
11851 cosmaxd = cosmaxd < d3 ? cosmaxd : d3;
11852 }
11853 doflip = (*key < cosmaxd);
11854 }
11855
11856 if (doflip) {
11857 flip22(&abtetlist[0], NULL);
11858
11859 if (key) *key = cosmaxd;
11860 }
11861
11862 return doflip;
11863 }
11864
11866
11867
11868
11869
11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11883
11884 bool tetgenmesh::removefacebyflip23(REAL *key, triface *abctetlist,
11885 triface *newtetlist, queue *flipque)
11886 {
11887 triface edab, edbc, edca;
11888 triface newfront, oldfront, adjfront;
11889 face checksh;
11890 point pa, pb, pc, pd, pe;
11891 REAL ori, cosmaxd, d1, d2, d3;
11892 REAL attrib, volume;
11893 bool doflip;
11894 int i;
11895
11896 cosmaxd = 0.0;
11897
11898 adjustedgering(abctetlist[0], CCW);
11899 pa = org(abctetlist[0]);
11900 pb = dest(abctetlist[0]);
11901 pc = apex(abctetlist[0]);
11902 pd = oppo(abctetlist[0]);
11903 pe = oppo(abctetlist[1]);
11904
11905
11906 ori = orient3d(pe, pd, pa, pb);
11907 if (ori < 0.0) {
11908 ori = orient3d(pe, pd, pb, pc);
11909 if (ori < 0.0) {
11910 ori = orient3d(pe, pd, pc, pa);
11911 }
11912 }
11913 doflip = (ori < 0.0);
11914 if (doflip && (key != (REAL *) NULL)) {
11915 if (*key > -1.0) {
11916
11917 tetalldihedral(pe, pd, pa, pb, NULL, &d1, NULL);
11918 tetalldihedral(pe, pd, pb, pc, NULL, &d2, NULL);
11919 tetalldihedral(pe, pd, pc, pa, NULL, &d3, NULL);
11920 cosmaxd = d1 < d2 ? d1 : d2;
11921 cosmaxd = cosmaxd < d3 ? cosmaxd : d3;
11922 doflip = (*key < cosmaxd);
11923 }
11924 }
11925
11926 if (doflip) {
11927
11928 flip23s++;
11929
11930 maketetrahedron(&edab);
11931 setorg(edab, pe);
11932 setdest(edab, pd);
11933 setapex(edab, pa);
11934 setoppo(edab, pb);
11935 maketetrahedron(&edbc);
11936 setorg(edbc, pe);
11937 setdest(edbc, pd);
11938 setapex(edbc, pb);
11939 setoppo(edbc, pc);
11940 maketetrahedron(&edca);
11941 setorg(edca, pe);
11942 setdest(edca, pd);
11943 setapex(edca, pc);
11944 setoppo(edca, pa);
11945
11946 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
11947 attrib = elemattribute(abctetlist[0].tet, i);
11948 setelemattribute(edab.tet, i, attrib);
11949 setelemattribute(edbc.tet, i, attrib);
11950 setelemattribute(edca.tet, i, attrib);
11951 }
11952
11953 if (b->varvolume && !b->refine) {
11954 volume = volumebound(abctetlist[0].tet);
11955 setvolumebound(edab.tet, volume);
11956 setvolumebound(edbc.tet, volume);
11957 setvolumebound(edca.tet, volume);
11958 }
11959
11960 newtetlist[0] = edab;
11961 newtetlist[1] = edbc;
11962 newtetlist[2] = edca;
11963
11964 for (i = 0; i < 3; i++) {
11965 fnext(newtetlist[i], newfront);
11966 bond(newfront, newtetlist[(i + 1) % 3]);
11967 }
11968
11969 for (i = 0; i < 3; i++) {
11970 fnext(abctetlist[0], oldfront);
11971 sym(oldfront, adjfront);
11972 enextfnext(newtetlist[i], newfront);
11973 bond(newfront, adjfront);
11974 if (checksubfaces) {
11975 tspivot(oldfront, checksh);
11976 if (checksh.sh != dummysh) {
11977 tsbond(newfront, checksh);
11978 }
11979 }
11980 if (flipque != (queue *) NULL) {
11981 enqueueflipface(newfront, flipque);
11982 }
11983 enextself(abctetlist[0]);
11984 }
11985 findedge(&(abctetlist[1]), pb, pa);
11986 for (i = 0; i < 3; i++) {
11987 fnext(abctetlist[1], oldfront);
11988 sym(oldfront, adjfront);
11989 enext2fnext(newtetlist[i], newfront);
11990 bond(newfront, adjfront);
11991 if (checksubfaces) {
11992 tspivot(oldfront, checksh);
11993 if (checksh.sh != dummysh) {
11994 tsbond(newfront, checksh);
11995 }
11996 }
11997 if (flipque != (queue *) NULL) {
11998 enqueueflipface(newfront, flipque);
11999 }
12000 enext2self(abctetlist[1]);
12001 }
12002
12003
12004
12005
12006
12007 if (key != (REAL *) NULL) *key = cosmaxd;
12008 return true;
12009 }
12010
12011 return false;
12012 }
12013
12015
12016
12017
12018
12019
12020
12021
12022
12023
12024
12025
12026
12027
12028
12029
12030
12031
12032
12033
12035
12036 bool tetgenmesh::removeedgebyflip32(REAL *key, triface *abtetlist,
12037 triface *newtetlist, queue *flipque)
12038 {
12039 triface dcea, cdeb;
12040 triface newfront, oldfront, adjfront;
12041 face checksh;
12042 point pa, pb, pc, pd, pe;
12043 REAL ori, cosmaxd, d1, d2;
12044 REAL attrib, volume;
12045 bool doflip;
12046 int i;
12047
12048 pa = org(abtetlist[0]);
12049 pb = dest(abtetlist[0]);
12050 pc = apex(abtetlist[0]);
12051 pd = apex(abtetlist[1]);
12052 pe = apex(abtetlist[2]);
12053
12054 ori = orient3d(pd, pc, pe, pa);
12055 if (ori < 0.0) {
12056 ori = orient3d(pc, pd, pe, pb);
12057 }
12058 doflip = (ori < 0.0);
12059
12060
12061 if (doflip && (key != (REAL *) NULL)) {
12062 if (*key > -1.0) {
12063
12064 tetalldihedral(pd, pc, pe, pa, NULL, &d1, NULL);
12065 tetalldihedral(pc, pd, pe, pb, NULL, &d2, NULL);
12066 cosmaxd = d1 < d2 ? d1 : d2;
12067 doflip = (*key < cosmaxd);
12068
12069 *key = cosmaxd;
12070 }
12071 }
12072
12073 if (doflip) {
12074
12075 maketetrahedron(&dcea);
12076 setorg(dcea, pd);
12077 setdest(dcea, pc);
12078 setapex(dcea, pe);
12079 setoppo(dcea, pa);
12080 maketetrahedron(&cdeb);
12081 setorg(cdeb, pc);
12082 setdest(cdeb, pd);
12083 setapex(cdeb, pe);
12084 setoppo(cdeb, pb);
12085
12086 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12087 attrib = elemattribute(abtetlist[0].tet, i);
12088 setelemattribute(dcea.tet, i, attrib);
12089 setelemattribute(cdeb.tet, i, attrib);
12090 }
12091
12092 if (b->varvolume && !b->refine) {
12093 volume = volumebound(abtetlist[0].tet);
12094 setvolumebound(dcea.tet, volume);
12095 setvolumebound(cdeb.tet, volume);
12096 }
12097
12098 newtetlist[0] = dcea;
12099 newtetlist[1] = cdeb;
12100
12101 bond(dcea, cdeb);
12102
12103 for (i = 0; i < 3; i++) {
12104 fnext(dcea, newfront);
12105 esym(abtetlist[(i + 1) % 3], oldfront);
12106 enextfnextself(oldfront);
12107
12108 sym(oldfront, adjfront);
12109 bond(newfront, adjfront);
12110 if (checksubfaces) {
12111 tspivot(oldfront, checksh);
12112 if (checksh.sh != dummysh) {
12113 tsbond(newfront, checksh);
12114 }
12115 }
12116 if (flipque != (queue *) NULL) {
12117 enqueueflipface(newfront, flipque);
12118 }
12119 enext2self(dcea);
12120 }
12121 for (i = 0; i < 3; i++) {
12122 fnext(cdeb, newfront);
12123 esym(abtetlist[(i + 1) % 3], oldfront);
12124 enext2fnextself(oldfront);
12125
12126 sym(oldfront, adjfront);
12127 bond(newfront, adjfront);
12128 if (checksubfaces) {
12129 tspivot(oldfront, checksh);
12130 if (checksh.sh != dummysh) {
12131 tsbond(newfront, checksh);
12132 }
12133 }
12134 if (flipque != (queue *) NULL) {
12135 enqueueflipface(newfront, flipque);
12136 }
12137 enextself(cdeb);
12138 }
12139
12140
12141
12142
12143 return true;
12144 }
12145
12146 return false;
12147 }
12148
12150
12151
12152
12153
12154
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186
12187
12189
12190 bool tetgenmesh::removeedgebytranNM(REAL *key, int n, triface *abtetlist,
12191 triface *newtetlist, point e1, point e2, queue *flipque)
12192 {
12193 triface tmpabtetlist[9];
12194 triface newfront, oldfront, adjfront;
12195 face checksh;
12196 point pa, pb, p[10];
12197 REAL ori, cosmaxd, d1, d2;
12198 REAL tmpkey;
12199 REAL attrib, volume;
12200 bool doflip, copflag, success;
12201 int i, j, k;
12202
12203 cosmaxd = 0.0;
12204
12205 assert(n <= 10);
12206
12207 pa = org(abtetlist[0]);
12208 pb = dest(abtetlist[0]);
12209
12210
12211
12212
12213 for (i = 0; i < n; i++) {
12214
12215 for (j = 0; j < n; j++) {
12216 p[j] = apex(abtetlist[(i + j) % n]);
12217 }
12218
12219 if ((e1 != (point) NULL) && (e2 != (point) NULL)) {
12220
12221 if (!(((p[1] == e1) && (p[n - 1] == e2)) ||
12222 ((p[1] == e2) && (p[n - 1] == e1)))) continue;
12223 }
12224
12225
12226
12227
12228
12229
12230 ori = orient3d(pa, pb, p[1], p[n - 1]);
12231 copflag = (ori == 0.0);
12232 if (ori >= 0.0) {
12233
12234 ori = orient3d(pb, p[0], p[1], p[n - 1]);
12235 if (ori > 0.0) {
12236 ori = orient3d(p[0], pa, p[1], p[n - 1]);
12237 }
12238 }
12239
12240 if (ori > 0.0) {
12241
12242 copflag ? flip44s++ : flip23s++;
12243 doflip = true;
12244 if (key != (REAL *) NULL) {
12245 if (*key > -1.0) {
12246
12247
12248
12249 tetalldihedral(p[n - 1], p[1], p[0], pa, NULL, &d1, NULL);
12250 tetalldihedral(p[1], p[n - 1], p[0], pb, NULL, &d2, NULL);
12251 cosmaxd = d1 < d2 ? d1 : d2;
12252 doflip = *key < cosmaxd;
12253 }
12254 }
12255 if (doflip) {
12256 tmpkey = key != NULL ? *key : -1.0;
12257
12258 maketetrahedron(&(newtetlist[0]));
12259 setorg(newtetlist[0], p[n - 1]);
12260 setdest(newtetlist[0], p[1]);
12261 setapex(newtetlist[0], p[0]);
12262 setoppo(newtetlist[0], pa);
12263 maketetrahedron(&(newtetlist[1]));
12264 setorg(newtetlist[1], p[1]);
12265 setdest(newtetlist[1], p[n - 1]);
12266 setapex(newtetlist[1], p[0]);
12267 setoppo(newtetlist[1], pb);
12268
12269 maketetrahedron(&(tmpabtetlist[0]));
12270 setorg(tmpabtetlist[0], pa);
12271 setdest(tmpabtetlist[0], pb);
12272 setapex(tmpabtetlist[0], p[n - 1]);
12273 setoppo(tmpabtetlist[0], p[1]);
12274 for (j = 1; j < n - 1; j++) {
12275 maketetrahedron(&(tmpabtetlist[j]));
12276 setorg(tmpabtetlist[j], pa);
12277 setdest(tmpabtetlist[j], pb);
12278 setapex(tmpabtetlist[j], p[j]);
12279 setoppo(tmpabtetlist[j], p[j + 1]);
12280 }
12281
12282 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12283 attrib = elemattribute(abtetlist[0].tet, j);
12284 setelemattribute(newtetlist[0].tet, j, attrib);
12285 setelemattribute(newtetlist[1].tet, j, attrib);
12286 for (k = 0; k < n - 1; k++) {
12287 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12288 }
12289 }
12290
12291 if (b->varvolume && !b->refine) {
12292 volume = volumebound(abtetlist[0].tet);
12293 setvolumebound(newtetlist[0].tet, volume);
12294 setvolumebound(newtetlist[1].tet, volume);
12295 for (k = 0; k < n - 1; k++) {
12296 setvolumebound(tmpabtetlist[k].tet, volume);
12297 }
12298 }
12299
12300 bond(newtetlist[0], newtetlist[1]);
12301 fnext(newtetlist[0], newfront);
12302 enext2fnext(tmpabtetlist[0], adjfront);
12303 bond(newfront, adjfront);
12304 fnext(newtetlist[1], newfront);
12305 enextfnext(tmpabtetlist[0], adjfront);
12306 bond(newfront, adjfront);
12307
12308 for (j = 0; j < n - 1; j++) {
12309 fnext(tmpabtetlist[j], newfront);
12310 bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]);
12311 }
12312
12313
12314
12315
12316
12317
12318 for (j = 0; j < n; j++) {
12319
12320 oldfront = abtetlist[(i + j) % n];
12321 esymself(oldfront);
12322 enextfnextself(oldfront);
12323
12324 sym(oldfront, adjfront);
12325
12326 if (j == 0) {
12327 enext2fnext(newtetlist[0], newfront);
12328 } else if (j == 1) {
12329 enextfnext(newtetlist[0], newfront);
12330 } else {
12331 enext2fnext(tmpabtetlist[j - 1], newfront);
12332 }
12333 bond(newfront, adjfront);
12334 if (checksubfaces) {
12335 tspivot(oldfront, checksh);
12336 if (checksh.sh != dummysh) {
12337 tsbond(newfront, checksh);
12338 }
12339 }
12340 if (flipque != (queue *) NULL) {
12341
12342 if (j < 2) enqueueflipface(newfront, flipque);
12343 }
12344 }
12345 for (j = 0; j < n; j++) {
12346
12347 oldfront = abtetlist[(i + j) % n];
12348 esymself(oldfront);
12349 enext2fnextself(oldfront);
12350
12351 sym(oldfront, adjfront);
12352
12353 if (j == 0) {
12354 enextfnext(newtetlist[1], newfront);
12355 } else if (j == 1) {
12356 enext2fnext(newtetlist[1], newfront);
12357 } else {
12358 enextfnext(tmpabtetlist[j - 1], newfront);
12359 }
12360 bond(newfront, adjfront);
12361 if (checksubfaces) {
12362 tspivot(oldfront, checksh);
12363 if (checksh.sh != dummysh) {
12364 tsbond(newfront, checksh);
12365 }
12366 }
12367 if (flipque != (queue *) NULL) {
12368
12369 if (j < 2) enqueueflipface(newfront, flipque);
12370 }
12371 }
12372
12373
12374 for (j = 0; j < n - 1; j++) {
12375 fnextself(tmpabtetlist[j]);
12376 }
12377 if (n > 4) {
12378 success = removeedgebytranNM(&tmpkey, n-1, tmpabtetlist,
12379 &(newtetlist[2]), NULL, NULL, flipque);
12380 } else {
12381 success = removeedgebyflip32(&tmpkey, tmpabtetlist,
12382 &(newtetlist[2]), flipque);
12383 }
12384
12385 for (j = 0; j < n - 1; j++) {
12386 tetrahedrondealloc(tmpabtetlist[j].tet);
12387 }
12388 if (success) {
12389
12390
12391
12392
12393
12394
12395 if (key != (REAL *) NULL) {
12396 *key = (tmpkey < cosmaxd ? tmpkey : cosmaxd);
12397 }
12398 return true;
12399 } else {
12400
12401 for (j = 0; j < n; j++) {
12402 oldfront = abtetlist[(i + j) % n];
12403 esymself(oldfront);
12404 enextfnextself(oldfront);
12405 sym(oldfront, adjfront);
12406 bond(oldfront, adjfront);
12407 if (checksubfaces) {
12408 tspivot(oldfront, checksh);
12409 if (checksh.sh != dummysh) {
12410 tsbond(oldfront, checksh);
12411 }
12412 }
12413 }
12414 for (j = 0; j < n; j++) {
12415 oldfront = abtetlist[(i + j) % n];
12416 esymself(oldfront);
12417 enext2fnextself(oldfront);
12418 sym(oldfront, adjfront);
12419 bond(oldfront, adjfront);
12420 if (checksubfaces) {
12421 tspivot(oldfront, checksh);
12422 if (checksh.sh != dummysh) {
12423 tsbond(oldfront, checksh);
12424 }
12425 }
12426 }
12427
12428 tetrahedrondealloc(newtetlist[0].tet);
12429 tetrahedrondealloc(newtetlist[1].tet);
12430
12431
12432 if (key && (tmpkey < *key)) {
12433 *key = tmpkey;
12434 return false;
12435 }
12436 }
12437 }
12438 }
12439 }
12440
12441 return false;
12442 }
12443
12445
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457
12458
12459
12460
12461
12462
12463
12464
12465
12466
12467
12468
12469
12470
12471
12472
12473
12474
12475
12476
12477
12478
12479
12480
12481
12482
12483
12485
12486 bool tetgenmesh::removeedgebycombNM(REAL *key, int n, triface *abtetlist,
12487 int *n1, triface *bftetlist, triface *newtetlist, queue *flipque)
12488 {
12489 triface tmpabtetlist[11];
12490 triface newfront, oldfront, adjfront;
12491 face checksh;
12492 point pa, pb, p[10];
12493 REAL ori, tmpkey, tmpkey2;
12494 REAL attrib, volume;
12495 bool doflip, success;
12496 int twice, count;
12497 int i, j, k, m;
12498
12499
12500 assert(n <= 10);
12501
12502
12503
12504 twice = 0;
12505 do {
12506
12507 pa = org(abtetlist[0]);
12508 pb = dest(abtetlist[0]);
12509
12510 for (i = 0; i < n; i++) {
12511
12512 for (j = 0; j < n; j++) {
12513 p[j] = apex(abtetlist[(i + j) % n]);
12514 }
12515
12516 ori = orient3d(pb, p[0], p[1], p[n - 1]);
12517 if ((ori > 0) && (key != (REAL *) NULL)) {
12518
12519
12520
12521 tetalldihedral(pb, p[0], p[n - 1], p[1], NULL, &tmpkey, NULL);
12522 if (tmpkey < *key) ori = 0.0;
12523 }
12524 if (ori <= 0.0) {
12525
12526 bftetlist[0] = abtetlist[i];
12527 enextself(bftetlist[0]);
12528 adjustedgering(bftetlist[0], CW);
12529 assert(apex(bftetlist[0]) == pa);
12530
12531 doflip = true;
12532 *n1 = 0;
12533 do {
12534
12535 if (*n1 == 10) break;
12536 if (checksubfaces) {
12537
12538 tspivot(bftetlist[*n1], checksh);
12539 if (checksh.sh != dummysh) {
12540 doflip = false; break;
12541 }
12542 }
12543
12544 fnext(bftetlist[*n1], bftetlist[(*n1) + 1]);
12545 (*n1)++;
12546 } while (apex(bftetlist[*n1]) != pa);
12547
12548 if (doflip) {
12549 success = false;
12550 tmpkey = -1.0;
12551 if (key != (REAL *) NULL) tmpkey = *key;
12552 m = 0;
12553 if (*n1 == 3) {
12554
12555 success = removeedgebyflip32(&tmpkey,bftetlist,newtetlist,flipque);
12556 m = 2;
12557 } else if ((*n1 > 3) && (*n1 < 7)) {
12558
12559 success = removeedgebytranNM(&tmpkey, *n1, bftetlist, newtetlist,
12560 p[1], p[n - 1], flipque);
12561
12562 m = ((*n1) - 2) * 2;
12563 } else {
12564 if (b->verbose > 1) {
12565 printf(" !! Unhandled case: n1 = %d.\n", *n1);
12566 }
12567 }
12568 if (success) {
12569
12570
12571
12572
12573
12574 setpointmark(pa, -pointmark(pa) - 1);
12575 setpointmark(pb, -pointmark(pb) - 1);
12576 assert(m > 0);
12577 for (j = 0; j < m; j++) {
12578 tmpabtetlist[0] = newtetlist[j];
12579
12580 count = 0;
12581 for (k = 0; k < 4; k++) {
12582 if (pointmark((point)(tmpabtetlist[0].tet[4+k])) < 0) count++;
12583 }
12584 if (count == 2) {
12585
12586 for (tmpabtetlist[0].loc = 0; tmpabtetlist[0].loc < 4;
12587 tmpabtetlist[0].loc++) {
12588 if ((oppo(tmpabtetlist[0]) != pa) &&
12589 (oppo(tmpabtetlist[0]) != pb)) break;
12590 }
12591
12592 assert(tmpabtetlist[0].loc < 4);
12593 findedge(&(tmpabtetlist[0]), pa, pb);
12594 break;
12595 }
12596 }
12597 assert(j < m);
12598
12599 newtetlist[j] = newtetlist[m - 1];
12600 setpointmark(pa, -(pointmark(pa) + 1));
12601 setpointmark(pb, -(pointmark(pb) + 1));
12602
12603 adjustedgering(tmpabtetlist[0], CCW);
12604 if (org(tmpabtetlist[0]) != pa) {
12605 fnextself(tmpabtetlist[0]);
12606 esymself(tmpabtetlist[0]);
12607 }
12608 #ifdef SELF_CHECK
12609
12610 assert(org(tmpabtetlist[0]) == pa);
12611 assert(dest(tmpabtetlist[0]) == pb);
12612 assert(apex(tmpabtetlist[0]) == p[n - 1]);
12613 assert(oppo(tmpabtetlist[0]) == p[1]);
12614 #endif // SELF_CHECK
12615
12616 for (j = 1; j < n - 1; j++) {
12617 maketetrahedron(&(tmpabtetlist[j]));
12618 setorg(tmpabtetlist[j], pa);
12619 setdest(tmpabtetlist[j], pb);
12620 setapex(tmpabtetlist[j], p[j]);
12621 setoppo(tmpabtetlist[j], p[j + 1]);
12622 }
12623
12624 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12625 attrib = elemattribute(abtetlist[0].tet, j);
12626 for (k = 0; k < n - 1; k++) {
12627 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12628 }
12629 }
12630
12631 if (b->varvolume && !b->refine) {
12632 volume = volumebound(abtetlist[0].tet);
12633 for (k = 0; k < n - 1; k++) {
12634 setvolumebound(tmpabtetlist[k].tet, volume);
12635 }
12636 }
12637
12638 for (j = 0; j < n - 1; j++) {
12639 fnext(tmpabtetlist[j], newfront);
12640 bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]);
12641 }
12642
12643
12644
12645
12646
12647
12648 for (j = 2; j < n; j++) {
12649
12650 oldfront = abtetlist[(i + j) % n];
12651 esymself(oldfront);
12652 enextfnextself(oldfront);
12653
12654 sym(oldfront, adjfront);
12655
12656
12657 enext2fnext(tmpabtetlist[j - 1], newfront);
12658 bond(newfront, adjfront);
12659 if (checksubfaces) {
12660 tspivot(oldfront, checksh);
12661 if (checksh.sh != dummysh) {
12662 tsbond(newfront, checksh);
12663 }
12664 }
12665 }
12666 for (j = 2; j < n; j++) {
12667
12668 oldfront = abtetlist[(i + j) % n];
12669 esymself(oldfront);
12670 enext2fnextself(oldfront);
12671
12672 sym(oldfront, adjfront);
12673
12674
12675 enextfnext(tmpabtetlist[j - 1], newfront);
12676 bond(newfront, adjfront);
12677 if (checksubfaces) {
12678 tspivot(oldfront, checksh);
12679 if (checksh.sh != dummysh) {
12680 tsbond(newfront, checksh);
12681 }
12682 }
12683 }
12684
12685
12686 for (j = 0; j < n - 1; j++) {
12687 fnextself(tmpabtetlist[j]);
12688 }
12689 tmpkey2 = -1;
12690 if (key) tmpkey2 = *key;
12691 if ((n - 1) == 3) {
12692 success = removeedgebyflip32(&tmpkey2, tmpabtetlist,
12693 &(newtetlist[m - 1]), flipque);
12694 } else {
12695 success = removeedgebytranNM(&tmpkey2, n - 1, tmpabtetlist,
12696 &(newtetlist[m - 1]), NULL, NULL, flipque);
12697 }
12698
12699 for (j = 0; j < n - 1; j++) {
12700 tetrahedrondealloc(tmpabtetlist[j].tet);
12701 }
12702 if (success) {
12703
12704
12705
12706
12707
12708
12709 if (key != (REAL *) NULL) {
12710 *key = tmpkey2 < tmpkey ? tmpkey2 : tmpkey;
12711 }
12712 return true;
12713 } else {
12714
12715 for (j = 0; j < n; j++) {
12716 oldfront = abtetlist[(i + j) % n];
12717 esymself(oldfront);
12718 enextfnextself(oldfront);
12719 sym(oldfront, adjfront);
12720 bond(oldfront, adjfront);
12721 if (checksubfaces) {
12722 tspivot(oldfront, checksh);
12723 if (checksh.sh != dummysh) {
12724 tsbond(oldfront, checksh);
12725 }
12726 }
12727 }
12728 for (j = 0; j < n; j++) {
12729 oldfront = abtetlist[(i + j) % n];
12730 esymself(oldfront);
12731 enext2fnextself(oldfront);
12732 sym(oldfront, adjfront);
12733 bond(oldfront, adjfront);
12734 if (checksubfaces) {
12735 tspivot(oldfront, checksh);
12736 if (checksh.sh != dummysh) {
12737 tsbond(oldfront, checksh);
12738 }
12739 }
12740 }
12741
12742 for (j = 0; j < *n1; j++) {
12743 oldfront = bftetlist[j];
12744 esymself(oldfront);
12745 enextfnextself(oldfront);
12746 sym(oldfront, adjfront);
12747 bond(oldfront, adjfront);
12748 if (checksubfaces) {
12749 tspivot(oldfront, checksh);
12750 if (checksh.sh != dummysh) {
12751 tsbond(oldfront, checksh);
12752 }
12753 }
12754 }
12755 for (j = 0; j < *n1; j++) {
12756 oldfront = bftetlist[j];
12757 esymself(oldfront);
12758 enext2fnextself(oldfront);
12759 sym(oldfront, adjfront);
12760 bond(oldfront, adjfront);
12761 if (checksubfaces) {
12762 tspivot(oldfront, checksh);
12763 if (checksh.sh != dummysh) {
12764 tsbond(oldfront, checksh);
12765 }
12766 }
12767 }
12768
12769
12770 for (j = 0; j < m - 1; j++) {
12771 tetrahedrondealloc(newtetlist[j].tet);
12772 }
12773 }
12774 }
12775 }
12776 }
12777 }
12778
12779 for (i = 0; i < n; i++) newtetlist[i] = abtetlist[i];
12780 for (i = 0; i < n; i++) {
12781 oldfront = newtetlist[n - i - 1];
12782 esymself(oldfront);
12783 fnextself(oldfront);
12784 abtetlist[i] = oldfront;
12785 }
12786 twice++;
12787 } while (twice < 2);
12788
12789 return false;
12790 }
12791
12793
12794
12795
12796
12797
12798
12799
12800
12801
12802
12803
12804
12805
12807
12808 void tetgenmesh::splittetrahedron(point newpoint, triface* splittet,
12809 queue* flipqueue)
12810 {
12811 triface oldabd, oldbcd, oldcad;
12812 triface abdcasing, bcdcasing, cadcasing;
12813 face abdsh, bcdsh, cadsh;
12814 triface abcv, badv, cbdv, acdv;
12815 triface worktet;
12816 face abseg, bcseg, caseg;
12817 face adseg, bdseg, cdseg;
12818 point pa, pb, pc, pd;
12819 REAL attrib, volume;
12820 int i;
12821
12822 abcv = *splittet;
12823 abcv.ver = 0;
12824
12825 pa = org(abcv);
12826 pb = dest(abcv);
12827 pc = apex(abcv);
12828 pd = oppo(abcv);
12829
12830 if (b->verbose > 1) {
12831 printf(" Inserting point %d in tetrahedron (%d, %d, %d, %d).\n",
12832 pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc),
12833 pointmark(pd));
12834 }
12835
12836 fnext(abcv, oldabd);
12837 enextfnext(abcv, oldbcd);
12838 enext2fnext(abcv, oldcad);
12839 sym(oldabd, abdcasing);
12840 sym(oldbcd, bcdcasing);
12841 sym(oldcad, cadcasing);
12842 maketetrahedron(&badv);
12843 maketetrahedron(&cbdv);
12844 maketetrahedron(&acdv);
12845
12846
12847 setorg (badv, pb);
12848 setdest(badv, pa);
12849 setapex(badv, pd);
12850 setoppo(badv, newpoint);
12851
12852 setorg (cbdv, pc);
12853 setdest(cbdv, pb);
12854 setapex(cbdv, pd);
12855 setoppo(cbdv, newpoint);
12856
12857 setorg (acdv, pa);
12858 setdest(acdv, pc);
12859 setapex(acdv, pd);
12860 setoppo(acdv, newpoint);
12861
12862 setoppo(abcv, newpoint);
12863
12864
12865 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12866 attrib = elemattribute(abcv.tet, i);
12867 setelemattribute(badv.tet, i, attrib);
12868 setelemattribute(cbdv.tet, i, attrib);
12869 setelemattribute(acdv.tet, i, attrib);
12870 }
12871
12872 if (b->varvolume) {
12873 volume = volumebound(abcv.tet);
12874 setvolumebound(badv.tet, volume);
12875 setvolumebound(cbdv.tet, volume);
12876 setvolumebound(acdv.tet, volume);
12877 }
12878
12879
12880 bond(badv, abdcasing);
12881 bond(cbdv, bcdcasing);
12882 bond(acdv, cadcasing);
12883
12884 if (checksubfaces) {
12885 tspivot(oldabd, abdsh);
12886 if (abdsh.sh != dummysh) {
12887 tsdissolve(oldabd);
12888 tsbond(badv, abdsh);
12889 }
12890 tspivot(oldbcd, bcdsh);
12891 if (bcdsh.sh != dummysh) {
12892 tsdissolve(oldbcd);
12893 tsbond(cbdv, bcdsh);
12894 }
12895 tspivot(oldcad, cadsh);
12896 if (cadsh.sh != dummysh) {
12897 tsdissolve(oldcad);
12898 tsbond(acdv, cadsh);
12899 }
12900 } else if (checksubsegs) {
12901 tsspivot1(abcv, abseg);
12902 if (abseg.sh != dummysh) {
12903 tssbond1(badv, abseg);
12904 }
12905 enext(abcv, worktet);
12906 tsspivot1(worktet, bcseg);
12907 if (bcseg.sh != dummysh) {
12908 tssbond1(cbdv, bcseg);
12909 }
12910 enext2(abcv, worktet);
12911 tsspivot1(worktet, caseg);
12912 if (caseg.sh != dummysh) {
12913 tssbond1(acdv, caseg);
12914 }
12915 fnext(abcv, worktet);
12916 enext2self(worktet);
12917 tsspivot1(worktet, adseg);
12918 if (adseg.sh != dummysh) {
12919 tssdissolve1(worktet);
12920 enext(badv, worktet);
12921 tssbond1(worktet, adseg);
12922 enext2(acdv, worktet);
12923 tssbond1(worktet, adseg);
12924 }
12925 enextfnext(abcv, worktet);
12926 enext2self(worktet);
12927 tsspivot1(worktet, bdseg);
12928 if (bdseg.sh != dummysh) {
12929 tssdissolve1(worktet);
12930 enext(cbdv, worktet);
12931 tssbond1(worktet, bdseg);
12932 enext2(badv, worktet);
12933 tssbond1(worktet, bdseg);
12934 }
12935 enext2fnext(abcv, worktet);
12936 enext2self(worktet);
12937 tsspivot1(worktet, cdseg);
12938 if (cdseg.sh != dummysh) {
12939 tssdissolve1(worktet);
12940 enext(acdv, worktet);
12941 tssbond1(worktet, cdseg);
12942 enext2(cbdv, worktet);
12943 tssbond1(worktet, cdseg);
12944 }
12945 }
12946 badv.loc = 3;
12947 cbdv.loc = 2;
12948 bond(badv, cbdv);
12949 cbdv.loc = 3;
12950 acdv.loc = 2;
12951 bond(cbdv, acdv);
12952 acdv.loc = 3;
12953 badv.loc = 2;
12954 bond(acdv, badv);
12955 badv.loc = 1;
12956 bond(badv, oldabd);
12957 cbdv.loc = 1;
12958 bond(cbdv, oldbcd);
12959 acdv.loc = 1;
12960 bond(acdv, oldcad);
12961
12962 badv.loc = 0;
12963 cbdv.loc = 0;
12964 acdv.loc = 0;
12965 if (b->verbose > 3) {
12966 printf(" Updating abcv ");
12967 printtet(&abcv);
12968 printf(" Creating badv ");
12969 printtet(&badv);
12970 printf(" Creating cbdv ");
12971 printtet(&cbdv);
12972 printf(" Creating acdv ");
12973 printtet(&acdv);
12974 }
12975
12976 if (flipqueue != (queue *) NULL) {
12977 enqueueflipface(abcv, flipqueue);
12978 enqueueflipface(badv, flipqueue);
12979 enqueueflipface(cbdv, flipqueue);
12980 enqueueflipface(acdv, flipqueue);
12981 }
12982
12983
12984 recenttet = abcv;
12985
12986 *splittet = abcv;
12987 }
12988
12990
12991
12992
12993
12994
12995
12996
12997
12998
12999
13000
13001
13003
13004 void tetgenmesh::unsplittetrahedron(triface* splittet)
13005 {
13006 triface abcv, badv, cbdv, acdv;
13007 triface oldabv, oldbcv, oldcav;
13008 triface badcasing, cbdcasing, acdcasing;
13009 face badsh, cbdsh, acdsh;
13010
13011 abcv = *splittet;
13012 adjustedgering(abcv, CCW);
13013 fnext(abcv, oldabv);
13014 fnext(oldabv, badv);
13015 esymself(badv);
13016 enextfnext(abcv, oldbcv);
13017 fnext(oldbcv, cbdv);
13018 esymself(cbdv);
13019 enext2fnext(abcv, oldcav);
13020 fnext(oldcav, acdv);
13021 esymself(acdv);
13022
13023 if (b->verbose > 1) {
13024 printf(" Removing point %d in tetrahedron (%d, %d, %d, %d).\n",
13025 pointmark(oppo(abcv)), pointmark(org(abcv)), pointmark(dest(abcv)),
13026 pointmark(apex(abcv)), pointmark(apex(badv)));
13027 }
13028
13029 sym(badv, badcasing);
13030 tspivot(badv, badsh);
13031 sym(cbdv, cbdcasing);
13032 tspivot(cbdv, cbdsh);
13033 sym(acdv, acdcasing);
13034 tspivot(acdv, acdsh);
13035
13036
13037 setoppo(abcv, apex(badv));
13038 bond(oldabv, badcasing);
13039 if (badsh.sh != dummysh) {
13040 tsbond(oldabv, badsh);
13041 }
13042 bond(oldbcv, cbdcasing);
13043 if (cbdsh.sh != dummysh) {
13044 tsbond(oldbcv, cbdsh);
13045 }
13046 bond(oldcav, acdcasing);
13047 if (acdsh.sh != dummysh) {
13048 tsbond(oldcav, acdsh);
13049 }
13050
13051
13052 tetrahedrondealloc(badv.tet);
13053 tetrahedrondealloc(cbdv.tet);
13054 tetrahedrondealloc(acdv.tet);
13055 }
13056
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13069
13070
13071
13072
13073
13074
13075
13077
13078 void tetgenmesh::splittetface(point newpoint, triface* splittet,
13079 queue* flipqueue)
13080 {
13081 triface abcd, bace;
13082 triface oldbcd, oldcad, oldace, oldcbe;
13083 triface bcdcasing, cadcasing, acecasing, cbecasing;
13084 face abcsh, bcdsh, cadsh, acesh, cbesh;
13085 triface abvd, bcvd, cavd, bave, cbve, acve;
13086 triface worktet;
13087 face bcseg, caseg;
13088 face adseg, bdseg, cdseg;
13089 face aeseg, beseg, ceseg;
13090 point pa, pb, pc, pd, pe;
13091 REAL attrib, volume;
13092 bool mirrorflag;
13093 int i;
13094
13095 abcd = *splittet;
13096
13097 adjustedgering(abcd, CCW);
13098 pa = org(abcd);
13099 pb = dest(abcd);
13100 pc = apex(abcd);
13101 pd = oppo(abcd);
13102 pe = (point) NULL;
13103
13104 mirrorflag = issymexist(&abcd);
13105 if (mirrorflag) {
13106
13107 sym(abcd, bace);
13108 findedge(&bace, dest(abcd), org(abcd));
13109 pe = oppo(bace);
13110 }
13111 if (checksubfaces) {
13112
13113 tspivot(abcd, abcsh);
13114 if (abcsh.sh != dummysh) {
13115
13116 findedge(&abcsh, org(abcd), dest(abcd));
13117 }
13118 }
13119
13120 if (b->verbose > 1) {
13121 printf(" Inserting point %d on face (%d, %d, %d).\n", pointmark(newpoint),
13122 pointmark(pa), pointmark(pb), pointmark(pc));
13123 }
13124
13125
13126 enextfnext(abcd, oldbcd);
13127 enext2fnext(abcd, oldcad);
13128 sym(oldbcd, bcdcasing);
13129 sym(oldcad, cadcasing);
13130
13131 maketetrahedron(&bcvd);
13132 maketetrahedron(&cavd);
13133 if (mirrorflag) {
13134
13135 enextfnext(bace, oldace);
13136 enext2fnext(bace, oldcbe);
13137 sym(oldace, acecasing);
13138 sym(oldcbe, cbecasing);
13139
13140 maketetrahedron(&acve);
13141 maketetrahedron(&cbve);
13142 } else {
13143
13144 hullsize += 2;
13145 }
13146
13147
13148 abvd = abcd;
13149 setapex(abvd, newpoint);
13150 setorg (bcvd, pb);
13151 setdest(bcvd, pc);
13152 setapex(bcvd, newpoint);
13153 setoppo(bcvd, pd);
13154 setorg (cavd, pc);
13155 setdest(cavd, pa);
13156 setapex(cavd, newpoint);
13157 setoppo(cavd, pd);
13158
13159 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13160 attrib = elemattribute(abvd.tet, i);
13161 setelemattribute(bcvd.tet, i, attrib);
13162 setelemattribute(cavd.tet, i, attrib);
13163 }
13164 if (b->varvolume) {
13165
13166 volume = volumebound(abvd.tet);
13167 setvolumebound(bcvd.tet, volume);
13168 setvolumebound(cavd.tet, volume);
13169 }
13170 if (mirrorflag) {
13171 bave = bace;
13172 setapex(bave, newpoint);
13173 setorg (acve, pa);
13174 setdest(acve, pc);
13175 setapex(acve, newpoint);
13176 setoppo(acve, pe);
13177 setorg (cbve, pc);
13178 setdest(cbve, pb);
13179 setapex(cbve, newpoint);
13180 setoppo(cbve, pe);
13181
13182 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13183 attrib = elemattribute(bave.tet, i);
13184 setelemattribute(acve.tet, i, attrib);
13185 setelemattribute(cbve.tet, i, attrib);
13186 }
13187 if (b->varvolume) {
13188
13189 volume = volumebound(bave.tet);
13190 setvolumebound(acve.tet, volume);
13191 setvolumebound(cbve.tet, volume);
13192 }
13193 }
13194
13195
13196 bcvd.loc = 1;
13197 bond(bcvd, bcdcasing);
13198 cavd.loc = 1;
13199 bond(cavd, cadcasing);
13200 bcvd.loc = 3;
13201 bond(bcvd, oldbcd);
13202 cavd.loc = 2;
13203 bond(cavd, oldcad);
13204 bcvd.loc = 2;
13205 cavd.loc = 3;
13206 bond(bcvd, cavd);
13207 if (mirrorflag) {
13208 acve.loc = 1;
13209 bond(acve, acecasing);
13210 cbve.loc = 1;
13211 bond(cbve, cbecasing);
13212 acve.loc = 3;
13213 bond(acve, oldace);
13214 cbve.loc = 2;
13215 bond(cbve, oldcbe);
13216 acve.loc = 2;
13217 cbve.loc = 3;
13218 bond(acve, cbve);
13219
13220 bcvd.loc = 0;
13221 cbve.loc = 0;
13222 bond(bcvd, cbve);
13223 cavd.loc = 0;
13224 acve.loc = 0;
13225 bond(cavd, acve);
13226 }
13227
13228
13229 if (checksubfaces) {
13230 tspivot(oldbcd, bcdsh);
13231 if (bcdsh.sh != dummysh) {
13232 tsdissolve(oldbcd);
13233 bcvd.loc = 1;
13234 tsbond(bcvd, bcdsh);
13235 }
13236 tspivot(oldcad, cadsh);
13237 if (cadsh.sh != dummysh) {
13238 tsdissolve(oldcad);
13239 cavd.loc = 1;
13240 tsbond(cavd, cadsh);
13241 }
13242 if (mirrorflag) {
13243 tspivot(oldace, acesh);
13244 if (acesh.sh != dummysh) {
13245 tsdissolve(oldace);
13246 acve.loc = 1;
13247 tsbond(acve, acesh);
13248 }
13249 tspivot(oldcbe, cbesh);
13250 if (cbesh.sh != dummysh) {
13251 tsdissolve(oldcbe);
13252 cbve.loc = 1;
13253 tsbond(cbve, cbesh);
13254 }
13255 }
13256
13257 if (abcsh.sh != dummysh) {
13258
13259 splitsubface(newpoint, &abcsh, (queue *) NULL);
13260 }
13261 } else if (checksubsegs) {
13262
13263 bcvd.loc = bcvd.ver = 0;
13264 cavd.loc = cavd.ver = 0;
13265 if (mirrorflag) {
13266
13267 cbve.loc = cbve.ver = 0;
13268 acve.loc = acve.ver = 0;
13269 }
13270 enext(abvd, worktet);
13271 tsspivot1(worktet, bcseg);
13272 if (bcseg.sh != dummysh) {
13273 tssdissolve1(worktet);
13274 tssbond1(bcvd, bcseg);
13275 if (mirrorflag) {
13276 enext2(bave, worktet);
13277 tssdissolve1(worktet);
13278 tssbond1(cbve, bcseg);
13279 }
13280 }
13281 enext2(abvd, worktet);
13282 tsspivot1(worktet, caseg);
13283 if (caseg.sh != dummysh) {
13284 tssdissolve1(worktet);
13285 tssbond1(cavd, caseg);
13286 if (mirrorflag) {
13287 enext(bave, worktet);
13288 tssdissolve1(worktet);
13289 tssbond1(acve, caseg);
13290 }
13291 }
13292 fnext(abvd, worktet);
13293 enext2self(worktet);
13294 tsspivot1(worktet, adseg);
13295 if (adseg.sh != dummysh) {
13296 fnext(cavd, worktet);
13297 enextself(worktet);
13298 tssbond1(worktet, adseg);
13299 }
13300 fnext(abvd, worktet);
13301 enextself(worktet);
13302 tsspivot1(worktet, bdseg);
13303 if (bdseg.sh != dummysh) {
13304 fnext(bcvd, worktet);
13305 enext2self(worktet);
13306 tssbond1(worktet, bdseg);
13307 }
13308 enextfnext(abvd, worktet);
13309 enextself(worktet);
13310 tsspivot1(worktet, cdseg);
13311 if (cdseg.sh != dummysh) {
13312 tssdissolve1(worktet);
13313 fnext(bcvd, worktet);
13314 enextself(worktet);
13315 tssbond1(worktet, cdseg);
13316 fnext(cavd, worktet);
13317 enext2self(worktet);
13318 tssbond1(worktet, cdseg);
13319 }
13320 if (mirrorflag) {
13321 fnext(bave, worktet);
13322 enextself(worktet);
13323 tsspivot1(worktet, aeseg);
13324 if (aeseg.sh != dummysh) {
13325 fnext(acve, worktet);
13326 enext2self(worktet);
13327 tssbond1(worktet, aeseg);
13328 }
13329 fnext(bave, worktet);
13330 enext2self(worktet);
13331 tsspivot1(worktet, beseg);
13332 if (beseg.sh != dummysh) {
13333 fnext(cbve, worktet);
13334 enextself(worktet);
13335 tssbond1(worktet, beseg);
13336 }
13337 enextfnext(bave, worktet);
13338 enextself(worktet);
13339 tsspivot1(worktet, ceseg);
13340 if (ceseg.sh != dummysh) {
13341 tssdissolve1(worktet);
13342 fnext(cbve, worktet);
13343 enext2self(worktet);
13344 tssbond1(worktet, ceseg);
13345 fnext(acve, worktet);
13346 enextself(worktet);
13347 tssbond1(worktet, ceseg);
13348 }
13349 }
13350 }
13351
13352
13353 recenttet = abvd;
13354
13355 *splittet = abvd;
13356
13357 bcvd.loc = 0;
13358 cavd.loc = 0;
13359 if (mirrorflag) {
13360 cbve.loc = 0;
13361 acve.loc = 0;
13362 }
13363 if (b->verbose > 3) {
13364 printf(" Updating abvd ");
13365 printtet(&abvd);
13366 printf(" Creating bcvd ");
13367 printtet(&bcvd);
13368 printf(" Creating cavd ");
13369 printtet(&cavd);
13370 if (mirrorflag) {
13371 printf(" Updating bave ");
13372 printtet(&bave);
13373 printf(" Creating cbve ");
13374 printtet(&cbve);
13375 printf(" Creating acve ");
13376 printtet(&acve);
13377 }
13378 }
13379
13380 if (flipqueue != (queue *) NULL) {
13381 fnextself(abvd);
13382 enqueueflipface(abvd, flipqueue);
13383 fnextself(bcvd);
13384 enqueueflipface(bcvd, flipqueue);
13385 fnextself(cavd);
13386 enqueueflipface(cavd, flipqueue);
13387 if (mirrorflag) {
13388 fnextself(bave);
13389 enqueueflipface(bave, flipqueue);
13390 fnextself(cbve);
13391 enqueueflipface(cbve, flipqueue);
13392 fnextself(acve);
13393 enqueueflipface(acve, flipqueue);
13394 }
13395 }
13396 }
13397
13399
13400
13401
13402
13403
13404
13405
13406
13407
13408
13409
13410
13411
13412
13413
13414
13416
13417 void tetgenmesh::unsplittetface(triface* splittet)
13418 {
13419 triface abvd, bcvd, cavd, bave, cbve, acve;
13420 triface oldbvd, oldvad, oldvbe, oldave;
13421 triface bcdcasing, cadcasing, cbecasing, acecasing;
13422 face bcdsh, cadsh, cbesh, acesh;
13423 face abvsh;
13424 bool mirrorflag;
13425
13426 abvd = *splittet;
13427 adjustedgering(abvd, CCW);
13428 enextfnext(abvd, oldbvd);
13429 fnext(oldbvd, bcvd);
13430 esymself(bcvd);
13431 enextself(bcvd);
13432 enext2fnext(abvd, oldvad);
13433 fnext(oldvad, cavd);
13434 esymself(cavd);
13435 enext2self(cavd);
13436
13437 sym(abvd, bave);
13438 mirrorflag = bave.tet != dummytet;
13439 if (mirrorflag) {
13440 findedge(&bave, dest(abvd), org(abvd));
13441 enextfnext(bave, oldave);
13442 fnext(oldave, acve);
13443 esymself(acve);
13444 enextself(acve);
13445 enext2fnext(bave, oldvbe);
13446 fnext(oldvbe, cbve);
13447 esymself(cbve);
13448 enext2self(cbve);
13449 } else {
13450
13451 hullsize -= 2;
13452 }
13453
13454 tspivot(abvd, abvsh);
13455 if (abvsh.sh != dummysh) {
13456
13457 findedge(&abvsh, org(abvd), dest(abvd));
13458 }
13459
13460 if (b->verbose > 1) {
13461 printf(" Removing point %d on face (%d, %d, %d).\n",
13462 pointmark(apex(abvd)), pointmark(org(abvd)), pointmark(dest(abvd)),
13463 pointmark(dest(bcvd)));
13464 }
13465
13466 fnextself(bcvd);
13467 sym(bcvd, bcdcasing);
13468 tspivot(bcvd, bcdsh);
13469 fnextself(cavd);
13470 sym(cavd, cadcasing);
13471 tspivot(cavd, cadsh);
13472 if (mirrorflag) {
13473 fnextself(acve);
13474 sym(acve, acecasing);
13475 tspivot(acve, acesh);
13476 fnextself(cbve);
13477 sym(cbve, cbecasing);
13478 tspivot(cbve, cbesh);
13479 }
13480
13481
13482 setapex(abvd, dest(bcvd));
13483 bond(oldbvd, bcdcasing);
13484 if (bcdsh.sh != dummysh) {
13485 tsbond(oldbvd, bcdsh);
13486 }
13487 bond(oldvad, cadcasing);
13488 if (cadsh.sh != dummysh) {
13489 tsbond(oldvad, cadsh);
13490 }
13491 if (mirrorflag) {
13492
13493 setapex(bave, dest(acve));
13494 bond(oldave, acecasing);
13495 if (acesh.sh != dummysh) {
13496 tsbond(oldave, acesh);
13497 }
13498 bond(oldvbe, cbecasing);
13499 if (cbesh.sh != dummysh) {
13500 tsbond(oldvbe, cbesh);
13501 }
13502 }
13503
13504
13505 if (abvsh.sh != dummysh) {
13506 unsplitsubface(&abvsh);
13507 }
13508
13509
13510 tetrahedrondealloc(bcvd.tet);
13511 tetrahedrondealloc(cavd.tet);
13512 if (mirrorflag) {
13513 tetrahedrondealloc(acve.tet);
13514 tetrahedrondealloc(cbve.tet);
13515 }
13516 }
13517
13519
13520
13521
13522
13523
13524
13525
13526
13527
13528
13529
13530
13531
13532
13533
13534
13535
13536
13537
13538
13539
13541
13542 void tetgenmesh::splitsubface(point newpoint, face* splitface,
13543 queue* flipqueue)
13544 {
13545 triface abvd, bcvd, cavd, bave, cbve, acve;
13546 face abc, oldbc, oldca, bc, ca, spinsh;
13547 face bccasin, bccasout, cacasin, cacasout;
13548 face abv, bcv, cav;
13549 point pa, pb, pc;
13550
13551 abc = *splitface;
13552
13553 adjustedgering(abc, CCW);
13554 pa = sorg(abc);
13555 pb = sdest(abc);
13556 pc = sapex(abc);
13557
13558 if (b->verbose > 1) {
13559 printf(" Inserting point %d on subface (%d, %d, %d).\n",
13560 pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc));
13561 }
13562
13563
13564
13565 senext(abc, oldbc);
13566 senext2(abc, oldca);
13567 spivot(oldbc, bccasout);
13568 sspivot(oldbc, bc);
13569 if (bc.sh != dummysh) {
13570 if (oldbc.sh != bccasout.sh) {
13571
13572 spinsh = bccasout;
13573 do {
13574 bccasin = spinsh;
13575 spivotself(spinsh);
13576 } while (spinsh.sh != oldbc.sh);
13577 } else {
13578 bccasout.sh = dummysh;
13579 }
13580 ssdissolve(oldbc);
13581 }
13582 spivot(oldca, cacasout);
13583 sspivot(oldca, ca);
13584 if (ca.sh != dummysh) {
13585 if (oldca.sh != cacasout.sh) {
13586
13587 spinsh = cacasout;
13588 do {
13589 cacasin = spinsh;
13590 spivotself(spinsh);
13591 } while (spinsh.sh != oldca.sh);
13592 } else {
13593 cacasout.sh = dummysh;
13594 }
13595 ssdissolve(oldca);
13596 }
13597
13598 makeshellface(subfaces, &bcv);
13599 makeshellface(subfaces, &cav);
13600
13601
13602 abv = abc;
13603 setsapex(abv, newpoint);
13604 setsorg(bcv, pb);
13605 setsdest(bcv, pc);
13606 setsapex(bcv, newpoint);
13607 setsorg(cav, pc);
13608 setsdest(cav, pa);
13609 setsapex(cav, newpoint);
13610 if (b->quality && varconstraint) {
13611
13612 setareabound(bcv, areabound(abv));
13613 setareabound(cav, areabound(abv));
13614 }
13615
13616 setshellmark(bcv, shellmark(abv));
13617 setshellmark(cav, shellmark(abv));
13618
13619 setshelltype(bcv, shelltype(abv));
13620 setshelltype(cav, shelltype(abv));
13621 if (checkpbcs) {
13622
13623 setshellpbcgroup(bcv, shellpbcgroup(abv));
13624 setshellpbcgroup(cav, shellpbcgroup(abv));
13625 }
13626
13627 if (bc.sh != dummysh) {
13628 if (bccasout.sh != dummysh) {
13629 sbond1(bccasin, bcv);
13630 sbond1(bcv, bccasout);
13631 } else {
13632
13633 sbond(bcv, bcv);
13634 }
13635 ssbond(bcv, bc);
13636 } else {
13637 sbond(bcv, bccasout);
13638 }
13639 if (ca.sh != dummysh) {
13640 if (cacasout.sh != dummysh) {
13641 sbond1(cacasin, cav);
13642 sbond1(cav, cacasout);
13643 } else {
13644
13645 sbond(cav, cav);
13646 }
13647 ssbond(cav, ca);
13648 } else {
13649 sbond(cav, cacasout);
13650 }
13651 senext2self(bcv);
13652 sbond(bcv, oldbc);
13653 senextself(cav);
13654 sbond(cav, oldca);
13655 senext2self(bcv);
13656 senextself(cav);
13657 sbond(bcv, cav);
13658
13659
13660 stpivot(abv, abvd);
13661 if (abvd.tet != dummytet) {
13662
13663 findedge(&abvd, sorg(abv), sdest(abv));
13664 enextfnext(abvd, bcvd);
13665 #ifdef SELF_CHECK
13666 assert(bcvd.tet != dummytet);
13667 #endif
13668 fnextself(bcvd);
13669 enext2fnext(abvd, cavd);
13670 #ifdef SELF_CHECK
13671 assert(cavd.tet != dummytet);
13672 #endif
13673 fnextself(cavd);
13674
13675 tsbond(bcvd, bcv);
13676 tsbond(cavd, cav);
13677 }
13678
13679 sesymself(abv);
13680 stpivot(abv, bave);
13681 if (bave.tet != dummytet) {
13682 sesymself(bcv);
13683 sesymself(cav);
13684
13685 findedge(&bave, sorg(abv), sdest(abv));
13686 enextfnext(bave, acve);
13687 #ifdef SELF_CHECK
13688 assert(acve.tet != dummytet);
13689 #endif
13690 fnextself(acve);
13691 enext2fnext(bave, cbve);
13692 #ifdef SELF_CHECK
13693 assert(cbve.tet != dummytet);
13694 #endif
13695 fnextself(cbve);
13696
13697 tsbond(acve, cav);
13698 tsbond(cbve, bcv);
13699 }
13700
13701 bcv.shver = 0;
13702 cav.shver = 0;
13703 if (b->verbose > 3) {
13704 printf(" Updating abv ");
13705 printsh(&abv);
13706 printf(" Creating bcv ");
13707 printsh(&bcv);
13708 printf(" Creating cav ");
13709 printsh(&cav);
13710 }
13711
13712 if (flipqueue != (queue *) NULL) {
13713 enqueueflipedge(abv, flipqueue);
13714 enqueueflipedge(bcv, flipqueue);
13715 enqueueflipedge(cav, flipqueue);
13716 }
13717
13718
13719 *splitface = abv;
13720 }
13721
13723
13724
13725
13726
13727
13728
13729
13730
13731
13732
13733
13734
13736
13737 void tetgenmesh::unsplitsubface(face* splitsh)
13738 {
13739 face abv, bcv, cav;
13740 face oldbv, oldva, bc, ca, spinsh;
13741 face bccasin, bccasout, cacasin, cacasout;
13742
13743 abv = *splitsh;
13744 senext(abv, oldbv);
13745 spivot(oldbv, bcv);
13746 if (sorg(bcv) != sdest(oldbv)) {
13747 sesymself(bcv);
13748 }
13749 senextself(bcv);
13750 senext2(abv, oldva);
13751 spivot(oldva, cav);
13752 if (sorg(cav) != sdest(oldva)) {
13753 sesymself(cav);
13754 }
13755 senext2self(cav);
13756
13757 if (b->verbose > 1) {
13758 printf(" Removing point %d on subface (%d, %d, %d).\n",
13759 pointmark(sapex(abv)), pointmark(sorg(abv)), pointmark(sdest(abv)),
13760 pointmark(sdest(bcv)));
13761 }
13762
13763 spivot(bcv, bccasout);
13764 sspivot(bcv, bc);
13765 if (bc.sh != dummysh) {
13766 if (bcv.sh != bccasout.sh) {
13767
13768 spinsh = bccasout;
13769 do {
13770 bccasin = spinsh;
13771 spivotself(spinsh);
13772 } while (spinsh.sh != bcv.sh);
13773 } else {
13774 bccasout.sh = dummysh;
13775 }
13776 }
13777 spivot(cav, cacasout);
13778 sspivot(cav, ca);
13779 if (ca.sh != dummysh) {
13780 if (cav.sh != cacasout.sh) {
13781
13782 spinsh = cacasout;
13783 do {
13784 cacasin = spinsh;
13785 spivotself(spinsh);
13786 } while (spinsh.sh != cav.sh);
13787 } else {
13788 cacasout.sh = dummysh;
13789 }
13790 }
13791
13792
13793 setsapex(abv, sdest(bcv));
13794 if (bc.sh != dummysh) {
13795 if (bccasout.sh != dummysh) {
13796 sbond1(bccasin, oldbv);
13797 sbond1(oldbv, bccasout);
13798 } else {
13799
13800 sbond(oldbv, oldbv);
13801 }
13802 ssbond(oldbv, bc);
13803 } else {
13804 sbond(oldbv, bccasout);
13805 }
13806 if (ca.sh != dummysh) {
13807 if (cacasout.sh != dummysh) {
13808 sbond1(cacasin, oldva);
13809 sbond1(oldva, cacasout);
13810 } else {
13811
13812 sbond(oldva, oldva);
13813 }
13814 ssbond(oldva, ca);
13815 } else {
13816 sbond(oldva, cacasout);
13817 }
13818
13819
13820 shellfacedealloc(subfaces, bcv.sh);
13821 shellfacedealloc(subfaces, cav.sh);
13822 }
13823
13825
13826
13827
13828
13829
13830
13831
13832
13833
13834
13835
13836
13837
13838
13839
13840
13841
13842
13843
13844
13845
13847
13848 void tetgenmesh::splittetedge(point newpoint, triface* splittet,
13849 queue* flipqueue)
13850 {
13851 triface *bots, *newtops;
13852 triface oldtop, topcasing;
13853 triface spintet, tmpbond0, tmpbond1;
13854 face abseg, splitsh, topsh, spinsh;
13855 triface worktet;
13856 face n1n2seg, n2vseg, n1vseg;
13857 point pa, pb, n1, n2;
13858 REAL attrib, volume;
13859 int wrapcount, hitbdry;
13860 int i, j;
13861
13862 if (checksubfaces) {
13863
13864 tsspivot(splittet, &abseg);
13865 if (abseg.sh != dummysh) {
13866 abseg.shver = 0;
13867
13868 if (org(*splittet) != sorg(abseg)) {
13869 esymself(*splittet);
13870 }
13871 }
13872 }
13873 spintet = *splittet;
13874 pa = org(spintet);
13875 pb = dest(spintet);
13876
13877 if (b->verbose > 1) {
13878 printf(" Inserting point %d on edge (%d, %d).\n",
13879 pointmark(newpoint), pointmark(pa), pointmark(pb));
13880 }
13881
13882
13883 n1 = apex(spintet);
13884 hitbdry = 0;
13885 wrapcount = 1;
13886 if (checksubfaces && abseg.sh != dummysh) {
13887
13888
13889
13890 while (true) {
13891 if (!fnextself(spintet)) {
13892
13893 hitbdry ++;
13894 tspivot(spintet, spinsh);
13895 #ifdef SELF_CHECK
13896 assert(spinsh.sh != dummysh);
13897 #endif
13898 findedge(&spinsh, pa, pb);
13899 sfnextself(spinsh);
13900 stpivot(spinsh, spintet);
13901 #ifdef SELF_CHECK
13902 assert(spintet.tet != dummytet);
13903 #endif
13904 findedge(&spintet, pa, pb);
13905
13906 *splittet = spintet;
13907
13908 hullsize += 2;
13909 }
13910 if (apex(spintet) == n1) break;
13911 wrapcount ++;
13912 }
13913 if (hitbdry > 0) {
13914 wrapcount -= hitbdry;
13915 }
13916 } else {
13917
13918
13919 splitsh.sh = dummysh;
13920 while (hitbdry < 2) {
13921 if (checksubfaces && splitsh.sh == dummysh) {
13922 tspivot(spintet, splitsh);
13923 }
13924 if (fnextself(spintet)) {
13925 if (apex(spintet) == n1) break;
13926 wrapcount++;
13927 } else {
13928 hitbdry ++;
13929 if (hitbdry < 2) {
13930 esym(*splittet, spintet);
13931 }
13932 }
13933 }
13934 if (hitbdry > 0) {
13935
13936 wrapcount -= 1;
13937
13938 esym(spintet, *splittet);
13939
13940 hullsize += 2;
13941 }
13942 }
13943
13944
13945 bots = new triface[wrapcount];
13946 newtops = new triface[wrapcount];
13947
13948 spintet = *splittet;
13949 for (i = 0; i < wrapcount; i++) {
13950
13951 enext2fnext(spintet, bots[i]);
13952 esymself(bots[i]);
13953
13954 maketetrahedron(&(newtops[i]));
13955
13956 fnextself(spintet);
13957 if (checksubfaces && abseg.sh != dummysh) {
13958 if (!issymexist(&spintet)) {
13959
13960 tspivot(spintet, spinsh);
13961 #ifdef SELF_CHECK
13962 assert(spinsh.sh != dummysh);
13963 #endif
13964 findedge(&spinsh, pa, pb);
13965 sfnextself(spinsh);
13966 stpivot(spinsh, spintet);
13967 #ifdef SELF_CHECK
13968 assert(spintet.tet != dummytet);
13969 #endif
13970 findedge(&spintet, pa, pb);
13971 }
13972 }
13973 }
13974
13975
13976 for (i = 0; i < wrapcount; i++) {
13977
13978 setoppo(bots[i], newpoint);
13979
13980 n1 = dest(bots[i]);
13981 n2 = apex(bots[i]);
13982
13983 setorg(newtops[i], pb);
13984 setdest(newtops[i], n2);
13985 setapex(newtops[i], n1);
13986 setoppo(newtops[i], newpoint);
13987
13988 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
13989 attrib = elemattribute(bots[i].tet, j);
13990 setelemattribute(newtops[i].tet, j, attrib);
13991 }
13992 if (b->varvolume) {
13993
13994 volume = volumebound(bots[i].tet);
13995 setvolumebound(newtops[i].tet, volume);
13996 }
13997 #ifdef SELF_CHECK
13998
13999
14000
14001
14002
14003
14004
14005
14006
14007 #endif
14008 }
14009
14010
14011 for (i = 0; i < wrapcount; i++) {
14012
14013 enextfnext(bots[i], oldtop);
14014 sym(oldtop, topcasing);
14015 bond(newtops[i], topcasing);
14016 if (checksubfaces) {
14017 tspivot(oldtop, topsh);
14018 if (topsh.sh != dummysh) {
14019 tsdissolve(oldtop);
14020 tsbond(newtops[i], topsh);
14021 }
14022 }
14023 enextfnext(newtops[i], tmpbond0);
14024 bond(oldtop, tmpbond0);
14025 }
14026
14027 fnext(newtops[0], tmpbond0);
14028 enext2fnext(bots[0], spintet);
14029 for (i = 1; i < wrapcount; i ++) {
14030 if (issymexist(&spintet)) {
14031 enext2fnext(newtops[i], tmpbond1);
14032 bond(tmpbond0, tmpbond1);
14033 }
14034 fnext(newtops[i], tmpbond0);
14035 enext2fnext(bots[i], spintet);
14036 }
14037
14038 if (issymexist(&spintet)) {
14039 enext2fnext(newtops[0], tmpbond1);
14040 bond(tmpbond0, tmpbond1);
14041 }
14042 if (checksubsegs) {
14043 for (i = 0; i < wrapcount; i++) {
14044 enextfnext(bots[i], worktet);
14045 tsspivot1(worktet, n1n2seg);
14046 if (n1n2seg.sh != dummysh) {
14047 enext(newtops[i], tmpbond0);
14048 tssbond1(tmpbond0, n1n2seg);
14049 }
14050 enextself(worktet);
14051 tsspivot1(worktet, n2vseg);
14052 if (n2vseg.sh != dummysh) {
14053 tssdissolve1(worktet);
14054 tssbond1(newtops[i], n2vseg);
14055 }
14056 enextself(worktet);
14057 tsspivot1(worktet, n1vseg);
14058 if (n1vseg.sh != dummysh) {
14059 tssdissolve1(worktet);
14060 enext2(newtops[i], tmpbond0);
14061 tssbond1(tmpbond0, n1vseg);
14062 }
14063 }
14064 }
14065
14066
14067 if (checksubfaces) {
14068 if (abseg.sh != dummysh) {
14069
14070 spivot(abseg, splitsh);
14071 #ifdef SELF_CHECK
14072 assert(splitsh.sh != dummysh);
14073 #endif
14074 }
14075 if (splitsh.sh != dummysh) {
14076
14077 findedge(&splitsh, pa, pb);
14078 splitsubedge(newpoint, &splitsh, (queue *) NULL);
14079 }
14080 }
14081
14082 if (b->verbose > 3) {
14083 for (i = 0; i < wrapcount; i++) {
14084 printf(" Updating bots[%i] ", i);
14085 printtet(&(bots[i]));
14086 printf(" Creating newtops[%i] ", i);
14087 printtet(&(newtops[i]));
14088 }
14089 }
14090
14091 if (flipqueue != (queue *) NULL) {
14092 for (i = 0; i < wrapcount; i++) {
14093 enqueueflipface(bots[i], flipqueue);
14094 enqueueflipface(newtops[i], flipqueue);
14095 }
14096 }
14097
14098
14099
14100 fnext(bots[0], spintet);
14101 esymself(spintet);
14102 enextself(spintet);
14103 *splittet = spintet;
14104
14105 delete [] bots;
14106 delete [] newtops;
14107 }
14108
14110
14111
14112
14113
14114
14115
14116
14117
14118
14119
14120
14121
14122
14123
14124
14126
14127 void tetgenmesh::unsplittetedge(triface* splittet)
14128 {
14129 triface *bots, *newtops;
14130 triface oldtop, topcasing;
14131 triface spintet;
14132 face avseg, splitsh, topsh, spinsh;
14133 point pa, pv, n1;
14134 int wrapcount, hitbdry;
14135 int i;
14136
14137 spintet = *splittet;
14138 pa = org(spintet);
14139 pv = dest(spintet);
14140 if (checksubfaces) {
14141
14142 tsspivot(splittet, &avseg);
14143 if (avseg.sh != dummysh) {
14144
14145 if (sorg(avseg) != pa) {
14146 sesymself(avseg);
14147 }
14148 }
14149 }
14150
14151 n1 = apex(spintet);
14152 hitbdry = 0;
14153 wrapcount = 1;
14154 if (checksubfaces && avseg.sh != dummysh) {
14155
14156
14157
14158 while (true) {
14159 if (!fnextself(spintet)) {
14160
14161 hitbdry ++;
14162 tspivot(spintet, spinsh);
14163 #ifdef SELF_CHECK
14164 assert(spinsh.sh != dummysh);
14165 #endif
14166 findedge(&spinsh, pa, pv);
14167 sfnextself(spinsh);
14168 stpivot(spinsh, spintet);
14169 #ifdef SELF_CHECK
14170 assert(spintet.tet != dummytet);
14171 #endif
14172 findedge(&spintet, pa, pv);
14173
14174 *splittet = spintet;
14175
14176 hullsize += 2;
14177 }
14178 if (apex(spintet) == n1) break;
14179 wrapcount ++;
14180 }
14181 if (hitbdry > 0) {
14182 wrapcount -= hitbdry;
14183 }
14184 } else {
14185
14186
14187 splitsh.sh = dummysh;
14188 while (hitbdry < 2) {
14189 if (checksubfaces && splitsh.sh == dummysh) {
14190 tspivot(spintet, splitsh);
14191 }
14192 if (fnextself(spintet)) {
14193 if (apex(spintet) == n1) break;
14194 wrapcount++;
14195 } else {
14196 hitbdry ++;
14197 if (hitbdry < 2) {
14198 esym(*splittet, spintet);
14199 }
14200 }
14201 }
14202 if (hitbdry > 0) {
14203
14204 wrapcount -= 1;
14205
14206 esym(spintet, *splittet);
14207
14208 hullsize += 2;
14209 }
14210 }
14211
14212
14213 bots = new triface[wrapcount];
14214 newtops = new triface[wrapcount];
14215
14216 spintet = *splittet;
14217 for (i = 0; i < wrapcount; i++) {
14218
14219 enext2fnext(spintet, bots[i]);
14220 esymself(bots[i]);
14221
14222 enextfnext(bots[i], oldtop);
14223
14224 fnext(oldtop, newtops[i]);
14225 esymself(newtops[i]);
14226 enext2self(newtops[i]);
14227
14228 fnextself(spintet);
14229 if (checksubfaces && avseg.sh != dummysh) {
14230 if (!issymexist(&spintet)) {
14231
14232 tspivot(spintet, spinsh);
14233 #ifdef SELF_CHECK
14234 assert(spinsh.sh != dummysh);
14235 #endif
14236 findedge(&spinsh, pa, pv);
14237 sfnextself(spinsh);
14238 stpivot(spinsh, spintet);
14239 #ifdef SELF_CHECK
14240 assert(spintet.tet != dummytet);
14241 #endif
14242 findedge(&spintet, pa, pv);
14243 }
14244 }
14245 }
14246
14247 if (b->verbose > 1) {
14248 printf(" Removing point %d from edge (%d, %d).\n",
14249 pointmark(oppo(bots[0])), pointmark(org(bots[0])),
14250 pointmark(org(newtops[0])));
14251 }
14252
14253 for (i = 0; i < wrapcount; i++) {
14254
14255 setoppo(bots[i], org(newtops[i]));
14256
14257 enextfnext(bots[i], oldtop);
14258
14259 sym(newtops[i], topcasing);
14260
14261 bond(oldtop, topcasing);
14262 if (checksubfaces) {
14263 tspivot(newtops[i], topsh);
14264 if (topsh.sh != dummysh) {
14265 tsbond(oldtop, topsh);
14266 }
14267 }
14268
14269 tetrahedrondealloc(newtops[i].tet);
14270 }
14271
14272
14273 if (checksubfaces) {
14274 if (avseg.sh != dummysh) {
14275 spivot(avseg, splitsh);
14276 #ifdef SELF_CHECK
14277 assert(splitsh.sh != dummysh);
14278 #endif
14279 }
14280 if (splitsh.sh != dummysh) {
14281 findedge(&splitsh, pa, pv);
14282 unsplitsubedge(&splitsh);
14283 }
14284 }
14285
14286 delete [] bots;
14287 delete [] newtops;
14288 }
14289
14291
14292
14293
14294
14295
14296
14297
14298
14299
14300
14301
14302
14303
14304
14305
14306
14307
14308
14309
14310
14312
14313 void tetgenmesh::splitsubedge(point newpoint, face* splitsh, queue* flipqueue)
14314 {
14315 triface abcd, bace, vbcd, bvce;
14316 face startabc, spinabc, spinsh;
14317 face oldbc, bccasin, bccasout;
14318 face ab, bc;
14319 face avc, vbc, vbc1;
14320 face av, vb;
14321 point pa, pb;
14322
14323 startabc = *splitsh;
14324
14325 sspivot(startabc, ab);
14326 if (ab.sh != dummysh) {
14327 ab.shver = 0;
14328 if (sorg(startabc) != sorg(ab)) {
14329 sesymself(startabc);
14330 }
14331 }
14332 pa = sorg(startabc);
14333 pb = sdest(startabc);
14334
14335 if (b->verbose > 1) {
14336 printf(" Inserting point %d on subedge (%d, %d) %s.\n",
14337 pointmark(newpoint), pointmark(pa), pointmark(pb),
14338 (ab.sh != dummysh ? "(seg)" : " "));
14339 }
14340
14341
14342 spinabc = startabc;
14343 do {
14344
14345 if (sorg(spinabc) != pa) {
14346 sesymself(spinabc);
14347 }
14348
14349
14350 senext(spinabc, oldbc);
14351 spivot(oldbc, bccasout);
14352 sspivot(oldbc, bc);
14353 if (bc.sh != dummysh) {
14354 if (spinabc.sh != bccasout.sh) {
14355
14356 spinsh = bccasout;
14357 do {
14358 bccasin = spinsh;
14359 spivotself(spinsh);
14360 } while (spinsh.sh != oldbc.sh);
14361 } else {
14362 bccasout.sh = dummysh;
14363 }
14364 ssdissolve(oldbc);
14365 }
14366
14367 makeshellface(subfaces, &vbc);
14368
14369 avc = spinabc;
14370 setsdest(avc, newpoint);
14371
14372 vbc.shver = avc.shver;
14373 setsorg(vbc, newpoint);
14374 setsdest(vbc, pb);
14375 setsapex(vbc, sapex(avc));
14376 if (b->quality && varconstraint) {
14377
14378 setareabound(vbc, areabound(avc));
14379 }
14380
14381 setshellmark(vbc, shellmark(avc));
14382 setshelltype(vbc, shelltype(avc));
14383 if (checkpbcs) {
14384
14385 setshellpbcgroup(vbc, shellpbcgroup(avc));
14386 }
14387
14388 senext2self(vbc);
14389 sbond(vbc, oldbc);
14390
14391 senext2self(vbc);
14392 if (bc.sh != dummysh) {
14393 if (bccasout.sh != dummysh) {
14394
14395 sbond1(bccasin, vbc);
14396 sbond1(vbc, bccasout);
14397 } else {
14398
14399 sbond(vbc, vbc);
14400 }
14401 ssbond(vbc, bc);
14402 } else {
14403 sbond(vbc, bccasout);
14404 }
14405
14406 spivotself(spinabc);
14407 if (spinabc.sh == dummysh) {
14408 break;
14409 }
14410 } while (spinabc.sh != startabc.sh);
14411
14412
14413 senext(startabc, oldbc);
14414 spivot(oldbc, vbc);
14415 if (sorg(vbc) == newpoint) {
14416 sesymself(vbc);
14417 }
14418 #ifdef SELF_CHECK
14419 assert(sorg(vbc) == sdest(oldbc) && sdest(vbc) == sorg(oldbc));
14420 #endif
14421 senextself(vbc);
14422
14423 spinabc = startabc;
14424 do {
14425
14426 spivotself(spinabc);
14427 if (spinabc.sh == dummysh) {
14428 break;
14429 }
14430 if (sorg(spinabc) != pa) {
14431 sesymself(spinabc);
14432 }
14433
14434 senext(spinabc, oldbc);
14435 spivot(oldbc, vbc1);
14436 if (sorg(vbc1) == newpoint) {
14437 sesymself(vbc1);
14438 }
14439 #ifdef SELF_CHECK
14440 assert(sorg(vbc1) == sdest(oldbc) && sdest(vbc1) == sorg(oldbc));
14441 #endif
14442 senextself(vbc1);
14443
14444 sbond1(vbc, vbc1);
14445
14446 vbc = vbc1;
14447 } while (spinabc.sh != startabc.sh);
14448
14449
14450 if (ab.sh != dummysh) {
14451
14452 av = ab;
14453 setsdest(av, newpoint);
14454
14455 makeshellface(subsegs, &vb);
14456 setsorg(vb, newpoint);
14457 setsdest(vb, pb);
14458
14459 setshellmark(vb, shellmark(av));
14460 setshelltype(vb, shelltype(av));
14461 if (b->quality && varconstraint) {
14462
14463 setareabound(vb, areabound(av));
14464 }
14465
14466 senext(av, oldbc);
14467 spivot(oldbc, bccasout);
14468
14469 senext2(vb, bccasin);
14470 sbond(bccasin, oldbc);
14471 if (bccasout.sh != dummysh) {
14472
14473
14474 bccasout.shver = 0;
14475 if (sorg(bccasout) != pb) sesymself(bccasout);
14476 #ifdef SELF_CHECK
14477 assert(sorg(bccasout) == pb);
14478 #endif
14479 senext2self(bccasout);
14480 senext(vb, bccasin);
14481 sbond(bccasin, bccasout);
14482 }
14483
14484 spinabc = startabc;
14485 do {
14486
14487 if (sorg(spinabc) != pa) {
14488 sesymself(spinabc);
14489 }
14490
14491 senext(spinabc, oldbc);
14492 spivot(oldbc, vbc);
14493 if (sorg(vbc) == newpoint) {
14494 sesymself(vbc);
14495 }
14496 senextself(vbc);
14497
14498 ssbond(vbc, vb);
14499
14500 spivotself(spinabc);
14501 #ifdef SELF_CHECK
14502 assert(spinabc.sh != dummysh);
14503 #endif
14504 } while (spinabc.sh != startabc.sh);
14505 }
14506
14507
14508
14509 spinabc = startabc;
14510 do {
14511
14512 if (sorg(spinabc) != pa) {
14513 sesymself(spinabc);
14514 }
14515
14516 senext(spinabc, oldbc);
14517 spivot(oldbc, vbc);
14518 if (sorg(vbc) == newpoint) {
14519 sesymself(vbc);
14520 }
14521 senextself(vbc);
14522
14523 stpivot(spinabc, abcd);
14524 if (abcd.tet != dummytet) {
14525 findedge(&abcd, sorg(spinabc), sdest(spinabc));
14526 enextfnext(abcd, vbcd);
14527 fnextself(vbcd);
14528 #ifdef SELF_CHECK
14529 assert(vbcd.tet != dummytet);
14530 #endif
14531 tsbond(vbcd, vbc);
14532 sym(vbcd, bvce);
14533 sesymself(vbc);
14534 tsbond(bvce, vbc);
14535 } else {
14536
14537 sesymself(spinabc);
14538 stpivot(spinabc, bace);
14539 if (bace.tet != dummytet) {
14540 findedge(&bace, sorg(spinabc), sdest(spinabc));
14541 enext2fnext(bace, bvce);
14542 fnextself(bvce);
14543 #ifdef SELF_CHECK
14544 assert(bvce.tet != dummytet);
14545 #endif
14546 sesymself(vbc);
14547 tsbond(bvce, vbc);
14548 }
14549 }
14550
14551 spivotself(spinabc);
14552 if (spinabc.sh == dummysh) {
14553 break;
14554 }
14555 } while (spinabc.sh != startabc.sh);
14556
14557 if (b->verbose > 3) {
14558 spinabc = startabc;
14559 do {
14560
14561 if (sorg(spinabc) != pa) {
14562 sesymself(spinabc);
14563 }
14564 printf(" Updating abc:\n");
14565 printsh(&spinabc);
14566
14567 senext(spinabc, oldbc);
14568 spivot(oldbc, vbc);
14569 if (sorg(vbc) == newpoint) {
14570 sesymself(vbc);
14571 }
14572 senextself(vbc);
14573 printf(" Creating vbc:\n");
14574 printsh(&vbc);
14575
14576 spivotself(spinabc);
14577 if (spinabc.sh == dummysh) {
14578 break;
14579 }
14580 } while (spinabc.sh != startabc.sh);
14581 }
14582
14583 if (flipqueue != (queue *) NULL) {
14584 spinabc = startabc;
14585 do {
14586
14587 if (sorg(spinabc) != pa) {
14588 sesymself(spinabc);
14589 }
14590 senext2(spinabc, oldbc);
14591 enqueueflipedge(oldbc, flipqueue);
14592
14593 senext(spinabc, oldbc);
14594 spivot(oldbc, vbc);
14595 if (sorg(vbc) == newpoint) {
14596 sesymself(vbc);
14597 }
14598 senextself(vbc);
14599 senext(vbc, oldbc);
14600 enqueueflipedge(oldbc, flipqueue);
14601
14602 spivotself(spinabc);
14603 if (spinabc.sh == dummysh) {
14604 break;
14605 }
14606 } while (spinabc.sh != startabc.sh);
14607 }
14608 }
14609
14611
14612
14613
14614
14615
14616
14617
14618
14619
14620
14621
14622
14623
14624
14626
14627 void tetgenmesh::unsplitsubedge(face* splitsh)
14628 {
14629 face startavc, spinavc, spinbcv;
14630 face oldvc, bccasin, bccasout, spinsh;
14631 face av, vb, bc;
14632 point pa, pv, pb;
14633
14634 startavc = *splitsh;
14635 sspivot(startavc, av);
14636 if (av.sh != dummysh) {
14637
14638 if (sorg(av) != sorg(startavc)) {
14639 sesymself(av);
14640 }
14641 #ifdef SELF_CHECK
14642 assert(av.shver == 0);
14643 #endif
14644 }
14645 senext(startavc, oldvc);
14646 spivot(oldvc, vb);
14647 if (sorg(vb) != sdest(oldvc)) {
14648 sesymself(vb);
14649 }
14650 senextself(vb);
14651 pa = sorg(startavc);
14652 pv = sdest(startavc);
14653 pb = sdest(vb);
14654
14655 if (b->verbose > 1) {
14656 printf(" Removing point %d from subedge (%d, %d).\n",
14657 pointmark(pv), pointmark(pa), pointmark(pb));
14658 }
14659
14660
14661 spinavc = startavc;
14662 do {
14663
14664 if (sorg(spinavc) != pa) {
14665 sesymself(spinavc);
14666 }
14667
14668
14669 senext(spinavc, oldvc);
14670 spivot(oldvc, spinbcv);
14671 if (sorg(spinbcv) != sdest(oldvc)) {
14672 sesymself(spinbcv);
14673 }
14674 senext2self(spinbcv);
14675 spivot(spinbcv, bccasout);
14676 sspivot(spinbcv, bc);
14677 if (bc.sh != dummysh) {
14678 if (spinbcv.sh != bccasout.sh) {
14679
14680 spinsh = bccasout;
14681 do {
14682 bccasin = spinsh;
14683 spivotself(spinsh);
14684 } while (spinsh.sh != spinbcv.sh);
14685 } else {
14686 bccasout.sh = dummysh;
14687 }
14688 }
14689
14690 setsdest(spinavc, pb);
14691 if (bc.sh != dummysh) {
14692 if (bccasout.sh != dummysh) {
14693 sbond1(bccasin, oldvc);
14694 sbond1(oldvc, bccasout);
14695 } else {
14696
14697 sbond(oldvc, oldvc);
14698 }
14699 ssbond(oldvc, bc);
14700 } else {
14701 sbond(oldvc, bccasout);
14702 }
14703
14704 shellfacedealloc(subfaces, spinbcv.sh);
14705
14706 spivotself(spinavc);
14707 if (spinavc.sh == dummysh) {
14708 break;
14709 }
14710 } while (spinavc.sh != startavc.sh);
14711
14712
14713 if (av.sh != dummysh) {
14714 senext(av, oldvc);
14715 spivot(oldvc, vb);
14716 vb.shver = 0;
14717 #ifdef SELF_CHECK
14718 assert(sdest(av) == sorg(vb));
14719 #endif
14720 senext(vb, spinbcv);
14721 spivot(spinbcv, bccasout);
14722
14723 setsdest(av, pb);
14724 sbond(oldvc, bccasout);
14725
14726 shellfacedealloc(subsegs, vb.sh);
14727 }
14728 }
14729
14731
14732
14733
14734
14735
14736
14737
14738
14739
14740
14741
14742
14743
14744
14745
14746
14747
14748
14749
14751
14752 enum tetgenmesh::insertsiteresult tetgenmesh::insertsite(point newpoint,
14753 triface* searchtet, bool approx, queue* flipqueue)
14754 {
14755 enum locateresult intersect, exactloc;
14756 point checkpt;
14757 REAL epspp, checklen;
14758 int count;
14759
14760 if (b->verbose > 1) {
14761 printf(" Insert point to mesh: (%.12g, %.12g, %.12g) %d.\n",
14762 newpoint[0], newpoint[1], newpoint[2], pointmark(newpoint));
14763 }
14764
14765 if (searchtet->tet == (tetrahedron *) NULL) {
14766
14767 searchtet->tet = dummytet;
14768 exactloc = locate(newpoint, searchtet);
14769 } else {
14770
14771 exactloc = preciselocate(newpoint, searchtet, tetrahedrons->items);
14772 }
14773 intersect = exactloc;
14774 if (approx && (exactloc != ONVERTEX)) {
14775
14776 epspp = b->epsilon;
14777 count = 0;
14778 while (count < 16) {
14779 intersect = adjustlocate(newpoint, searchtet, exactloc, epspp);
14780 if (intersect == ONVERTEX) {
14781 checkpt = org(*searchtet);
14782 checklen = distance(checkpt, newpoint);
14783 if (checklen / longest > b->epsilon) {
14784 epspp *= 1e-2;
14785 count++;
14786 continue;
14787 }
14788 }
14789 break;
14790 }
14791 }
14792
14793 recenttet = *searchtet;
14794
14795
14796 switch (intersect) {
14797 case ONVERTEX:
14798
14799
14800 if (b->verbose > 1) {
14801 printf(" Not insert for duplicating point.\n");
14802 }
14803 return DUPLICATEPOINT;
14804
14805 case OUTSIDE:
14806 if (b->verbose > 1) {
14807 printf(" Not insert for locating outside the mesh.\n");
14808 }
14809 return OUTSIDEPOINT;
14810
14811 case ONEDGE:
14812
14813 splittetedge(newpoint, searchtet, flipqueue);
14814 return SUCCESSONEDGE;
14815
14816 case ONFACE:
14817
14818 splittetface(newpoint, searchtet, flipqueue);
14819 return SUCCESSONFACE;
14820
14821 case INTETRAHEDRON:
14822
14823 splittetrahedron(newpoint, searchtet, flipqueue);
14824 return SUCCESSINTET;
14825
14826 default:
14827
14828 return OUTSIDEPOINT;
14829 }
14830 }
14831
14833
14834
14835
14836
14837
14838
14839
14840
14841
14842
14844
14845 void tetgenmesh::undosite(enum insertsiteresult insresult, triface* splittet,
14846 point torg, point tdest, point tapex, point toppo)
14847 {
14848
14849 findface(splittet, torg, tdest, tapex);
14850 if (oppo(*splittet) != toppo) {
14851 symself(*splittet);
14852 #ifdef SELF_CHECK
14853 assert(oppo(*splittet) == toppo);
14854 #endif
14855
14856 findedge(splittet, torg, tdest);
14857 }
14858
14859
14860 switch (insresult) {
14861 case SUCCESSINTET:
14862
14863 unsplittetrahedron(splittet);
14864 break;
14865 case SUCCESSONFACE:
14866
14867
14868 unsplittetface(splittet);
14869 break;
14870 case SUCCESSONEDGE:
14871
14872 unsplittetedge(splittet);
14873 break;
14874 default:
14875 break;
14876 }
14877 }
14878
14880
14881
14882
14883
14884
14885
14886
14887
14888
14890
14891 void tetgenmesh::closeopenface(triface* openface, queue* flipque)
14892 {
14893 triface newtet, oldhull;
14894 triface newopenface, closeface;
14895 point inspoint, pa, pb, pc;
14896 REAL attrib, volume;
14897 int i;
14898
14899
14900 inspoint = apex(*openface);
14901
14902 esym(*openface, oldhull);
14903 while (fnextself(oldhull)) ;
14904 if (apex(oldhull) != inspoint) {
14905
14906 pa = org(oldhull);
14907 pb = dest(oldhull);
14908 pc = apex(oldhull);
14909 if (orient3d(pa, pb, pc, inspoint) < 0.0) {
14910
14911 maketetrahedron(&newtet);
14912 setorg(newtet, pa);
14913 setdest(newtet, pb);
14914 setapex(newtet, pc);
14915 setoppo(newtet, inspoint);
14916 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14917 attrib = elemattribute(oldhull.tet, i);
14918 setelemattribute(newtet.tet, i, attrib);
14919 }
14920 if (b->varvolume) {
14921 volume = volumebound(oldhull.tet);
14922 setvolumebound(newtet.tet, volume);
14923 }
14924
14925 bond(newtet, oldhull);
14926
14927 fnext(newtet, newopenface);
14928 bond(newopenface, *openface);
14929
14930 enqueueflipface(oldhull, flipque);
14931
14932 hullsize--;
14933
14934 enextself(newtet);
14935 for (i = 0; i < 2; i++) {
14936 fnext(newtet, newopenface);
14937 sym(newopenface, closeface);
14938 if (closeface.tet == dummytet) {
14939 closeopenface(&newopenface, flipque);
14940 }
14941 enextself(newtet);
14942 }
14943 } else {
14944
14945 hullsize++;
14946
14947 dummytet[0] = encode(*openface);
14948 }
14949 } else {
14950
14951 bond(*openface, oldhull);
14952
14953 enqueueflipface(*openface, flipque);
14954 }
14955 }
14956
14958
14959
14960
14961
14962
14963
14964
14965
14966
14967
14968
14969
14970
14971
14973
14974 void tetgenmesh::inserthullsite(point inspoint, triface* horiz, queue* flipque)
14975 {
14976 triface firstnewtet;
14977 triface openface, closeface;
14978 REAL attrib, volume;
14979 int i;
14980
14981
14982 adjustedgering(*horiz, CW);
14983
14984 maketetrahedron(&firstnewtet);
14985 setorg (firstnewtet, org(*horiz));
14986 setdest(firstnewtet, dest(*horiz));
14987 setapex(firstnewtet, apex(*horiz));
14988 setoppo(firstnewtet, inspoint);
14989 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14990 attrib = elemattribute(horiz->tet, i);
14991 setelemattribute(firstnewtet.tet, i, attrib);
14992 }
14993 if (b->varvolume) {
14994 volume = volumebound(horiz->tet);
14995 setvolumebound(firstnewtet.tet, volume);
14996 }
14997
14998 bond(firstnewtet, *horiz);
14999
15000 enqueueflipface(*horiz, flipque);
15001
15002 hullsize--;
15003
15004
15005 for (i = 0; i < 3; i++) {
15006
15007 fnext(firstnewtet, openface);
15008
15009 sym(openface, closeface);
15010 if (closeface.tet == dummytet) {
15011 closeopenface(&openface, flipque);
15012 }
15013
15014 enextself(firstnewtet);
15015 }
15016 }
15017
15019
15020
15021
15022
15023
15024
15025
15026
15027
15028
15029
15030
15031
15032
15033
15034
15036
15038
15039
15040
15041
15042
15043
15044
15045
15046
15048
15049 void tetgenmesh::formbowatcavitysub(point bp, face* bpseg, list* sublist,
15050 list* subceillist)
15051 {
15052 triface adjtet;
15053 face startsh, neighsh;
15054 face checkseg;
15055 point pa, pb, pc, pd;
15056 REAL sign;
15057 int i, j;
15058
15059
15060 for (i = 0; i < sublist->len(); i++) {
15061 startsh = * (face *)(* sublist)[i];
15062
15063 for (j = 0; j < 3; j++) {
15064 sspivot(startsh, checkseg);
15065 if (checkseg.sh == dummysh) {
15066
15067 spivot(startsh, neighsh);
15068
15069 if (!sinfected(neighsh)) {
15070 stpivot(neighsh, adjtet);
15071 if (adjtet.tet == dummytet) {
15072 sesymself(neighsh);
15073 stpivot(neighsh, adjtet);
15074 }
15075
15076 adjustedgering(adjtet, CW);
15077 pa = org(adjtet);
15078 pb = dest(adjtet);
15079 pc = apex(adjtet);
15080 pd = oppo(adjtet);
15081 sign = insphere(pa, pb, pc, pd, bp);
15082 if (sign >= 0.0) {
15083
15084 if (sorg(neighsh) != sdest(startsh)) sesymself(neighsh);
15085
15086 sinfect(neighsh);
15087 sublist->append(&neighsh);
15088 } else {
15089 subceillist->append(&startsh);
15090 }
15091 }
15092 } else {
15093
15094 if (bpseg != (face *) NULL) {
15095 if (checkseg.sh != bpseg->sh) {
15096 subceillist->append(&startsh);
15097 }
15098 } else {
15099 subceillist->append(&startsh);
15100 }
15101 }
15102 senextself(startsh);
15103 }
15104 }
15105
15106 if (b->verbose > 2) {
15107 printf(" Collect CBC(%d): %d subfaces, %d edges.\n", pointmark(bp),
15108 sublist->len(), subceillist->len());
15109 }
15110 }
15111
15113
15114
15115
15116
15117
15118
15119
15120
15121
15122
15123
15125
15126 void tetgenmesh::formbowatcavityquad(point bp, list* tetlist, list* ceillist)
15127 {
15128 triface starttet, neightet;
15129 face checksh;
15130 point pa, pb, pc, pd;
15131 REAL sign;
15132 int i;
15133
15134
15135 for (i = 0; i < tetlist->len(); i++) {
15136 starttet = * (triface *)(* tetlist)[i];
15137 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15138
15139 tspivot(starttet, checksh);
15140 if (checksh.sh == dummysh) {
15141
15142 sym(starttet, neightet);
15143
15144 if (!infected(neightet)) {
15145
15146 adjustedgering(neightet, CW);
15147 pa = org(neightet);
15148 pb = dest(neightet);
15149 pc = apex(neightet);
15150 pd = oppo(neightet);
15151 sign = insphere(pa, pb, pc, pd, bp);
15152 if (sign >= 0.0) {
15153
15154 infect(neightet);
15155 tetlist->append(&neightet);
15156 } else {
15157 ceillist->append(&starttet);
15158 }
15159 }
15160 } else {
15161
15162 if (!sinfected(checksh)) {
15163 ceillist->append(&starttet);
15164 }
15165 }
15166 }
15167 }
15168
15169 if (b->verbose > 2) {
15170 printf(" Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15171 tetlist->len(), ceillist->len());
15172 }
15173 }
15174
15176
15177
15178
15179
15180
15181
15182
15183
15184
15185
15186
15187
15188
15189
15191
15192 void tetgenmesh::formbowatcavitysegquad(point bp, list* tetlist,list* ceillist)
15193 {
15194 triface starttet, neightet, cavtet;
15195 face checksh;
15196 point pa, pb, pc, pd, pe;
15197 REAL sign;
15198 int i;
15199
15200
15201 for (i = 0; i < tetlist->len(); i++) {
15202 starttet = * (triface *)(* tetlist)[i];
15203 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15204
15205 tspivot(starttet, checksh);
15206 if (checksh.sh == dummysh) {
15207
15208 sym(starttet, neightet);
15209
15210 if (!infected(neightet)) {
15211
15212 adjustedgering(neightet, CW);
15213 pa = org(neightet);
15214 pb = dest(neightet);
15215 pc = apex(neightet);
15216 pd = oppo(neightet);
15217 sign = insphere(pa, pb, pc, pd, bp);
15218 if (sign >= 0.0) {
15219
15220 infect(neightet);
15221 tetlist->append(&neightet);
15222 } else {
15223
15224 pe = oppo(starttet);
15225 sign = insphere(pa, pb, pc, pd, pe);
15226 if (sign >= 0.0) {
15227
15228 infect(neightet);
15229 tetlist->append(&neightet);
15230 }
15231 }
15232 }
15233 }
15234 }
15235 }
15236
15237
15238 for (i = 0; i < tetlist->len(); i++) {
15239 cavtet = * (triface *)(* tetlist)[i];
15240 for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15241 tspivot(cavtet, checksh);
15242 if (checksh.sh == dummysh) {
15243 sym(cavtet, neightet);
15244 if (!infected(neightet)) {
15245 ceillist->append(&cavtet);
15246 }
15247 } else {
15248
15249 if (!sinfected(checksh)) {
15250 ceillist->append(&cavtet);
15251 }
15252 }
15253 }
15254 }
15255
15256 if (b->verbose > 2) {
15257 printf(" Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15258 tetlist->len(), ceillist->len());
15259 }
15260 }
15261
15263
15264
15265
15266
15267
15268
15269
15271
15272 void tetgenmesh::formbowatcavity(point bp, face* bpseg, face* bpsh, int* n,
15273 int* nmax, list** sublists, list** subceillists, list** tetlists,
15274 list** ceillists)
15275 {
15276 list *sublist;
15277 triface adjtet;
15278 face startsh, spinsh;
15279 point pa, pb;
15280 int i, j;
15281
15282 *n = 0;
15283 if (bpseg != (face *) NULL) {
15284
15285 bpseg->shver = 0;
15286 pa = sorg(*bpseg);
15287 pb = sdest(*bpseg);
15288
15289 spivot(*bpseg, startsh);
15290 spinsh = startsh;
15291 do {
15292 (*n)++;
15293 spivotself(spinsh);
15294 } while (spinsh.sh != startsh.sh);
15295
15296 if (*n > *nmax) {
15297
15298 delete [] tetlists;
15299 delete [] ceillists;
15300 delete [] sublists;
15301 delete [] subceillists;
15302 tetlists = new list*[*n];
15303 ceillists = new list*[*n];
15304 sublists = new list*[*n];
15305 subceillists = new list*[*n];
15306 *nmax = *n;
15307 }
15308
15309 spinsh = startsh;
15310 for (i = 0; i < *n; i++) {
15311 sublists[i] = new list(sizeof(face), NULL, 256);
15312 subceillists[i] = new list(sizeof(face), NULL, 256);
15313
15314 startsh = spinsh;
15315
15316 findedge(&startsh, pa, pb);
15317 sinfect(startsh);
15318 sublists[i]->append(&startsh);
15319 formbowatcavitysub(bp, bpseg, sublists[i], subceillists[i]);
15320
15321 spivotself(spinsh);
15322 }
15323 } else if (sublists != (list **) NULL) {
15324
15325 *n = 2;
15326
15327 sublists[0] = new list(sizeof(face), NULL, 256);
15328 subceillists[0] = new list(sizeof(face), NULL, 256);
15329 sinfect(*bpsh);
15330 sublists[0]->append(bpsh);
15331 formbowatcavitysub(bp, NULL, sublists[0], subceillists[0]);
15332 } else {
15333
15334 *n = 1;
15335 }
15336
15337
15338 for (i = 0; i < *n; i++) {
15339 tetlists[i] = new list(sizeof(triface), NULL, 256);
15340 ceillists[i] = new list(sizeof(triface), NULL, 256);
15341 if (sublists != (list **) NULL) {
15342
15343 sublist = ((bpseg == (face *) NULL) ? sublists[0] : sublists[i]);
15344
15345 for (j = 0; j < sublist->len(); j++) {
15346 startsh = * (face *)(* sublist)[j];
15347
15348 if ((bpseg == (face *) NULL) && (i == 1)) sesymself(startsh);
15349 stpivot(startsh, adjtet);
15350 if (adjtet.tet != dummytet) {
15351 if (!infected(adjtet)) {
15352 infect(adjtet);
15353 tetlists[i]->append(&adjtet);
15354 }
15355 }
15356 }
15357 if (bpseg != (face *) NULL) {
15358
15359 sublist = ((i < *n - 1) ? sublists[i + 1] : sublists[0]);
15360 for (j = 0; j < sublist->len(); j++) {
15361 startsh = * (face *)(* sublist)[j];
15362
15363 sesymself(startsh);
15364 stpivot(startsh, adjtet);
15365 if (adjtet.tet != dummytet) {
15366 if (!infected(adjtet)) {
15367 infect(adjtet);
15368 tetlists[i]->append(&adjtet);
15369 }
15370 }
15371 }
15372 }
15373 }
15374
15375 if (tetlists[i]->len() == 0) continue;
15376
15377
15378
15379
15380 formbowatcavityquad(bp, tetlists[i], ceillists[i]);
15381
15382 }
15383 }
15384
15386
15387
15388
15389
15391
15392 void tetgenmesh::releasebowatcavity(face* bpseg, int n, list** sublists,
15393 list** subceillist, list** tetlists, list** ceillists)
15394 {
15395 triface oldtet;
15396 face oldsh;
15397 int i, j;
15398
15399 if (sublists != (list **) NULL) {
15400
15401 for (i = 0; i < n; i++) {
15402
15403 for (j = 0; j < sublists[i]->len(); j++) {
15404 oldsh = * (face *)(* (sublists[i]))[j];
15405 #ifdef SELF_CHECK
15406 assert(sinfected(oldsh));
15407 #endif
15408 suninfect(oldsh);
15409 }
15410 delete sublists[i];
15411 delete subceillist[i];
15412 sublists[i] = (list *) NULL;
15413 subceillist[i] = (list *) NULL;
15414 if (bpseg == (face *) NULL) break;
15415 }
15416 }
15417
15418 for (i = 0; i < n; i++) {
15419
15420 for (j = 0; j < tetlists[i]->len(); j++) {
15421 oldtet = * (triface *)(* (tetlists[i]))[j];
15422 #ifdef SELF_CHECK
15423 assert(infected(oldtet));
15424 #endif
15425 uninfect(oldtet);
15426 }
15427 delete tetlists[i];
15428 delete ceillists[i];
15429 tetlists[i] = (list *) NULL;
15430 ceillists[i] = (list *) NULL;
15431 }
15432 }
15433
15435
15436
15437
15438
15439
15440
15441
15442
15443
15445
15446 bool tetgenmesh::validatebowatcavityquad(point bp,list* ceillist,REAL maxcosd)
15447 {
15448 triface ceiltet;
15449 point pa, pb, pc;
15450 REAL ori, cosd;
15451 int remcount, i;
15452
15453
15454 remcount = 0;
15455 for (i = 0; i < ceillist->len(); i++) {
15456 ceiltet = * (triface *)(* ceillist)[i];
15457 if (infected(ceiltet)) {
15458 adjustedgering(ceiltet, CCW);
15459 pa = org(ceiltet);
15460 pb = dest(ceiltet);
15461 pc = apex(ceiltet);
15462 ori = orient3d(pa, pb, pc, bp);
15463 if (ori >= 0.0) {
15464
15465 uninfect(ceiltet);
15466 remcount++;
15467 continue;
15468 }
15469
15470 if (maxcosd > -1.0) {
15471
15472 tetalldihedral(pa, pb, pc, bp, NULL, &cosd, NULL);
15473
15474 if (cosd < maxcosd) {
15475 uninfect(ceiltet);
15476 remcount++;
15477 }
15478 }
15479 }
15480 }
15481 return remcount == 0;
15482 }
15483
15485
15486
15487
15488
15489
15490
15491
15493
15494 void tetgenmesh::updatebowatcavityquad(list* tetlist, list* ceillist)
15495 {
15496 triface cavtet, neightet;
15497 face checksh;
15498 int remcount, i;
15499
15500 remcount = 0;
15501 for (i = 0; i < tetlist->len(); i++) {
15502 cavtet = * (triface *)(* tetlist)[i];
15503 if (!infected(cavtet)) {
15504 tetlist->del(i, 1);
15505 remcount++;
15506 i--;
15507 }
15508 }
15509
15510
15511 if (remcount > 0) {
15512
15513 ceillist->clear();
15514 for (i = 0; i < tetlist->len(); i++) {
15515 cavtet = * (triface *)(* tetlist)[i];
15516 for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15517 tspivot(cavtet, checksh);
15518 if (checksh.sh == dummysh) {
15519 sym(cavtet, neightet);
15520 if (!infected(neightet)) {
15521 ceillist->append(&cavtet);
15522 }
15523 } else {
15524
15525 if (!sinfected(checksh)) {
15526 ceillist->append(&cavtet);
15527 }
15528 }
15529 }
15530 }
15531 if (b->verbose > 2) {
15532 printf(" Update BC_i(p): %d tets, %d faces.\n", tetlist->len(),
15533 ceillist->len());
15534 }
15535 }
15536 }
15537
15539
15540
15541
15542
15543
15544
15545
15546
15547
15548
15549
15550
15551
15552
15553
15554
15555
15556
15557
15558
15559
15560
15561
15563
15564 void tetgenmesh::updatebowatcavitysub(list* sublist, list* subceillist,
15565 int* cutcount)
15566 {
15567 triface adjtet, rotface;
15568 face checksh, neighsh;
15569 face checkseg;
15570 point pa, pb, pc;
15571 REAL ori1, ori2;
15572 int remcount;
15573 int i, j;
15574
15575 remcount = 0;
15576
15577 for (i = 0; i < sublist->len(); i++) {
15578 checksh = * (face *)(* sublist)[i];
15579
15580 for (j = 0; j < 2; j++) {
15581 stpivot(checksh, adjtet);
15582 if (adjtet.tet != dummytet) {
15583 if (!infected(adjtet)) {
15584
15585 suninfect(checksh);
15586
15587 sesymself(checksh);
15588 stpivot(checksh, adjtet);
15589 if (adjtet.tet != dummytet) {
15590 if (infected(adjtet)) {
15591
15592 uninfect(adjtet);
15593 (*cutcount)++;
15594 }
15595 }
15596
15597 sublist->del(i, 1);
15598 i--;
15599 remcount++;
15600 break;
15601 }
15602 }
15603 sesymself(checksh);
15604 }
15605 }
15606 if (remcount > 0) {
15607 if (b->verbose > 2) {
15608 printf(" Removed %d subfaces from CBC(p).\n", remcount);
15609 }
15610
15611 subceillist->clear();
15612 for (i = 0; i < sublist->len(); i++) {
15613 checksh = * (face *)(* sublist)[i];
15614 for (j = 0; j < 3; j++) {
15615 spivot(checksh, neighsh);
15616 if (!sinfected(neighsh)) {
15617 subceillist->append(&checksh);
15618 }
15619 senextself(checksh);
15620 }
15621 }
15622 if (b->verbose > 2) {
15623 printf(" Update CBC(p): %d subs, %d edges.\n", sublist->len(),
15624 subceillist->len());
15625 }
15626 }
15627
15628
15629 for (i = 0; i < subceillist->len(); i++) {
15630 checksh = * (face *)(* subceillist)[i];
15631 sspivot(checksh, checkseg);
15632 if (checkseg.sh != dummysh) {
15633
15634 stpivot(checksh, adjtet);
15635 if (adjtet.tet == dummytet) {
15636 sesym(checksh, neighsh);
15637 stpivot(neighsh, adjtet);
15638 }
15639 findedge(&adjtet, sorg(checkseg), sdest(checkseg));
15640 adjustedgering(adjtet, CCW);
15641 fnext(adjtet, rotface);
15642
15643
15644
15645
15646 do {
15647 if (!infected(rotface)) break;
15648 tspivot(rotface, neighsh);
15649 if (neighsh.sh != dummysh) break;
15650
15651 fnextself(rotface);
15652 } while (apex(rotface) != apex(adjtet));
15653
15654 if (apex(rotface) == apex(adjtet)) {
15655
15656 pa = org(adjtet);
15657 pb = dest(adjtet);
15658 pc = apex(adjtet);
15659
15660
15661
15662 fnext(adjtet, rotface);
15663 do {
15664 fnextself(rotface);
15665 assert(infected(rotface));
15666 ori1 = orient3d(pa, pb, pc, apex(rotface));
15667 ori2 = orient3d(pa, pb, pc, oppo(rotface));
15668 } while (ori1 * ori2 > 0.0);
15669
15670 uninfect(rotface);
15671 (*cutcount)++;
15672 }
15673 } else {
15674
15675
15676
15677
15678
15679
15680
15681
15682
15683
15684
15685
15686
15687
15688
15689
15690
15691 }
15692 }
15693 }
15694
15696
15697
15698
15699
15700
15701
15702
15703
15704
15705
15706
15707
15708
15709
15710
15711
15712
15713
15714
15715
15716
15717
15719
15720 bool tetgenmesh::trimbowatcavity(point bp, face* bpseg, int n, list** sublists,
15721 list** subceillists, list** tetlists, list** ceillists, REAL maxcosd)
15722 {
15723 bool valflag;
15724 int oldnum, cutnum, cutcount;
15725 int i;
15726
15727 cutnum = 0;
15728 valflag = true;
15729
15730 do {
15731
15732 for (i = 0; i < n && valflag; i++) {
15733 oldnum = tetlists[i]->len();
15734
15735 while (!validatebowatcavityquad(bp, ceillists[i], maxcosd)) {
15736
15737 updatebowatcavityquad(tetlists[i], ceillists[i]);
15738 valflag = tetlists[i]->len() > 0;
15739 }
15740 cutnum += (oldnum - tetlists[i]->len());
15741 }
15742 if (valflag && (sublists != (list **) NULL)) {
15743
15744 cutcount = 0;
15745 for (i = 0; i < n; i++) {
15746 updatebowatcavitysub(sublists[i], subceillists[i], &cutcount);
15747
15748 if (bpseg == (face *) NULL) break;
15749 }
15750
15751 if (cutcount > 0) {
15752
15753 for (i = 0; i < n; i++) {
15754 if (tetlists[i]->len() > 0) {
15755 updatebowatcavityquad(tetlists[i], ceillists[i]);
15756 if (valflag) {
15757 valflag = tetlists[i]->len() > 0;
15758 }
15759 }
15760 }
15761 cutnum += cutcount;
15762
15763 continue;
15764 }
15765 }
15766 break;
15767 } while (true);
15768
15769
15770 if (valflag && (sublists != (list **) NULL)) {
15771 for (i = 0; i < n && valflag; i++) {
15772 valflag = (sublists[i]->len() > 0);
15773 if (bpseg == (face *) NULL) break;
15774 }
15775 }
15776
15777 if (valflag && (cutnum > 0)) {
15778
15779 if (bpseg != (face *) NULL) {
15780 updsegcount++;
15781 } else if (sublists != (list **) NULL) {
15782 updsubcount++;
15783 } else {
15784 updvolcount++;
15785 }
15786 }
15787
15788 if (!valflag) {
15789
15790 if (bpseg != (face *) NULL) {
15791 failsegcount++;
15792 } else if (sublists != (list **) NULL) {
15793 failsubcount++;
15794 } else {
15795 failvolcount++;
15796 }
15797 }
15798
15799 return valflag;
15800 }
15801
15803
15804
15805
15806
15807
15808
15809
15810
15811
15812
15813
15814
15815
15816
15817
15818
15819
15820
15821
15822
15823
15824
15825
15826
15827
15828
15829
15830
15831
15832
15833
15835
15836 void tetgenmesh::bowatinsertsite(point bp,face* splitseg,int n,list** sublists,
15837 list** subceillists, list** tetlists, list** ceillists, list* verlist,
15838 queue* flipque, bool chkencseg, bool chkencsub, bool chkbadtet)
15839 {
15840 list *ceillist, *subceillist;
15841 triface oldtet, newtet, newface, rotface, neightet;
15842 face oldsh, newsh, newedge, checksh;
15843 face spinsh, casingin, casingout;
15844 face *apsegshs, *pbsegshs;
15845 face apseg, pbseg, checkseg;
15846 point pa, pb, pc;
15847 pa=NULL;
15848 pb=NULL;
15849 REAL attrib, volume;
15850 int idx, i, j, k;
15851
15852 apsegshs = NULL;
15853 pbsegshs = NULL;
15854
15855 if (b->verbose > 1) {
15856 printf(" Insert point %d (%.12g, %.12g, %.12g)", pointmark(bp), bp[0],
15857 bp[1], bp[2]);
15858 }
15859 if (splitseg != (face *) NULL) {
15860 if (b->verbose > 1) {
15861 printf(" on segment.\n");
15862 }
15863 bowatsegcount++;
15864 } else {
15865 if (subceillists != (list **) NULL) {
15866 if (b->verbose > 1) {
15867 printf(" on facet.\n");
15868 }
15869 bowatsubcount++;
15870 } else {
15871 if (b->verbose > 1) {
15872 printf(" in volume.\n");
15873 }
15874 bowatvolcount++;
15875 }
15876 }
15877
15878
15879 for (k = 0; k < n; k++) {
15880
15881 ceillist = ceillists[k];
15882 for (i = 0; i < ceillist->len(); i++) {
15883 oldtet = * (triface *)(* ceillist)[i];
15884 adjustedgering(oldtet, CCW);
15885 pa = org(oldtet);
15886 pb = dest(oldtet);
15887 pc = apex(oldtet);
15888 maketetrahedron(&newtet);
15889 setorg(newtet, pa);
15890 setdest(newtet, pb);
15891 setapex(newtet, pc);
15892 setoppo(newtet, bp);
15893 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
15894 attrib = elemattribute(oldtet.tet, j);
15895 setelemattribute(newtet.tet, j, attrib);
15896 }
15897 if (b->varvolume) {
15898 volume = volumebound(oldtet.tet);
15899 if (volume > 0.0) {
15900 if (!b->fixedvolume && b->refine) {
15901
15902
15903
15904 volume *= 1.2;
15905 }
15906 }
15907 setvolumebound(newtet.tet, volume);
15908 }
15909 sym(oldtet, neightet);
15910 tspivot(oldtet, checksh);
15911 if (neightet.tet != dummytet) {
15912 bond(newtet, neightet);
15913 }
15914 if (checksh.sh != dummysh) {
15915 tsbond(newtet, checksh);
15916 }
15917 if (verlist != (list *) NULL) {
15918
15919 idx = pointmark(pa);
15920 if (idx >= 0) {
15921 setpointmark(pa, -idx - 1);
15922 verlist->append(&pa);
15923 }
15924 idx = pointmark(pb);
15925 if (idx >= 0) {
15926 setpointmark(pb, -idx - 1);
15927 verlist->append(&pb);
15928 }
15929 idx = pointmark(pc);
15930 if (idx >= 0) {
15931 setpointmark(pc, -idx - 1);
15932 verlist->append(&pc);
15933 }
15934 }
15935
15936 * (triface *)(* ceillist)[i] = newtet;
15937 }
15938 }
15939 if (verlist != (list *) NULL) {
15940
15941 for (i = 0; i < verlist->len(); i++) {
15942 pa = * (point *)(* verlist)[i];
15943 idx = pointmark(pa);
15944 setpointmark(pa, -(idx + 1));
15945 }
15946 }
15947
15948
15949
15950 for (k = 0; k < n; k++) {
15951 ceillist = ceillists[k];
15952 for (i = 0; i < ceillist->len(); i++) {
15953 newtet = * (triface *)(* ceillist)[i];
15954 newtet.ver = 0;
15955 for (j = 0; j < 3; j++) {
15956 fnext(newtet, newface);
15957 sym(newface, neightet);
15958 if (neightet.tet == dummytet) {
15959
15960 esym(newtet, rotface);
15961 pa = org(rotface);
15962 pb = dest(rotface);
15963 while (fnextself(rotface));
15964
15965 tspivot(rotface, checksh);
15966 if (checksh.sh != dummysh) {
15967
15968 do {
15969 findedge(&checksh, pa, pb);
15970 sfnextself(checksh);
15971 assert((sorg(checksh) == pa) && (sdest(checksh) == pb));
15972 stpivot(checksh, rotface);
15973 if (infected(rotface)) {
15974
15975
15976 break;
15977 }
15978 findedge(&rotface, pa, pb);
15979 while (fnextself(rotface));
15980 tspivot(rotface, checksh);
15981 } while (checksh.sh != dummysh);
15982 }
15983
15984 if (apex(rotface) == apex(newface)) {
15985
15986 bond(newface, rotface);
15987
15988 if (flipque != (queue *) NULL) {
15989 enqueueflipface(newface, flipque);
15990 }
15991 }
15992 }
15993 enextself(newtet);
15994 }
15995 }
15996 }
15997
15998 if (subceillists != (list **) NULL) {
15999
16000 if (splitseg != (face *) NULL) {
16001
16002 splitseg->shver = 0;
16003 pa = sorg(*splitseg);
16004 pb = sdest(*splitseg);
16005
16006
16007 apsegshs = new face[n];
16008 pbsegshs = new face[n];
16009 }
16010
16011
16012
16013
16014 for (k = 0; k < n; k++) {
16015 subceillist = subceillists[k];
16016
16017
16018 oldsh = * (face *)(* subceillist)[0];
16019 stpivot(oldsh, neightet);
16020 if (neightet.tet != dummytet) {
16021 sesymself(oldsh);
16022 stpivot(oldsh, neightet);
16023 }
16024 if (neightet.tet == dummytet) {
16025
16026 hullsize += (subceillist->len() - sublists[k]->len());
16027 }
16028
16029
16030 for (i = 0; i < subceillist->len(); i++) {
16031 oldsh = * (face *)(* subceillist)[i];
16032 makeshellface(subfaces, &newsh);
16033 setsorg(newsh, sorg(oldsh));
16034 setsdest(newsh, sdest(oldsh));
16035 setsapex(newsh, bp);
16036 if (b->quality && varconstraint) {
16037 setareabound(newsh, areabound(oldsh));
16038 }
16039 setshellmark(newsh, shellmark(oldsh));
16040 setshelltype(newsh, shelltype(oldsh));
16041 if (checkpbcs) {
16042 setshellpbcgroup(newsh, shellpbcgroup(oldsh));
16043 }
16044
16045 spivot(oldsh, casingout);
16046 sspivot(oldsh, checkseg);
16047 if (checkseg.sh != dummysh) {
16048
16049 if (oldsh.sh != casingout.sh) {
16050
16051 spinsh = casingout;
16052 do {
16053 casingin = spinsh;
16054 spivotself(spinsh);
16055 } while (sapex(spinsh) != sapex(oldsh));
16056 assert(casingin.sh != oldsh.sh);
16057
16058 sbond1(casingin, newsh);
16059 sbond1(newsh, casingout);
16060 } else {
16061
16062 sbond(newsh, newsh);
16063 }
16064
16065 ssbond(newsh, checkseg);
16066 } else {
16067
16068 sbond(newsh, casingout);
16069 }
16070
16071
16072 stpivot(oldsh, neightet);
16073 if (neightet.tet == dummytet) {
16074 sesymself(oldsh);
16075 sesymself(newsh);
16076 stpivot(oldsh, neightet);
16077 }
16078 assert(infected(neightet));
16079
16080 findedge(&neightet, sorg(oldsh), sdest(oldsh));
16081
16082 adjustedgering(neightet, CCW);
16083 rotface = neightet;
16084
16085
16086
16087 do {
16088 fnextself(rotface);
16089 sym(rotface, neightet);
16090 if (neightet.tet == dummytet) {
16091 tspivot(rotface, checksh);
16092 assert(checksh.sh != dummysh);
16093 stpivot(checksh, newtet);
16094 break;
16095 } else if (!infected(neightet)) {
16096 sym(neightet, newtet);
16097 break;
16098 }
16099 } while (true);
16100 assert(newtet.tet != rotface.tet);
16101
16102 findedge(&newtet, sorg(oldsh), sdest(oldsh));
16103
16104 adjustedgering(newtet, CCW);
16105 fnext(newtet, newface);
16106 assert(apex(newface) == bp);
16107
16108 tsbond(newface, newsh);
16109 sym(newface, neightet);
16110 sesymself(newsh);
16111 tsbond(neightet, newsh);
16112
16113
16114 * (face *)(* subceillist)[i] = newsh;
16115 }
16116
16117
16118 for (i = 0; i < subceillist->len(); i++) {
16119
16120 newsh = * (face *)(* subceillist)[i];
16121
16122 stpivot(newsh, newtet);
16123 if (newtet.tet == dummytet) {
16124 sesymself(newsh);
16125 stpivot(newsh, newtet);
16126 }
16127 for (j = 0; j < 2; j++) {
16128 if (j == 0) {
16129 senext(newsh, newedge);
16130 } else {
16131 senext2(newsh, newedge);
16132 sesymself(newedge);
16133 }
16134 if (splitseg != (face *) NULL) {
16135
16136 if (sorg(newedge) == pa) {
16137 apsegshs[k] = newedge;
16138 continue;
16139 } else if (sorg(newedge) == pb) {
16140 pbsegshs[k] = newedge;
16141 continue;
16142 }
16143 }
16144
16145 sspivot(newedge, checkseg);
16146 assert(checkseg.sh == dummysh);
16147 spivot(newedge, casingout);
16148 if (casingout.sh == dummysh) {
16149 rotface = newtet;
16150 findedge(&rotface, sorg(newedge), sdest(newedge));
16151
16152
16153 adjustedgering(rotface, CCW);
16154 do {
16155 fnextself(rotface);
16156 tspivot(rotface, checksh);
16157 if (checksh.sh != dummysh) break;
16158 } while (true);
16159 findedge(&checksh, sorg(newedge), sdest(newedge));
16160 sbond(newedge, checksh);
16161 }
16162 }
16163 }
16164
16165 if (splitseg == (face *) NULL) break;
16166 }
16167
16168 if (splitseg != (face *) NULL) {
16169
16170 apseg = *splitseg;
16171 setsdest(apseg, bp);
16172
16173 makeshellface(subsegs, &pbseg);
16174 setsorg(pbseg, bp);
16175 setsdest(pbseg, pb);
16176
16177 setshellmark(pbseg, shellmark(apseg));
16178 setshelltype(pbseg, shelltype(apseg));
16179 if (b->quality && varconstraint) {
16180
16181 setareabound(pbseg, areabound(apseg));
16182 }
16183 senext(apseg, checkseg);
16184
16185 spivot(checkseg, casingout);
16186
16187 senext2(pbseg, casingin);
16188 sbond(casingin, checkseg);
16189 if (casingout.sh != dummysh) {
16190
16191 casingout.shver = 0;
16192 #ifdef SELF_CHECK
16193 assert(sorg(casingout) == pb);
16194 #endif
16195 senext2self(casingout);
16196 senext(pbseg, casingin);
16197 sbond(casingin, casingout);
16198 }
16199
16200
16201 for (i = 0; i < n; i++) {
16202 spinsh = apsegshs[i];
16203 findedge(&spinsh, pa, bp);
16204 ssbond(spinsh, apseg);
16205 spinsh = pbsegshs[i];
16206 findedge(&spinsh, bp, pb);
16207 ssbond(spinsh, pbseg);
16208 }
16209
16210 for (i = 0; i < n; i++) {
16211 spinsh = apsegshs[i];
16212 if (i < (n - 1)) {
16213 casingout = apsegshs[i + 1];
16214 } else {
16215 casingout = apsegshs[0];
16216 }
16217 sbond1(spinsh, casingout);
16218 }
16219
16220 for (i = 0; i < n; i++) {
16221 spinsh = pbsegshs[i];
16222 if (i < (n - 1)) {
16223 casingout = pbsegshs[i + 1];
16224 } else {
16225 casingout = pbsegshs[0];
16226 }
16227 sbond1(spinsh, casingout);
16228 }
16229 delete [] apsegshs;
16230 delete [] pbsegshs;
16231
16232
16233 if (chkencseg) {
16234
16235 checkseg4encroach(&apseg, NULL, NULL, true);
16236 checkseg4encroach(&pbseg, NULL, NULL, true);
16237
16238 tallencsegs(bp, n, ceillists);
16239 }
16240 }
16241
16242
16243 for (k = 0; k < n; k++) {
16244 for (i = 0; i < sublists[k]->len(); i++) {
16245 oldsh = * (face *)(* (sublists[k]))[i];
16246 shellfacedealloc(subfaces, oldsh.sh);
16247 }
16248
16249
16250 sublists[k]->clear();
16251
16252 if (splitseg == (face *) NULL) break;
16253 }
16254
16255
16256 if (chkencsub) {
16257
16258 for (k = 0; k < n; k++) {
16259 subceillist = subceillists[k];
16260 for (i = 0; i < subceillist->len(); i++) {
16261 newsh = * (face *)(* subceillist)[i];
16262 checksub4encroach(&newsh, NULL, true);
16263 }
16264
16265 if (splitseg == (face *) NULL) break;
16266 }
16267
16268 tallencsubs(bp, n, ceillists);
16269 }
16270 }
16271
16272
16273 for (k = 0; k < n; k++) {
16274 for (i = 0; i < tetlists[k]->len(); i++) {
16275 oldtet = * (triface *)(* (tetlists[k]))[i];
16276 tetrahedrondealloc(oldtet.tet);
16277 }
16278
16279
16280 tetlists[k]->clear();
16281 }
16282
16283
16284 if (chkbadtet) {
16285 for (k = 0; k < n; k++) {
16286 ceillist = ceillists[k];
16287 for (i = 0; i < ceillist->len(); i++) {
16288 newtet = * (triface *)(* ceillist)[i];
16289 checktet4badqual(&newtet, true);
16290 }
16291 }
16292 }
16293
16294 if (flipque != (queue *) NULL) {
16295
16296
16297
16298 repairflipcount += flip(flipque, NULL);
16299 }
16300 }
16301
16302
16303
16304
16305
16306
16307
16308
16309
16311
16312
16313
16314
16315
16316
16317
16318
16319
16320
16321
16323
16324 void tetgenmesh::formstarpolyhedron(point pt, list* tetlist, list* verlist,
16325 bool complete)
16326 {
16327 triface starttet, neightet;
16328 face checksh;
16329 point ver[3];
16330 int idx, i, j;
16331
16332
16333 starttet = * (triface *)(* tetlist)[0];
16334
16335 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
16336 if (oppo(starttet) == pt) break;
16337 }
16338 assert(starttet.loc < 4);
16339
16340 * (triface *)(* tetlist)[0] = starttet;
16341 infect(starttet);
16342 if (verlist != (list *) NULL) {
16343
16344 ver[0] = org(starttet);
16345 ver[1] = dest(starttet);
16346 ver[2] = apex(starttet);
16347 for (i = 0; i < 3; i++) {
16348
16349 idx = pointmark(ver[i]);
16350 setpointmark(ver[i], -idx - 1);
16351 verlist->append(&(ver[i]));
16352 }
16353 }
16354
16355
16356 for (i = 0; i < tetlist->len(); i++) {
16357 starttet = * (triface *)(* tetlist)[i];
16358 starttet.ver = 0;
16359 for (j = 0; j < 3; j++) {
16360 fnext(starttet, neightet);
16361 tspivot(neightet, checksh);
16362
16363 if ((checksh.sh == dummysh) || complete) {
16364
16365 symself(neightet);
16366 if ((neightet.tet != dummytet) && !infected(neightet)) {
16367
16368 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
16369 if (oppo(neightet) == pt) break;
16370 }
16371 assert(neightet.loc < 4);
16372
16373 infect(neightet);
16374 tetlist->append(&neightet);
16375 if (verlist != (list *) NULL) {
16376
16377 ver[0] = org(starttet);
16378 ver[1] = dest(starttet);
16379 findedge(&neightet, ver[0], ver[1]);
16380 ver[2] = apex(neightet);
16381 idx = pointmark(ver[2]);
16382 if (idx >= 0) {
16383 setpointmark(ver[2], -idx - 1);
16384 verlist->append(&(ver[2]));
16385 }
16386 }
16387 }
16388 }
16389 enextself(starttet);
16390 }
16391 }
16392
16393
16394 for (i = 0; i < tetlist->len(); i++) {
16395 starttet = * (triface *)(* tetlist)[i];
16396 uninfect(starttet);
16397 }
16398 if (verlist != (list *) NULL) {
16399
16400 for (i = 0; i < verlist->len(); i++) {
16401 ver[0] = * (point *)(* verlist)[i];
16402 idx = pointmark(ver[0]);
16403 setpointmark(ver[0], -(idx + 1));
16404 }
16405 }
16406 }
16407
16409
16410
16411
16412
16413
16414
16415
16416
16417
16419
16420 bool tetgenmesh::unifypoint(point testpt, triface *starttet, enum locateresult
16421 loc, REAL eps)
16422 {
16423 triface symtet, spintet;
16424 point checkpt, tapex;
16425 REAL tol;
16426 bool merged;
16427 int hitbdry;
16428 int i;
16429
16430 merged = false;
16431 tol = longest * eps;
16432 if ((loc == OUTSIDE) || (loc == INTETRAHEDRON) || (loc == ONFACE)) {
16433
16434 for (i = 0; i < 4; i++) {
16435 checkpt = (point) starttet->tet[4 + i];
16436 if (distance(testpt, checkpt) < tol) {
16437 merged = true;
16438 break;
16439 }
16440 }
16441 if (!merged && (loc == ONFACE)) {
16442
16443 sym(*starttet, symtet);
16444 if (symtet.tet != dummytet) {
16445 checkpt = oppo(symtet);
16446 if (distance(testpt, checkpt) < tol) {
16447 merged = true;
16448 }
16449 }
16450 }
16451 } else if (loc == ONEDGE) {
16452
16453 checkpt = org(*starttet);
16454 if (distance(testpt, checkpt) < tol) {
16455 merged = true;
16456 }
16457 if (!merged) {
16458 checkpt = dest(*starttet);
16459 if (distance(testpt, checkpt) < tol) {
16460 merged = true;
16461 }
16462 }
16463 if (!merged) {
16464
16465 spintet = *starttet;
16466 tapex = apex(*starttet);
16467 hitbdry = 0;
16468 do {
16469 checkpt = apex(spintet);
16470 if (distance(testpt, checkpt) < tol) {
16471 merged = true;
16472 break;
16473 }
16474 if (!fnextself(spintet)) {
16475 hitbdry++;
16476 if (hitbdry < 2) {
16477 esym(*starttet, spintet);
16478 if (!fnextself(spintet)) {
16479 hitbdry++;
16480 }
16481 }
16482 }
16483 } while ((apex(spintet) != tapex) && (hitbdry < 2));
16484 }
16485 }
16486 if (merged) {
16487 if (b->object != tetgenbehavior::STL) {
16488 if (!b->quiet) {
16489 printf("Warning: Point %d is unified to point %d.\n",
16490 pointmark(testpt), pointmark(checkpt));
16491 }
16492
16493 dupverts++;
16494 }
16495
16496 setpointtype(testpt, DUPLICATEDVERTEX);
16497
16498 setpoint2ppt(testpt, checkpt);
16499 }
16500 return merged;
16501 }
16502
16504
16505
16506
16507
16508
16509
16510
16511
16512
16513
16514
16515
16516
16517
16518
16519
16521
16522 void tetgenmesh::incrflipdelaunay(triface* oldtet, point* insertarray,
16523 long arraysize, bool jump, bool merge, REAL eps, queue* flipque)
16524 {
16525 triface newtet, searchtet;
16526 point swappt, lastpt;
16527 enum locateresult loc;
16528 REAL det, n[3];
16529 REAL attrib, volume;
16530 int i, j;
16531 #ifdef SELF_CHECK
16532 clock_t loc_start, loc_end;
16533 #endif
16534
16535 det = 0.0;
16536 if (b->verbose > 0) {
16537 printf(" Creating initial tetrahedralization.\n");
16538 }
16539
16540
16541
16542
16543
16544
16545 for (i = 1; i < arraysize; i++) {
16546 det = distance(insertarray[0], insertarray[i]);
16547 if (det > (longest * eps)) break;
16548 }
16549 if (i == arraysize) {
16550 printf("\nAll points seem to be identical.\n");
16551 return;
16552 } else {
16553
16554 swappt = insertarray[i];
16555 insertarray[i] = insertarray[1];
16556 insertarray[1] = swappt;
16557 }
16558
16559 for (i++; i < arraysize; i++) {
16560 if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
16561 break;
16562 }
16563 if (i == arraysize) {
16564 printf("\nAll points seem to be collinear.\n");
16565 return;
16566 } else {
16567
16568 swappt = insertarray[i];
16569 insertarray[i] = insertarray[2];
16570 insertarray[2] = swappt;
16571 }
16572
16573 for (i++; i < arraysize; i++) {
16574 det = orient3d(insertarray[0], insertarray[1], insertarray[2],
16575 insertarray[i]);
16576 if (det == 0.0) continue;
16577 if (!iscoplanar(insertarray[0], insertarray[1], insertarray[2],
16578 insertarray[i], det, eps)) break;
16579 }
16580 if (i == arraysize) {
16581
16582 in->mesh_dim = 2;
16583
16584 if (b->plc) {
16585
16586 facenormal(insertarray[0], insertarray[1], insertarray[2], n, &det);
16587 if (det != 0.0) for (j = 0; j < 3; j++) n[j] /= det;
16588
16589 det = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
16590
16591 makepoint(&lastpt);
16592 for (j = 0; j < 3; j++) lastpt[j] = insertarray[0][j] + det * n[j];
16593 abovepoint = lastpt;
16594 det = orient3d(insertarray[0], insertarray[1], insertarray[2], lastpt);
16595
16596 i = 3;
16597 } else {
16598 printf("\nAll points seem to be coplanar.\n");
16599 return;
16600 }
16601 } else {
16602
16603 swappt = insertarray[i];
16604 insertarray[i] = insertarray[3];
16605 insertarray[3] = swappt;
16606 lastpt = insertarray[3];
16607
16608 i = 4;
16609 }
16610
16611
16612 maketetrahedron(&newtet);
16613 if (det > 0.0) {
16614
16615 swappt = insertarray[0];
16616 insertarray[0] = insertarray[1];
16617 insertarray[1] = swappt;
16618 }
16619 if (b->verbose > 2) {
16620 printf(" Create the first tet (%d, %d, %d, %d).\n",
16621 pointmark(insertarray[0]), pointmark(insertarray[1]),
16622 pointmark(insertarray[2]), pointmark(lastpt));
16623 }
16624 setorg(newtet, insertarray[0]);
16625 setdest(newtet, insertarray[1]);
16626 setapex(newtet, insertarray[2]);
16627 setoppo(newtet, lastpt);
16628 if (oldtet != (triface *) NULL) {
16629 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
16630 attrib = elemattribute(oldtet->tet, j);
16631 setelemattribute(newtet.tet, j, attrib);
16632 }
16633 if (b->varvolume) {
16634 volume = volumebound(oldtet->tet);
16635 setvolumebound(newtet.tet, volume);
16636 }
16637 }
16638
16639 if (pointtype(insertarray[0]) == UNUSEDVERTEX) {
16640 setpointtype(insertarray[0], FREEVOLVERTEX);
16641 }
16642 if (pointtype(insertarray[1]) == UNUSEDVERTEX) {
16643 setpointtype(insertarray[1], FREEVOLVERTEX);
16644 }
16645 if (pointtype(insertarray[2]) == UNUSEDVERTEX) {
16646 setpointtype(insertarray[2], FREEVOLVERTEX);
16647 }
16648 if (pointtype(lastpt) == UNUSEDVERTEX) {
16649 setpointtype(lastpt, FREEVOLVERTEX);
16650 }
16651
16652 dummytet[0] = encode(newtet);
16653 if (b->verbose > 3) {
16654 printf(" Creating tetra ");
16655 printtet(&newtet);
16656 }
16657
16658 hullsize = 4;
16659
16660 if (b->verbose > 0) {
16661 printf(" Incrementally inserting points.\n");
16662 }
16663
16664 flip23s = flip32s = flip22s = flip44s = 0;
16665 searchtet.tet = (tetrahedron *) NULL;
16666
16667
16668 for (; i < arraysize; i++) {
16669
16670 #ifdef SELF_CHECK
16671 loc_start = clock();
16672 #endif
16673 if (jump) {
16674 loc = locate(insertarray[i], &searchtet);
16675 } else {
16676 loc = preciselocate(insertarray[i], &searchtet, tetrahedrons->items);
16677 }
16678 #ifdef SELF_CHECK
16679 loc_end = clock();
16680 tloctime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16681 #endif
16682
16683 recenttet = searchtet;
16684 if (loc == ONVERTEX) {
16685 if (b->object != tetgenbehavior::STL) {
16686 if (!b->quiet) {
16687 printf("Warning: Point %d is identical with point %d.\n",
16688 pointmark(insertarray[i]), pointmark(org(searchtet)));
16689 }
16690 }
16691
16692 dupverts++;
16693
16694 setpointtype(insertarray[i], DUPLICATEDVERTEX);
16695 if (b->plc || b->refine) {
16696
16697 setpoint2ppt(insertarray[i], org(searchtet));
16698 }
16699 continue;
16700 }
16701 if (merge) {
16702
16703 if (unifypoint(insertarray[i], &searchtet, loc, eps)) {
16704 continue;
16705 }
16706 }
16707
16708 if (loc != OUTSIDE) {
16709 if (b->verbose > 1) {
16710 printf(" Insert point %d in tetrahedralization.\n",
16711 pointmark(insertarray[i]));
16712 }
16713 if (loc == INTETRAHEDRON) {
16714 splittetrahedron(insertarray[i], &searchtet, flipque);
16715 } else if (loc == ONFACE) {
16716 splittetface(insertarray[i], &searchtet, flipque);
16717 } else if (loc == ONEDGE) {
16718 splittetedge(insertarray[i], &searchtet, flipque);
16719 }
16720 } else {
16721 if (b->verbose > 1) {
16722 printf(" Insert point %d on convex hull.\n",
16723 pointmark(insertarray[i]));
16724 }
16725 inserthullsite(insertarray[i], &searchtet, flipque);
16726 }
16727 if (pointtype(insertarray[i]) == UNUSEDVERTEX) {
16728
16729 setpointtype(insertarray[i], FREEVOLVERTEX);
16730 }
16731 #ifdef SELF_CHECK
16732 loc_start = clock();
16733 #endif
16734 if (!b->noflip) {
16735
16736 flip(flipque, NULL);
16737 } else {
16738 lawson(NULL, flipque);
16739
16740
16741 }
16742 #ifdef SELF_CHECK
16743 loc_end = clock();
16744 tfliptime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16745 #endif
16746 }
16747
16748 if (b->verbose > 0) {
16749 printf(" %ld Flips (T23 %ld, T32 %ld, T22 %ld, T44 %ld)\n",
16750 flip23s+flip32s+flip22s+flip44s, flip23s, flip32s, flip22s, flip44s);
16751 }
16752 }
16753
16755
16756
16757
16758
16759
16760
16761
16763
16764 long tetgenmesh::delaunizevertices()
16765 {
16766 queue *flipque;
16767 point *insertarray;
16768 long arraysize;
16769 int i, j;
16770
16771 if (!b->quiet) {
16772 if (!b->noflip) {
16773 printf("Constructing Delaunay tetrahedralization.\n");
16774 } else {
16775 printf("Constructing regular tetrahedralization.\n");
16776 }
16777 }
16778
16779 flipque = new queue(sizeof(badface));
16780
16781 arraysize = points->items;
16782 insertarray = new point[arraysize];
16783 points->traversalinit();
16784
16785
16786
16787 for (i = 0; i < arraysize; i++) {
16788 j = (int) randomnation(i + 1);
16789 insertarray[i] = insertarray[j];
16790 insertarray[j] = pointtraverse();
16791 }
16792
16793
16794 b->noflip = 1;
16795
16796
16797 incrflipdelaunay(NULL, insertarray, arraysize, true, b->plc, b->epsilon,
16798 flipque);
16799
16800 b->noflip = 0;
16801
16802 delete [] insertarray;
16803 delete flipque;
16804 return hullsize;
16805 }
16806
16807
16808
16809
16810
16811
16812
16813
16814
16816
16817
16818
16819
16820
16821
16822
16823
16824
16825
16827
16828 void tetgenmesh::formstarpolygon(point pt, list* trilist, list* vertlist)
16829 {
16830 face steinsh, lnextsh, rnextsh;
16831 face checkseg;
16832 point pa, pb, pc, pd;
16833 int i;
16834
16835
16836 steinsh = * (face *)(* trilist)[0];
16837 steinsh.shver = 0;
16838
16839 for (i = 0; i < 3; i++) {
16840 if (sapex(steinsh) == pt) break;
16841 senextself(steinsh);
16842 }
16843 assert(i < 3);
16844
16845 * (face *)(* trilist)[0] = steinsh;
16846 pa = sorg(steinsh);
16847 pb = sdest(steinsh);
16848 if (vertlist != (list *) NULL) {
16849
16850 vertlist->append(&pa);
16851 vertlist->append(&pb);
16852 }
16853
16854
16855 lnextsh = steinsh;
16856 pc = pa;
16857 do {
16858 senext2self(lnextsh);
16859 assert(sorg(lnextsh) == pt);
16860 sspivot(lnextsh, checkseg);
16861 if (checkseg.sh != dummysh) break;
16862
16863 spivotself(lnextsh);
16864 if (lnextsh.sh == dummysh) break;
16865
16866 if (sdest(lnextsh) != pt) sesymself(lnextsh);
16867 assert(sdest(lnextsh) == pt);
16868 senext2self(lnextsh);
16869
16870 trilist->append(&lnextsh);
16871
16872 pc = sorg(lnextsh);
16873 if (pc == pb) break;
16874 if (vertlist != (list *) NULL) {
16875
16876 vertlist->append(&pc);
16877 }
16878 } while (true);
16879
16880 if (pc != pb) {
16881
16882 rnextsh = steinsh;
16883 do {
16884 senextself(rnextsh);
16885 assert(sdest(rnextsh) == pt);
16886 sspivot(rnextsh, checkseg);
16887 if (checkseg.sh != dummysh) break;
16888
16889 spivotself(rnextsh);
16890 if (rnextsh.sh == dummysh) break;
16891
16892 if (sorg(rnextsh) != pt) sesymself(rnextsh);
16893 assert(sorg(rnextsh) == pt);
16894 senextself(rnextsh);
16895
16896 trilist->append(&rnextsh);
16897
16898 pd = sdest(rnextsh);
16899 if (pd == pa) break;
16900 if (vertlist != (list *) NULL) {
16901
16902 vertlist->append(&pd);
16903 }
16904 } while (true);
16905 }
16906 }
16907
16909
16910
16911
16912
16913
16914
16915
16916
16917
16918
16919
16920
16921
16922
16923
16925
16927
16928
16929
16930
16931
16932
16934
16935 void tetgenmesh::getfacetabovepoint(face* facetsh)
16936 {
16937 list *verlist, *trilist, *tetlist;
16938 triface adjtet;
16939 face symsh;
16940 point p1, p2, p3, pa;
16941 enum locateresult loc;
16942 REAL smallcos, cosa;
16943 REAL largevol, volume;
16944 REAL v1[3], v2[3], len;
16945 int smallidx, largeidx;
16946 int shmark;
16947 int i, j;
16948
16949 abovecount++;
16950
16951 verlist = new list(sizeof(point *), NULL);
16952 trilist = new list(sizeof(face), NULL);
16953 tetlist = new list(sizeof(triface), NULL);
16954
16955
16956
16957
16958
16959 p1 = sorg(*facetsh);
16960 pa = sdest(*facetsh);
16961 if (pointmark(pa) < pointmark(p1)) p1 = pa;
16962 pa = sapex(*facetsh);
16963 if (pointmark(pa) < pointmark(p1)) p1 = pa;
16964
16965 trilist->append(facetsh);
16966 formstarpolygon(p1, trilist, verlist);
16967
16968
16969 p2 = * (point *)(* verlist)[0];
16970
16971 for (i = 0; i < 3; i++) v1[i] = p2[i] - p1[i];
16972 len = sqrt(dot(v1, v1));
16973 assert(len > 0.0);
16974 for (i = 0; i < 3; i++) v1[i] /= len;
16975
16976
16977
16978 smallcos = 1.0;
16979 smallidx = 1;
16980 for (i = 1; i < verlist->len(); i++) {
16981 p3 = * (point *)(* verlist)[i];
16982 for (j = 0; j < 3; j++) v2[j] = p3[j] - p1[j];
16983 len = sqrt(dot(v2, v2));
16984 if (len > 0.0) {
16985 cosa = fabs(dot(v1, v2)) / len;
16986 if (cosa < smallcos) {
16987 smallidx = i;
16988 smallcos = cosa;
16989 }
16990 }
16991 }
16992 assert(smallcos < 1.0);
16993 p3 = * (point *)(* verlist)[smallidx];
16994 verlist->clear();
16995
16996 if (tetrahedrons->items > 0l) {
16997
16998 stpivot(*facetsh, adjtet);
16999 if (adjtet.tet == dummytet) {
17000 sesym(*facetsh, symsh);
17001 stpivot(symsh, adjtet);
17002 }
17003 if (adjtet.tet == dummytet) {
17004 decode(point2tet(p1), adjtet);
17005 if (isdead(&adjtet)) {
17006 adjtet.tet = dummytet;
17007 } else {
17008 if (!findorg(&adjtet, p1)) {
17009 adjtet.tet = dummytet;
17010 }
17011 }
17012 }
17013 if (adjtet.tet == dummytet) {
17014 loc = locate(p1, &adjtet);
17015 if (loc == ONVERTEX) {
17016 setpoint2tet(p1, encode(adjtet));
17017 } else {
17018 adjtet.tet = dummytet;
17019 }
17020 }
17021 if (adjtet.tet != dummytet) {
17022
17023 tetlist->append(&adjtet);
17024 formstarpolyhedron(p1, tetlist, verlist, false);
17025 }
17026 }
17027
17028
17029
17030 largevol = 0.0;
17031 largeidx = 0;
17032 for (i = 0; i < verlist->len(); i++) {
17033 pa = * (point *)(* verlist)[i];
17034 volume = orient3d(p1, p2, p3, pa);
17035 if (!iscoplanar(p1, p2, p3, pa, volume, b->epsilon * 1e+2)) {
17036 if (fabs(volume) > largevol) {
17037 largevol = fabs(volume);
17038 largeidx = i;
17039 }
17040 }
17041 }
17042
17043
17044 if (largevol > 0.0) {
17045 abovepoint = * (point *)(* verlist)[largeidx];
17046 if (b->verbose > 1) {
17047 printf(" Chosen abovepoint %d for facet %d.\n", pointmark(abovepoint),
17048 shellmark(*facetsh));
17049 }
17050 } else {
17051
17052 facenormal(p1, p2, p3, v1, &len);
17053 if (len != 0.0) for (i = 0; i < 3; i++) v1[i] /= len;
17054
17055 len = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
17056
17057 makepoint(&abovepoint);
17058 setpointtype(abovepoint, UNUSEDVERTEX);
17059 unuverts++;
17060 for (i = 0; i < 3; i++) abovepoint[i] = p1[i] + len * v1[i];
17061 if (b->verbose > 1) {
17062 printf(" Calculated abovepoint %d for facet %d.\n",
17063 pointmark(abovepoint), shellmark(*facetsh));
17064 }
17065 }
17066
17067 shmark = shellmark(*facetsh);
17068 facetabovepointarray[shmark] = abovepoint;
17069
17070 delete trilist;
17071 delete tetlist;
17072 delete verlist;
17073 }
17074
17076
17077
17078
17079
17080
17081
17083
17084 void tetgenmesh::collectcavsubs(point newpoint, list* cavsublist)
17085 {
17086 face startsub, neighsub;
17087 face checkseg;
17088 point pa, pb, pc;
17089 REAL sign, ori;
17090 int i, j;
17091
17092
17093 for (i = 0; i < cavsublist->len(); i++) {
17094 startsub = * (face *)(* cavsublist)[i];
17095 sinfect(startsub);
17096 }
17097
17098 for (i = 0; i < cavsublist->len(); i++) {
17099 startsub = * (face *)(* cavsublist)[i];
17100 for (j = 0; j < 3; j++) {
17101 sspivot(startsub, checkseg);
17102
17103 if (checkseg.sh == dummysh) {
17104
17105 spivot(startsub, neighsub);
17106 if (!sinfected(neighsub)) {
17107 pa = sorg(neighsub);
17108 pb = sdest(neighsub);
17109 pc = sapex(neighsub);
17110 sign = insphere(pa, pb, pc, abovepoint, newpoint);
17111 ori = orient3d(pa, pb, pc, abovepoint);
17112 if (sign != 0.0) {
17113
17114 sign = ori > 0.0 ? sign : -sign;
17115 }
17116 if (sign > 0.0) {
17117
17118 sinfect(neighsub);
17119 cavsublist->append(&neighsub);
17120 }
17121 }
17122 }
17123 senextself(startsub);
17124 }
17125 }
17126
17127 for (i = 0; i < cavsublist->len(); i++) {
17128 startsub = * (face *)(* cavsublist)[i];
17129 suninfect(startsub);
17130 }
17131 }
17132
17134
17135
17136
17137
17138
17139
17140
17141
17142
17144
17145 void tetgenmesh::collectvisiblesubs(int shmark, point inspoint, face* horiz,
17146 queue* flipqueue)
17147 {
17148 face newsh, hullsh;
17149 face rightsh, leftsh, spinedge;
17150 point horg, hdest;
17151 bool aboveflag;
17152 REAL ori, sign;
17153
17154
17155 adjustedgering(*horiz, CCW);
17156 horg = sorg(*horiz);
17157 hdest = sdest(*horiz);
17158 ori = orient3d(horg, hdest, sapex(*horiz), abovepoint);
17159 sign = ori > 0.0 ? -1 : 1;
17160
17161
17162 makeshellface(subfaces, &newsh);
17163 setsorg(newsh, hdest);
17164 setsdest(newsh, horg);
17165 setsapex(newsh, inspoint);
17166 setshellmark(newsh, shmark);
17167 if (b->quality && varconstraint) {
17168 setareabound(newsh, areabound(*horiz));
17169 }
17170 if (checkpbcs) {
17171 setshellpbcgroup(newsh, shellpbcgroup(*horiz));
17172 }
17173
17174 sbond(newsh, *horiz);
17175
17176 enqueueflipedge(*horiz, flipqueue);
17177
17178
17179 hullsh = *horiz;
17180 while (1) {
17181 senext(newsh, rightsh);
17182
17183
17184 spinedge = hullsh;
17185 do {
17186 hullsh = spinedge;
17187 senext2self(hullsh);
17188 spivot(hullsh, spinedge);
17189 if (spinedge.sh == dummysh) break;
17190 if (sorg(spinedge) != horg) sesymself(spinedge);
17191 assert(sorg(spinedge) == horg);
17192 } while (true);
17193 horg = sorg(hullsh);
17194
17195 ori = orient3d(horg, sdest(hullsh), abovepoint, inspoint);
17196 ori *= sign;
17197 aboveflag = ori < 0.0;
17198 if (aboveflag) {
17199
17200 makeshellface(subfaces, &newsh);
17201 setsorg(newsh, sdest(hullsh));
17202 setsdest(newsh, horg);
17203 setsapex(newsh, inspoint);
17204 setshellmark(newsh, shmark);
17205 if (b->quality && varconstraint) {
17206 setareabound(newsh, areabound(hullsh));
17207 }
17208 if (checkpbcs) {
17209 setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17210 }
17211
17212 sbond(newsh, hullsh);
17213 senext2(newsh, leftsh);
17214 sbond(leftsh, rightsh);
17215
17216 enqueueflipedge(hullsh, flipqueue);
17217 } else {
17218
17219 dummysh[0] = sencode(rightsh);
17220 break;
17221 }
17222 }
17223
17224
17225 hullsh = *horiz;
17226 spivot(*horiz, newsh);
17227 while (1) {
17228 senext2(newsh, leftsh);
17229
17230 spinedge = hullsh;
17231 do {
17232 hullsh = spinedge;
17233 senextself(hullsh);
17234 spivot(hullsh, spinedge);
17235 if (spinedge.sh == dummysh) break;
17236 if (sdest(spinedge) != hdest) sesymself(spinedge);
17237 assert(sdest(spinedge) == hdest);
17238 } while (true);
17239
17240 hdest = sdest(hullsh);
17241
17242 ori = orient3d(sorg(hullsh), hdest, abovepoint, inspoint);
17243 ori *= sign;
17244 aboveflag = ori < 0.0;
17245 if (aboveflag) {
17246
17247 makeshellface(subfaces, &newsh);
17248 setsorg(newsh, hdest);
17249 setsdest(newsh, sorg(hullsh));
17250 setsapex(newsh, inspoint);
17251 setshellmark(newsh, shmark);
17252 if (b->quality && varconstraint) {
17253 setareabound(newsh, areabound(hullsh));
17254 }
17255 if (checkpbcs) {
17256 setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17257 }
17258
17259 sbond(newsh, hullsh);
17260 senext(newsh, rightsh);
17261 sbond(rightsh, leftsh);
17262
17263 enqueueflipedge(hullsh, flipqueue);
17264 } else {
17265
17266 dummysh[0] = sencode(leftsh);
17267 break;
17268 }
17269 }
17270 }
17271
17273
17274
17275
17276
17277
17278
17279
17281
17282 void tetgenmesh::incrflipdelaunaysub(int shmark, REAL eps, list* ptlist,
17283 int holes, REAL* holelist, queue* flipque)
17284 {
17285 face newsh, startsh;
17286 point *insertarray;
17287 point swappt;
17288 pbcdata *pd;
17289 enum locateresult loc;
17290 REAL det, area;
17291 bool aboveflag;
17292 int arraysize;
17293 int epscount;
17294 int fmarker;
17295 int idx, i, j, k;
17296
17297
17298 insertarray = (point *) ptlist->base;
17299 arraysize = ptlist->len();
17300 if (arraysize < 3) return;
17301
17302
17303 aboveflag = (arraysize > 3);
17304
17305
17306
17307
17308
17309 epscount = 0;
17310 while (true) {
17311 for (i = 1; i < arraysize; i++) {
17312 det = distance(insertarray[0], insertarray[i]);
17313 if (det > (longest * eps)) break;
17314 }
17315 if (i < arraysize) {
17316
17317 swappt = insertarray[i];
17318 insertarray[i] = insertarray[1];
17319 insertarray[1] = swappt;
17320 }
17321
17322 for (i++; i < arraysize; i++) {
17323 if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
17324 break;
17325 }
17326 if (i < arraysize) {
17327
17328 swappt = insertarray[i];
17329 insertarray[i] = insertarray[2];
17330 insertarray[2] = swappt;
17331 i = 3;
17332 } else {
17333
17334
17335
17336 if ((eps == 0.0) || (epscount > 16)) {
17337 printf("Error: Invalid PLC.\n");
17338 printf(" Facet (%d, %d, %d", pointmark(insertarray[0]),
17339 pointmark(insertarray[1]), pointmark(insertarray[2]));
17340 if (ptlist->len() > 3) {
17341 printf(", ...");
17342 }
17343 printf(") (%d) is not a valid polygon.\n", shmark);
17344 terminatetetgen(1);
17345 }
17346
17347 eps *= 1e-2;
17348 epscount++;
17349 continue;
17350 }
17351 break;
17352 }
17353
17354
17355 makeshellface(subfaces, &newsh);
17356 setsorg(newsh, insertarray[0]);
17357 setsdest(newsh, insertarray[1]);
17358 setsapex(newsh, insertarray[2]);
17359
17360 setshellmark(newsh, shmark);
17361
17362 if (pointtype(insertarray[0]) == FREEVOLVERTEX) {
17363 setpointtype(insertarray[0], FREESUBVERTEX);
17364 }
17365 if (pointtype(insertarray[1]) == FREEVOLVERTEX) {
17366 setpointtype(insertarray[1], FREESUBVERTEX);
17367 }
17368 if (pointtype(insertarray[2]) == FREEVOLVERTEX) {
17369 setpointtype(insertarray[2], FREESUBVERTEX);
17370 }
17371
17372 dummysh[0] = sencode(newsh);
17373
17374
17375 if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
17376 idx = in->facetmarkerlist[shmark - 1];
17377 for (k = 0; k < in->numberoffacetconstraints; k++) {
17378 fmarker = (int) in->facetconstraintlist[k * 2];
17379 if (fmarker == idx) {
17380 area = in->facetconstraintlist[k * 2 + 1];
17381 setareabound(newsh, area);
17382 break;
17383 }
17384 }
17385 }
17386
17387
17388 if (checkpbcs) {
17389 idx = in->facetmarkerlist[shmark - 1];
17390 for (k = 0; k < in->numberofpbcgroups; k++) {
17391 pd = &subpbcgrouptable[k];
17392 for (j = 0; j < 2; j++) {
17393 if (pd->fmark[j] == idx) {
17394 setshellpbcgroup(newsh, k);
17395 pd->ss[j] = newsh;
17396 }
17397 }
17398 }
17399 }
17400
17401 if (aboveflag) {
17402
17403 abovepoint = facetabovepointarray[shmark];
17404 if (abovepoint == (point) NULL) {
17405 getfacetabovepoint(&newsh);
17406 }
17407 }
17408
17409 if (holes > 0) {
17410
17411 REAL prj[3];
17412 for (k = 0; k < holes; k++) {
17413 projpt2face(&(holelist[k * 3]), insertarray[0], insertarray[1],
17414 insertarray[2], prj);
17415 for (j = 0; j < 3; j++) holelist[k * 3 + j] = prj[j];
17416 }
17417 }
17418
17419
17420 for (; i < arraysize; i++) {
17421
17422 startsh.sh = dummysh;
17423 loc = locatesub(insertarray[i], &startsh, 0, 0.0);
17424 if (loc == ONFACE) {
17425 splitsubface(insertarray[i], &startsh, flipque);
17426 } else if (loc == ONEDGE) {
17427 splitsubedge(insertarray[i], &startsh, flipque);
17428 } else if (loc == OUTSIDE) {
17429 collectvisiblesubs(shmark, insertarray[i], &startsh, flipque);
17430 } else if (loc == ONVERTEX) {
17431
17432 }
17433
17434 if (pointtype(insertarray[i]) == FREEVOLVERTEX) {
17435 setpointtype(insertarray[i], FREESUBVERTEX);
17436 }
17437 flipsub(flipque);
17438 }
17439 }
17440
17442
17443
17444
17445
17446
17447
17448
17449
17450
17451
17452
17453
17455
17456 enum tetgenmesh::finddirectionresult tetgenmesh::finddirectionsub(
17457 face* searchsh, point tend)
17458 {
17459 face checksh;
17460 point startpoint, leftpoint, rightpoint;
17461 REAL leftccw, rightccw;
17462 REAL ori, sign;
17463 int leftflag, rightflag;
17464
17465 startpoint = sorg(*searchsh);
17466
17467 adjustedgering(*searchsh, CCW);
17468
17469 if (sorg(*searchsh) != startpoint) senextself(*searchsh);
17470 rightpoint = sdest(*searchsh);
17471 leftpoint = sapex(*searchsh);
17472 ori = orient3d(startpoint, rightpoint, leftpoint, abovepoint);
17473 sign = ori > 0.0 ? -1 : 1;
17474
17475
17476 ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17477 leftccw = ori * sign;
17478 leftflag = leftccw > 0.0;
17479
17480 ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17481 rightccw = ori * sign;
17482 rightflag = rightccw > 0.0;
17483 if (leftflag && rightflag) {
17484
17485
17486 senext2(*searchsh, checksh);
17487 spivotself(checksh);
17488 if (checksh.sh == dummysh) {
17489 leftflag = 0;
17490 } else {
17491 rightflag = 0;
17492 }
17493 }
17494 while (leftflag) {
17495
17496 senext2self(*searchsh);
17497 spivotself(*searchsh);
17498 if (searchsh->sh == dummysh) {
17499 printf("Internal error in finddirectionsub(): Unable to find a\n");
17500 printf(" subface leading from %d to %d.\n", pointmark(startpoint),
17501 pointmark(tend));
17502 internalerror();
17503 }
17504 if (sorg(*searchsh) != startpoint) sesymself(*searchsh);
17505 assert(sorg(*searchsh) == startpoint);
17506 leftpoint = sapex(*searchsh);
17507 rightccw = leftccw;
17508 ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17509 leftccw = ori * sign;
17510 leftflag = leftccw > 0.0;
17511 }
17512 while (rightflag) {
17513
17514 spivotself(*searchsh);
17515 if (searchsh->sh == dummysh) {
17516 printf("Internal error in finddirectionsub(): Unable to find a\n");
17517 printf(" subface leading from %d to %d.\n", pointmark(startpoint),
17518 pointmark(tend));
17519 internalerror();
17520 }
17521 if (sdest(*searchsh) != startpoint) sesymself(*searchsh);
17522 assert(sdest(*searchsh) == startpoint);
17523 senextself(*searchsh);
17524 rightpoint = sdest(*searchsh);
17525 leftccw = rightccw;
17526 ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17527 rightccw = ori * sign;
17528 rightflag = rightccw > 0.0;
17529 }
17530 if (leftccw == 0.0) {
17531 return LEFTCOLLINEAR;
17532 } else if (rightccw == 0.0) {
17533 return RIGHTCOLLINEAR;
17534 } else {
17535 return ACROSSEDGE;
17536 }
17537 }
17538
17540
17541
17542
17543
17544
17545
17546
17547
17549
17550 void tetgenmesh::insertsubseg(face* tri)
17551 {
17552 face oppotri;
17553 face newsubseg;
17554 point pa, pb;
17555 REAL len;
17556 int e1, e2;
17557 int i;
17558
17559
17560 sspivot(*tri, newsubseg);
17561 if (newsubseg.sh == dummysh) {
17562
17563 makeshellface(subsegs, &newsubseg);
17564 pa = sorg(*tri);
17565 pb = sdest(*tri);
17566 setsorg(newsubseg, pa);
17567 setsdest(newsubseg, pb);
17568
17569 if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
17570 for (i = 0; i < in->numberofsegmentconstraints; i++) {
17571 e1 = (int) in->segmentconstraintlist[i * 3];
17572 e2 = (int) in->segmentconstraintlist[i * 3 + 1];
17573 if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
17574 ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
17575 len = in->segmentconstraintlist[i * 3 + 2];
17576 setareabound(newsubseg, len);
17577 break;
17578 }
17579 }
17580 }
17581
17582 ssbond(*tri, newsubseg);
17583 spivot(*tri, oppotri);
17584
17585 if (oppotri.sh != dummysh) {
17586 ssbond(oppotri, newsubseg);
17587 }
17588
17589
17590
17591 }
17592 }
17593
17595
17596
17597
17598
17599
17600
17601
17602
17603
17605
17606 bool tetgenmesh::scoutsegmentsub(face* searchsh, point tend)
17607 {
17608 face newsubseg;
17609 face crosssub, crosssubseg;
17610 point leftpoint, rightpoint;
17611 enum finddirectionresult collinear;
17612
17613 collinear = finddirectionsub(searchsh, tend);
17614 rightpoint = sdest(*searchsh);
17615 leftpoint = sapex(*searchsh);
17616 if (rightpoint == tend || leftpoint == tend) {
17617
17618 if (leftpoint == tend) {
17619 senext2self(*searchsh);
17620 }
17621
17622 insertsubseg(searchsh);
17623 return true;
17624 } else if (collinear == LEFTCOLLINEAR) {
17625
17626
17627 senextself(*searchsh);
17628
17629 insertsubseg(searchsh);
17630
17631 return scoutsegmentsub(searchsh, tend);
17632 } else if (collinear == RIGHTCOLLINEAR) {
17633
17634
17635 insertsubseg(searchsh);
17636
17637 senextself(*searchsh);
17638
17639 return scoutsegmentsub(searchsh, tend);
17640 } else {
17641 senext(*searchsh, crosssub);
17642
17643 sspivot(crosssub, crosssubseg);
17644 #ifdef SELF_CHECK
17645 assert(crosssubseg.sh == dummysh);
17646 #endif
17647 return false;
17648 }
17649 }
17650
17652
17653
17654
17655
17656
17657
17658
17659
17660
17662
17663 void tetgenmesh::flipedgerecursive(face* flipedge, queue* flipqueue)
17664 {
17665 face fixupsh;
17666 point pa, pb, pc, pd;
17667 REAL oria, orib;
17668 bool doflip;
17669
17670 pa = sorg(*flipedge);
17671 pb = sdest(*flipedge);
17672 pc = sapex(*flipedge);
17673 do {
17674 spivot(*flipedge, fixupsh);
17675 pd = sapex(fixupsh);
17676 oria = orient3d(pc, pd, abovepoint, pa);
17677 orib = orient3d(pc, pd, abovepoint, pb);
17678 doflip = (oria * orib < 0.0);
17679 if (doflip) {
17680
17681 flip22sub(flipedge, flipqueue);
17682
17683 findedge(flipedge, pc, pd);
17684 } else {
17685
17686 if (sorg(fixupsh) != pb) sesymself(fixupsh);
17687 assert(sdest(fixupsh) == pa);
17688 if (fabs(oria) > fabs(orib)) {
17689
17690 senextself(fixupsh);
17691 } else {
17692
17693 senext2self(fixupsh);
17694 }
17695
17696 flipedgerecursive(&fixupsh, flipqueue);
17697 }
17698 } while (!doflip);
17699 }
17700
17702
17703
17704
17705
17706
17707
17708
17709
17710
17712
17713 void tetgenmesh::constrainededge(face* startsh, point tend, queue* flipqueue)
17714 {
17715 point tstart, tright, tleft;
17716 REAL rori, lori;
17717 bool collision;
17718
17719 tstart = sorg(*startsh);
17720 do {
17721
17722 do {
17723 tright = sdest(*startsh);
17724 tleft = sapex(*startsh);
17725
17726 rori = orient3d(tstart, tright, abovepoint, tend);
17727 collision = (rori == 0.0);
17728 if (collision) break;
17729 lori = orient3d(tstart, tleft, abovepoint, tend);
17730 collision = (lori == 0.0);
17731 if (collision) {
17732 senext2self(*startsh);
17733 break;
17734 }
17735 if (rori * lori < 0.0) break;
17736
17737 finddirectionsub(startsh, tend);
17738 } while (true);
17739 if (collision) break;
17740
17741 senextself(*startsh);
17742
17743 flipedgerecursive(startsh, flipqueue);
17744
17745 assert(sorg(*startsh) == tstart);
17746 } while (sdest(*startsh) != tend);
17747
17748
17749 insertsubseg(startsh);
17750
17751
17752 if (collision) {
17753
17754 if (!scoutsegmentsub(startsh, tend)) {
17755 constrainededge(startsh, tend, flipqueue);
17756 }
17757 }
17758 }
17759
17761
17762
17763
17765
17766 void tetgenmesh::recoversegment(point tstart, point tend, queue* flipqueue)
17767 {
17768 face searchsh;
17769
17770 if (b->verbose > 2) {
17771 printf(" Insert seg (%d, %d).\n", pointmark(tstart), pointmark(tend));
17772 }
17773
17774
17775 searchsh.sh = dummysh;
17776
17777 if (locatesub(tstart, &searchsh, 0, 0.0) != ONVERTEX) {
17778
17779 list *newshlist;
17780 int i, j;
17781 newshlist = new list(sizeof(face), NULL, 256);
17782
17783 retrievenewsubs(newshlist, false);
17784
17785 for (i = 0; i < newshlist->len(); i++) {
17786 searchsh = * (face *)(* newshlist)[i];
17787 for (j = 0; j < 3; j++) {
17788 if (sorg(searchsh) == tstart) break;
17789 senextself(searchsh);
17790 }
17791 if (j < 3) break;
17792 }
17793 delete newshlist;
17794 if (sorg(searchsh) != tstart) {
17795 printf("Internal error in recoversegment(): Vertex location failed.\n");
17796 internalerror();
17797 }
17798 }
17799
17800 if (scoutsegmentsub(&searchsh, tend)) {
17801
17802 return;
17803 }
17804
17805 constrainededge(&searchsh, tend, flipqueue);
17806
17807 flipsub(flipqueue);
17808 }
17809
17811
17812
17813
17814
17816
17817 void tetgenmesh::infecthullsub(memorypool* viri)
17818 {
17819 face hulltri, nexttri, starttri;
17820 face hullsubseg;
17821 shellface **deadshellface;
17822
17823
17824 hulltri.sh = dummysh;
17825 hulltri.shver = 0;
17826 spivotself(hulltri);
17827 adjustedgering(hulltri, CCW);
17828
17829 starttri = hulltri;
17830
17831 do {
17832
17833 if (!sinfected(hulltri)) {
17834
17835 sspivot(hulltri, hullsubseg);
17836 if (hullsubseg.sh == dummysh) {
17837
17838 if (!sinfected(hulltri)) {
17839 sinfect(hulltri);
17840 deadshellface = (shellface **) viri->alloc();
17841 *deadshellface = hulltri.sh;
17842 }
17843 }
17844 }
17845
17846 senextself(hulltri);
17847 spivot(hulltri, nexttri);
17848 if (nexttri.sh == hulltri.sh) {
17849 nexttri.sh = dummysh;
17850 } else {
17851 adjustedgering(nexttri, CCW);
17852 senextself(nexttri);
17853 }
17854 while (nexttri.sh != dummysh) {
17855 hulltri = nexttri;
17856 spivot(hulltri, nexttri);
17857 if (nexttri.sh == hulltri.sh) {
17858 nexttri.sh = dummysh;
17859 } else {
17860 adjustedgering(nexttri, CCW);
17861 senextself(nexttri);
17862 }
17863 }
17864 } while (hulltri != starttri);
17865 }
17866
17868
17869
17870
17871
17872
17873
17874
17876
17877 void tetgenmesh::plaguesub(memorypool* viri)
17878 {
17879 face testtri, neighbor, ghostsh;
17880 face neighborsubseg;
17881 shellface **virusloop;
17882 shellface **deadshellface;
17883 int i;
17884
17885
17886
17887 viri->traversalinit();
17888 virusloop = (shellface **) viri->traverse();
17889 while (virusloop != (shellface **) NULL) {
17890 testtri.sh = *virusloop;
17891
17892 for (i = 0; i < 3; i++) {
17893
17894 spivot(testtri, neighbor);
17895
17896 sspivot(testtri, neighborsubseg);
17897
17898 if ((neighbor.sh == dummysh) || sinfected(neighbor)) {
17899 if (neighborsubseg.sh != dummysh) {
17900
17901
17902
17903 shellfacedealloc(subsegs, neighborsubseg.sh);
17904 if (neighbor.sh != dummysh) {
17905
17906
17907 ssdissolve(neighbor);
17908 }
17909 }
17910 } else {
17911 if (neighborsubseg.sh == dummysh) {
17912
17913
17914 sinfect(neighbor);
17915
17916 deadshellface = (shellface **) viri->alloc();
17917 *deadshellface = neighbor.sh;
17918 } else {
17919
17920 ssbond(neighbor, neighborsubseg);
17921 }
17922 }
17923 senextself(testtri);
17924 }
17925 virusloop = (shellface **) viri->traverse();
17926 }
17927
17928 ghostsh.sh = dummysh;
17929 viri->traversalinit();
17930 virusloop = (shellface **) viri->traverse();
17931 while (virusloop != (shellface **) NULL) {
17932 testtri.sh = *virusloop;
17933
17934
17935 for (i = 0; i < 3; i++) {
17936 spivot(testtri, neighbor);
17937 if (neighbor.sh != dummysh) {
17938
17939
17940 sbond(neighbor, ghostsh);
17941 }
17942 senextself(testtri);
17943 }
17944
17945 shellfacedealloc(subfaces, testtri.sh);
17946 virusloop = (shellface **) viri->traverse();
17947 }
17948
17949 viri->restart();
17950 }
17951
17953
17954
17955
17956
17957
17958
17959
17960
17962
17963 void tetgenmesh::carveholessub(int holes, REAL* holelist, memorypool *viri)
17964 {
17965 face searchtri, triangleloop;
17966 shellface **holetri;
17967 enum locateresult intersect;
17968 int i;
17969
17970
17971
17972 infecthullsub(viri);
17973
17974 if (holes > 0) {
17975
17976 for (i = 0; i < 3 * holes; i += 3) {
17977
17978 if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
17979 && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)
17980 && (holelist[i + 2] >= zmin) && (holelist[i + 2] <= zmax)) {
17981
17982 searchtri.sh = dummysh;
17983
17984 intersect = locatesub(&holelist[i], &searchtri, 0, 0.0);
17985 if ((intersect != OUTSIDE) && (!sinfected(searchtri))) {
17986
17987
17988 sinfect(searchtri);
17989 holetri = (shellface **) viri->alloc();
17990 *holetri = searchtri.sh;
17991 }
17992 }
17993 }
17994 }
17995
17996 if (viri->items > 0) {
17997
17998 plaguesub(viri);
17999 }
18000
18001 }
18002
18004
18005
18006
18007
18008
18009
18010
18011
18012
18013
18014
18015
18016
18017
18018
18020
18021 void tetgenmesh::triangulate(int shmark, REAL eps, list* ptlist, list* conlist,
18022 int holes, REAL* holelist, memorypool* viri, queue* flipqueue)
18023 {
18024 face newsh;
18025 point *cons;
18026 int i;
18027
18028 if (b->verbose > 1) {
18029 printf(" %d vertices, %d segments", ptlist->len(), conlist->len());
18030 if (holes > 0) {
18031 printf(", %d holes", holes);
18032 }
18033 printf(", shmark: %d.\n", shmark);
18034 }
18035
18036
18037 incrflipdelaunaysub(shmark, eps, ptlist, holes, holelist, flipqueue);
18038
18039 if (ptlist->len() > 3) {
18040
18041 for (i = 0; i < conlist->len(); i++) {
18042 cons = (point *)(* conlist)[i];
18043 recoversegment(cons[0], cons[1], flipqueue);
18044 }
18045
18046 carveholessub(holes, holelist, viri);
18047 } else if (ptlist->len() == 3) {
18048
18049 newsh.sh = dummysh;
18050 newsh.shver = 0;
18051 spivotself(newsh);
18052 for (i = 0; i < 3; i++) {
18053 insertsubseg(&newsh);
18054 senextself(newsh);
18055 }
18056 } else if (ptlist->len() == 2) {
18057
18058
18059
18060 cons = (point *)(* conlist)[0];
18061 makeshellface(subsegs, &newsh);
18062 setsorg(newsh, cons[0]);
18063 setsdest(newsh, cons[1]);
18064 }
18065 }
18066
18068
18069
18070
18071
18072
18073
18074
18075
18076
18077
18079
18080 void tetgenmesh::retrievenewsubs(list* newshlist, bool removeseg)
18081 {
18082 face startsh, neighsh;
18083 face deadseg;
18084 int i, j;
18085
18086
18087 startsh.sh = dummysh;
18088 startsh.shver = 0;
18089 spivotself(startsh);
18090 assert(startsh.sh != dummysh);
18091 sinfect(startsh);
18092 newshlist->append(&startsh);
18093
18094
18095 for (i = 0; i < newshlist->len(); i++) {
18096
18097 startsh = * (face *)(* newshlist)[i];
18098 for (j = 0; j < 3; j++) {
18099 spivot(startsh, neighsh);
18100 if (neighsh.sh != dummysh) {
18101 if (!sinfected(neighsh)) {
18102
18103 sinfect(neighsh);
18104 newshlist->append(&neighsh);
18105 }
18106 } else {
18107
18108 if (removeseg) {
18109
18110 sspivot(startsh, deadseg);
18111 if (deadseg.sh != dummysh) {
18112
18113 ssdissolve(startsh);
18114
18115 shellfacedealloc(subsegs, deadseg.sh);
18116 }
18117 }
18118 }
18119 senextself(startsh);
18120 }
18121 }
18122 for (i = 0; i < newshlist->len(); i++) {
18123 startsh = * (face *)(* newshlist)[i];
18124 suninfect(startsh);
18125 }
18126 }
18127
18129
18130
18131
18132
18133
18134
18135
18136
18137
18138
18139
18140
18141
18142
18144
18145 void tetgenmesh::unifysegments()
18146 {
18147 list *sfacelist;
18148 shellface **facesperverlist;
18149 face subsegloop, testseg;
18150 face sface, sface1, sface2;
18151 point torg, tdest;
18152 REAL da1, da2;
18153 int *idx2facelist;
18154 int segmarker;
18155 int idx, k, m;
18156
18157 if (b->verbose > 0) {
18158 printf(" Unifying segments.\n");
18159 }
18160
18161
18162 makesubfacemap(idx2facelist, facesperverlist);
18163
18164 sfacelist = new list(sizeof(face), NULL);
18165
18166 segmarker = 1;
18167 subsegs->traversalinit();
18168 subsegloop.sh = shellfacetraverse(subsegs);
18169 while (subsegloop.sh != (shellface *) NULL) {
18170 subsegloop.shver = 0;
18171 torg = sorg(subsegloop);
18172 tdest = sdest(subsegloop);
18173 idx = pointmark(torg) - in->firstnumber;
18174
18175
18176
18177
18178 for (k = idx2facelist[idx]; k < idx2facelist[idx + 1]; k++) {
18179 sface.sh = facesperverlist[k];
18180 sface.shver = 0;
18181
18182 if (!isdead(&sface) && isfacehasedge(&sface, torg, tdest)) {
18183
18184 findedge(&sface, torg, tdest);
18185
18186 if (sfacelist->len() < 2) {
18187 sfacelist->append(&sface);
18188 } else {
18189 for (m = 0; m < sfacelist->len() - 1; m++) {
18190 sface1 = * (face *)(* sfacelist)[m];
18191 sface2 = * (face *)(* sfacelist)[m + 1];
18192 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(sface));
18193 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
18194 if (da1 < da2) {
18195 break;
18196 }
18197 }
18198 sfacelist->insert(m + 1, &sface);
18199 }
18200 }
18201 }
18202 if (b->verbose > 1) {
18203 printf(" Identifying %d segments of (%d %d).\n", sfacelist->len(),
18204 pointmark(torg), pointmark(tdest));
18205 }
18206
18207
18208 for (k = 0; k < sfacelist->len(); k++) {
18209 sface = *(face *)(* sfacelist)[k];
18210 sspivot(sface, testseg);
18211
18212
18213
18214 if ((testseg.sh != subsegloop.sh) && !isdead(&testseg)) {
18215 shellfacedealloc(subsegs, testseg.sh);
18216 }
18217
18218
18219 ssbond(sface, subsegloop);
18220 }
18221
18222 sface = *(face *)(* sfacelist)[0];
18223 for (k = 1; k <= sfacelist->len(); k++) {
18224 if (k < sfacelist->len()) {
18225 sface1 = *(face *)(* sfacelist)[k];
18226 } else {
18227 sface1 = *(face *)(* sfacelist)[0];
18228 }
18229
18230
18231
18232
18233
18234
18235
18236
18237
18238
18239
18240
18241
18242
18243
18244
18245
18246
18247
18248
18249
18250
18251
18252
18253
18254
18255
18256 if (b->verbose > 2) {
18257 printf(" Bond subfaces (%d, %d, %d) and (%d, %d, %d).\n",
18258 pointmark(torg), pointmark(tdest), pointmark(sapex(sface)),
18259 pointmark(torg), pointmark(tdest), pointmark(sapex(sface1)));
18260 }
18261 sbond1(sface, sface1);
18262 sface = sface1;
18263 }
18264
18265 setshellmark(subsegloop, segmarker);
18266
18267 segmarker++;
18268
18269 sfacelist->clear();
18270 subsegloop.sh = shellfacetraverse(subsegs);
18271 }
18272
18273 delete [] idx2facelist;
18274 delete [] facesperverlist;
18275 delete sfacelist;
18276 }
18277
18279
18280
18281
18282
18283
18284
18285
18286
18287
18289
18290 void tetgenmesh::mergefacets(queue* flipqueue)
18291 {
18292 face parentsh, neighsh, neineighsh;
18293 face segloop;
18294 point eorg, edest;
18295 REAL ori;
18296 bool mergeflag, pbcflag;
18297 int* segspernodelist;
18298 int fidx1, fidx2;
18299 int i, j;
18300
18301 if (b->verbose > 0) {
18302 printf(" Merging coplanar facets.\n");
18303 }
18304
18305 segspernodelist = new int[points->items + 1];
18306 for (i = 0; i < points->items + 1; i++) segspernodelist[i] = 0;
18307
18308
18309 subsegs->traversalinit();
18310 segloop.sh = shellfacetraverse(subsegs);
18311 while (segloop.sh != (shellface *) NULL) {
18312
18313 for (i = 0; i < 2; i++) {
18314 j = pointmark((point) segloop.sh[3 + i]);
18315 segspernodelist[j]++;
18316 }
18317 segloop.sh = shellfacetraverse(subsegs);
18318 }
18319
18320
18321 subsegs->traversalinit();
18322 segloop.sh = shellfacetraverse(subsegs);
18323 while (segloop.sh != (shellface *) NULL) {
18324 eorg = sorg(segloop);
18325 edest = sdest(segloop);
18326 spivot(segloop, parentsh);
18327 spivot(parentsh, neighsh);
18328 spivot(neighsh, neineighsh);
18329 if (parentsh.sh != neighsh.sh && parentsh.sh == neineighsh.sh) {
18330
18331 fidx1 = shellmark(parentsh) - 1;
18332 fidx2 = shellmark(neighsh) - 1;
18333 pbcflag = false;
18334 if (checkpbcs) {
18335 pbcflag = (shellpbcgroup(parentsh) >= 0)
18336 || (shellpbcgroup(neighsh) >= 0);
18337 }
18338
18339 if ((fidx1 != fidx2) && !pbcflag) {
18340
18341 ori = orient3d(eorg, edest, sapex(parentsh), sapex(neighsh));
18342 if (ori != 0.0) {
18343 if (iscoplanar(eorg, edest, sapex(parentsh), sapex(neighsh), ori,
18344 b->epsilon)) {
18345 ori = 0.0;
18346 }
18347 }
18348 if (ori == 0.0) {
18349 mergeflag = (in->facetmarkerlist == (int *) NULL ||
18350 in->facetmarkerlist[fidx1] == in->facetmarkerlist[fidx2]);
18351 if (mergeflag) {
18352
18353 if (b->verbose > 1) {
18354 printf(" Removing segment (%d, %d).\n", pointmark(eorg),
18355 pointmark(edest));
18356 }
18357 ssdissolve(parentsh);
18358 ssdissolve(neighsh);
18359 shellfacedealloc(subsegs, segloop.sh);
18360 j = pointmark(eorg);
18361 segspernodelist[j]--;
18362 if (segspernodelist[j] == 0) {
18363 setpointtype(eorg, FREESUBVERTEX);
18364 }
18365 j = pointmark(edest);
18366 segspernodelist[j]--;
18367 if (segspernodelist[j] == 0) {
18368 setpointtype(edest, FREESUBVERTEX);
18369 }
18370
18371 enqueueflipedge(parentsh, flipqueue);
18372 }
18373 }
18374 }
18375 }
18376 segloop.sh = shellfacetraverse(subsegs);
18377 }
18378
18379 if (!flipqueue->empty()) {
18380
18381 flipsub(flipqueue);
18382 }
18383
18384 delete [] segspernodelist;
18385 }
18386
18388
18389
18390
18391
18392
18393
18394
18395
18396
18397
18398
18399
18400
18401
18402
18403
18404
18406
18407 long tetgenmesh::meshsurface()
18408 {
18409 list *ptlist, *conlist;
18410 queue *flipqueue;
18411 tetgenio::facet *f;
18412 tetgenio::polygon *p;
18413 memorypool *viri;
18414 point *idx2verlist;
18415 point tstart, tend, *cons;
18416 int *worklist;
18417 int end1, end2;
18418 int shmark, i, j;
18419
18420 if (!b->quiet) {
18421 printf("Creating surface mesh.\n");
18422 }
18423
18424
18425 makeindex2pointmap(idx2verlist);
18426
18427 makepoint2tetmap();
18428
18429 facetabovepointarray = new point[in->numberoffacets + 1];
18430 for (i = 0; i < in->numberoffacets + 1; i++) {
18431 facetabovepointarray[i] = (point) NULL;
18432 }
18433 if (checkpbcs) {
18434
18435 createsubpbcgrouptable();
18436 }
18437
18438
18439 viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
18440 flipqueue = new queue(sizeof(badface));
18441 ptlist = new list(sizeof(point *), NULL, 256);
18442 conlist = new list(sizeof(point *) * 2, NULL, 256);
18443 worklist = new int[points->items + 1];
18444 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
18445
18446
18447
18448
18449 for (shmark = 1; shmark <= in->numberoffacets; shmark++) {
18450
18451 f = &in->facetlist[shmark - 1];
18452
18453
18454
18455
18456
18457 if ((b->object == tetgenbehavior::STL) || dupverts) {
18458
18459 for (i = 0; i < f->numberofpolygons; i++) {
18460 p = &(f->polygonlist[i]);
18461
18462 for (j = 0; j < p->numberofvertices; j++) {
18463 end1 = p->vertexlist[j];
18464 tstart = idx2verlist[end1 - in->firstnumber];
18465 if (pointtype(tstart) == DUPLICATEDVERTEX) {
18466
18467 tend = point2ppt(tstart);
18468 end2 = pointmark(tend);
18469 p->vertexlist[j] = end2;
18470 }
18471 }
18472 }
18473 }
18474
18475
18476 for (i = 0; i < f->numberofpolygons; i++) {
18477
18478 p = &(f->polygonlist[i]);
18479
18480 end1 = p->vertexlist[0];
18481 if ((end1 < in->firstnumber) ||
18482 (end1 >= in->firstnumber + in->numberofpoints)) {
18483 if (!b->quiet) {
18484 printf("Warning: Invalid the 1st vertex %d of polygon", end1);
18485 printf(" %d in facet %d.\n", i + 1, shmark);
18486 }
18487 continue;
18488 }
18489 tstart = idx2verlist[end1 - in->firstnumber];
18490
18491 if (worklist[end1] == 0) {
18492 ptlist->append(&tstart);
18493 worklist[end1] = 1;
18494 }
18495
18496 for (j = 1; j <= p->numberofvertices; j++) {
18497
18498 if (j < p->numberofvertices) {
18499 end2 = p->vertexlist[j];
18500 } else {
18501 end2 = p->vertexlist[0];
18502 }
18503 if ((end2 < in->firstnumber) ||
18504 (end2 >= in->firstnumber + in->numberofpoints)) {
18505 if (!b->quiet) {
18506 printf("Warning: Invalid vertex %d in polygon %d", end2, i + 1);
18507 printf(" in facet %d.\n", shmark);
18508 }
18509 } else {
18510 if (end1 != end2) {
18511
18512 tend = idx2verlist[end2 - in->firstnumber];
18513
18514 if (worklist[end2] == 0) {
18515 ptlist->append(&tend);
18516 worklist[end2] = 1;
18517 }
18518
18519 cons = (point *) conlist->append(NULL);
18520 cons[0] = tstart;
18521 cons[1] = tend;
18522
18523 end1 = end2;
18524 tstart = tend;
18525 } else {
18526
18527 if (p->numberofvertices > 2) {
18528
18529
18530 if (!b->quiet) {
18531 printf("Warning: Polygon %d has two identical verts", i + 1);
18532 printf(" in facet %d.\n", shmark);
18533 }
18534 }
18535
18536 }
18537 }
18538
18539 if (p->numberofvertices == 2) break;
18540 }
18541 }
18542
18543 for (i = 0; i < ptlist->len(); i++) {
18544 tstart = * (point *)(* ptlist)[i];
18545 end1 = pointmark(tstart);
18546 assert(worklist[end1] == 1);
18547 worklist[end1] = 0;
18548 }
18549
18550
18551 triangulate(shmark, b->epsilon * 1e+2, ptlist, conlist, f->numberofholes,
18552 f->holelist, viri, flipqueue);
18553
18554 ptlist->clear();
18555 conlist->clear();
18556 viri->restart();
18557 }
18558
18559
18560
18561 unifysegments();
18562
18563 insegments = subsegs->items;
18564
18565 if (checkpbcs) {
18566
18567 createsegpbcgrouptable();
18568 }
18569
18570 if (b->object == tetgenbehavior::STL) {
18571
18572 jettisonnodes();
18573 }
18574
18575 if (!b->nomerge && !b->nobisect && !checkpbcs) {
18576
18577 mergefacets(flipqueue);
18578 }
18579
18580 delete [] idx2verlist;
18581 delete [] worklist;
18582 delete ptlist;
18583 delete conlist;
18584 delete flipqueue;
18585 delete viri;
18586
18587 return subsegs->items;
18588 }
18589
18590
18591
18592
18593
18595
18596
18597
18598
18599
18600
18601
18602
18603
18604
18605
18606
18607
18608
18609
18610
18611
18612
18613
18614
18615
18617
18618 void tetgenmesh::
18619 interecursive(shellface** subfacearray, int arraysize, int axis, REAL bxmin,
18620 REAL bxmax, REAL bymin, REAL bymax, REAL bzmin, REAL bzmax,
18621 int* internum)
18622 {
18623 shellface **leftarray, **rightarray;
18624 face sface1, sface2;
18625 point p1, p2, p3;
18626 point p4, p5, p6;
18627 enum interresult intersect;
18628 REAL split;
18629 bool toleft, toright;
18630 int leftsize, rightsize;
18631 int i, j;
18632
18633 if (b->verbose > 1) {
18634 printf(" Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
18635 arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
18636 axis == 0 ? "x" : (axis == 1 ? "y" : "z"));
18637 }
18638
18639 leftarray = new shellface*[arraysize];
18640 if (leftarray == NULL) {
18641 printf("Error in interecursive(): Insufficient memory.\n");
18642 terminatetetgen(1);
18643 }
18644 rightarray = new shellface*[arraysize];
18645 if (rightarray == NULL) {
18646 printf("Error in interecursive(): Insufficient memory.\n");
18647 terminatetetgen(1);
18648 }
18649 leftsize = rightsize = 0;
18650
18651 if (axis == 0) {
18652
18653 split = 0.5 * (bxmin + bxmax);
18654 } else if (axis == 1) {
18655
18656 split = 0.5 * (bymin + bymax);
18657 } else {
18658
18659 split = 0.5 * (bzmin + bzmax);
18660 }
18661
18662 for (i = 0; i < arraysize; i++) {
18663 sface1.sh = subfacearray[i];
18664 p1 = (point) sface1.sh[3];
18665 p2 = (point) sface1.sh[4];
18666 p3 = (point) sface1.sh[5];
18667 toleft = toright = false;
18668 if (p1[axis] < split) {
18669 toleft = true;
18670 if (p2[axis] >= split || p3[axis] >= split) {
18671 toright = true;
18672 }
18673 } else if (p1[axis] > split) {
18674 toright = true;
18675 if (p2[axis] <= split || p3[axis] <= split) {
18676 toleft = true;
18677 }
18678 } else {
18679
18680 toleft = true;
18681 toright = true;
18682 }
18683
18684 #ifdef SELF_CHECK
18685 assert(!(toleft == false && toright == false));
18686 #endif
18687 if (toleft) {
18688 leftarray[leftsize] = sface1.sh;
18689 leftsize++;
18690 }
18691 if (toright) {
18692 rightarray[rightsize] = sface1.sh;
18693 rightsize++;
18694 }
18695 }
18696
18697 if (leftsize < arraysize && rightsize < arraysize) {
18698
18699
18700
18701
18702 delete [] subfacearray;
18703
18704 if (axis == 0) {
18705 interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax,
18706 bzmin, bzmax, internum);
18707 interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax,
18708 bzmin, bzmax, internum);
18709 } else if (axis == 1) {
18710 interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split,
18711 bzmin, bzmax, internum);
18712 interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax,
18713 bzmin, bzmax, internum);
18714 } else {
18715 interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax,
18716 bzmin, split, internum);
18717 interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax,
18718 split, bzmax, internum);
18719 }
18720 } else {
18721 if (b->verbose > 1) {
18722 printf(" Checking intersecting faces.\n");
18723 }
18724
18725 for (i = 0; i < arraysize; i++) {
18726 sface1.sh = subfacearray[i];
18727 p1 = (point) sface1.sh[3];
18728 p2 = (point) sface1.sh[4];
18729 p3 = (point) sface1.sh[5];
18730 for (j = i + 1; j < arraysize; j++) {
18731 sface2.sh = subfacearray[j];
18732 p4 = (point) sface2.sh[3];
18733 p5 = (point) sface2.sh[4];
18734 p6 = (point) sface2.sh[5];
18735 intersect = tri_tri_inter(p1, p2, p3, p4, p5, p6);
18736 if (intersect == INTERSECT || intersect == SHAREFACE) {
18737 if (!b->quiet) {
18738 if (intersect == INTERSECT) {
18739 printf(" Facet #%d intersects facet #%d at triangles:\n",
18740 shellmark(sface1), shellmark(sface2));
18741 printf(" (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
18742 pointmark(p1), pointmark(p2), pointmark(p3),
18743 pointmark(p4), pointmark(p5), pointmark(p6));
18744 } else {
18745 printf(" Facet #%d duplicates facet #%d at triangle:\n",
18746 shellmark(sface1), shellmark(sface2));
18747 printf(" (%4d, %4d, %4d)\n", pointmark(p1), pointmark(p2),
18748 pointmark(p3));
18749 }
18750 }
18751
18752 (*internum)++;
18753
18754 sinfect(sface1);
18755 sinfect(sface2);
18756 }
18757 }
18758 }
18759
18760 delete [] leftarray;
18761 delete [] rightarray;
18762 delete [] subfacearray;
18763 }
18764 }
18765
18767
18768
18769
18770
18771
18772
18773
18774
18775
18776
18777
18778
18779
18780
18781
18782
18783
18784
18785
18786
18787
18788
18790
18791 void tetgenmesh::detectinterfaces()
18792 {
18793 shellface **subfacearray;
18794 face shloop;
18795 int internum;
18796 int i;
18797
18798 if (!b->quiet) {
18799 printf("Detecting intersecting facets.\n");
18800 }
18801
18802
18803 subfacearray = new shellface*[subfaces->items];
18804 subfaces->traversalinit();
18805 shloop.sh = shellfacetraverse(subfaces);
18806 i = 0;
18807 while (shloop.sh != (shellface *) NULL) {
18808 subfacearray[i] = shloop.sh;
18809 shloop.sh = shellfacetraverse(subfaces);
18810 i++;
18811 }
18812
18813 internum = 0;
18814
18815
18816
18817 interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax,
18818 zmin, zmax, &internum);
18819
18820 if (!b->quiet) {
18821 if (internum > 0) {
18822 printf("\n!! Found %d pairs of faces are intersecting.\n\n", internum);
18823 } else {
18824 printf("\nNo faces are intersecting.\n\n");
18825 }
18826 }
18827
18828 if (internum > 0) {
18829
18830
18831
18832 subfaces->traversalinit();
18833 shloop.sh = shellfacetraverse(subfaces);
18834 while (shloop.sh != (shellface *) NULL) {
18835 if (sinfected(shloop)) {
18836 suninfect(shloop);
18837 } else {
18838 shellfacedealloc(subfaces, shloop.sh);
18839 }
18840 shloop.sh = shellfacetraverse(subfaces);
18841 }
18842 } else {
18843
18844 subfaces->restart();
18845 }
18846 }
18847
18848
18849
18850
18851
18853
18854
18855
18856
18857
18858
18859
18860
18861
18862
18863
18865
18866 void tetgenmesh::createsubpbcgrouptable()
18867 {
18868 tetgenio::pbcgroup *pg;
18869 pbcdata *pd;
18870 REAL A[4][4], rhs[4], D;
18871 int indx[4];
18872 int i, j, k;
18873
18874 subpbcgrouptable = new pbcdata[in->numberofpbcgroups];
18875 for (i = 0; i < in->numberofpbcgroups; i++) {
18876 pg = &(in->pbcgrouplist[i]);
18877 pd = &(subpbcgrouptable[i]);
18878
18879 pd->fmark[0] = pg->fmark1;
18880 pd->fmark[1] = pg->fmark2;
18881
18882 pd->ss[0].sh = dummysh;
18883 pd->ss[1].sh = dummysh;
18884
18885 for (j = 0; j < 4; j++) {
18886 for (k = 0; k < 4; k++) {
18887 pd->transmat[0][j][k] = pg->transmat[j][k];
18888
18889 A[j][k] = pg->transmat[j][k];
18890 }
18891 }
18892
18893 lu_decmp(A, 4, indx, &D, 0);
18894 for (j = 0; j < 4; j++) {
18895 for (k = 0; k < 4; k++) rhs[k] = 0.0;
18896 rhs[j] = 1.0;
18897 lu_solve(A, 4, indx, rhs, 0);
18898 for (k = 0; k < 4; k++) pd->transmat[1][k][j] = rhs[k];
18899 }
18900 }
18901 }
18902
18904
18905
18906
18907
18908
18909
18910
18912
18913 void tetgenmesh::getsubpbcgroup(face* pbcsub, pbcdata** pd, int *f1, int *f2)
18914 {
18915 int groupid, fmark, idx;
18916
18917 groupid = shellpbcgroup(*pbcsub);
18918 *pd = &subpbcgrouptable[groupid];
18919
18920
18921 idx = shellmark(*pbcsub);
18922
18923 fmark = in->facetmarkerlist[idx - 1];
18924 if ((*pd)->fmark[0] == fmark) {
18925 *f1 = 0;
18926 } else {
18927 #ifdef SELF_CHECK
18928 assert((*pd)->fmark[1] == fmark);
18929 #endif
18930 *f1 = 1;
18931 }
18932 *f2 = 1 - (*f1);
18933 }
18934
18936
18937
18938
18939
18940
18941
18942
18944
18945 enum tetgenmesh::locateresult tetgenmesh:: getsubpbcsympoint(point newpoint,
18946 face* splitsub, point sympoint, face* symsplitsub)
18947 {
18948 pbcdata *pd;
18949 face subloop;
18950 point pa, pb, pc;
18951 enum locateresult symloc;
18952 REAL ori;
18953 int f1, f2, i;
18954
18955
18956 getsubpbcgroup(splitsub, &pd, &f1, &f2);
18957
18958
18959 for (i = 0; i < 3; i++) {
18960 sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
18961 + pd->transmat[f1][i][1] * newpoint[1]
18962 + pd->transmat[f1][i][2] * newpoint[2]
18963 + pd->transmat[f1][i][3] * 1.0;
18964 }
18965
18966 symloc = OUTSIDE;
18967 *symsplitsub = pd->ss[f2];
18968
18969 if ((symsplitsub->sh != dummysh) && !isdead(symsplitsub)) {
18970
18971 i = shellmark(*symsplitsub);
18972 if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18973
18974 pa = sorg(*symsplitsub);
18975 pb = sdest(*symsplitsub);
18976 pc = sapex(*symsplitsub);
18977
18978
18979 ori = orient3d(pa, pb, pc, sympoint);
18980 if (iscoplanar(pa, pb, pc, sympoint, ori, b->epsilon * 1e+2)) {
18981
18982 abovepoint = facetabovepointarray[shellmark(*symsplitsub)];
18983 if (abovepoint == (point) NULL) {
18984 getfacetabovepoint(symsplitsub);
18985 }
18986 symloc = locatesub(sympoint, symsplitsub, 0, b->epsilon * 1e+2);
18987 }
18988 }
18989 }
18990 if (symloc == OUTSIDE) {
18991
18992 REAL epspp = b->epsilon * 1e+2;
18993 int lcount = 0;
18994 do {
18995
18996 subfaces->traversalinit();
18997 subloop.sh = shellfacetraverse(subfaces);
18998 while (subloop.sh != (shellface *) NULL) {
18999 i = shellmark(subloop);
19000 if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
19001
19002 pa = sorg(subloop);
19003 pb = sdest(subloop);
19004 pc = sapex(subloop);
19005
19006
19007 ori = orient3d(pa, pb, pc, sympoint);
19008 if (iscoplanar(pa, pb, pc, sympoint, ori, epspp)) {
19009
19010
19011 abovepoint = facetabovepointarray[shellmark(subloop)];
19012
19013 if (abovepoint == (point) NULL) {
19014 getfacetabovepoint(&subloop);
19015 }
19016
19017 symloc = locatesub(sympoint, &subloop, 0, epspp);
19018 if (symloc != OUTSIDE) break;
19019 }
19020 }
19021 subloop.sh = shellfacetraverse(subfaces);
19022 }
19023 lcount++;
19024 epspp *= 10.0;
19025 } while ((symloc == OUTSIDE) && (lcount < 3));
19026 #ifdef SELF_CHECK
19027
19028 assert(symloc != OUTSIDE);
19029 #endif
19030
19031 *symsplitsub = subloop;
19032
19033 pd->ss[f2] = *symsplitsub;
19034 }
19035
19036 return adjustlocatesub(sympoint, symsplitsub, symloc, b->epsilon);
19037 }
19038
19040
19041
19042
19043
19044
19045
19046
19047
19048
19049
19051
19052 void tetgenmesh::createsegpbcgrouptable()
19053 {
19054 shellface** segsperverlist;
19055 pbcdata *pd, *ppd, pd1, pd2;
19056 face segloop, symseg;
19057 face startsh, spinsh, symsh;
19058 point pa, pb, syma, symb;
19059 enum locateresult symloc;
19060 REAL testpt[3], sympt[3];
19061 bool inflag;
19062 int *idx2seglist;
19063 int segid1, segid2;
19064 int f1, f2;
19065 int i, j, k, l;
19066
19067
19068 segpbcgrouptable = new list(sizeof(pbcdata), NULL, 256);
19069
19070 if (b->refine) {
19071
19072 makesegmentmap(idx2seglist, segsperverlist);
19073 }
19074
19075
19076 subsegs->traversalinit();
19077 segloop.sh = shellfacetraverse(subsegs);
19078 while (segloop.sh != (shellface *) NULL) {
19079
19080 pa = sorg(segloop);
19081 pb = sdest(segloop);
19082 segid1 = shellmark(segloop);
19083 spivot(segloop, startsh);
19084 spinsh = startsh;
19085 do {
19086
19087 if (sorg(spinsh) != pa) {
19088 sesymself(spinsh);
19089 }
19090
19091 if (shellpbcgroup(spinsh) != -1) {
19092
19093 if (b->refine) {
19094 getsubpbcgroup(&spinsh, &pd, &f1, &f2);
19095
19096 for (i = 0; i < 3; i++) {
19097 sympt[i] = pd->transmat[f1][i][0] * pa[0]
19098 + pd->transmat[f1][i][1] * pa[1]
19099 + pd->transmat[f1][i][2] * pa[2]
19100 + pd->transmat[f1][i][3] * 1.0;
19101 }
19102 syma = point2pbcpt(pa);
19103
19104 if (distance(sympt, syma) > (longest * b->epsilon)) {
19105
19106 symloc = getsubpbcsympoint(pa, &spinsh, sympt, &symsh);
19107 syma = sorg(symsh);
19108 if (symloc != ONVERTEX) {
19109
19110 assert(0);
19111 }
19112 }
19113
19114 for (i = 0; i < 3; i++) {
19115 sympt[i] = pd->transmat[f1][i][0] * pb[0]
19116 + pd->transmat[f1][i][1] * pb[1]
19117 + pd->transmat[f1][i][2] * pb[2]
19118 + pd->transmat[f1][i][3] * 1.0;
19119 }
19120
19121 symseg.shver = 0;
19122 j = pointmark(syma) - in->firstnumber;
19123 for (i = idx2seglist[j]; i < idx2seglist[j + 1]; i++) {
19124 symseg.sh = segsperverlist[i];
19125 if (sorg(symseg) == syma) symb = sdest(symseg);
19126 else symb = sorg(symseg);
19127 if (distance(sympt, symb) <= (longest * b->epsilon)) break;
19128 }
19129 assert(i < idx2seglist[j + 1]);
19130 } else {
19131
19132 for (i = 0; i < 3; i++) testpt[i] = 0.5 * (pa[i] + pb[i]);
19133 symloc = getsubpbcsympoint(testpt, &spinsh, sympt, &symsh);
19134 #ifdef SELF_CHECK
19135 assert(symloc == ONEDGE);
19136 #endif
19137 sspivot(symsh, symseg);
19138 }
19139 #ifdef SELF_CHECK
19140 assert(symseg.sh != dummysh);
19141 #endif
19142
19143 segid2 = shellmark(symseg);
19144 inflag = false;
19145 for (i = 0; i < segpbcgrouptable->len() && !inflag; i++) {
19146 pd = (pbcdata *)(* segpbcgrouptable)[i];
19147 if (pd->segid[0] == segid1) {
19148 if (pd->segid[1] == segid2) inflag = true;
19149 } else if (pd->segid[0] == segid2) {
19150 if (pd->segid[1] == segid1) inflag = true;
19151 }
19152 }
19153 if (!inflag) {
19154
19155 pd = (pbcdata *) segpbcgrouptable->append(NULL);
19156
19157 pd->segid[0] = segid1;
19158 pd->segid[1] = segid2;
19159
19160 pd->ss[0] = segloop;
19161 pd->ss[1] = symseg;
19162
19163 getsubpbcgroup(&spinsh, &ppd, &f1, &f2);
19164 pd->fmark[0] = ppd->fmark[f1];
19165 pd->fmark[1] = ppd->fmark[f2];
19166
19167 for (i = 0; i < 4; i++) {
19168 for (j = 0; j < 4; j++) {
19169 pd->transmat[0][i][j] = ppd->transmat[f1][i][j];
19170 }
19171 }
19172
19173 for (i = 0; i < 4; i++) {
19174 for (j = 0; j < 4; j++) {
19175 pd->transmat[1][i][j] = ppd->transmat[f2][i][j];
19176 }
19177 }
19178 }
19179 }
19180
19181 spivotself(spinsh);
19182 } while (spinsh.sh != startsh.sh);
19183 segloop.sh = shellfacetraverse(subsegs);
19184 }
19185
19186 if (b->refine) {
19187 delete [] segsperverlist;
19188 delete [] idx2seglist;
19189 }
19190
19191
19192
19193
19194
19195 for (i = 0; i < segpbcgrouptable->len(); i++) {
19196 pd1 = * (pbcdata *)(* segpbcgrouptable)[i];
19197 for (f1 = 0; f1 < 2; f1++) {
19198
19199 for (j = 0; j < segpbcgrouptable->len(); j++) {
19200 if (j == i) continue;
19201 pd2 = * (pbcdata *)(* segpbcgrouptable)[j];
19202 f2 = -1;
19203 if (pd1.segid[f1] == pd2.segid[0]) {
19204 f2 = 0;
19205 } else if (pd1.segid[f1] == pd2.segid[1]) {
19206 f2 = 1;
19207 }
19208 if (f2 != -1) {
19209 #ifdef SELF_CHECK
19210 assert(pd1.segid[f1] == pd2.segid[f2]);
19211 #endif
19212 segid1 = pd1.segid[1 - f1];
19213 segid2 = pd2.segid[1 - f2];
19214
19215 inflag = false;
19216 for (k = 0; k < segpbcgrouptable->len() && !inflag; k++) {
19217 pd = (pbcdata *)(* segpbcgrouptable)[k];
19218 if (pd->segid[0] == segid1) {
19219 if (pd->segid[1] == segid2) inflag = true;
19220 } else if (pd->segid[0] == segid2) {
19221 if (pd->segid[1] == segid1) inflag = true;
19222 }
19223 }
19224 if (!inflag) {
19225 pd = (pbcdata *) segpbcgrouptable->append(NULL);
19226 pd->segid[0] = pd1.segid[1 - f1];
19227 pd->segid[1] = pd2.segid[1 - f2];
19228 pd->ss[0] = pd1.ss[1 - f1];
19229 pd->ss[1] = pd2.ss[1 - f2];
19230
19231 pd->fmark[0] = pd->fmark[1] = 0;
19232
19233
19234 for (k = 0; k < 4; k++) {
19235 for (l = 0; l < 4; l++) {
19236 pd->transmat[0][k][l] = pd2.transmat[f2][k][l];
19237 }
19238 }
19239 m4xm4(pd->transmat[0], pd1.transmat[1 - f1]);
19240
19241
19242 for (k = 0; k < 4; k++) {
19243 for (l = 0; l < 4; l++) {
19244 pd->transmat[1][k][l] = pd1.transmat[f1][k][l];
19245 }
19246 }
19247 m4xm4(pd->transmat[1], pd2.transmat[1 - f2]);
19248 }
19249 }
19250 }
19251 }
19252 }
19253
19254
19255 idx2segpglist = new int[subsegs->items + 1];
19256 for (i = 0; i < subsegs->items + 1; i++) idx2segpglist[i] = 0;
19257
19258
19259 for (i = 0; i < segpbcgrouptable->len(); i++) {
19260 pd = (pbcdata *)(* segpbcgrouptable)[i];
19261 for (j = 0; j < 2; j++) {
19262 k = pd->segid[j] - 1;
19263 idx2segpglist[k]++;
19264 }
19265 }
19266
19267 j = idx2segpglist[0];
19268 idx2segpglist[0] = 0;
19269 for (i = 0; i < subsegs->items; i++) {
19270 k = idx2segpglist[i + 1];
19271 idx2segpglist[i + 1] = idx2segpglist[i] + j;
19272 j = k;
19273 }
19274
19275 segpglist = new int[idx2segpglist[i]];
19276
19277 for (i = 0; i < segpbcgrouptable->len(); i++) {
19278 pd = (pbcdata *)(* segpbcgrouptable)[i];
19279 for (j = 0; j < 2; j++) {
19280 k = pd->segid[j] - 1;
19281 segpglist[idx2segpglist[k]] = i;
19282 idx2segpglist[k]++;
19283 }
19284 }
19285
19286 for (i = subsegs->items - 1; i >= 0; i--) {
19287 idx2segpglist[i + 1] = idx2segpglist[i];
19288 }
19289 idx2segpglist[0] = 0;
19290 }
19291
19293
19294
19295
19296
19297
19298
19299
19301
19302 enum tetgenmesh::locateresult tetgenmesh::
19303 getsegpbcsympoint(point newpoint, face* splitseg, point sympoint,
19304 face* symsplitseg, int groupid)
19305 {
19306 pbcdata *pd;
19307 enum locateresult symloc;
19308 int segid, f1, f2, i;
19309
19310 pd = (pbcdata *)(* segpbcgrouptable)[groupid];
19311 segid = shellmark(*splitseg);
19312 if (pd->segid[0] == segid) {
19313 f1 = 0;
19314 } else {
19315 #ifdef SELF_CHECK
19316 assert(pd->segid[1] == segid);
19317 #endif
19318 f1 = 1;
19319 }
19320 f2 = 1 - f1;
19321
19322
19323 for (i = 0; i < 3; i++) {
19324 sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
19325 + pd->transmat[f1][i][1] * newpoint[1]
19326 + pd->transmat[f1][i][2] * newpoint[2]
19327 + pd->transmat[f1][i][3] * 1.0;
19328 }
19329
19330 *symsplitseg = pd->ss[f2];
19331 #ifdef SELF_CHECK
19332 assert(symsplitseg->sh != dummysh);
19333 #endif
19334
19335 symloc = locateseg(sympoint, symsplitseg);
19336 symloc = adjustlocateseg(sympoint, symsplitseg, symloc, b->epsilon * 1e+2);
19337 return symloc;
19338 }
19339
19340
19341
19342
19343
19344
19345
19346
19347
19349
19350
19351
19353
19354 REAL tetgenmesh::randgenerator(REAL range)
19355 {
19356 REAL worknumber, result;
19357 int expo;
19358
19359 if (range == 0.0) return 0.0;
19360
19361 expo = 0;
19362 worknumber = fabs(range);
19363
19364 if (worknumber > 10.0) {
19365 while (worknumber > 10.0) {
19366 worknumber /= 10.0;
19367 expo++;
19368 }
19369 } else if (worknumber < 1.0) {
19370 while (worknumber < 1.0) {
19371 worknumber *= 10.0;
19372 expo--;
19373 }
19374 }
19375 #ifdef SELF_CHECK
19376 assert(worknumber >= 1.0 && worknumber <= 10.0);
19377 #endif
19378
19379
19380 worknumber *= 1e+3;
19381 expo -= 3;
19382
19383 result = (double) randomnation((int) worknumber);
19384
19385
19386 if (expo > 0) {
19387 while (expo != 0) {
19388 result *= 10.0;
19389 expo--;
19390 }
19391 } else if (expo < 0) {
19392 while (expo != 0) {
19393 result /= 10.0;
19394 expo++;
19395 }
19396 }
19397 #ifdef SELF_CHECK
19398 assert((result >= 0.0) && (result <= fabs(range)));
19399 #endif
19400
19401 return result;
19402 }
19403
19405
19406
19407
19408
19409
19410
19411
19412
19413
19414
19415
19416
19417
19419
19420 bool tetgenmesh::checksub4cocir(face* testsub, REAL eps, bool once,
19421 bool enqflag)
19422 {
19423 badface *cocirsub;
19424 face subloop, neighsub;
19425 face checkseg;
19426 point pa, pb, pc, pd;
19427 REAL sign;
19428 int i;
19429
19430 subloop = *testsub;
19431 subloop.shver = 0;
19432
19433 abovepoint = facetabovepointarray[shellmark(subloop)];
19434
19435 if (abovepoint == (point) NULL) {
19436 getfacetabovepoint(&subloop);
19437 }
19438
19439 for (i = 0; i < 3; i++) {
19440 sspivot(subloop, checkseg);
19441 if (checkseg.sh == dummysh) {
19442
19443 spivot(subloop, neighsub);
19444
19445 if (!once || (once && (neighsub.sh > subloop.sh))) {
19446 pa = sorg(subloop);
19447 pb = sdest(subloop);
19448 pc = sapex(subloop);
19449 pd = sapex(neighsub);
19450 sign = insphere(pa, pb, pc, abovepoint, pd);
19451 if ((sign != 0.0) && (eps > 0.0)) {
19452 if (iscospheric(pa, pb, pc, abovepoint, pd, sign, eps)) sign = 0.0;
19453 }
19454 if (sign == 0.0) {
19455
19456 if (enqflag && badsubfaces != (memorypool *) NULL) {
19457
19458 cocirsub = (badface *) badsubfaces->alloc();
19459 cocirsub->ss = subloop;
19460 cocirsub->forg = pa;
19461 cocirsub->fdest = pb;
19462 cocirsub->fapex = pc;
19463 cocirsub->foppo = pd;
19464 setshell2badface(cocirsub->ss, cocirsub);
19465 }
19466 if (b->verbose > 1) {
19467 printf(" Found set (%d, %d, %d, %d).\n", pointmark(pa),
19468 pointmark(pb), pointmark(pc), pointmark(pd));
19469 }
19470 return true;
19471 }
19472 }
19473 }
19474 senextself(subloop);
19475 }
19476
19477 return false;
19478 }
19479
19481
19482
19483
19485
19486 void tetgenmesh::tallcocirsubs(REAL eps, bool enqflag)
19487 {
19488 face subloop;
19489
19490
19491 subfaces->traversalinit();
19492 subloop.sh = shellfacetraverse(subfaces);
19493 while (subloop.sh != (shellface *) NULL) {
19494 checksub4cocir(&subloop, eps, true, enqflag);
19495 subloop.sh = shellfacetraverse(subfaces);
19496 }
19497 }
19498
19500
19501
19502
19504
19505 bool tetgenmesh::tallencsegsfsubs(point testpt, list* cavsublist)
19506 {
19507 face startsub, checkseg;
19508 long oldencnum;
19509 int i, j;
19510
19511
19512 oldencnum = badsubsegs->items;
19513
19514
19515 for (i = 0; i < cavsublist->len(); i++) {
19516 startsub = * (face *)(* cavsublist)[i];
19517
19518 for (j = 0; j < 3; j++) {
19519 sspivot(startsub, checkseg);
19520 if (checkseg.sh != dummysh) {
19521 if (!shell2badface(checkseg)) {
19522 checkseg4encroach(&checkseg, testpt, NULL, true);
19523 }
19524 }
19525 senextself(startsub);
19526 }
19527 }
19528
19529 return (badsubsegs->items > oldencnum);
19530 }
19531
19533
19534
19535
19536
19537
19538
19539
19540
19542
19543 void tetgenmesh::
19544 collectflipedges(point inspoint, face* splitseg, queue* flipqueue)
19545 {
19546 face startsh, spinsh, checksh;
19547 face nextseg;
19548 point pa, pb;
19549
19550
19551 splitseg->shver = 0;
19552 if (sdest(*splitseg) != inspoint) {
19553 sesymself(*splitseg);
19554 }
19555 #ifdef SELF_CHECK
19556 assert(sdest(*splitseg) == inspoint);
19557 #endif
19558 pa = sorg(*splitseg);
19559 spivot(*splitseg, startsh);
19560 spinsh = startsh;
19561 do {
19562 findedge(&spinsh, pa, inspoint);
19563 senext2(spinsh, checksh);
19564 enqueueflipedge(checksh, flipqueue);
19565 spivotself(spinsh);
19566 } while (spinsh.sh != startsh.sh);
19567
19568
19569 senext(*splitseg, nextseg);
19570 spivotself(nextseg);
19571 #ifdef SELF_CHECK
19572 assert(nextseg.sh != (shellface *) NULL);
19573 #endif
19574
19575
19576 nextseg.shver = 0;
19577 if (sorg(nextseg) != inspoint) {
19578 sesymself(nextseg);
19579 }
19580 #ifdef SELF_CHECK
19581 assert(sorg(nextseg) == inspoint);
19582 #endif
19583 pb = sdest(nextseg);
19584 spivot(nextseg, startsh);
19585 spinsh = startsh;
19586 do {
19587 findedge(&spinsh, inspoint, pb);
19588 senext(spinsh, checksh);
19589 enqueueflipedge(checksh, flipqueue);
19590 spivotself(spinsh);
19591 } while (spinsh.sh != startsh.sh);
19592 }
19593
19595
19596
19597
19598
19599
19600
19602
19603 void tetgenmesh::perturbrepairencsegs(queue* flipqueue)
19604 {
19605 badface *encloop;
19606 tetrahedron encodedtet;
19607 triface splittet;
19608 face splitsub, symsplitsub;
19609 face splitseg, symsplitseg;
19610 point newpoint, sympoint;
19611 point pa, pb, pc;
19612 enum insertsiteresult success;
19613 enum locateresult loc, symloc;
19614 REAL cent[3], d1, ps, rs;
19615 int i, j;
19616
19617
19618
19619 badsubsegs->traversalinit();
19620 encloop = badfacetraverse(badsubsegs);
19621 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19622 splitseg = encloop->ss;
19623 #ifdef SELF_CHECK
19624 assert(shell2badface(splitseg) == encloop);
19625 #endif
19626 setshell2badface(splitseg, NULL);
19627 pa = sorg(splitseg);
19628 pb = sdest(splitseg);
19629 if ((pa == encloop->forg) && (pb == encloop->fdest)) {
19630 if (b->verbose > 1) {
19631 printf(" Get seg (%d, %d).\n", pointmark(pa), pointmark(pb));
19632 }
19633
19634 makepoint(&newpoint);
19635
19636 for (i = 0; i < 3; i++) cent[i] = 0.5 * (pa[i] + pb[i]);
19637 d1 = 0.5 * distance(pa, pb);
19638
19639 ps = randgenerator(d1 * 1.0e-3);
19640 rs = ps / d1;
19641
19642 for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19643 setpointtype(newpoint, FREESEGVERTEX);
19644
19645 setpoint2sh(newpoint, sencode(splitseg));
19646
19647
19648 if (checkpbcs) {
19649
19650 i = shellmark(splitseg) - 1;
19651 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
19652 makepoint(&sympoint);
19653 symloc = getsegpbcsympoint(newpoint, &splitseg, sympoint,
19654 &symsplitseg, segpglist[j]);
19655 #ifdef SELF_CHECK
19656 assert(symloc != OUTSIDE);
19657 #endif
19658
19659
19660 if ((symloc == ONEDGE) && (symsplitseg.sh != splitseg.sh)) {
19661 setpointtype(sympoint, FREESEGVERTEX);
19662 setpoint2sh(sympoint, sencode(symsplitseg));
19663
19664 pc = sorg(symsplitseg);
19665 splittet.tet = dummytet;
19666
19667 encodedtet = point2tet(pc);
19668 if (encodedtet != (tetrahedron) NULL) {
19669 decode(encodedtet, splittet);
19670 if (isdead(&splittet)) {
19671 splittet.tet = dummytet;
19672 }
19673 }
19674
19675 success = insertsite(sympoint, &splittet, false, flipqueue);
19676 #ifdef SELF_CHECK
19677 assert(success != DUPLICATEPOINT);
19678 #endif
19679 if (success == OUTSIDEPOINT) {
19680 inserthullsite(sympoint, &splittet, flipqueue);
19681 }
19682 if (steinerleft > 0) steinerleft--;
19683
19684 setpoint2tet(sympoint, encode(splittet));
19685
19686 flip(flipqueue, NULL);
19687
19688 symloc = locateseg(sympoint, &symsplitseg);
19689 if (symloc == ONEDGE) {
19690 symsplitseg.shver = 0;
19691 spivot(symsplitseg, symsplitsub);
19692
19693 splitsubedge(sympoint, &symsplitsub, flipqueue);
19694 } else {
19695
19696 #ifdef SELF_CHECK
19697 assert(symloc == ONVERTEX);
19698 assert(checksubfaces);
19699 #endif
19700
19701 collectflipedges(sympoint, &symsplitseg, flipqueue);
19702 }
19703
19704 flipsub(flipqueue);
19705 } else {
19706
19707
19708 pointdealloc(sympoint);
19709 }
19710 }
19711 }
19712
19713
19714 splittet.tet = dummytet;
19715
19716 encodedtet = point2tet(pa);
19717 if (encodedtet != (tetrahedron) NULL) {
19718 decode(encodedtet, splittet);
19719 if (isdead(&splittet)) {
19720 splittet.tet = dummytet;
19721 }
19722 }
19723 if (splittet.tet == dummytet) {
19724 encodedtet = point2tet(pb);
19725 if (encodedtet != (tetrahedron) NULL) {
19726 decode(encodedtet, splittet);
19727 if (isdead(&splittet)) {
19728 splittet.tet = dummytet;
19729 }
19730 }
19731 }
19732
19733 success = insertsite(newpoint, &splittet, false, flipqueue);
19734 #ifdef SELF_CHECK
19735 assert(success != DUPLICATEPOINT);
19736 #endif
19737 if (success == OUTSIDEPOINT) {
19738
19739
19740
19741 inserthullsite(newpoint, &splittet, flipqueue);
19742 }
19743 if (steinerleft > 0) steinerleft--;
19744
19745 setpoint2tet(newpoint, encode(splittet));
19746
19747 flip(flipqueue, NULL);
19748
19749 loc = locateseg(newpoint, &splitseg);
19750 if (loc == ONEDGE) {
19751 splitseg.shver = 0;
19752 spivot(splitseg, splitsub);
19753
19754 splitsubedge(newpoint, &splitsub, flipqueue);
19755 } else {
19756
19757 #ifdef SELF_CHECK
19758 assert(loc == ONVERTEX);
19759 assert(checksubfaces);
19760 #endif
19761
19762 collectflipedges(newpoint, &splitseg, flipqueue);
19763 }
19764
19765 flipsub(flipqueue);
19766 }
19767
19768 badfacedealloc(badsubsegs, encloop);
19769
19770 encloop = badfacetraverse(badsubsegs);
19771 }
19772 }
19773
19775
19776
19777
19778
19779
19780
19781
19782
19784
19785 void tetgenmesh::perturbrepairencsubs(list* cavsublist, queue* flipqueue)
19786 {
19787 badface *encloop, *encsubseg;
19788 tetrahedron encodedtet;
19789 triface splittet;
19790 face splitsub, symsplitsub;
19791 face checkseg, symsplitseg;
19792 point newpoint, sympoint;
19793 point pa, pb, pc, pd;
19794 enum insertsiteresult success;
19795 enum locateresult loc, symloc;
19796 REAL cent[3], d1, ps, rs;
19797 bool reject;
19798 int i;
19799
19800
19801
19802 while ((badsubfaces->items > 0) && (steinerleft != 0)) {
19803 badsubfaces->traversalinit();
19804 encloop = badfacetraverse(badsubfaces);
19805 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19806 splitsub = encloop->ss;
19807 #ifdef SELF_CHECK
19808 assert(shell2badface(splitsub) == encloop);
19809 #endif
19810 setshell2badface(splitsub, NULL);
19811 pa = sorg(splitsub);
19812 pb = sdest(splitsub);
19813 pc = sapex(splitsub);
19814
19815
19816
19817 if ((pa == encloop->forg) && (pb == encloop->fdest) &&
19818 (pc == encloop->fapex)) {
19819 if (b->verbose > 1) {
19820 printf(" Get subface (%d, %d, %d).\n", pointmark(pa),
19821 pointmark(pb), pointmark(pc));
19822 }
19823
19824 makepoint(&newpoint);
19825
19826 circumsphere(pa, pb, pc, NULL, cent, &d1);
19827 #ifdef SELF_CHECK
19828 assert(d1 > 0.0);
19829 #endif
19830
19831
19832 ps = randgenerator(d1 * 1.0e-3);
19833 rs = ps / d1;
19834
19835 for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19836
19837 abovepoint = facetabovepointarray[shellmark(splitsub)];
19838
19839 if (abovepoint == (point) NULL) {
19840 getfacetabovepoint(&splitsub);
19841 }
19842 loc = locatesub(newpoint, &splitsub, 1, 0.0);
19843 #ifdef SELF_CHECK
19844 assert(loc != ONVERTEX);
19845 #endif
19846 if (loc != OUTSIDE) {
19847
19848 cavsublist->append(&splitsub);
19849
19850 collectcavsubs(newpoint, cavsublist);
19851
19852 reject = tallencsegsfsubs(newpoint, cavsublist);
19853
19854 cavsublist->clear();
19855 } else {
19856
19857 sspivot(splitsub, checkseg);
19858 #ifdef SELF_CHECK
19859 assert(checkseg.sh != dummysh);
19860 #endif
19861
19862 if (b->verbose > 2) {
19863 printf(" Queuing boundary segment (%d, %d).\n",
19864 pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
19865 }
19866 encsubseg = (badface *) badsubsegs->alloc();
19867 encsubseg->ss = checkseg;
19868 encsubseg->forg = sorg(checkseg);
19869 encsubseg->fdest = sdest(checkseg);
19870 encsubseg->foppo = (point) NULL;
19871 setshell2badface(encsubseg->ss, encsubseg);
19872
19873 reject = true;
19874 }
19875
19876 if (!reject) {
19877
19878
19879
19880 if (checkpbcs) {
19881 if (shellpbcgroup(splitsub) >= 0) {
19882
19883 makepoint(&sympoint);
19884
19885 symloc = getsubpbcsympoint(newpoint, &splitsub, sympoint,
19886 &symsplitsub);
19887 #ifdef SELF_CHECK
19888 assert(symloc != ONVERTEX);
19889 #endif
19890 setpoint2pbcpt(newpoint, sympoint);
19891 setpoint2pbcpt(sympoint, newpoint);
19892 setpointtype(sympoint, FREESUBVERTEX);
19893
19894
19895 pd = sorg(symsplitsub);
19896 splittet.tet = dummytet;
19897
19898 encodedtet = point2tet(pd);
19899 if (encodedtet != (tetrahedron) NULL) {
19900 decode(encodedtet, splittet);
19901 if (isdead(&splittet)) {
19902 splittet.tet = dummytet;
19903 }
19904 }
19905
19906 success = insertsite(sympoint, &splittet, false, flipqueue);
19907 #ifdef SELF_CHECK
19908 assert(success != DUPLICATEPOINT);
19909 #endif
19910 if (success == OUTSIDEPOINT) {
19911 inserthullsite(sympoint, &splittet, flipqueue);
19912 }
19913 if (steinerleft > 0) steinerleft--;
19914
19915 setpoint2tet(sympoint, encode(splittet));
19916
19917 flip(flipqueue, NULL);
19918
19919
19920
19921 if (symloc == ONFACE) {
19922 splitsubface(sympoint, &symsplitsub, flipqueue);
19923 } else if (symloc == ONEDGE) {
19924 splitsubedge(sympoint, &symsplitsub, flipqueue);
19925 } else {
19926
19927 #ifdef SELF_CHECK
19928 assert(symloc == ONVERTEX);
19929 assert(checksubfaces);
19930 #endif
19931
19932 flipqueue->clear();
19933 }
19934
19935 flipsub(flipqueue);
19936 }
19937 }
19938
19939
19940 splittet.tet = dummytet;
19941
19942 encodedtet = point2tet(pa);
19943 if (encodedtet != (tetrahedron) NULL) {
19944 decode(encodedtet, splittet);
19945 if (isdead(&splittet)) {
19946 splittet.tet = dummytet;
19947 }
19948 }
19949 if (splittet.tet == dummytet) {
19950 encodedtet = point2tet(pb);
19951 if (encodedtet != (tetrahedron) NULL) {
19952 decode(encodedtet, splittet);
19953 if (isdead(&splittet)) {
19954 splittet.tet = dummytet;
19955 }
19956 }
19957 }
19958
19959 success = insertsite(newpoint, &splittet, false, flipqueue);
19960 #ifdef SELF_CHECK
19961 assert(success != DUPLICATEPOINT);
19962 #endif
19963 if (success == OUTSIDEPOINT) {
19964 inserthullsite(newpoint, &splittet, flipqueue);
19965 }
19966 if (steinerleft > 0) steinerleft--;
19967
19968 setpoint2tet(newpoint, encode(splittet));
19969
19970 flip(flipqueue, NULL);
19971
19972
19973
19974
19975
19976
19977 if (loc == ONFACE) {
19978
19979 splitsubface(newpoint, &splitsub, flipqueue);
19980 } else if (loc == ONEDGE) {
19981
19982 splitsubedge(newpoint, &splitsub, flipqueue);
19983 } else {
19984
19985 #ifdef SELF_CHECK
19986 assert(loc == ONVERTEX);
19987 assert(checksubfaces);
19988 #endif
19989
19990 flipqueue->clear();
19991 }
19992
19993 setpointtype(newpoint, FREESUBVERTEX);
19994
19995
19996
19997 flipsub(flipqueue);
19998
19999
20000 badfacedealloc(badsubfaces, encloop);
20001 } else {
20002
20003 pointdealloc(newpoint);
20004
20005 perturbrepairencsegs(flipqueue);
20006
20007 setshell2badface(encloop->ss, encloop);
20008 }
20009 } else {
20010
20011 badfacedealloc(badsubfaces, encloop);
20012
20013
20014 }
20015
20016 encloop = badfacetraverse(badsubfaces);
20017 }
20018 }
20019 }
20020
20022
20023
20024
20025
20026
20027
20028
20029
20030
20031
20032
20033
20035
20036 void tetgenmesh::incrperturbvertices(REAL eps)
20037 {
20038 queue *flipqueue;
20039 list *cavsublist;
20040 long vertcount;
20041
20042 if (!b->quiet) {
20043 printf("Perturbing vertices.\n");
20044 }
20045
20046 vertcount = points->items;
20047
20048
20049
20050
20051 flipqueue = new queue(sizeof(badface));
20052 cavsublist = new list(sizeof(face), NULL, 256);
20053
20054 badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20055 badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20056
20057 tallcocirsubs(eps, true);
20058 if (b->verbose && badsubfaces->items > 0) {
20059 printf(" Removing degenerate subfaces.\n");
20060 }
20061 perturbrepairencsubs(cavsublist, flipqueue);
20062
20063 if (b->verbose > 0) {
20064 printf(" %ld break points.\n", points->items - vertcount);
20065 }
20066
20067 delete cavsublist;
20068 delete flipqueue;
20069 delete badsubfaces;
20070 delete badsubsegs;
20071 badsubsegs = (memorypool *) NULL;
20072 badsubfaces = (memorypool *) NULL;
20073 }
20074
20075
20076
20077
20078
20079
20080
20081
20082
20084
20085
20086
20087
20088
20089
20090
20091
20092
20093
20094
20095
20096
20097
20099
20100 void tetgenmesh::markacutevertices(REAL acuteangle)
20101 {
20102 shellface **segsperverlist;
20103 face segloop, nextseg;
20104 point pointloop, edest, eapex;
20105 REAL cosbound, anglearc;
20106 REAL v1[3], v2[3], L, D;
20107 bool isacute;
20108 int *idx2seglist;
20109 int acutecount;
20110 int idx, i, j, k;
20111
20112 if (b->verbose > 0) {
20113 printf(" Marking acute vertices.\n");
20114 }
20115
20116 anglearc = acuteangle * PI / 180.0;
20117 cosbound = cos(anglearc);
20118 acutecount = 0;
20119
20120 makesegmentmap(idx2seglist, segsperverlist);
20121
20122
20123 points->traversalinit();
20124 pointloop = pointtraverse();
20125 while (pointloop != (point) NULL) {
20126 idx = pointmark(pointloop) - in->firstnumber;
20127
20128 if (idx2seglist[idx + 1] > idx2seglist[idx]) {
20129
20130 setpointtype(pointloop, NACUTEVERTEX);
20131 isacute = false;
20132
20133 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isacute; i++) {
20134 segloop.sh = segsperverlist[i];
20135
20136 if (sorg(segloop) != pointloop) sesymself(segloop);
20137 edest = sdest(segloop);
20138 for (j = i + 1; j < idx2seglist[idx + 1] && !isacute; j++) {
20139 nextseg.sh = segsperverlist[j];
20140
20141 if (sorg(nextseg) != pointloop) sesymself(nextseg);
20142 eapex = sdest(nextseg);
20143
20144 for (k = 0; k < 3; k++) {
20145 v1[k] = edest[k] - pointloop[k];
20146 v2[k] = eapex[k] - pointloop[k];
20147 }
20148 L = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
20149 for (k = 0; k < 3; k++) v1[k] /= L;
20150 L = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
20151 for (k = 0; k < 3; k++) v2[k] /= L;
20152 D = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
20153
20154 isacute = (D >= cosbound);
20155 }
20156 }
20157 if (isacute) {
20158
20159 setpointtype(pointloop, ACUTEVERTEX);
20160 acutecount++;
20161 }
20162 }
20163 pointloop = pointtraverse();
20164 }
20165
20166 delete [] idx2seglist;
20167 delete [] segsperverlist;
20168
20169 if ((b->verbose > 0) && (acutecount > 0)) {
20170 printf(" %d acute vertices.\n", acutecount);
20171 }
20172 }
20173
20175
20176
20177
20178
20179
20180
20181
20182
20183
20184
20185
20186
20187
20188
20189
20190
20191
20192
20193
20194
20195
20196
20197
20198
20199
20200
20201
20202
20203
20204
20206
20207 enum tetgenmesh::finddirectionresult tetgenmesh::
20208 finddirection(triface *searchtet, point tend, long maxtetnumber)
20209 {
20210 triface neightet;
20211 point tstart, tdest, tapex, toppo;
20212 REAL ori1, ori2, ori3;
20213 long tetnumber;
20214
20215 tstart = org(*searchtet);
20216 #ifdef SELF_CHECK
20217 assert(tstart != tend);
20218 #endif
20219 adjustedgering(*searchtet, CCW);
20220 if (tstart != org(*searchtet)) {
20221 enextself(*searchtet);
20222 }
20223 tdest = dest(*searchtet);
20224 if (tdest == tend) {
20225 return RIGHTCOLLINEAR;
20226 }
20227 tapex = apex(*searchtet);
20228 if (tapex == tend) {
20229 return LEFTCOLLINEAR;
20230 }
20231
20232 ori1 = orient3d(tstart, tdest, tapex, tend);
20233 if (ori1 > 0.0) {
20234
20235 sym(*searchtet, neightet);
20236 if (neightet.tet != dummytet) {
20237 findorg(&neightet, tstart);
20238 adjustedgering(neightet, CCW);
20239 if (org(neightet) != tstart) {
20240 enextself(neightet);
20241 }
20242
20243 *searchtet = neightet;
20244 ori1 = -1.0;
20245 tdest = dest(*searchtet);
20246 tapex = apex(*searchtet);
20247 } else {
20248
20249 #ifdef SELF_CHECK
20250 assert(nonconvex);
20251 #endif
20252 return BELOWHULL;
20253 }
20254 }
20255
20256
20257
20258
20259 tetnumber = 0l;
20260 while ((maxtetnumber > 0) && (tetnumber <= maxtetnumber)) {
20261 tetnumber++;
20262 toppo = oppo(*searchtet);
20263 if (toppo == tend) {
20264 return TOPCOLLINEAR;
20265 }
20266 ori2 = orient3d(tstart, toppo, tdest, tend);
20267 if (ori2 > 0.0) {
20268
20269 fnext(*searchtet, neightet);
20270 symself(neightet);
20271 if (neightet.tet != dummytet) {
20272 findorg(&neightet, tstart);
20273 adjustedgering(neightet, CCW);
20274 if (org(neightet) != tstart) {
20275 enextself(neightet);
20276 }
20277
20278 *searchtet = neightet;
20279 ori1 = -1.0;
20280 tdest = dest(*searchtet);
20281 tapex = apex(*searchtet);
20282
20283 continue;
20284 } else {
20285
20286 #ifdef SELF_CHECK
20287 assert(nonconvex);
20288 #endif
20289 return BELOWHULL;
20290 }
20291 }
20292 ori3 = orient3d(tapex, toppo, tstart, tend);
20293 if (ori3 > 0.0) {
20294
20295 enext2fnext(*searchtet, neightet);
20296 symself(neightet);
20297 if (neightet.tet != dummytet) {
20298 findorg(&neightet, tstart);
20299 adjustedgering(neightet, CCW);
20300 if (org(neightet) != tstart) {
20301 enextself(neightet);
20302 }
20303
20304 *searchtet = neightet;
20305 ori1 = -1.0;
20306 tdest = dest(*searchtet);
20307 tapex = apex(*searchtet);
20308
20309 continue;
20310 } else {
20311
20312 #ifdef SELF_CHECK
20313 assert(nonconvex);
20314 #endif
20315 return BELOWHULL;
20316 }
20317 }
20318
20319 if (ori1 < 0.0) {
20320
20321 if (ori2 < 0.0) {
20322 if (ori3 < 0.0) {
20323 return ACROSSFACE;
20324 } else {
20325
20326 enext2fnextself(*searchtet);
20327 esymself(*searchtet);
20328 return ACROSSEDGE;
20329 }
20330 } else {
20331 if (ori3 < 0.0) {
20332
20333 fnextself(*searchtet);
20334 esymself(*searchtet);
20335 enextself(*searchtet);
20336 return ACROSSEDGE;
20337 } else {
20338
20339 return TOPCOLLINEAR;
20340 }
20341 }
20342 } else {
20343
20344 if (ori2 < 0.0) {
20345 if (ori3 < 0.0) {
20346
20347 return ACROSSEDGE;
20348 } else {
20349
20350 return LEFTCOLLINEAR;
20351 }
20352 } else {
20353 #ifdef SELF_CHECK
20354 assert(ori3 != 0.0);
20355 #endif
20356
20357 return RIGHTCOLLINEAR;
20358 }
20359 }
20360 }
20361
20362 return BELOWHULL;
20363 }
20364
20366
20367
20368
20369
20370
20371
20372
20374
20375 void tetgenmesh::getsearchtet(point p1, point p2, triface* searchtet,
20376 point* tend)
20377 {
20378 tetrahedron encodedtet1, encodedtet2;
20379
20380
20381 if ((searchtet->tet != (tetrahedron *) NULL) && !isdead(searchtet)) {
20382
20383 if (findorg(searchtet, p1)) {
20384 *tend = p2;
20385 return;
20386 } else {
20387 if (findorg(searchtet, p2)) {
20388 *tend = p1;
20389 return;
20390 }
20391 }
20392 }
20393
20394 *tend = (point) NULL;
20395 encodedtet1 = point2tet(p1);
20396 encodedtet2 = point2tet(p2);
20397 if (encodedtet1 != (tetrahedron) NULL) {
20398 decode(encodedtet1, *searchtet);
20399
20400 if (findorg(searchtet, p1)) {
20401 *tend = p2;
20402 }
20403 } else if (encodedtet2 != (tetrahedron) NULL) {
20404 decode(encodedtet2, *searchtet);
20405
20406 if (findorg(searchtet, p2)) {
20407 *tend = p1;
20408 }
20409 }
20410
20411
20412
20413 if (*tend == (point) NULL) {
20414 if (encodedtet1 != (tetrahedron) NULL) {
20415 decode(encodedtet1, *searchtet);
20416
20417 }
20418 if (isdead(searchtet)) {
20419 if (encodedtet2 != (tetrahedron) NULL) {
20420 decode(encodedtet2, *searchtet);
20421
20422 }
20423 if (isdead(searchtet)) {
20424 searchtet->tet = dummytet;
20425 searchtet->loc = 0;
20426 symself(*searchtet);
20427 }
20428 #ifdef SELF_CHECK
20429 assert(!isdead(searchtet));
20430 #endif
20431 }
20432 if (locate(p1, searchtet) != ONVERTEX) {
20433 printf("Internal error in getsearchtet(): Failed to locate point\n");
20434 internalerror();
20435 }
20436
20437 setpoint2tet(p1, encode(*searchtet));
20438 *tend = p2;
20439 }
20440 }
20441
20443
20444
20445
20446
20447
20448
20449
20450
20452
20453 bool tetgenmesh::isedgeencroached(point p1, point p2, point testpt,
20454 bool degflag)
20455 {
20456 REAL dotproduct;
20457
20458
20459 dotproduct = (p1[0] - testpt[0]) * (p2[0] - testpt[0])
20460 + (p1[1] - testpt[1]) * (p2[1] - testpt[1])
20461 + (p1[2] - testpt[2]) * (p2[2] - testpt[2]);
20462 if (dotproduct < 0) {
20463 return true;
20464 } else if (dotproduct == 0 && degflag) {
20465 return true;
20466 } else {
20467 return false;
20468 }
20469 }
20470
20472
20473
20474
20475
20476
20477
20478
20479
20480
20481
20482
20483
20484
20486
20487 tetgenmesh::point tetgenmesh::scoutrefpoint(triface* searchtet, point tend)
20488 {
20489 triface checkface;
20490 point tstart, testpt, refpoint;
20491 REAL cent[3], radius, largest;
20492 REAL ahead;
20493 bool ncollinear;
20494 int sides;
20495
20496 if (b->verbose > 2) {
20497 printf(" Scout the reference point of segment (%d, %d).\n",
20498 pointmark(org(*searchtet)), pointmark(tend));
20499 }
20500
20501 tstart = org(*searchtet);
20502 refpoint = (point) NULL;
20503 largest = 0;
20504
20505
20506 testpt = apex(*searchtet);
20507 if (isedgeencroached(tstart, tend, testpt, true)) {
20508 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20509 #ifdef SELF_CHECK
20510 assert(ncollinear);
20511 #endif
20512 refpoint = testpt;
20513 largest = radius;
20514 }
20515 testpt = dest(*searchtet);
20516 if (isedgeencroached(tstart, tend, testpt, true)) {
20517 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20518 #ifdef SELF_CHECK
20519 assert(ncollinear);
20520 #endif
20521 if (refpoint == (point) NULL) {
20522 refpoint = testpt;
20523 largest = radius;
20524 } else {
20525 if (radius > largest) {
20526 refpoint = testpt;
20527 largest = radius;
20528 }
20529 }
20530 }
20531 testpt = oppo(*searchtet);
20532 if (isedgeencroached(tstart, tend, testpt, true)) {
20533 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20534 #ifdef SELF_CHECK
20535 assert(ncollinear);
20536 #endif
20537 if (refpoint == (point) NULL) {
20538 refpoint = testpt;
20539 largest = radius;
20540 } else {
20541 if (radius > largest) {
20542 refpoint = testpt;
20543 largest = radius;
20544 }
20545 }
20546 }
20547
20548
20549 sym(*searchtet, checkface);
20550 if (checkface.tet != dummytet) {
20551 testpt = oppo(checkface);
20552 if (isedgeencroached(tstart, tend, testpt, true)) {
20553 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20554 #ifdef SELF_CHECK
20555 assert(ncollinear);
20556 #endif
20557 if (refpoint == (point) NULL) {
20558 refpoint = testpt;
20559 largest = radius;
20560 } else {
20561 if (radius > largest) {
20562 refpoint = testpt;
20563 largest = radius;
20564 }
20565 }
20566 }
20567 }
20568
20569
20570 enextfnext(*searchtet, checkface);
20571 sym(checkface, *searchtet);
20572 while (true) {
20573
20574 #ifdef SELF_CHECK
20575 assert(searchtet->tet != dummytet);
20576 #endif
20577
20578 searchtet->ver = 0;
20579
20580 testpt = oppo(*searchtet);
20581 if (testpt == tend) {
20582
20583 break;
20584 } else {
20585
20586 if ((testpt != tstart) && (testpt != refpoint)) {
20587 if (isedgeencroached(tstart, tend, testpt, true)) {
20588 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20589 if (!ncollinear) {
20590
20591
20592
20593
20594
20595 refpoint = testpt;
20596 break;
20597 }
20598 if (refpoint == (point) NULL) {
20599 refpoint = testpt;
20600 largest = radius;
20601 } else {
20602 if (radius > largest) {
20603 refpoint = testpt;
20604 largest = radius;
20605 }
20606 }
20607 }
20608 }
20609 }
20610
20611
20612 for (sides = 0; sides < 3; sides++) {
20613 fnext(*searchtet, checkface);
20614 ahead = orient3d(org(checkface), dest(checkface), testpt, tend);
20615 if (ahead < 0.0) {
20616
20617 sym(checkface, *searchtet);
20618 break;
20619 }
20620 enextself(*searchtet);
20621 }
20622 #ifdef SELF_CHECK
20623 assert (sides < 3);
20624 #endif
20625 }
20626
20627 #ifdef SELF_CHECK
20628 assert(refpoint != (point) NULL);
20629 #endif
20630 return refpoint;
20631 }
20632
20634
20635
20636
20637
20638
20639
20640
20641
20643
20644 tetgenmesh::point tetgenmesh::getsegmentorigin(face* splitseg)
20645 {
20646 face workseg;
20647 point farorg;
20648
20649 farorg = sorg(*splitseg);
20650 if ((pointtype(farorg) != ACUTEVERTEX) &&
20651 (pointtype(farorg) != NACUTEVERTEX)) {
20652 workseg = *splitseg;
20653 do {
20654 senext2self(workseg);
20655 spivotself(workseg);
20656 if (workseg.sh != dummysh) {
20657 workseg.shver = 0;
20658 if (sdest(workseg) != farorg) {
20659 sesymself(workseg);
20660 #ifdef SELF_CHECK
20661 assert(sdest(workseg) == farorg);
20662 #endif
20663 }
20664 farorg = sorg(workseg);
20665 if ((pointtype(farorg) == ACUTEVERTEX) ||
20666 (pointtype(farorg) == NACUTEVERTEX)) break;
20667 }
20668 } while (workseg.sh != dummysh);
20669 }
20670 #ifdef SELF_CHECK
20671 assert((pointtype(farorg) == ACUTEVERTEX) ||
20672 (pointtype(farorg) == NACUTEVERTEX));
20673 #endif
20674 return farorg;
20675 }
20676
20678
20679
20680
20681
20682
20683
20684
20685
20686
20687
20688
20689
20690
20691
20693
20694 tetgenmesh::point tetgenmesh::getsplitpoint(face* splitseg, point refpoint)
20695 {
20696 point splitpoint;
20697 point farorg, fardest;
20698 point ei, ej, ek, c;
20699 REAL v[3], r, split;
20700 REAL d1, d2, ps, rs;
20701 bool acuteorg, acutedest;
20702 int stype, rule;
20703 int i;
20704
20705
20706 farorg = getsegmentorigin(splitseg);
20707 acuteorg = (pointtype(farorg) == ACUTEVERTEX);
20708 sesymself(*splitseg);
20709 fardest = getsegmentorigin(splitseg);
20710 acutedest = (pointtype(fardest) == ACUTEVERTEX);
20711 sesymself(*splitseg);
20712
20713 ek = (point) NULL;
20714
20715 if (acuteorg) {
20716 if (acutedest) {
20717 stype = 3;
20718 } else {
20719 stype = 2;
20720 ek = farorg;
20721 }
20722 } else {
20723 if (acutedest) {
20724 stype = 2;
20725
20726 sesymself(*splitseg);
20727 ek = fardest;
20728 } else {
20729 stype = 1;
20730 }
20731 }
20732 ei = sorg(*splitseg);
20733 ej = sdest(*splitseg);
20734
20735 if (b->verbose > 1) {
20736 printf(" Splitting segment (%d, %d) type-%d with refpoint %d.\n",
20737 pointmark(ei), pointmark(ej), stype, pointmark(refpoint));
20738 }
20739
20740 if (stype == 1 || stype == 3) {
20741
20742 REAL eij, eip, ejp;
20743 eij = distance(ei, ej);
20744 eip = distance(ei, refpoint);
20745 ejp = distance(ej, refpoint);
20746 if ((eip < ejp) && (eip < 0.5 * eij)) {
20747 c = ei;
20748 r = eip;
20749 } else if ((eip > ejp) && (ejp < 0.5 * eij)) {
20750 c = ej;
20751 ej = ei;
20752 r = ejp;
20753 } else {
20754 c = ei;
20755 r = 0.5 * eij;
20756 }
20757 split = r / eij;
20758 for (i = 0; i < 3; i++) {
20759 v[i] = c[i] + split * (ej[i] - c[i]);
20760 }
20761 rule = 1;
20762 } else {
20763
20764 REAL eki, ekj, ekp, evj, evp, eiv;
20765 c = ek;
20766 eki = distance(ek, ei);
20767 ekj = distance(ek, ej);
20768 ekp = distance(ek, refpoint);
20769
20770 r = ekp;
20771
20772 if (!(eki < r && r < ekj)) {
20773 printf("Error: Invalid PLC.\n");
20774 printf(" Hint: Use -d switch to check it.\n");
20775 terminatetetgen(1);
20776 }
20777 split = r / ekj;
20778 for (i = 0; i < 3; i++) {
20779 v[i] = c[i] + split * (ej[i] - c[i]);
20780 }
20781 rule = 2;
20782 evj = ekj - r;
20783 evp = distance(v, refpoint);
20784 if (evj < evp) {
20785
20786 eiv = distance(ei, v);
20787 if (evp <= 0.5 * eiv) {
20788 r = eki + eiv - evp;
20789 } else {
20790 r = eki + 0.5 * eiv;
20791 }
20792 #ifdef SELF_CHECK
20793 assert(eki < r && r < ekj);
20794 #endif
20795 split = r / ekj;
20796 for (i = 0; i < 3; i++) {
20797 v[i] = c[i] + split * (ej[i] - c[i]);
20798 }
20799 if (b->verbose > 1) {
20800 printf(" Using rule-3.\n");
20801 }
20802 rule = 3;
20803 }
20804 }
20805
20806
20807 if (rule == 1) r1count++;
20808 else if (rule == 2) r2count++;
20809 else if (rule == 3) r3count++;
20810
20811 if (b->verbose > 1) {
20812 if (stype == 2) {
20813 printf(" Split = %.12g.\n", distance(ei, v) / distance(ei, ej));
20814 } else {
20815 printf(" Split = %.12g.\n", distance(c, v) / distance(c, ej));
20816 }
20817 }
20818
20819
20820 makepoint(&splitpoint);
20821
20822 d1 = distance(c, v);
20823 d2 = distance(refpoint, v);
20824 if (stype == 1 || stype == 3) {
20825 ps = randgenerator(d1 * 1.0e-3);
20826 } else {
20827
20828
20829
20830 ps = randgenerator(d2 * 1.0e-5);
20831 }
20832 rs = ps / d1;
20833
20834 for (i = 0; i < 3; i++) {
20835 splitpoint[i] = c[i] + (1.0 + rs) * (v[i] - c[i]);
20836 }
20837
20838
20839
20840 if (stype == 3) {
20841
20842 setpointtype(splitpoint, NACUTEVERTEX);
20843 } else {
20844
20845 setpointtype(splitpoint, FREESEGVERTEX);
20846 }
20847 setpoint2sh(splitpoint, sencode(*splitseg));
20848
20849 return splitpoint;
20850 }
20851
20853
20854
20855
20857
20858 bool tetgenmesh::insertsegment(face *insseg, list *misseglist)
20859 {
20860 badface *misseg;
20861 triface searchtet, spintet;
20862 point tend, checkpoint;
20863 point p1, p2;
20864 enum finddirectionresult collinear;
20865 int hitbdry;
20866
20867
20868 p1 = (point) insseg->sh[3];
20869 p2 = (point) insseg->sh[4];
20870 getsearchtet(p1, p2, &searchtet, &tend);
20871 collinear = finddirection(&searchtet, tend, tetrahedrons->items);
20872 if (collinear == LEFTCOLLINEAR) {
20873 checkpoint = apex(searchtet);
20874 enext2self(searchtet);
20875 esymself(searchtet);
20876 } else if (collinear == RIGHTCOLLINEAR) {
20877 checkpoint = dest(searchtet);
20878 } else if (collinear == TOPCOLLINEAR) {
20879 checkpoint = oppo(searchtet);
20880 fnextself(searchtet);
20881 enext2self(searchtet);
20882 esymself(searchtet);
20883 } else {
20884
20885 checkpoint = (point) NULL;
20886 }
20887 if (checkpoint == tend) {
20888
20889 hitbdry = 0;
20890 adjustedgering(searchtet, CCW);
20891 fnextself(searchtet);
20892 spintet = searchtet;
20893 do {
20894 tssbond1(spintet, *insseg);
20895 if (!fnextself(spintet)) {
20896 hitbdry++;
20897 if (hitbdry < 2) {
20898 esym(searchtet, spintet);
20899 if (!fnextself(spintet)) {
20900 hitbdry++;
20901 }
20902 }
20903 }
20904 } while ((apex(spintet) != apex(searchtet)) && (hitbdry < 2));
20905 return true;
20906 } else {
20907
20908 if (misseglist != (list *) NULL) {
20909 if (b->verbose > 2) {
20910 printf(" Queuing missing segment (%d, %d).\n", pointmark(p1),
20911 pointmark(p2));
20912 }
20913 misseg = (badface *) misseglist->append(NULL);
20914 misseg->ss = *insseg;
20915 misseg->forg = p1;
20916 misseg->fdest = p2;
20917 misseg->foppo = (point) NULL;
20918
20919 }
20920 return false;
20921 }
20922 }
20923
20925
20926
20927
20929
20930 void tetgenmesh::tallmissegs(list *misseglist)
20931 {
20932 face segloop;
20933
20934 if (b->verbose) {
20935 printf(" Queuing missing segments.\n");
20936 }
20937
20938 subsegs->traversalinit();
20939 segloop.sh = shellfacetraverse(subsegs);
20940 while (segloop.sh != (shellface *) NULL) {
20941 insertsegment(&segloop, misseglist);
20942 segloop.sh = shellfacetraverse(subsegs);
20943 }
20944 }
20945
20947
20948
20949
20950
20951
20952
20953
20954
20955
20956
20957
20958
20959
20960
20961
20962
20963
20964
20965
20966
20967
20968
20969
20970
20971
20972
20973
20974
20975
20976
20977
20978
20979
20980
20982
20983 void tetgenmesh::delaunizesegments()
20984 {
20985 list *misseglist;
20986 queue *flipqueue;
20987 badface *misloop;
20988 tetrahedron encodedtet;
20989 triface searchtet, splittet;
20990 face splitsh, symsplitsub;
20991 face segloop, symsplitseg;
20992 point refpoint, splitpoint, sympoint;
20993 point tend, checkpoint;
20994 point p1, p2, pa;
20995 enum finddirectionresult collinear;
20996 enum insertsiteresult success;
20997 enum locateresult symloc;
20998 bool coll;
20999 long vertcount;
21000 int i, j;
21001
21002 if (!b->quiet) {
21003 printf("Delaunizing segments.\n");
21004 }
21005
21006
21007 makepoint2tetmap();
21008
21009 flipqueue = new queue(sizeof(badface));
21010
21011 misseglist = new list(sizeof(badface), NULL, SUBPERBLOCK);
21012
21013 tallmissegs(misseglist);
21014
21015 checksubsegs = 1;
21016
21017 vertcount = points->items;
21018
21019 r1count = r2count = r3count = 0l;
21020
21021
21022 while (misseglist->items > 0) {
21023
21024 i = randomnation(misseglist->items);
21025 misloop = (badface *)(* misseglist)[i];
21026 segloop = misloop->ss;
21027
21028 *misloop = *(badface *)(* misseglist)[misseglist->items - 1];
21029 misseglist->items--;
21030
21031 p1 = (point) segloop.sh[3];
21032 p2 = (point) segloop.sh[4];
21033 if (b->verbose > 1) {
21034 printf(" Recover segment (%d, %d).\n", pointmark(p1), pointmark(p2));
21035 }
21036 getsearchtet(p1, p2, &searchtet, &tend);
21037 collinear = finddirection(&searchtet, tend, tetrahedrons->items);
21038 if (collinear == LEFTCOLLINEAR) {
21039 checkpoint = apex(searchtet);
21040 } else if (collinear == RIGHTCOLLINEAR) {
21041 checkpoint = dest(searchtet);
21042 } else if (collinear == TOPCOLLINEAR) {
21043 checkpoint = oppo(searchtet);
21044 } else {
21045 #ifdef SELF_CHECK
21046 assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
21047 #endif
21048 checkpoint = (point) NULL;
21049 }
21050 if (checkpoint != tend) {
21051
21052 splitpoint = (point) NULL;
21053 if (checkpoint != (point) NULL) {
21054
21055
21056
21057 splitpoint = checkpoint;
21058 if (pointtype(checkpoint) == FREEVOLVERTEX) {
21059
21060 setpointtype(splitpoint, NACUTEVERTEX);
21061 } else if (pointtype(checkpoint) == ACUTEVERTEX) {
21062
21063 } else if (pointtype(checkpoint) == NACUTEVERTEX) {
21064
21065 } else {
21066
21067 }
21068 } else {
21069
21070 refpoint = scoutrefpoint(&searchtet, tend);
21071 if (pointtype(refpoint) == FREEVOLVERTEX) {
21072
21073 coll = iscollinear(p1, p2, refpoint, b->epsilon);
21074 if (coll) {
21075
21076
21077 splitpoint = refpoint;
21078 setpointtype(splitpoint, NACUTEVERTEX);
21079 }
21080 }
21081 if (splitpoint == (point) NULL) {
21082
21083 splitpoint = getsplitpoint(&segloop, refpoint);
21084
21085
21086 if (checkpbcs) {
21087
21088 i = shellmark(segloop) - 1;
21089 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
21090 makepoint(&sympoint);
21091 symloc = getsegpbcsympoint(splitpoint, &segloop, sympoint,
21092 &symsplitseg, segpglist[j]);
21093 #ifdef SELF_CHECK
21094 assert(symloc != OUTSIDE);
21095 #endif
21096 if ((symloc == ONEDGE) && (symsplitseg.sh != segloop.sh)) {
21097 #ifdef SELF_CHECK
21098 assert(symsplitseg.sh != dummysh);
21099 #endif
21100 setpointtype(sympoint, FREESEGVERTEX);
21101 setpoint2sh(sympoint, sencode(symsplitseg));
21102
21103 pa = sorg(symsplitseg);
21104 splittet.tet = dummytet;
21105
21106 encodedtet = point2tet(pa);
21107 if (encodedtet != (tetrahedron) NULL) {
21108 decode(encodedtet, splittet);
21109 if (isdead(&splittet)) {
21110 splittet.tet = dummytet;
21111 }
21112 }
21113
21114 success = insertsite(sympoint, &splittet, false, flipqueue);
21115 #ifdef SELF_CHECK
21116 assert(success != DUPLICATEPOINT);
21117 #endif
21118 if (success == OUTSIDEPOINT) {
21119 inserthullsite(sympoint, &splittet, flipqueue);
21120 }
21121 if (steinerleft > 0) steinerleft--;
21122
21123 setpoint2tet(sympoint, encode(splittet));
21124
21125 lawson(misseglist, flipqueue);
21126
21127 symsplitseg.shver = 0;
21128 spivot(symsplitseg, symsplitsub);
21129
21130 splitsubedge(sympoint, &symsplitsub, flipqueue);
21131
21132 flipsub(flipqueue);
21133
21134 symsplitseg.shver = 0;
21135 insertsegment(&symsplitseg, misseglist);
21136 senextself(symsplitseg);
21137 spivotself(symsplitseg);
21138 symsplitseg.shver = 0;
21139 insertsegment(&symsplitseg, misseglist);
21140 } else {
21141
21142
21143 pointdealloc(sympoint);
21144 }
21145 }
21146 }
21147
21148
21149 if (isdead(&searchtet)) searchtet.tet = dummytet;
21150 success = insertsite(splitpoint, &searchtet, false, flipqueue);
21151 if (success == OUTSIDEPOINT) {
21152
21153
21154
21155 inserthullsite(splitpoint, &searchtet, flipqueue);
21156 }
21157 if (steinerleft > 0) steinerleft--;
21158
21159
21160 setpoint2tet(splitpoint, encode(searchtet));
21161
21162 lawson(misseglist, flipqueue);
21163 }
21164 }
21165
21166 spivot(segloop, splitsh);
21167 splitsubedge(splitpoint, &splitsh, flipqueue);
21168 flipsub(flipqueue);
21169
21170 segloop.shver = 0;
21171 insertsegment(&segloop, misseglist);
21172 senextself(segloop);
21173 spivotself(segloop);
21174 segloop.shver = 0;
21175 insertsegment(&segloop, misseglist);
21176 }
21177 }
21178
21179
21180 tetrahedrons->traversalinit();
21181 searchtet.tet = tetrahedrontraverse();
21182 while (searchtet.tet != (tetrahedron *) NULL) {
21183 for (i = 0; i < 6; i++) {
21184 searchtet.tet[8 + i] = (tetrahedron) dummysh;
21185 }
21186 searchtet.tet = tetrahedrontraverse();
21187 }
21188
21189 checksubsegs = 0;
21190
21191 if (b->verbose > 0) {
21192 printf(" %ld protect points.\n", points->items - vertcount);
21193 printf(" R1: %ld, R2: %ld, R3: %ld.\n", r1count, r2count, r3count);
21194 }
21195
21196 delete flipqueue;
21197 delete misseglist;
21198 }
21199
21200
21201
21202
21203
21204
21205
21206
21207
21209
21210
21211
21212
21213
21214
21216
21217 bool tetgenmesh::insertsubface(face* insertsh, triface* searchtet)
21218 {
21219 triface spintet, symtet;
21220 face testsh, testseg;
21221 face spinsh, casin, casout;
21222 point tapex, checkpoint;
21223 enum finddirectionresult collinear;
21224 int hitbdry;
21225
21226
21227 getsearchtet(sorg(*insertsh), sdest(*insertsh), searchtet, &checkpoint);
21228 collinear = finddirection(searchtet, checkpoint, tetrahedrons->items);
21229 if (collinear == LEFTCOLLINEAR) {
21230 enext2self(*searchtet);
21231 esymself(*searchtet);
21232 } else if (collinear == TOPCOLLINEAR) {
21233 fnextself(*searchtet);
21234 enext2self(*searchtet);
21235 esymself(*searchtet);
21236 }
21237 if (dest(*searchtet) != checkpoint) {
21238
21239 return false;
21240 }
21241
21242
21243 tapex = sapex(*insertsh);
21244 spintet = *searchtet;
21245 hitbdry = 0;
21246 do {
21247 if (apex(spintet) == tapex) {
21248
21249 tspivot(spintet, testsh);
21250 if (testsh.sh == dummysh) {
21251 adjustedgering(spintet, CCW);
21252 findedge(insertsh, org(spintet), dest(spintet));
21253 tsbond(spintet, *insertsh);
21254 sym(spintet, symtet);
21255 sesymself(*insertsh);
21256 tsbond(symtet, *insertsh);
21257 } else {
21258
21259 if (!b->quiet) {
21260 printf("Warning: Two subfaces are found duplicated at ");
21261 printf("(%d, %d, %d)\n", pointmark(sorg(testsh)),
21262 pointmark(sdest(testsh)), pointmark(sapex(testsh)));
21263 printf(" Subface of facet #%d is deleted.\n", shellmark(*insertsh));
21264
21265 }
21266 shellfacedealloc(subfaces, insertsh->sh);
21267 }
21268 return true;
21269 }
21270 if (!fnextself(spintet)) {
21271 hitbdry ++;
21272 if (hitbdry < 2) {
21273 esym(*searchtet, spintet);
21274 if (!fnextself(spintet)) {
21275 hitbdry ++;
21276 }
21277 }
21278 }
21279 } while (hitbdry < 2 && apex(spintet) != apex(*searchtet));
21280
21281
21282 return false;
21283 }
21284
21286
21287
21288
21289
21290
21291
21292
21293
21295
21296 bool tetgenmesh::tritritest(triface* checktet, point p1, point p2, point p3)
21297 {
21298 point forg, fdest, fapex;
21299 enum interresult intersect;
21300
21301 forg = org(*checktet);
21302 fdest = dest(*checktet);
21303 fapex = apex(*checktet);
21304
21305 #ifdef SELF_CHECK
21306 REAL ax, ay, az, bx, by, bz;
21307 REAL n[3];
21308
21309
21310 ax = forg[0] - fdest[0];
21311 ay = forg[1] - fdest[1];
21312 az = forg[2] - fdest[2];
21313 bx = forg[0] - fapex[0];
21314 by = forg[1] - fapex[1];
21315 bz = forg[2] - fapex[2];
21316 n[0] = ay * bz - by * az;
21317 n[1] = az * bx - bz * ax;
21318 n[2] = ax * by - bx * ay;
21319 assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21320
21321
21322 ax = p1[0] - p2[0];
21323 ay = p1[1] - p2[1];
21324 az = p1[2] - p2[2];
21325 bx = p1[0] - p3[0];
21326 by = p1[1] - p3[1];
21327 bz = p1[2] - p3[2];
21328 n[0] = ay * bz - by * az;
21329 n[1] = az * bx - bz * ax;
21330 n[2] = ax * by - bx * ay;
21331 assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21332
21333 #endif
21334
21335 intersect = tri_tri_inter(forg, fdest, fapex, p1, p2, p3);
21336 return intersect == INTERSECT;
21337 }
21338
21340
21341
21342
21343
21344
21345
21346
21347
21348
21349
21350
21351
21352
21354
21355 void tetgenmesh::initializecavity(list* floorlist, list* ceillist,
21356 list* frontlist)
21357 {
21358 triface neightet, casingtet;
21359 triface faketet;
21360 face worksh;
21361 int i;
21362
21363
21364 for (i = 0; i < floorlist->len(); i++) {
21365
21366 worksh = * (face *)(* floorlist)[i];
21367 #ifdef SELF_CHECK
21368
21369 stpivot(worksh, neightet);
21370 assert(neightet.tet == dummytet);
21371 #endif
21372
21373 sesymself(worksh);
21374 stpivot(worksh, casingtet);
21375
21376 if (casingtet.tet == dummytet) {
21377
21378 maketetrahedron(&faketet);
21379 setorg(faketet, sorg(worksh));
21380 setdest(faketet, sdest(worksh));
21381 setapex(faketet, sapex(worksh));
21382 setoppo(faketet, (point) NULL);
21383 tsbond(faketet, worksh);
21384 frontlist->append(&faketet);
21385 } else {
21386 frontlist->append(&casingtet);
21387 }
21388 }
21389
21390 for (i = 0; i < ceillist->len(); i++) {
21391
21392 neightet = * (triface *) (* ceillist)[i];
21393 #ifdef SELF_CHECK
21394
21395 assert(infected(neightet));
21396 #endif
21397
21398 sym(neightet, casingtet);
21399
21400 if (casingtet.tet == dummytet) {
21401
21402 maketetrahedron(&faketet);
21403
21404 adjustedgering(neightet, CW);
21405 setorg(faketet, org(neightet));
21406 setdest(faketet, dest(neightet));
21407 setapex(faketet, apex(neightet));
21408 setoppo(faketet, (point) NULL);
21409
21410 tspivot(neightet, worksh);
21411 if (worksh.sh != dummysh) {
21412 sesymself(worksh);
21413 tsbond(faketet, worksh);
21414 }
21415
21416 bond(faketet, neightet);
21417
21418 infect(neightet);
21419 frontlist->append(&faketet);
21420 } else {
21421 frontlist->append(&casingtet);
21422 }
21423 }
21424 }
21425
21427
21428
21429
21430
21431
21432
21434
21435 void tetgenmesh::retrievenewtets(list* newtetlist)
21436 {
21437 triface searchtet, casingtet;
21438 int i;
21439
21440
21441 for (i = 0; i < newtetlist->len(); i++) {
21442 searchtet = * (triface *)(* newtetlist)[i];
21443 if (isdead(&searchtet)) {
21444 newtetlist->del(i, 0); i--;
21445 continue;
21446 }
21447 infect(searchtet);
21448 }
21449
21450 for (i = 0; i < newtetlist->len(); i++) {
21451 searchtet = * (triface *)(* newtetlist)[i];
21452 for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
21453 sym(searchtet, casingtet);
21454 if ((casingtet.tet != dummytet) && !infected(casingtet)) {
21455 infect(casingtet);
21456 newtetlist->append(&casingtet);
21457 }
21458 }
21459 }
21460
21461 for (i = 0; i < newtetlist->len(); i++) {
21462 searchtet = * (triface *)(* newtetlist)[i];
21463 uninfect(searchtet);
21464 }
21465 }
21466
21468
21469
21470
21471
21472
21473
21474
21475
21476
21477
21479
21480 void tetgenmesh::delaunizecavvertices(triface* oldtet, list* floorptlist,
21481 list* ceilptlist, list* newtetlist, queue* flipque)
21482 {
21483 point *insertarray;
21484 triface bakhulltet, newtet;
21485 long bakhullsize;
21486 long arraysize;
21487 int bakchksub;
21488 int i, j;
21489
21490
21491 arraysize = floorptlist->len();
21492 if (ceilptlist != (list *) NULL) {
21493 arraysize += ceilptlist->len();
21494 }
21495 insertarray = new point[arraysize];
21496 for (i = 0; i < floorptlist->len(); i++) {
21497 insertarray[i] = * (point *)(* floorptlist)[i];
21498 }
21499 if (ceilptlist != (list *) NULL) {
21500 for (j = 0; j < ceilptlist->len(); j++) {
21501 insertarray[i + j] = * (point *)(* ceilptlist)[j];
21502 }
21503 }
21504
21505
21506 decode(dummytet[0], bakhulltet);
21507 bakhullsize = hullsize;
21508 bakchksub = checksubfaces;
21509 checksubfaces = 0;
21510 b->verbose--;
21511
21512
21513
21514 incrflipdelaunay(oldtet, insertarray, arraysize, false, false, 0.0, flipque);
21515
21516
21517 decode(dummytet[0], newtet);
21518 newtetlist->append(&newtet);
21519
21520 retrievenewtets(newtetlist);
21521
21522
21523 dummytet[0] = encode(bakhulltet);
21524 hullsize = bakhullsize;
21525 checksubfaces = bakchksub;
21526 b->verbose++;
21527
21528 delete [] insertarray;
21529 }
21530
21532
21533
21534
21535
21536
21537
21538
21539
21540
21541
21542
21544
21545 void tetgenmesh::insertauxsubface(triface* front, triface* idfront)
21546 {
21547 triface neightet;
21548 face auxsh;
21549
21550
21551 makeshellface(subfaces, &auxsh);
21552
21553 tsbond(*idfront, auxsh);
21554
21555 sym(*idfront, neightet);
21556 if (neightet.tet != dummytet) {
21557
21558 sesymself(auxsh);
21559 tsbond(neightet, auxsh);
21560 }
21561
21562 auxsh.sh[0] = (shellface) encode(*front);
21563 }
21564
21566
21567
21568
21569
21570
21571
21573
21574 bool tetgenmesh::scoutfront(triface* front, triface* idfront, list* newtetlist)
21575 {
21576 triface spintet;
21577 point pa, pb, pc;
21578 enum locateresult loc;
21579 enum finddirectionresult col;
21580 int hitbdry;
21581 int i;
21582
21583
21584 pa = org(*front);
21585 pb = dest(*front);
21586
21587 *idfront = recenttet;
21588
21589 if (isdead(idfront)) {
21590
21591 for (i = 0; i < newtetlist->len(); i++) {
21592 recenttet = * (triface *)(* newtetlist)[i];
21593 if (!isdead(&recenttet)) break;
21594 }
21595 assert(i < newtetlist->len());
21596 }
21597
21598
21599 loc = preciselocate(pa, idfront, (long) newtetlist->len());
21600 UNUSED_OPT(loc);
21601 assert(loc == ONVERTEX);
21602 recenttet = *idfront;
21603
21604 col = finddirection(idfront, pb, (long) newtetlist->len());
21605 if (col == RIGHTCOLLINEAR) {
21606
21607 } else if (col == LEFTCOLLINEAR) {
21608 enext2self(*idfront);
21609 esymself(*idfront);
21610 } else if (col == TOPCOLLINEAR) {
21611 fnextself(*idfront);
21612 enext2self(*idfront);
21613 esymself(*idfront);
21614 }
21615
21616 if (dest(*idfront) == pb) {
21617
21618 pc = apex(*front);
21619 spintet = *idfront;
21620 hitbdry = 0;
21621 do {
21622 if (apex(spintet) == pc) {
21623
21624
21625 *idfront = spintet;
21626 return true;
21627 }
21628 if (!fnextself(spintet)) {
21629 hitbdry ++;
21630 if (hitbdry < 2) {
21631 esym(*idfront, spintet);
21632 if (!fnextself(spintet)) {
21633 hitbdry ++;
21634 }
21635 }
21636 }
21637 if (apex(spintet) == apex(*idfront)) break;
21638 } while (hitbdry < 2);
21639 }
21640
21641
21642 if (b->verbose > 2) {
21643 printf(" Front (%d, %d, %d) is missing.\n", pointmark(pa),
21644 pointmark(pb), pointmark(apex(*front)));
21645 }
21646 return false;
21647 }
21648
21650
21651
21652
21653
21654
21655
21656
21657
21659
21660 void tetgenmesh::gluefronts(triface* front, triface* front1)
21661 {
21662 face consh;
21663
21664
21665
21666
21667
21668
21669
21670
21671
21672 tspivot(*front, consh);
21673 if (consh.sh != dummysh) {
21674 sesymself(consh);
21675 tsbond(*front1, consh);
21676 sesymself(consh);
21677 }
21678
21679 if (oppo(*front) == (point) NULL) {
21680
21681 assert(oppo(*front1) != (point) NULL);
21682
21683 if (consh.sh != dummysh) {
21684 stdissolve(consh);
21685 }
21686
21687 tetrahedrondealloc(front->tet);
21688
21689 dummytet[0] = encode(*front1);
21690 } else {
21691
21692 bond(*front, *front1);
21693 }
21694
21695 if (!isdead(front)) {
21696
21697 tspivot(*front1, consh);
21698
21699 if (oppo(*front1) == (point) NULL) {
21700
21701 assert(oppo(*front) != (point) NULL);
21702
21703 if (consh.sh != dummysh) {
21704 stdissolve(consh);
21705 sesymself(consh);
21706 tsbond(*front, consh);
21707 }
21708
21709 dissolve(*front);
21710
21711 tetrahedrondealloc(front1->tet);
21712
21713 dummytet[0] = encode(*front);
21714 } else {
21715
21716 if (consh.sh != dummysh) {
21717 sesymself(consh);
21718 tsbond(*front, consh);
21719 }
21720 }
21721 }
21722 }
21723
21725
21726
21727
21728
21729
21730
21731
21732
21734
21735 bool tetgenmesh::identifyfronts(list* frontlist, list* misfrontlist,
21736 list* newtetlist)
21737 {
21738 triface front, front1, tfront;
21739 triface idfront, neightet;
21740 face auxsh;
21741 int len, i, j;
21742
21743 misfrontlist->clear();
21744
21745 recenttet = * (triface *)(* newtetlist)[0];
21746
21747
21748 for (i = 0; i < frontlist->len(); i++) {
21749
21750 front = * (triface *)( *frontlist)[i];
21751 if (scoutfront(&front, &idfront, newtetlist)) {
21752
21753 assert((idfront.tet != dummytet) && !isdead(&idfront));
21754
21755 tspivot(idfront, auxsh);
21756 if (auxsh.sh != dummysh) {
21757
21758 decode((tetrahedron) auxsh.sh[0], front1);
21759 assert((front1.tet != dummytet) && !infected(front1));
21760
21761 tsdissolve(idfront);
21762 sym(idfront, neightet);
21763 if (neightet.tet != dummytet) {
21764 tsdissolve(neightet);
21765 }
21766
21767 shellfacedealloc(subfaces, auxsh.sh);
21768
21769 frontlist->del(i, 1); i--;
21770
21771 len = frontlist->len();
21772 for (j = 0; j < frontlist->len(); j++) {
21773 tfront = * (triface *)(* frontlist)[j];
21774 if ((tfront.tet == front1.tet) && (tfront.loc == front1.loc)) {
21775
21776 assert((tfront.tet != front.tet) || (tfront.loc != front.loc));
21777 frontlist->del(j, 1); i--;
21778 break;
21779 }
21780 }
21781 assert((frontlist->len() + 1) == len);
21782 UNUSED_OPT(len);
21783
21784 gluefronts(&front, &front1);
21785 } else {
21786
21787 insertauxsubface(&front, &idfront);
21788 }
21789 } else {
21790
21791 frontlist->del(i, 1); i--;
21792
21793 for (j = 0; j < misfrontlist->len(); j++) {
21794 front1 = * (triface *)(* misfrontlist)[j];
21795 if (isfacehaspoint(&front1, org(front)) &&
21796 isfacehaspoint(&front1, dest(front)) &&
21797 isfacehaspoint(&front1, apex(front))) break;
21798 }
21799 if (j < misfrontlist->len()) {
21800
21801 misfrontlist->del(j, 1);
21802
21803 gluefronts(&front, &front1);
21804 } else {
21805
21806 misfrontlist->append(&front);
21807 }
21808 }
21809 }
21810 return misfrontlist->len() == 0;
21811 }
21812
21814
21815
21816
21817
21818
21819
21820
21821
21823
21824 void tetgenmesh::detachauxsubfaces(list* newtetlist)
21825 {
21826 triface newtet, neightet;
21827 face auxsh;
21828 int i;
21829
21830 for (i = 0; i < newtetlist->len(); i++) {
21831
21832 newtet = * (triface *)(* newtetlist)[i];
21833
21834 if (isdead(&newtet)) continue;
21835 assert(!infected(newtet));
21836
21837 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
21838 tspivot(newtet, auxsh);
21839 if (auxsh.sh != dummysh) {
21840
21841 assert(sorg(auxsh) == (point) NULL);
21842 tsdissolve(newtet);
21843 sym(newtet, neightet);
21844 if (neightet.tet != dummytet) {
21845 assert(!isdead(&neightet));
21846 tsdissolve(neightet);
21847 }
21848
21849 shellfacedealloc(subfaces, auxsh.sh);
21850 }
21851 }
21852 }
21853 }
21854
21856
21857
21858
21859
21860
21861
21862
21863
21864
21866
21867 void tetgenmesh::expandcavity(list* frontlist, list* misfrontlist,
21868 list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
21869 {
21870 triface misfront, newfront, casingtet, crosstet;
21871 triface searchtet, faketet, bakhulltet;
21872 face checksh;
21873 point pd;
21874 enum insertsiteresult success;
21875 long bakhullsize;
21876 int bakchksub;
21877 int i, j, k;
21878
21879 if (b->verbose > 1) {
21880 printf(" Expand cavity (%d missing fronts).\n", misfrontlist->len());
21881 }
21882
21883 expcavcount++;
21884
21885 decode(dummytet[0], bakhulltet);
21886 bakhullsize = hullsize;
21887 bakchksub = checksubfaces;
21888 checksubfaces = 0;
21889 b->verbose--;
21890
21891
21892 recenttet = * (triface *)(* newtetlist)[0];
21893 assert((recenttet.tet != dummytet) && !isdead(&recenttet));
21894
21895
21896 for (i = 0; i < misfrontlist->len(); i++) {
21897
21898 misfront = * (triface *)(* misfrontlist)[i];
21899
21900 if (b->verbose > 1) {
21901 printf(" Get misfront (%d, %d, %d).\n", pointmark(org(misfront)),
21902 pointmark(dest(misfront)), pointmark(apex(misfront)));
21903 }
21904
21905 tspivot(misfront, checksh);
21906 if (checksh.sh != dummysh) {
21907
21908 sym(misfront, crosstet);
21909 if (!infected(crosstet)) {
21910
21911
21912 assert(checkpbcs);
21913
21914 continue;
21915 }
21916
21917 if (b->verbose > 1) {
21918 printf(" Queuing subface (%d, %d, %d).\n",
21919 pointmark(sorg(checksh)), pointmark(sdest(checksh)),
21920 pointmark(sapex(checksh)));
21921 }
21922
21923 tsdissolve(misfront);
21924 tsdissolve(crosstet);
21925
21926 stdissolve(checksh);
21927 sesymself(checksh);
21928 stdissolve(checksh);
21929
21930 sinfect(checksh);
21931 missingshqueue->push(&checksh);
21932 }
21933
21934 if (infected(misfront)) continue;
21935
21936 pd = oppo(misfront);
21937 #ifdef SELF_CHECK
21938
21939 assert(pd != (point) NULL);
21940 #endif
21941
21942
21943
21944 searchtet = recenttet;
21945
21946 if (isdead(&searchtet)) {
21947
21948 for (j = 0; j < newtetlist->len(); j++) {
21949 recenttet = * (triface *)(* newtetlist)[j];
21950 if (!isdead(&recenttet)) break;
21951 }
21952 assert(j < newtetlist->len());
21953 searchtet = recenttet;
21954 }
21955 success = insertsite(pd, &searchtet, false, flipque);
21956 if (success == OUTSIDEPOINT) {
21957
21958 inserthullsite(pd, &searchtet, flipque);
21959 }
21960 if (success != DUPLICATEPOINT) {
21961
21962 flip(flipque, NULL);
21963 }
21964
21965
21966
21967 adjustedgering(misfront, CCW);
21968 for (j = 0; j < 3; j++) {
21969
21970
21971
21972 fnext(misfront, newfront);
21973
21974 sym(newfront, casingtet);
21975
21976 if (!infected(casingtet)) {
21977
21978
21979 if (casingtet.tet == dummytet) {
21980
21981 maketetrahedron(&faketet);
21982
21983 adjustedgering(newfront, CW);
21984 setorg(faketet, org(newfront));
21985 setdest(faketet, dest(newfront));
21986 setapex(faketet, apex(newfront));
21987 setoppo(faketet, (point) NULL);
21988
21989 tspivot(newfront, checksh);
21990 if (checksh.sh != dummysh) {
21991 sesymself(checksh);
21992 tsbond(faketet, checksh);
21993 }
21994
21995 bond(faketet, newfront);
21996 frontlist->append(&faketet);
21997 } else {
21998
21999 frontlist->append(&casingtet);
22000 }
22001 } else {
22002
22003
22004
22005 for (k = frontlist->len() - 1; k >= 0; k--) {
22006 searchtet = * (triface *)(* frontlist)[k];
22007 if ((newfront.tet == searchtet.tet) &&
22008 (newfront.loc == searchtet.loc)) {
22009 frontlist->del(k, 0);
22010 break;
22011 }
22012 }
22013
22014 tspivot(newfront, checksh);
22015 if (checksh.sh != dummysh) {
22016
22017 if (b->verbose > 2) {
22018 printf(" Queuing subface (%d, %d, %d).\n",
22019 pointmark(sorg(checksh)), pointmark(sdest(checksh)),
22020 pointmark(sapex(checksh)));
22021 }
22022 tsdissolve(newfront);
22023 tsdissolve(casingtet);
22024
22025 stdissolve(checksh);
22026 sesymself(checksh);
22027 stdissolve(checksh);
22028 sinfect(checksh);
22029 missingshqueue->push(&checksh);
22030 }
22031 }
22032 enextself(misfront);
22033 }
22034
22035 if (!infected(misfront)) {
22036
22037 infect(misfront);
22038 crosstetlist->append(&misfront);
22039 }
22040 }
22041
22042
22043 for (i = 0; i < misfrontlist->len(); i++) {
22044 misfront = * (triface *)(* misfrontlist)[i];
22045 if (infected(misfront)) {
22046
22047 misfrontlist->del(i, 1);
22048 i--;
22049 }
22050 }
22051
22052
22053 if (misfrontlist->len() > 0) {
22054
22055
22056 assert(0);
22057 }
22058
22059
22060 retrievenewtets(newtetlist);
22061
22062
22063 dummytet[0] = encode(bakhulltet);
22064 hullsize = bakhullsize;
22065 checksubfaces = bakchksub;
22066 b->verbose++;
22067 }
22068
22070
22071
22072
22073
22074
22075
22076
22077
22078
22079
22080
22081
22082
22083
22084
22085
22087
22088 void tetgenmesh::carvecavity(list* newtetlist, list* outtetlist,
22089 queue* flipque)
22090 {
22091 triface newtet, neightet, front, outtet;
22092 face auxsh, consh;
22093 point pointptr;
22094 REAL ori;
22095 int i;
22096
22097
22098 outtetlist->clear();
22099
22100
22101 for (i = 0; i < newtetlist->len(); i++) {
22102
22103 newtet = * (triface *)(* newtetlist)[i];
22104 assert(!isdead(&newtet));
22105
22106 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22107 tspivot(newtet, auxsh);
22108 if (auxsh.sh != dummysh) {
22109
22110 sym(newtet, neightet);
22111 if (neightet.tet != dummytet) {
22112
22113
22114 decode((tetrahedron) auxsh.sh[0], front);
22115
22116 adjustedgering(front, CW);
22117 ori = orient3d(org(front), dest(front), apex(front), oppo(newtet));
22118 assert(ori != 0.0);
22119 if (ori < 0.0) {
22120
22121 outtet = neightet;
22122 } else {
22123
22124 outtet = newtet;
22125 }
22126
22127 if (!infected(outtet)) {
22128 infect(outtet);
22129 outtetlist->append(&outtet);
22130 }
22131 }
22132 }
22133 }
22134 }
22135
22136
22137 for (i = 0; i < outtetlist->len(); i++) {
22138 outtet = * (triface *)(* outtetlist)[i];
22139 for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22140 sym(outtet, neightet);
22141
22142 if ((neightet.tet != dummytet) && !infected(neightet)) {
22143
22144 tspivot(outtet, auxsh);
22145 if (auxsh.sh == dummysh) {
22146
22147 infect(neightet);
22148 outtetlist->append(&neightet);
22149 }
22150 }
22151 }
22152 }
22153
22154
22155 for (i = 0; i < outtetlist->len(); i++) {
22156
22157 outtet = * (triface *)(* outtetlist)[i];
22158
22159 for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22160
22161 tspivot(outtet, auxsh);
22162 if (auxsh.sh != dummysh) {
22163
22164 sym(outtet, neightet);
22165 assert(!infected(neightet));
22166
22167 dissolve(neightet);
22168 }
22169 }
22170
22171 tetrahedrondealloc(outtet.tet);
22172 }
22173
22174
22175 for (i = 0; i < newtetlist->len(); i++) {
22176
22177 newtet = * (triface *)(* newtetlist)[i];
22178
22179 if (isdead(&newtet)) continue;
22180
22181 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22182
22183 tspivot(newtet, auxsh);
22184 if (auxsh.sh != dummysh) {
22185
22186 decode((tetrahedron) auxsh.sh[0], front);
22187 assert((front.tet != dummytet) && !infected(front));
22188
22189 tsdissolve(newtet);
22190
22191 shellfacedealloc(subfaces, auxsh.sh);
22192
22193
22194 tspivot(front, consh);
22195 if (consh.sh != dummysh) {
22196 sesymself(consh);
22197
22198 tsbond(newtet, consh);
22199 }
22200
22201 if (oppo(front) == (point) NULL) {
22202
22203 if (consh.sh != dummysh) {
22204 sesymself(consh);
22205
22206 stdissolve(consh);
22207 }
22208
22209 tetrahedrondealloc(front.tet);
22210
22211 dummytet[0] = encode(newtet);
22212 } else {
22213
22214 bond(newtet, front);
22215 }
22216
22217 if (flipque != (queue *) NULL) {
22218 enqueueflipface(newtet, flipque);
22219 }
22220 }
22221 }
22222
22223 pointptr = org(newtet);
22224 setpoint2tet(pointptr, encode(newtet));
22225 pointptr = dest(newtet);
22226 setpoint2tet(pointptr, encode(newtet));
22227 pointptr = apex(newtet);
22228 setpoint2tet(pointptr, encode(newtet));
22229 pointptr = oppo(newtet);
22230 setpoint2tet(pointptr, encode(newtet));
22231 }
22232
22233 }
22234
22236
22237
22238
22239
22240
22241
22242
22244
22245 void tetgenmesh::delaunizecavity(list* floorlist, list* ceillist,
22246 list* ceilptlist, list* floorptlist, list* frontlist, list* misfrontlist,
22247 list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
22248 {
22249 int vertnum;
22250
22251 vertnum = floorptlist->len();
22252 vertnum += (ceilptlist != (list *) NULL ? ceilptlist->len() : 0);
22253 if (b->verbose > 1) {
22254 printf(" Delaunizing cavity (%d floors, %d ceilings, %d vertices).\n",
22255 floorlist->len(), ceillist->len(), vertnum);
22256 }
22257
22258 if ((floorlist->len() + ceillist->len()) > maxcavfaces) {
22259 maxcavfaces = floorlist->len() + ceillist->len();
22260 }
22261 if (vertnum > maxcavverts) {
22262 maxcavverts = vertnum;
22263 }
22264
22265
22266 frontlist->clear();
22267 misfrontlist->clear();
22268 newtetlist->clear();
22269
22270
22271 initializecavity(floorlist, ceillist, frontlist);
22272
22273 delaunizecavvertices(NULL, floorptlist, ceilptlist, newtetlist, flipque);
22274
22275 while (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
22276
22277 detachauxsubfaces(newtetlist);
22278
22279 expandcavity(frontlist, misfrontlist, newtetlist, crosstetlist,
22280 missingshqueue, flipque);
22281 }
22282
22283
22284 carvecavity(newtetlist, misfrontlist, NULL);
22285 }
22286
22288
22289
22290
22291
22292
22293
22294
22295
22296
22297
22298
22299
22300
22302
22303 void tetgenmesh::formmissingregion(face* missingsh, list* missingshlist,
22304 list* equatptlist, int* worklist)
22305 {
22306 face neighsh, worksh, workseg;
22307 point workpt[3];
22308 int idx, i, j;
22309
22310
22311 missingshlist->append(missingsh);
22312
22313 workpt[0] = sorg(*missingsh);
22314 workpt[1] = sdest(*missingsh);
22315 workpt[2] = sapex(*missingsh);
22316 for (i = 0; i < 3; i++) {
22317 idx = pointmark(workpt[i]) - in->firstnumber;
22318 worklist[idx] = 1;
22319 equatptlist->append(&workpt[i]);
22320 }
22321
22322 suninfect(*missingsh);
22323
22324
22325 for (i = 0; i < missingshlist->len(); i++) {
22326
22327 worksh = * (face *)(* missingshlist)[i];
22328
22329 for (j = 0; j < 3; j++) {
22330 sspivot(worksh, workseg);
22331 if (workseg.sh == dummysh) {
22332 spivot(worksh, neighsh);
22333 if (sinfected(neighsh)) {
22334
22335 if (sorg(neighsh) != sdest(worksh)) {
22336 sesymself(neighsh);
22337 }
22338 if (b->verbose > 2) {
22339 printf(" Add missing subface (%d, %d, %d).\n",
22340 pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
22341 pointmark(sapex(neighsh)));
22342 }
22343 missingshlist->append(&neighsh);
22344
22345 workpt[0] = sapex(neighsh);
22346 idx = pointmark(workpt[0]) - in->firstnumber;
22347
22348 if (worklist[idx] == 0) {
22349 worklist[idx] = 1;
22350 equatptlist->append(&workpt[0]);
22351 }
22352
22353 suninfect(neighsh);
22354 }
22355 }
22356 senextself(worksh);
22357 }
22358 }
22359
22360
22361 for (i = 0; i < missingshlist->len(); i++) {
22362 worksh = * (face *)(* missingshlist)[i];
22363 sinfect(worksh);
22364 }
22365 }
22366
22368
22369
22370
22371
22372
22373
22374
22375
22376
22377
22378
22379
22380
22381
22382
22384
22385 void tetgenmesh::rearrangesubfaces(list* missingshlist, list* boundedgelist,
22386 list* equatptlist, int* worklist)
22387 {
22388 link *boundedgelink;
22389 link *newshlink;
22390 triface starttet, spintet, neightet, worktet;
22391 face shloop, newsh, neighsh, spinsh, worksh;
22392 face workseg, casingin, casingout;
22393 point torg, tdest, workpt;
22394 point spt1, spt2, spt3;
22395 enum finddirectionresult collinear;
22396 enum shestype shtype;
22397 REAL area;
22398 bool matchflag, finishflag;
22399 int shmark, pbcgp, idx, hitbdry;
22400 int i, j;
22401
22402
22403 boundedgelink = new link(sizeof(face), NULL, 256);
22404
22405 newshlink = new link(sizeof(face), NULL, 256);
22406
22407
22408 worksh = * (face *)(* missingshlist)[0];
22409 shtype = shelltype(worksh);
22410
22411 for (i = 1; i < missingshlist->len(); i++) {
22412 worksh = * (face *)(* missingshlist)[i];
22413 assert(shelltype(worksh) == shtype);
22414 }
22415
22416 shmark = pbcgp = 0;
22417 area = 0.0;
22418
22419
22420 for (i = 0; i < boundedgelist->len(); i++) {
22421 shloop = * (face *)(* boundedgelist)[i];
22422 if (i == 0) {
22423
22424 shmark = shellmark(shloop);
22425 if (b->quality && varconstraint) {
22426
22427 area = areabound(shloop);
22428 }
22429 if (checkpbcs) {
22430
22431 pbcgp = shellpbcgroup(shloop);
22432 }
22433
22434 abovepoint = facetabovepointarray[shellmark(shloop)];
22435 if (abovepoint == (point) NULL) {
22436 getfacetabovepoint(&shloop);
22437 }
22438 }
22439 sspivot(shloop, workseg);
22440 if (workseg.sh == dummysh) {
22441
22442 spivot(shloop, neighsh);
22443 boundedgelink->add(&neighsh);
22444 } else {
22445
22446 boundedgelink->add(&shloop);
22447 }
22448 }
22449
22450
22451
22452
22453
22454
22455
22456
22457
22458
22459
22460 while (boundedgelink->len() > 0) {
22461
22462 shloop = * (face *) boundedgelink->del(1);
22463
22464 sspivot(shloop, workseg);
22465 torg = sorg(shloop);
22466 tdest = sdest(shloop);
22467
22468 getsearchtet(torg, tdest, &starttet, &workpt);
22469 collinear = finddirection(&starttet, workpt, tetrahedrons->items);
22470 if (collinear == LEFTCOLLINEAR) {
22471 enext2self(starttet);
22472 esymself(starttet);
22473 } else if (collinear == TOPCOLLINEAR) {
22474 fnextself(starttet);
22475 enext2self(starttet);
22476 esymself(starttet);
22477 }
22478 assert(dest(starttet) == workpt);
22479
22480 matchflag = false;
22481 spintet = starttet;
22482 hitbdry = 0;
22483 do {
22484 workpt = apex(spintet);
22485 idx = pointmark(workpt) - in->firstnumber;
22486 if (worklist[idx] == 1) {
22487
22488 finishflag = false;
22489 for (i = 0; i < missingshlist->len(); i++) {
22490 worksh = * (face *)(* missingshlist)[i];
22491 spt1 = sorg(worksh);
22492 spt2 = sdest(worksh);
22493 spt3 = sapex(worksh);
22494
22495 if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22496 == INTERSECT) {
22497 finishflag = true; break;
22498 }
22499
22500 if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22501 == INTERSECT) {
22502 finishflag = true; break;
22503 }
22504
22505 if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22506 == INTERSECT) {
22507 finishflag = true; break;
22508 }
22509 }
22510 if (finishflag) {
22511
22512 matchflag = true;
22513 for (i = 0; i < newshlink->len() && matchflag; i++) {
22514 worksh = * (face *) newshlink->getnitem(i + 1);
22515 spt1 = sorg(worksh);
22516 spt2 = sdest(worksh);
22517 spt3 = sapex(worksh);
22518
22519 if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22520 == INTERSECT) {
22521 matchflag = false; break;
22522 }
22523
22524 if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22525 == INTERSECT) {
22526 matchflag = false; break;
22527 }
22528
22529 if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22530 == INTERSECT) {
22531 matchflag = false; break;
22532 }
22533 }
22534 }
22535 if (matchflag == true) {
22536
22537 break;
22538 }
22539 }
22540 if (!fnextself(spintet)) {
22541 hitbdry ++;
22542 if (hitbdry < 2) {
22543 esym(starttet, spintet);
22544 if (!fnextself(spintet)) {
22545 hitbdry ++;
22546 }
22547 }
22548 }
22549 } while (hitbdry < 2 && apex(spintet) != apex(starttet));
22550 assert(matchflag == true);
22551 tspivot(spintet, neighsh);
22552 if (neighsh.sh != dummysh) {
22553 printf("Error: Invalid PLC.\n");
22554 printf(" Facet #%d and facet #%d overlap each other.\n",
22555 shellmark(neighsh), shellmark(shloop));
22556 printf(" It might be caused by a facet is defined more than once.\n");
22557 printf(" Hint: Use -d switch to find all overlapping facets.\n");
22558 exit(1);
22559 }
22560
22561 adjustedgering(spintet, CCW);
22562
22563 makeshellface(subfaces, &newsh);
22564 setsorg(newsh, org(spintet));
22565 setsdest(newsh, dest(spintet));
22566 setsapex(newsh, apex(spintet));
22567 if (b->quality && varconstraint) {
22568 setareabound(newsh, area);
22569 }
22570 if (checkpbcs) {
22571 setshellpbcgroup(newsh, pbcgp);
22572 }
22573 setshellmark(newsh, shmark);
22574 setshelltype(newsh, shtype);
22575
22576 newshlink->add(&newsh);
22577
22578 tsbond(spintet, newsh);
22579 sym(spintet, neightet);
22580 if (neightet.tet != dummytet) {
22581 sesym(newsh, neighsh);
22582 tsbond(neightet, neighsh);
22583 }
22584
22585 sspivot(shloop, workseg);
22586 if (workseg.sh == dummysh) {
22587 sbond(shloop, newsh);
22588 } else {
22589
22590
22591
22592
22593
22594
22595
22596 spivot(shloop, casingout);
22597 if (shloop.sh != casingout.sh) {
22598
22599 spinsh = casingout;
22600 do {
22601 casingin = spinsh;
22602 spivotself(spinsh);
22603 } while (sapex(spinsh) != sapex(shloop));
22604 assert(casingin.sh != shloop.sh);
22605
22606 sbond1(casingin, newsh);
22607 sbond1(newsh, casingout);
22608 } else {
22609
22610 sbond(newsh, newsh);
22611 }
22612
22613 ssbond(newsh, workseg);
22614 }
22615
22616
22617 for (i = 0; i < 2; i++) {
22618 if (i == 0) {
22619 senext(newsh, worksh);
22620 } else {
22621 senext2(newsh, worksh);
22622 }
22623 torg = sorg(worksh);
22624 tdest = sdest(worksh);
22625 finishflag = false;
22626 for (j = 0; j < boundedgelink->len() && !finishflag; j++) {
22627 neighsh = * (face *) boundedgelink->getnitem(j + 1);
22628 if ((sorg(neighsh) == torg && sdest(neighsh) == tdest) ||
22629 (sorg(neighsh) == tdest && sdest(neighsh) == torg)) {
22630
22631 sspivot(neighsh, workseg);
22632 if (workseg.sh == dummysh) {
22633 sbond(neighsh, worksh);
22634 } else {
22635
22636
22637 spivot(neighsh, casingout);
22638 if (neighsh.sh != casingout.sh) {
22639
22640 spinsh = casingout;
22641 do {
22642 casingin = spinsh;
22643 spivotself(spinsh);
22644 } while (sapex(spinsh) != sapex(neighsh));
22645 assert(casingin.sh != neighsh.sh);
22646
22647 sbond1(casingin, worksh);
22648 sbond1(worksh, casingout);
22649 } else {
22650
22651 sbond(worksh, worksh);
22652 }
22653
22654 ssbond(worksh, workseg);
22655 }
22656
22657 boundedgelink->del(j + 1);
22658 finishflag = true;
22659 }
22660 }
22661 if (!finishflag) {
22662
22663 boundedgelink->add(&worksh);
22664 }
22665 }
22666 }
22667
22668
22669 for (i = 0; i < missingshlist->len(); i++) {
22670 worksh = * (face *)(* missingshlist)[i];
22671 shellfacedealloc(subfaces, worksh.sh);
22672 }
22673
22674 for (i = 0; i < equatptlist->len(); i++) {
22675 workpt = * (point *)(* equatptlist)[i];
22676 idx = pointmark(workpt) - in->firstnumber;
22677 worklist[idx] = 0;
22678 }
22679
22680 delete boundedgelink;
22681 delete newshlink;
22682 }
22683
22685
22686
22687
22688
22689
22690
22691
22692
22693
22694
22695
22696
22698
22699 bool tetgenmesh::scoutcrossingedge(list* missingshlist, list* boundedgelist,
22700 list* crossedgelist, int* worklist)
22701 {
22702 triface starttet, spintet, worktet;
22703 face startsh, neighsh, worksh, workseg;
22704 point torg, tdest, tapex;
22705 point workpt[3], pa, pb, pc;
22706 enum finddirectionresult collinear;
22707 REAL ori1, ori2;
22708 bool crossflag;
22709 int hitbdry;
22710 int i, j, k;
22711
22712
22713
22714
22715 for (i = 0; i < missingshlist->len(); i++) {
22716 worksh = * (face *)(* missingshlist)[i];
22717 for (j = 0; j < 3; j++) {
22718 sspivot(worksh, workseg);
22719 if (workseg.sh == dummysh) {
22720 spivot(worksh, neighsh);
22721 if (!sinfected(neighsh)) {
22722 boundedgelist->append(&worksh);
22723 }
22724 } else {
22725 boundedgelist->append(&worksh);
22726 }
22727 senextself(worksh);
22728 }
22729 }
22730
22731 crossflag = false;
22732
22733
22734 for (i = 0; i < boundedgelist->len() && !crossflag; i++) {
22735 startsh = * (face *)(* boundedgelist)[i];
22736
22737 torg = sorg(startsh);
22738 tdest = sdest(startsh);
22739 tapex = sapex(startsh);
22740 getsearchtet(torg, tdest, &starttet, &workpt[0]);
22741 collinear = finddirection(&starttet, workpt[0], tetrahedrons->items);
22742 if (collinear == LEFTCOLLINEAR) {
22743 enext2self(starttet);
22744 esymself(starttet);
22745 } else if (collinear == TOPCOLLINEAR) {
22746 fnextself(starttet);
22747 enext2self(starttet);
22748 esymself(starttet);
22749 }
22750 #ifdef SELF_CHECK
22751 assert(dest(starttet) == workpt[0]);
22752 #endif
22753
22754 spintet = starttet;
22755 hitbdry = 0;
22756 do {
22757 if (fnextself(spintet)) {
22758
22759 workpt[1] = apex(spintet);
22760 workpt[2] = oppo(spintet);
22761 j = pointmark(workpt[1]) - in->firstnumber;
22762 k = pointmark(workpt[2]) - in->firstnumber;
22763 if (worklist[j] == 1) {
22764 ori1 = 0.0;
22765 } else {
22766
22767 ori1 = orient3d(torg, tdest, tapex, workpt[1]);
22768 }
22769 if (worklist[k] == 1) {
22770 ori2 = 0.0;
22771 } else {
22772
22773 ori2 = orient3d(torg, tdest, tapex, workpt[2]);
22774 }
22775
22776 if (ori1 * ori2 < 0.0) {
22777
22778 for (j = 0; j < missingshlist->len(); j++) {
22779 worksh = * (face *)(* missingshlist)[j];
22780 pa = sorg(worksh);
22781 pb = sdest(worksh);
22782 pc = sapex(worksh);
22783 crossflag = (tri_tri_inter(pa, pb, pc, workpt[0], workpt[1],
22784 workpt[2]) == INTERSECT);
22785 if (crossflag) {
22786
22787 worktet = spintet;
22788 adjustedgering(worktet, CCW);
22789 enextfnextself(worktet);
22790 enextself(worktet);
22791
22792 crossedgelist->append(&worktet);
22793 break;
22794 }
22795 }
22796 if (crossflag) break;
22797 }
22798 if (apex(spintet) == apex(starttet)) break;
22799 } else {
22800 hitbdry++;
22801
22802 if (hitbdry < 2) {
22803 esym(starttet, spintet);
22804 }
22805 }
22806 } while (hitbdry < 2);
22807 }
22808
22809 return crossflag;
22810 }
22811
22813
22814
22815
22816
22817
22818
22819
22820
22821
22822
22823
22824
22825
22826
22827
22828
22829
22830
22831
22832
22833
22834
22835
22836
22837
22838
22839
22841
22842 void tetgenmesh::formcavity(list* missingshlist, list* crossedgelist,
22843 list* equatptlist, list* crossshlist, list* crosstetlist,
22844 list* belowfacelist, list* abovefacelist, list* horizptlist,
22845 list* belowptlist, list* aboveptlist, queue* missingshqueue, int* worklist)
22846 {
22847 triface starttet, spintet, neightet, worktet;
22848 face startsh, neighsh, worksh, workseg;
22849 point torg, tdest, tapex, workpt[3];
22850 REAL checksign, orgori, destori;
22851 bool crossflag, inlistflag;
22852 bool belowflag, aboveflag;
22853 int idx, share;
22854 int i, j, k;
22855
22856
22857 startsh = * (face *)(* missingshlist)[0];
22858 torg = sorg(startsh);
22859 tdest = sdest(startsh);
22860 tapex = sapex(startsh);
22861
22862
22863 for (i = 0; i < crossedgelist->len(); i++) {
22864
22865 starttet = * (triface *)(* crossedgelist)[i];
22866 adjustedgering(starttet, CCW);
22867 if (b->verbose > 2) {
22868 printf(" Collect tets containing edge (%d, %d).\n",
22869 pointmark(org(starttet)), pointmark(dest(starttet)));
22870 }
22871 orgori = orient3d(torg, tdest, tapex, org(starttet));
22872 destori = orient3d(torg, tdest, tapex, dest(starttet));
22873 UNUSED_OPT(destori);
22874 #ifdef SELF_CHECK
22875 assert(orgori * destori < 0.0);
22876 #endif
22877 spintet = starttet;
22878 do {
22879
22880 fnextself(spintet);
22881
22882 tspivot(spintet, worksh);
22883 if (worksh.sh != dummysh) {
22884 printf("Error: Invalid PLC.\n");
22885 printf(" Two subfaces (%d, %d, %d) and (%d, %d, %d)\n",
22886 pointmark(torg), pointmark(tdest), pointmark(tapex),
22887 pointmark(sorg(worksh)), pointmark(sdest(worksh)),
22888 pointmark(sapex(worksh)));
22889 printf(" are found intersecting each other.\n");
22890 printf(" Hint: Use -d switch to find all intersecting facets.\n");
22891 terminatetetgen(1);
22892 }
22893 if (!infected(spintet)) {
22894 if (b->verbose > 2) {
22895 printf(" Add crossing tet (%d, %d, %d, %d).\n",
22896 pointmark(org(spintet)), pointmark(dest(spintet)),
22897 pointmark(apex(spintet)), pointmark(oppo(spintet)));
22898 }
22899 infect(spintet);
22900 crosstetlist->append(&spintet);
22901 }
22902
22903
22904
22905 workpt[0] = apex(spintet);
22906 idx = pointmark(workpt[0]) - in->firstnumber;
22907 if (worklist[idx] != 1) {
22908
22909 checksign = orient3d(torg, tdest, tapex, workpt[0]);
22910 #ifdef SELF_CHECK
22911 assert(checksign != 0.0);
22912 #endif
22913 if (checksign * orgori < 0.0) {
22914 enext2(spintet, worktet);
22915 workpt[1] = org(spintet);
22916 } else {
22917
22918 assert(checksign * destori < 0.0);
22919
22920 enext(spintet, worktet);
22921 workpt[1] = dest(spintet);
22922 }
22923
22924
22925 inlistflag = false;
22926 for (j = 0; j < crossedgelist->len() && !inlistflag; j++) {
22927 neightet = * (triface *)(* crossedgelist)[j];
22928 if (org(neightet) == workpt[0]) {
22929 if (dest(neightet) == workpt[1]) inlistflag = true;
22930 } else if (org(neightet) == workpt[1]) {
22931 if (dest(neightet) == workpt[0]) inlistflag = true;
22932 }
22933 }
22934 if (!inlistflag) {
22935 crossedgelist->append(&worktet);
22936 }
22937 }
22938 } while (apex(spintet) != apex(starttet));
22939 }
22940
22941
22942
22943
22944 for (i = 0; i < crosstetlist->len(); i++) {
22945
22946 starttet = * (triface *)(* crosstetlist)[i];
22947 #ifdef SELF_CHECK
22948 assert(infected(starttet));
22949 #endif
22950 adjustedgering(starttet, CCW);
22951
22952
22953 for (j = 0; j < 2; j++) {
22954 if (j == 0) {
22955 enextfnext(starttet, worktet);
22956 } else {
22957 enext2fnext(starttet, worktet);
22958 }
22959 sym(worktet, neightet);
22960
22961
22962 if ((neightet.tet == dummytet) || !infected(neightet)) {
22963 workpt[0] = org(worktet);
22964 workpt[1] = dest(worktet);
22965 workpt[2] = apex(worktet);
22966 belowflag = aboveflag = false;
22967 share = 0;
22968 for (k = 0; k < 3; k++) {
22969 idx = pointmark(workpt[k]) - in->firstnumber;
22970 if (worklist[idx] == 0) {
22971
22972 checksign = orient3d(torg, tdest, tapex, workpt[k]);
22973 #ifdef SELF_CHECK
22974 assert(checksign != 0.0);
22975 #endif
22976 if (checksign > 0.0) {
22977
22978 worklist[idx] = 2;
22979 belowptlist->append(&workpt[k]);
22980 } else if (checksign < 0.0) {
22981
22982 worklist[idx] = 3;
22983 aboveptlist->append(&workpt[k]);
22984 }
22985 }
22986 if (worklist[idx] == 2) {
22987
22988 belowflag = true;
22989 } else if (worklist[idx] == 3) {
22990
22991 aboveflag = true;
22992 } else {
22993 #ifdef SELF_CHECK
22994
22995 assert(worklist[idx] == 1);
22996 #endif
22997 share++;
22998 }
22999 }
23000 #ifdef SELF_CHECK
23001
23002 assert(share < 3);
23003
23004 assert(belowflag ^ aboveflag);
23005 #endif
23006 if (belowflag) {
23007 belowfacelist->append(&worktet);
23008 } else if (aboveflag) {
23009 abovefacelist->append(&worktet);
23010 }
23011 }
23012 }
23013 }
23014
23015
23016
23017
23018 for (i = 0; i < missingshlist->len(); i++) {
23019 worksh = * (face *)(* missingshlist)[i];
23020 #ifdef SELF_CHECK
23021 assert(sinfected(worksh));
23022 #endif
23023 workpt[0] = sorg(worksh);
23024 workpt[1] = sdest(worksh);
23025 workpt[2] = sapex(worksh);
23026 crossflag = false;
23027 for (j = 0; j < crosstetlist->len() && !crossflag; j++) {
23028
23029 starttet = * (triface *)(* crosstetlist)[j];
23030 adjustedgering(starttet, CCW);
23031
23032 for (k = 0; k < 2 && !crossflag; k++) {
23033 if (k == 0) {
23034 worktet = starttet;
23035 } else {
23036 fnext(starttet, worktet);
23037 }
23038 crossflag = tritritest(&worktet, workpt[0], workpt[1], workpt[2]);
23039 }
23040 }
23041 if (crossflag) {
23042
23043 suninfect(worksh);
23044 crossshlist->append(&worksh);
23045
23046 for (k = 0; k < 3; k++) {
23047 idx = pointmark(workpt[k]) - in->firstnumber;
23048 if (worklist[idx] != 4) {
23049 worklist[idx] = 4;
23050 horizptlist->append(&workpt[k]);
23051 }
23052 }
23053 }
23054 }
23055
23056
23057 for (i = 0; i < crosstetlist->len(); i++) {
23058 starttet = * (triface *)(* crosstetlist)[i];
23059 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
23060 sym(starttet, neightet);
23061
23062 if ((neightet.tet != dummytet) && infected(neightet)) {
23063 tspivot(starttet, worksh);
23064 if (worksh.sh != dummysh) {
23065
23066 if (b->verbose > 2) {
23067 printf(" Queuing subface (%d, %d, %d).\n",
23068 pointmark(sorg(worksh)), pointmark(sdest(worksh)),
23069 pointmark(sapex(worksh)));
23070 }
23071 tsdissolve(neightet);
23072 tsdissolve(starttet);
23073
23074 stdissolve(worksh);
23075 sesymself(worksh);
23076 stdissolve(worksh);
23077 sinfect(worksh);
23078 missingshqueue->push(&worksh);
23079 }
23080 }
23081 }
23082 }
23083
23084
23085 for (i = 0; i < equatptlist->len(); i++) {
23086 workpt[0] = * (point *)(* equatptlist)[i];
23087 idx = pointmark(workpt[0]) - in->firstnumber;
23088 #ifdef SELF_CHECK
23089 assert((worklist[idx] == 1) || (worklist[idx] == 4));
23090 #endif
23091 worklist[idx] = 0;
23092 }
23093 for (i = 0; i < belowptlist->len(); i++) {
23094 workpt[0] = * (point *)(* belowptlist)[i];
23095 idx = pointmark(workpt[0]) - in->firstnumber;
23096 #ifdef SELF_CHECK
23097 assert(worklist[idx] == 2);
23098 #endif
23099 worklist[idx] = 0;
23100 }
23101 for (i = 0; i < aboveptlist->len(); i++) {
23102 workpt[0] = * (point *)(* aboveptlist)[i];
23103 idx = pointmark(workpt[0]) - in->firstnumber;
23104 #ifdef SELF_CHECK
23105 assert(worklist[idx] == 3);
23106 #endif
23107 worklist[idx] = 0;
23108 }
23109 }
23110
23112
23113
23114
23115
23116
23117
23118
23120
23121 void tetgenmesh::insertallsubfaces(queue* missingshqueue)
23122 {
23123 triface searchtet;
23124 face subloop;
23125
23126 searchtet.tet = (tetrahedron *) NULL;
23127 subfaces->traversalinit();
23128 subloop.sh = shellfacetraverse(subfaces);
23129 while (subloop.sh != (shellface *) NULL) {
23130 if (!insertsubface(&subloop, &searchtet)) {
23131 if (b->verbose > 1) {
23132 printf(" Queuing subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23133 pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23134 }
23135 sinfect(subloop);
23136 missingshqueue->push(&subloop);
23137 }
23138 subloop.sh = shellfacetraverse(subfaces);
23139 }
23140 }
23141
23143
23144
23145
23146
23147
23148
23149
23150
23151
23152
23153
23154
23155
23156
23157
23158
23159
23160
23161
23162
23163
23165
23166 void tetgenmesh::constrainedfacets()
23167 {
23168 queue *missingshqueue, *flipque;
23169 list *missingshlist, *equatptlist;
23170 list *boundedgelist, *crossedgelist, *crosstetlist;
23171 list *crossshlist, *belowfacelist, *abovefacelist;
23172 list *horizptlist, *belowptlist, *aboveptlist;
23173 list *frontlist, *misfrontlist, *newtetlist;
23174 triface searchtet, worktet;
23175 face subloop, worksh;
23176 int *worklist;
23177 int i;
23178
23179 if (!b->quiet) {
23180 printf("Constraining facets.\n");
23181 }
23182
23183
23184 missingshqueue = new queue(sizeof(face));
23185 flipque = new queue(sizeof(badface));
23186
23187 missingshlist = new list(sizeof(face), NULL);
23188 boundedgelist = new list(sizeof(face), NULL);
23189 crossedgelist = new list(sizeof(triface), NULL);
23190 equatptlist = new list((char*) "point *");
23191 crossshlist = new list(sizeof(face), NULL);
23192 crosstetlist = new list(sizeof(triface), NULL);
23193 belowfacelist = new list(sizeof(triface), NULL);
23194 abovefacelist = new list(sizeof(triface), NULL);
23195 horizptlist = new list((char*)"point *");
23196 belowptlist = new list((char*)"point *");
23197 aboveptlist = new list((char*)"point *");
23198 frontlist = new list(sizeof(triface), NULL);
23199 misfrontlist = new list(sizeof(triface), NULL);
23200 newtetlist = new list(sizeof(triface), NULL);
23201
23202 worklist = new int[points->items + 1];
23203 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
23204
23205
23206 makepoint2tetmap();
23207
23208
23209 insertallsubfaces(missingshqueue);
23210
23211
23212 while (!missingshqueue->empty()) {
23213
23214 subloop = * (face *) missingshqueue->pop();
23215
23216 if (isdead(&subloop)) continue;
23217
23218 if (!sinfected(subloop)) continue;
23219
23220 if (insertsubface(&subloop, &searchtet)) {
23221 suninfect(subloop);
23222 continue;
23223 }
23224 if (b->verbose > 1) {
23225 printf(" Recover subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23226 pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23227 }
23228
23229 formmissingregion(&subloop, missingshlist, equatptlist, worklist);
23230
23231 if (scoutcrossingedge(missingshlist, boundedgelist, crossedgelist,
23232 worklist)) {
23233
23234 formcavity(missingshlist, crossedgelist, equatptlist, crossshlist,
23235 crosstetlist, belowfacelist, abovefacelist, horizptlist,
23236 belowptlist, aboveptlist, missingshqueue, worklist);
23237
23238 delaunizecavity(crossshlist, abovefacelist, aboveptlist, horizptlist,
23239 frontlist, misfrontlist, newtetlist, crosstetlist,
23240 missingshqueue, flipque);
23241
23242 for (i = 0; i < crossshlist->len(); i++) {
23243 worksh = * (face *)(* crossshlist)[i];
23244 sesymself(worksh);
23245 * (face *)(* crossshlist)[i] = worksh;
23246 }
23247
23248 delaunizecavity(crossshlist, belowfacelist, belowptlist, horizptlist,
23249 frontlist, misfrontlist, newtetlist, crosstetlist,
23250 missingshqueue, flipque);
23251
23252 for (i = 0; i < crosstetlist->len(); i++) {
23253 worktet = * (triface *)(* crosstetlist)[i];
23254 tetrahedrondealloc(worktet.tet);
23255 }
23256
23257
23258 for (i = 0; i < missingshlist->len(); i++) {
23259 worksh = * (face *)(* missingshlist)[i];
23260 if (sinfected(worksh)) {
23261
23262 missingshqueue->push(&worksh);
23263 }
23264 }
23265 crossshlist->clear();
23266 belowfacelist->clear();
23267 abovefacelist->clear();
23268 horizptlist->clear();
23269 belowptlist->clear();
23270 aboveptlist->clear();
23271 crosstetlist->clear();
23272 } else {
23273
23274
23275 rearrangesubfaces(missingshlist, boundedgelist, equatptlist, worklist);
23276 }
23277
23278 missingshlist->clear();
23279 boundedgelist->clear();
23280 crossedgelist->clear();
23281 equatptlist->clear();
23282 }
23283
23284
23285 checksubfaces = 1;
23286
23287 if (b->verbose > 0) {
23288 printf(" The biggest cavity: %d faces, %d vertices\n", maxcavfaces,
23289 maxcavverts);
23290 printf(" Enlarged %d times\n", expcavcount);
23291 }
23292
23293 delete missingshqueue;
23294 delete flipque;
23295 delete missingshlist;
23296 delete boundedgelist;
23297 delete crossedgelist;
23298 delete equatptlist;
23299 delete crossshlist;
23300 delete crosstetlist;
23301 delete belowfacelist;
23302 delete abovefacelist;
23303 delete horizptlist;
23304 delete belowptlist;
23305 delete aboveptlist;
23306 delete frontlist;
23307 delete misfrontlist;
23308 delete newtetlist;
23309 delete [] worklist;
23310 }
23311
23312
23313
23314
23315
23316
23317
23318
23319
23321
23322
23323
23324
23325
23326
23327
23329
23330 void tetgenmesh::infecthull(memorypool *viri)
23331 {
23332 triface tetloop, tsymtet;
23333 tetrahedron **deadtet;
23334 face hullface;
23335
23336
23337 if (b->verbose > 0) {
23338 printf(" Marking concavities for elimination.\n");
23339 }
23340 tetrahedrons->traversalinit();
23341 tetloop.tet = tetrahedrontraverse();
23342 while (tetloop.tet != (tetrahedron *) NULL) {
23343
23344 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
23345 sym(tetloop, tsymtet);
23346 if (tsymtet.tet == dummytet) {
23347
23348 tspivot(tetloop, hullface);
23349 if (hullface.sh == dummysh) {
23350
23351 if (!infected(tetloop)) {
23352 infect(tetloop);
23353 deadtet = (tetrahedron **) viri->alloc();
23354 *deadtet = tetloop.tet;
23355 break;
23356 }
23357 } else {
23358
23359 if (shellmark(hullface) == 0) {
23360 setshellmark(hullface, 1);
23361
23362
23363
23364
23365
23366
23367
23368
23369
23370
23371
23372
23373
23374
23375 }
23376 }
23377 }
23378 }
23379 tetloop.tet = tetrahedrontraverse();
23380 }
23381 }
23382
23384
23385
23386
23387
23388
23389
23390
23391
23392
23394
23395 void tetgenmesh::plague(memorypool *viri)
23396 {
23397 tetrahedron **virusloop;
23398 tetrahedron **deadtet;
23399 triface testtet, neighbor;
23400 face neighsh, testseg;
23401 face spinsh, casingin, casingout;
23402 int firstdadsub;
23403 int i;
23404
23405 if (b->verbose > 0) {
23406 printf(" Marking neighbors of marked tetrahedra.\n");
23407 }
23408 firstdadsub = 0;
23409
23410
23411 viri->traversalinit();
23412 virusloop = (tetrahedron **) viri->traverse();
23413 while (virusloop != (tetrahedron **) NULL) {
23414 testtet.tet = *virusloop;
23415
23416 uninfect(testtet);
23417
23418 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23419
23420 sym(testtet, neighbor);
23421
23422 tspivot(testtet, neighsh);
23423
23424 if ((neighbor.tet == dummytet) || infected(neighbor)) {
23425 if (neighsh.sh != dummysh) {
23426
23427
23428
23429
23430 neighsh.shver = 0;
23431 if (!firstdadsub) {
23432 firstdadsub = 1;
23433 if (!b->quiet) {
23434 printf("Warning: Detecting an open face (%d, %d, %d).\n",
23435 pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
23436 pointmark(sapex(neighsh)));
23437 }
23438 }
23439
23440 findedge(&testtet, sorg(neighsh), sdest(neighsh));
23441 for (i = 0; i < 3; i++) {
23442 sspivot(neighsh, testseg);
23443 if (testseg.sh != dummysh) {
23444
23445
23446 testseg.shver = 0;
23447 spinsh = neighsh;
23448 if (sorg(spinsh) != sorg(testseg)) {
23449 sesymself(spinsh);
23450 }
23451 spivot(spinsh, casingout);
23452 if (casingout.sh == spinsh.sh) {
23453
23454
23455 shellfacedealloc(subsegs, testseg.sh);
23456 } else {
23457 spinsh = casingout;
23458 do {
23459 casingin = spinsh;
23460 spivotself(spinsh);
23461 } while (spinsh.sh != neighsh.sh);
23462
23463 sbond1(casingin, casingout);
23464
23465 ssbond(casingin, testseg);
23466 }
23467 }
23468 senextself(neighsh);
23469 enextself(testtet);
23470 }
23471 if (neighbor.tet != dummytet) {
23472
23473
23474 tsdissolve(neighbor);
23475 }
23476
23477 if (in->mesh_dim > 2) {
23478 shellfacedealloc(subfaces, neighsh.sh);
23479 } else {
23480
23481
23482 stdissolve(neighsh);
23483 sesymself(neighsh);
23484 stdissolve(neighsh);
23485 }
23486 }
23487 } else {
23488 if (neighsh.sh == dummysh) {
23489
23490 infect(neighbor);
23491
23492 deadtet = (tetrahedron **) viri->alloc();
23493 *deadtet = neighbor.tet;
23494 } else {
23495
23496 stdissolve(neighsh);
23497
23498 if (shellmark(neighsh) == 0) {
23499 setshellmark(neighsh, 1);
23500 }
23501
23502 dummytet[0] = encode(neighbor);
23503 }
23504 }
23505 }
23506
23507
23508 infect(testtet);
23509 virusloop = (tetrahedron **) viri->traverse();
23510 }
23511 }
23512
23514
23515
23516
23517
23518
23519
23520
23521
23523
23524 void tetgenmesh::
23525 regionplague(memorypool *regionviri, REAL attribute, REAL volume)
23526 {
23527 tetrahedron **virusloop;
23528 tetrahedron **regiontet;
23529 triface testtet, neighbor;
23530 face neighsh;
23531
23532 if (b->verbose > 1) {
23533 printf(" Marking neighbors of marked tetrahedra.\n");
23534 }
23535
23536
23537
23538 regionviri->traversalinit();
23539 virusloop = (tetrahedron **) regionviri->traverse();
23540 while (virusloop != (tetrahedron **) NULL) {
23541 testtet.tet = *virusloop;
23542
23543 uninfect(testtet);
23544 if (b->regionattrib) {
23545
23546 setelemattribute(testtet.tet, in->numberoftetrahedronattributes,
23547 attribute);
23548 }
23549 if (b->varvolume) {
23550
23551 setvolumebound(testtet.tet, volume);
23552 }
23553
23554 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23555
23556 sym(testtet, neighbor);
23557
23558 tspivot(testtet, neighsh);
23559
23560
23561
23562 if ((neighbor.tet != dummytet) && !infected(neighbor)
23563 && (neighsh.sh == dummysh)) {
23564
23565 infect(neighbor);
23566
23567 regiontet = (tetrahedron **) regionviri->alloc();
23568 *regiontet = neighbor.tet;
23569 }
23570 }
23571
23572
23573 infect(testtet);
23574 virusloop = (tetrahedron **) regionviri->traverse();
23575 }
23576
23577
23578 if (b->verbose > 1) {
23579 printf(" Unmarking marked tetrahedra.\n");
23580 }
23581 regionviri->traversalinit();
23582 virusloop = (tetrahedron **) regionviri->traverse();
23583 while (virusloop != (tetrahedron **) NULL) {
23584 testtet.tet = *virusloop;
23585 uninfect(testtet);
23586 virusloop = (tetrahedron **) regionviri->traverse();
23587 }
23588
23589 regionviri->restart();
23590 }
23591
23593
23594
23595
23597
23598 void tetgenmesh::removeholetets(memorypool* viri)
23599 {
23600 tetrahedron **virusloop;
23601 triface testtet, neighbor;
23602 point checkpt;
23603 int *tetspernodelist;
23604 int i, j;
23605
23606 if (b->verbose > 0) {
23607 printf(" Deleting marked tetrahedra.\n");
23608 }
23609
23610
23611 tetspernodelist = new int[points->items + 1];
23612 for (i = 0; i < points->items + 1; i++) tetspernodelist[i] = 0;
23613
23614
23615 tetrahedrons->traversalinit();
23616 testtet.tet = tetrahedrontraverse();
23617 while (testtet.tet != (tetrahedron *) NULL) {
23618
23619 for (i = 0; i < 4; i++) {
23620 j = pointmark((point) testtet.tet[4 + i]);
23621 tetspernodelist[j]++;
23622 }
23623 testtet.tet = tetrahedrontraverse();
23624 }
23625
23626 viri->traversalinit();
23627 virusloop = (tetrahedron **) viri->traverse();
23628 while (virusloop != (tetrahedron **) NULL) {
23629 testtet.tet = *virusloop;
23630
23631
23632 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23633 sym(testtet, neighbor);
23634 if (neighbor.tet == dummytet) {
23635
23636
23637
23638 hullsize--;
23639 } else {
23640
23641 dissolve(neighbor);
23642
23643
23644 hullsize++;
23645 }
23646 }
23647
23648 for (i = 0; i < 4; i++) {
23649 checkpt = (point) testtet.tet[4 + i];
23650 j = pointmark(checkpt);
23651 tetspernodelist[j]--;
23652 if (tetspernodelist[j] == 0) {
23653
23654 if ((pointtype(checkpt) == FREEVOLVERTEX) || !b->nojettison) {
23655 setpointtype(checkpt, UNUSEDVERTEX);
23656 unuverts++;
23657 }
23658 }
23659 }
23660
23661 tetrahedrondealloc(testtet.tet);
23662 virusloop = (tetrahedron **) viri->traverse();
23663 }
23664
23665 delete [] tetspernodelist;
23666 }
23667
23669
23670
23671
23672
23673
23674
23675
23676
23677
23679
23680 void tetgenmesh::assignregionattribs()
23681 {
23682 list *regionnumlist;
23683 list *regiontetlist;
23684 triface tetloop, regiontet, neightet;
23685 face checksh;
23686 bool flag;
23687 int regionnum, num;
23688 int attridx, count;
23689 int i;
23690
23691 if (b->verbose > 0) {
23692 printf(" Assign region numbers.\n");
23693 }
23694
23695 regionnumlist = new list(sizeof(int), NULL, 256);
23696 regiontetlist = new list(sizeof(triface), NULL, 1024);
23697 attridx = in->numberoftetrahedronattributes;
23698
23699
23700
23701 tetrahedrons->traversalinit();
23702 tetloop.tet = tetrahedrontraverse();
23703 while (tetloop.tet != (tetrahedron *) NULL) {
23704 if (!infected(tetloop)) {
23705 regionnum = (int) elemattribute(tetloop.tet, attridx);
23706 if (regionnum != 0.0) {
23707
23708 infect(tetloop);
23709 regiontetlist->append(&tetloop);
23710
23711 for (i = 0; i < regiontetlist->len(); i++) {
23712 regiontet = * (triface *)(* regiontetlist)[i];
23713 for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23714
23715 tspivot(regiontet, checksh);
23716 if (checksh.sh == dummysh) {
23717 sym(regiontet, neightet);
23718 if ((neightet.tet != dummytet) && !infected(neightet)) {
23719 #ifdef SELF_CHECK
23720
23721 num = (int) elemattribute(neightet.tet, attridx);
23722 assert(num == regionnum);
23723 #endif
23724 infect(neightet);
23725 regiontetlist->append(&neightet);
23726 }
23727 }
23728 }
23729 }
23730
23731 flag = false;
23732 for (i = 0; i < regionnumlist->len() && !flag; i++) {
23733 num = * (int *)(* regionnumlist)[i];
23734 flag = (num == regionnum);
23735 }
23736 if (!flag) regionnumlist->append(®ionnum);
23737
23738 regiontetlist->clear();
23739 }
23740 }
23741 tetloop.tet = tetrahedrontraverse();
23742 }
23743
23744 if (b->verbose > 0) {
23745 printf(" %d user-specified regions.\n", regionnumlist->len());
23746 }
23747
23748
23749 tetrahedrons->traversalinit();
23750 tetloop.tet = tetrahedrontraverse();
23751 regionnum = 1;
23752 count = 0;
23753 while (tetloop.tet != (tetrahedron *) NULL) {
23754 if (!infected(tetloop)) {
23755
23756 count++;
23757 do {
23758 flag = false;
23759
23760 for (i = 0; i < regionnumlist->len() && !flag; i++) {
23761 num = * (int *)(* regionnumlist)[i];
23762 flag = (num == regionnum);
23763 }
23764 if (flag) regionnum++;
23765 } while (flag);
23766 setelemattribute(tetloop.tet, attridx, (REAL) regionnum);
23767 infect(tetloop);
23768 regiontetlist->append(&tetloop);
23769
23770 for (i = 0; i < regiontetlist->len(); i++) {
23771 regiontet = * (triface *)(* regiontetlist)[i];
23772 for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23773
23774 tspivot(regiontet, checksh);
23775 if (checksh.sh == dummysh) {
23776 sym(regiontet, neightet);
23777 if ((neightet.tet != dummytet) && !infected(neightet)) {
23778 #ifdef SELF_CHECK
23779
23780 num = (int) elemattribute(neightet.tet, attridx);
23781 assert(num == 0);
23782 #endif
23783 setelemattribute(neightet.tet, attridx, (REAL) regionnum);
23784 infect(neightet);
23785 regiontetlist->append(&neightet);
23786 }
23787 }
23788 }
23789 }
23790 regiontetlist->clear();
23791 regionnum++;
23792 }
23793 tetloop.tet = tetrahedrontraverse();
23794 }
23795
23796
23797 tetrahedrons->traversalinit();
23798 tetloop.tet = tetrahedrontraverse();
23799 while (tetloop.tet != (tetrahedron *) NULL) {
23800 #ifdef SELF_CHECK
23801 assert(infected(tetloop));
23802 #endif
23803 uninfect(tetloop);
23804 tetloop.tet = tetrahedrontraverse();
23805 }
23806
23807 if (b->verbose > 0) {
23808 printf(" %d regions are numbered.\n", count);
23809 }
23810
23811 delete regionnumlist;
23812 delete regiontetlist;
23813 }
23814
23816
23817
23818
23819
23820
23821
23822
23823
23825
23826 void tetgenmesh::carveholes()
23827 {
23828 memorypool *holeviri, *regionviri;
23829 tetrahedron *tptr, **holetet, **regiontet;
23830 triface searchtet, *holetets, *regiontets;
23831 enum locateresult intersect;
23832 int i;
23833
23834 if (!b->quiet) {
23835 printf("Removing unwanted tetrahedra.\n");
23836 if (b->verbose && (in->numberofholes > 0)) {
23837 printf(" Marking holes for elimination.\n");
23838 }
23839 }
23840
23841
23842 holeviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23843
23844 infecthull(holeviri);
23845
23846 if (in->numberofholes > 0) {
23847
23848 holetets = (triface *) new triface[in->numberofholes];
23849
23850 for (i = 0; i < 3 * in->numberofholes; i += 3) {
23851
23852 if ((in->holelist[i] >= xmin) && (in->holelist[i] <= xmax)
23853 && (in->holelist[i + 1] >= ymin)
23854 && (in->holelist[i + 1] <= ymax)
23855 && (in->holelist[i + 2] >= zmin)
23856 && (in->holelist[i + 2] <= zmax)) {
23857 searchtet.tet = dummytet;
23858
23859 intersect = locate(&in->holelist[i], &searchtet);
23860 if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23861
23862 holetets[i / 3] = searchtet;
23863 }
23864 }
23865 }
23866
23867
23868 for (i = 0; i < in->numberofholes; i++) {
23869 infect(holetets[i]);
23870 holetet = (tetrahedron **) holeviri->alloc();
23871 *holetet = holetets[i].tet;
23872 }
23873
23874 delete [] holetets;
23875 }
23876
23877
23878 plague(holeviri);
23879
23880
23881
23882 if (b->regionattrib) {
23883
23884 tetrahedrons->traversalinit();
23885 tptr = tetrahedrontraverse();
23886 while (tptr != (tetrahedron *) NULL) {
23887 setelemattribute(tptr, in->numberoftetrahedronattributes, 0.0);
23888 tptr = tetrahedrontraverse();
23889 }
23890 }
23891
23892 if (in->numberofregions > 0) {
23893 if (!b->quiet) {
23894 if (b->regionattrib) {
23895 if (b->varvolume) {
23896 printf("Spreading regional attributes and volume constraints.\n");
23897 } else {
23898 printf("Spreading regional attributes.\n");
23899 }
23900 } else {
23901 printf("Spreading regional volume constraints.\n");
23902 }
23903 }
23904
23905 regiontets = (triface *) new triface[in->numberofregions];
23906
23907 for (i = 0; i < in->numberofregions; i++) {
23908 regiontets[i].tet = dummytet;
23909
23910 if ((in->regionlist[5 * i] >= xmin)
23911 && (in->regionlist[5 * i] <= xmax)
23912 && (in->regionlist[5 * i + 1] >= ymin)
23913 && (in->regionlist[5 * i + 1] <= ymax)
23914 && (in->regionlist[5 * i + 2] >= zmin)
23915 && (in->regionlist[5 * i + 2] <= zmax)) {
23916 searchtet.tet = dummytet;
23917
23918 intersect = locate(&in->regionlist[5 * i], &searchtet);
23919 if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23920
23921
23922 regiontets[i] = searchtet;
23923 }
23924 }
23925 }
23926
23927
23928 regionviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23929
23930 for (i = 0; i < in->numberofregions; i++) {
23931 if (regiontets[i].tet != dummytet) {
23932
23933
23934 if (!isdead(&(regiontets[i]))) {
23935
23936 infect(regiontets[i]);
23937 regiontet = (tetrahedron **) regionviri->alloc();
23938 *regiontet = regiontets[i].tet;
23939
23940 regionplague(regionviri, in->regionlist[5 * i + 3],
23941 in->regionlist[5 * i + 4]);
23942
23943 }
23944 }
23945 }
23946
23947 delete [] regiontets;
23948 delete regionviri;
23949 }
23950
23951
23952 removeholetets(holeviri);
23953
23954 nonconvex = 1;
23955
23956 if (b->regionattrib) {
23957 if (b->regionattrib > 1) {
23958
23959 assignregionattribs();
23960 }
23961
23962 in->numberoftetrahedronattributes++;
23963 }
23964
23965
23966 delete holeviri;
23967 }
23968
23969
23970
23971
23972
23973
23974
23975
23976
23978
23979
23980
23981
23982
23983
23984
23985
23986
23987
23989
23990 void tetgenmesh::replacepolygonsubs(list* oldshlist, list* newshlist)
23991 {
23992 face newsh, oldsh, spinsh;
23993 face casingout, casingin;
23994 face checkseg;
23995 point pa, pb;
23996 int i, j, k, l;
23997
23998 for (i = 0; i < newshlist->len(); i++) {
23999
24000 newsh = * (face *)(* newshlist)[i];
24001
24002 for (k = 0; k < 3; k++) {
24003 spivot(newsh, casingout);
24004
24005 if (casingout.sh == dummysh) {
24006
24007 pa = sorg(newsh);
24008 pb = sdest(newsh);
24009 for (j = 0; j < oldshlist->len(); j++) {
24010 oldsh = * (face *)(* oldshlist)[j];
24011 for (l = 0; l < 3; l++) {
24012 if (((sorg(oldsh) == pa) && (sdest(oldsh) == pb)) ||
24013 ((sorg(oldsh) == pb) && (sdest(oldsh) == pa))) break;
24014 senextself(oldsh);
24015 }
24016 if (l < 3) break;
24017 }
24018
24019 if (j < oldshlist->len()) {
24020
24021 spivot(oldsh, casingout);
24022 sspivot(oldsh, checkseg);
24023 if (checkseg.sh != dummysh) {
24024
24025 if (oldsh.sh != casingout.sh) {
24026
24027 spinsh = casingout;
24028 do {
24029 casingin = spinsh;
24030 spivotself(spinsh);
24031 } while (sapex(spinsh) != sapex(oldsh));
24032 assert(casingin.sh != oldsh.sh);
24033
24034 sbond1(casingin, newsh);
24035 sbond1(newsh, casingout);
24036 } else {
24037
24038 sbond(newsh, newsh);
24039 }
24040
24041 ssbond(newsh, checkseg);
24042 } else {
24043
24044 sbond(newsh, casingout);
24045 }
24046
24047
24048 sdissolve(oldsh);
24049 ssdissolve(oldsh);
24050 }
24051 }
24052
24053 senextself(newsh);
24054 }
24055 }
24056 }
24057
24059
24060
24061
24062
24063
24064
24065
24066
24068
24069 void tetgenmesh::orientnewsubs(list* newshlist, face* orientsh, REAL* norm)
24070 {
24071 face *newsh;
24072 point pa, pb, pc;
24073 REAL ref[3], ori, len;
24074 int i;
24075
24076
24077 pa = sorg(*orientsh);
24078 pb = sdest(*orientsh);
24079 pc = sapex(*orientsh);
24080 facenormal(pa, pb, pc, norm, &len);
24081 for (i = 0; i < 3; i++) ref[i] = pa[i] + norm[i];
24082 for (i = 0; i < 3; i++) norm[i] /= len;
24083
24084
24085 for (i = 0; i < newshlist->len(); i++) {
24086 newsh = (face *)(* newshlist)[i];
24087 pa = sorg(*newsh);
24088 pb = sdest(*newsh);
24089 pc = sapex(*newsh);
24090 ori = orient3d(pa, pb, pc, ref);
24091 assert(ori != 0.0);
24092 if (ori > 0.0) {
24093 sesymself(*newsh);
24094 }
24095 }
24096 }
24097
24099
24100
24101
24102
24103
24104
24105
24106
24107
24108
24109
24110
24111
24112
24113
24114
24115
24116
24118
24119 bool tetgenmesh::constrainedflip(triface* flipface, triface* front,
24120 queue* flipque)
24121 {
24122 triface symface, spintet;
24123 face checksh;
24124 point pa, pb, pc, pd, pe;
24125 enum fliptype fc;
24126 REAL sign;
24127 bool doflip;
24128 int ia, ib, ic, id, ie;
24129 int i;
24130
24131
24132 tspivot(*flipface, checksh);
24133 if (checksh.sh != dummysh) return false;
24134
24135 sym(*flipface, symface);
24136 if (symface.tet == dummytet) return false;
24137
24138 adjustedgering(*flipface, CCW);
24139 pa = dest(*flipface);
24140 pb = org(*flipface);
24141 pc = apex(*flipface);
24142 pd = oppo(*flipface);
24143 pe = oppo(symface);
24144
24145 ia = pointmark(pa);
24146 ib = pointmark(pb);
24147 ic = pointmark(pc);
24148 id = pointmark(pd);
24149 ie = pointmark(pe);
24150 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24151 assert(sign != 0.0);
24152
24153
24154
24155 if (sign <= 0.0) {
24156
24157 checksubfaces = 0;
24158 fc = categorizeface(*flipface);
24159 checksubfaces = 1;
24160 if (fc == T23) {
24161 doflip = true;
24162
24163
24164
24165
24166
24167
24168
24169
24170
24171
24172
24173
24174
24175 if (doflip) {
24176 flip23(flipface, flipque);
24177 return true;
24178 }
24179 } else if (fc == T32) {
24180
24181 doflip = true;
24182 spintet = *flipface;
24183 for (i = 0; i < 2; i++) {
24184 fnextself(spintet);
24185 tspivot(spintet, checksh);
24186 if (checksh.sh != dummysh) {
24187 doflip = false; break;
24188 }
24189 }
24190 if (doflip) {
24191 flip32(flipface, flipque);
24192 return true;
24193 }
24194 } else if (fc == T22 || fc == T44) {
24195
24196 doflip = true;
24197 if (fc == T22) {
24198 for (i = 0; i < 2; i++) {
24199 spintet = *flipface;
24200 if (i == 1) {
24201 esymself(spintet);
24202 }
24203 fnextself(spintet);
24204 tspivot(spintet, checksh);
24205 if (checksh.sh != dummysh) {
24206 doflip = false; break;
24207 }
24208 }
24209 } else if (fc == T44) {
24210 spintet = *flipface;
24211 for (i = 0; i < 3; i++) {
24212 fnextself(spintet);
24213 tspivot(spintet, checksh);
24214 if (checksh.sh != dummysh) {
24215 doflip = false; break;
24216 }
24217 }
24218 }
24219 if (doflip) {
24220 flip22(flipface, flipque);
24221 return true;
24222 }
24223 } else if (fc == N32) {
24224
24225 if (front != (triface *) NULL) {
24226
24227 spintet = *flipface;
24228 while (fnextself(spintet)) {
24229 if (apex(spintet) == apex(*flipface)) break;
24230
24231 if (constrainedflip(&spintet, NULL, flipque)) {
24232
24233 return true;
24234 }
24235
24236 findedge(&spintet, org(*flipface), dest(*flipface));
24237 }
24238 }
24239 }
24240 }
24241
24242
24243 if (front != (triface *) NULL) {
24244
24245 pa = org(*front);
24246 pb = dest(*front);
24247 pc = apex(*front);
24248
24249
24250 if (oppo(symface) != pc) {
24251 adjustedgering(symface, CCW);
24252 for (i = 0; i < 3; i++) {
24253 fnext(symface, spintet);
24254
24255 sign = orient3d(org(spintet), dest(spintet), apex(spintet), pc);
24256 if (sign < 0.0) {
24257 if (tritritest(&spintet, pa, pb, pc)) {
24258 if (b->verbose > 2) {
24259 printf(" Next crossface (%d, %d, %d).\n",
24260 pointmark(org(spintet)), pointmark(dest(spintet)),
24261 pointmark(apex(spintet)));
24262 }
24263 return constrainedflip(&spintet, front, flipque);
24264
24265 }
24266 }
24267 enextself(symface);
24268 }
24269 }
24270 }
24271 return false;
24272 }
24273
24275
24276
24277
24278
24279
24280
24282
24283 bool tetgenmesh::recoverfront(triface* front, list* newtetlist, queue* flipque)
24284 {
24285 triface idfront, starttet, spintet;
24286 point pa, pb, pc, pd, ref;
24287 enum locateresult loc;
24288 enum finddirectionresult col;
24289 REAL ori, ori1, ori2, sign;
24290 int hitbdry;
24291 int i, j;
24292
24293
24294 for (i = 0; i < 3; i++) {
24295 pa = org(*front);
24296 pb = dest(*front);
24297
24298 idfront = recenttet;
24299
24300 if (isdead(&idfront)) {
24301
24302 for (j = 0; j < newtetlist->len(); j++) {
24303 recenttet = * (triface *)(* newtetlist)[j];
24304 if (!isdead(&recenttet)) break;
24305 }
24306 assert(j < newtetlist->len());
24307 }
24308 loc = preciselocate(pa, &idfront, (long) newtetlist->len());
24309 if (loc != ONVERTEX) {
24310
24311 for (j = 0; j < newtetlist->len(); j++) {
24312 idfront = * (triface *)(* newtetlist)[j];
24313 if (isdead(&idfront)) continue;
24314 if (findorg(&idfront, pa)) break;
24315 }
24316 assert(j < newtetlist->len());
24317 }
24318 recenttet = idfront;
24319
24320 col = finddirection(&idfront, pb, (long) newtetlist->len());
24321 if (col == BELOWHULL) {
24322
24323 for (j = 0; j < newtetlist->len(); j++) {
24324 idfront = * (triface *)(* newtetlist)[j];
24325 if (isdead(&idfront)) continue;
24326 if (findorg(&idfront, pa)) {
24327 assert(org(idfront) == pa);
24328 if (dest(idfront) == pb) {
24329 col = RIGHTCOLLINEAR; break;
24330 } else if (apex(idfront) == pb) {
24331 col = LEFTCOLLINEAR; break;
24332 } else if (oppo(idfront) == pb) {
24333 col = TOPCOLLINEAR; break;
24334 }
24335 }
24336 }
24337 }
24338 if (col == RIGHTCOLLINEAR) {
24339
24340 } else if (col == LEFTCOLLINEAR) {
24341 enext2self(idfront);
24342 esymself(idfront);
24343 } else if (col == TOPCOLLINEAR) {
24344 fnextself(idfront);
24345 enext2self(idfront);
24346 esymself(idfront);
24347 }
24348 if (dest(idfront) == pb) break;
24349
24350 enextself(*front);
24351 }
24352 if (i == 3) {
24353
24354 return false;
24355 }
24356
24357
24358 pc = apex(*front);
24359 spintet = idfront;
24360 hitbdry = 0;
24361 do {
24362 if (apex(spintet) == pc) {
24363
24364 insertauxsubface(front, &spintet);
24365 return true;
24366 }
24367 if (!fnextself(spintet)) {
24368 hitbdry ++;
24369 if (hitbdry < 2) {
24370 esym(idfront, spintet);
24371 if (!fnextself(spintet)) {
24372 hitbdry ++;
24373 }
24374 }
24375 }
24376 if (apex(spintet) == apex(idfront)) break;
24377 } while (hitbdry < 2);
24378
24379
24380 pd = apex(idfront);
24381 assert(pd != pc);
24382
24383 ori = orient3d(pa, pb, pc, pd);
24384 if (ori < 0.0) {
24385
24386 esym(idfront, starttet);
24387 sign = -1.0;
24388 } else if (ori > 0.0) {
24389
24390 starttet = idfront;
24391 sign = 1.0;
24392 } else {
24393 assert(ori == 0.0);
24394
24395 ref = oppo(idfront);
24396 ori1 = orient3d(pa, pb, ref, pc);
24397 ori2 = orient3d(pa, pb, ref, pd);
24398 assert(ori1 * ori2 != 0.0);
24399 if (ori1 * ori2 > 0) {
24400
24401
24402 ori1 = orient3d(pb, pc, ref, pd);
24403 ori2 = orient3d(pb, pc, ref, pa);
24404 assert(ori1 * ori2 != 0.0);
24405 if (ori1 * ori2 > 0) {
24406
24407 enextself(idfront);
24408 } else {
24409
24410 enext2self(idfront);
24411 }
24412 adjustedgering(idfront, CCW);
24413 fnextself(idfront);
24414 if (b->verbose > 2) {
24415 printf(" Get crossface (%d, %d, %d).\n", pointmark(org(idfront)),
24416 pointmark(dest(idfront)), pointmark(apex(idfront)));
24417 }
24418 if (constrainedflip(&idfront, front, flipque)) {
24419
24420 return recoverfront(front, newtetlist, flipque);
24421 }
24422
24423 return false;
24424 } else {
24425
24426 starttet = idfront;
24427 if (fnextself(starttet)) {
24428
24429 sign = 1.0;
24430 } else {
24431
24432 esym(idfront, starttet);
24433 sign = -1.0;
24434 }
24435 }
24436 }
24437
24438 assert(sign != 0.0);
24439 if (sign == -1) {
24440
24441 pa = org(starttet);
24442 pb = dest(starttet);
24443
24444 sign = -sign;
24445 }
24446
24447
24448 spintet = starttet;
24449 while (fnextself(spintet)) {
24450 pd = apex(spintet);
24451 assert(pd != pc);
24452
24453 ori = orient3d(pa, pb, pc, pd);
24454 if (ori == 0.0) {
24455
24456 ref = oppo(spintet);
24457 ori1 = orient3d(pb, pc, ref, pd);
24458 ori2 = orient3d(pb, pc, ref, pa);
24459 assert(ori1 * ori2 != 0.0);
24460 if (ori1 * ori2 > 0) {
24461
24462 enextself(spintet);
24463 } else {
24464
24465 enext2self(spintet);
24466 }
24467 adjustedgering(spintet, CCW);
24468 fnextself(spintet);
24469 if (b->verbose > 2) {
24470 printf(" Get crossface (%d, %d, %d).\n", pointmark(org(spintet)),
24471 pointmark(dest(spintet)), pointmark(apex(spintet)));
24472 }
24473 if (constrainedflip(&spintet, front, flipque)) {
24474
24475 return recoverfront(front, newtetlist, flipque);
24476 }
24477
24478 return false;
24479 } else if (ori * sign < 0.0) {
24480
24481 adjustedgering(spintet, CCW);
24482 enextself(spintet);
24483 for (i = 0; i < 2; i++) {
24484
24485 fnext(spintet, starttet);
24486 if (tritritest(&starttet, pa, pb, pc)) {
24487 if (b->verbose > 2) {
24488 printf(" Get crossface (%d, %d, %d).\n",
24489 pointmark(org(starttet)), pointmark(dest(starttet)),
24490 pointmark(apex(starttet)));
24491 }
24492 if (constrainedflip(&starttet, front, flipque)) {
24493
24494 return recoverfront(front, newtetlist, flipque);
24495 }
24496 }
24497 enextself(spintet);
24498 }
24499
24500 return false;
24501 }
24502 }
24503
24504 assert(0);
24505 return false;
24506 }
24507
24509
24510
24511
24513
24514 void tetgenmesh::repairflips(queue* flipque)
24515 {
24516 badface *qface;
24517 triface flipface, symface, spintet;
24518 face checksh;
24519 point pa, pb, pc, pd, pe;
24520 enum fliptype fc;
24521 REAL sign;
24522 long flipcount;
24523 bool doflip;
24524 int ia, ib, ic, id, ie;
24525 int i;
24526
24527 if (b->verbose > 1) {
24528 printf(" Repair flip %ld faces.\n", flipque->len());
24529 }
24530 flipcount = flip23s + flip32s + flip22s + flip44s;
24531
24532 while (!flipque->empty()) {
24533 qface = (badface *) flipque->pop();
24534 flipface = qface->tt;
24535
24536 if (isdead(&flipface) || flipface.tet == dummytet ||
24537 (org(flipface) != qface->forg) ||
24538 (dest(flipface) != qface->fdest) ||
24539 (apex(flipface) != qface->fapex) ||
24540 (oppo(flipface) == (point) NULL)) continue;
24541
24542 tspivot(flipface, checksh);
24543 if (checksh.sh != dummysh) continue;
24544
24545 sym(flipface, symface);
24546 if (symface.tet == dummytet) continue;
24547
24548 adjustedgering(flipface, CW);
24549 pa = org(flipface);
24550 pb = dest(flipface);
24551 pc = apex(flipface);
24552 pd = oppo(flipface);
24553 pe = oppo(symface);
24554
24555 ia = pointmark(pa);
24556 ib = pointmark(pb);
24557 ic = pointmark(pc);
24558 id = pointmark(pd);
24559 ie = pointmark(pe);
24560 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24561 assert(sign != 0.0);
24562
24563
24564
24565 if (sign > 0.0) {
24566
24567 checksubfaces = 0;
24568 fc = categorizeface(flipface);
24569 checksubfaces = 1;
24570 if (fc == T23) {
24571 doflip = true;
24572
24573
24574
24575
24576
24577
24578
24579
24580
24581
24582
24583
24584
24585 if (doflip) {
24586 flip23(&flipface, flipque);
24587 }
24588 } else if (fc == T32) {
24589
24590 doflip = true;
24591 spintet = flipface;
24592 for (i = 0; i < 2; i++) {
24593 fnextself(spintet);
24594 tspivot(spintet, checksh);
24595 if (checksh.sh != dummysh) {
24596 doflip = false; break;
24597 }
24598 }
24599 if (doflip) {
24600 flip32(&flipface, flipque);
24601 }
24602 } else if (fc == T22 || fc == T44) {
24603
24604 doflip = true;
24605 if (fc == T22) {
24606 for (i = 0; i < 2; i++) {
24607 spintet = flipface;
24608 if (i == 1) {
24609 esymself(spintet);
24610 }
24611 fnextself(spintet);
24612 tspivot(spintet, checksh);
24613 if (checksh.sh != dummysh) {
24614 doflip = false; break;
24615 }
24616 }
24617 } else if (fc == T44) {
24618 spintet = flipface;
24619 for (i = 0; i < 3; i++) {
24620 fnextself(spintet);
24621 tspivot(spintet, checksh);
24622 if (checksh.sh != dummysh) {
24623 doflip = false; break;
24624 }
24625 }
24626 }
24627 if (doflip) {
24628 flip22(&flipface, flipque);
24629 }
24630 }
24631 }
24632 }
24633 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
24634 if (b->verbose > 1) {
24635 printf(" %ld flips.\n", flipcount);
24636 }
24637 }
24638
24640
24641
24642
24643
24644
24645
24647
24648 bool tetgenmesh::constrainedcavity(triface* oldtet, list* floorlist,
24649 list* ceillist, list* ptlist, list* frontlist, list* misfrontlist,
24650 list* newtetlist, queue* flipque)
24651 {
24652 triface misfront, newtet;
24653 long facenum;
24654 int i;
24655
24656 if (b->verbose > 1) {
24657 printf(" Constrained cavity (%d floors, %d ceilings, %d vertices).\n",
24658 floorlist->len(), ceillist->len(), ptlist->len());
24659 }
24660
24661
24662
24663
24664 initializecavity(floorlist, ceillist, frontlist);
24665
24666 delaunizecavvertices(oldtet, ptlist, NULL, newtetlist, flipque);
24667
24668
24669 if (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
24670
24671 recenttet = * (triface *)(* newtetlist)[0];
24672 assert((recenttet.tet != dummytet) && !isdead(&recenttet));
24673
24674 do {
24675 facenum = misfrontlist->len();
24676 for (i = 0; i < misfrontlist->len(); i++) {
24677
24678 misfront = * (triface *)(* misfrontlist)[i];
24679
24680 adjustedgering(misfront, CW);
24681 if (b->verbose > 1) {
24682 printf(" Recover face (%d, %d, %d).\n", pointmark(org(misfront)),
24683 pointmark(dest(misfront)), pointmark(apex(misfront)));
24684 }
24685 if (recoverfront(&misfront, newtetlist, flipque)) {
24686
24687 frontlist->append(&misfront);
24688 misfrontlist->del(i, 0); i--;
24689 }
24690
24691 repairflips(flipque);
24692 }
24693
24694 if (misfrontlist->len() == 0) break;
24695
24696
24697 } while (misfrontlist->len() < facenum);
24698
24699 retrievenewtets(newtetlist);
24700 }
24701
24702
24703
24704 if (misfrontlist->len() == 0) {
24705
24706
24707
24708 carvecavity(newtetlist, misfrontlist, NULL);
24709
24710
24711 return true;
24712 } else {
24713
24714
24715 detachauxsubfaces(newtetlist);
24716
24717 for (i = 0; i < newtetlist->len(); i++) {
24718 newtet = * (triface *)(* newtetlist)[i];
24719 assert(!isdead(&newtet));
24720 tetrahedrondealloc(newtet.tet);
24721 }
24722 newtetlist->clear();
24723
24724 for (i = 0; i < misfrontlist->len(); i++) {
24725 misfront = * (triface *)(* misfrontlist)[i];
24726 frontlist->append(&misfront);
24727 }
24728 return false;
24729 }
24730 }
24731
24733
24734
24735
24736
24737
24738
24740
24741 void tetgenmesh::expandsteinercavity(point steinpt, REAL eps, list* frontlist,
24742 list* oldtetlist)
24743 {
24744 triface front, symfront, newfront, oldfront;
24745 face frontsh;
24746 point pa, pb, pc;
24747 REAL ori;
24748 bool expflag, newflag;
24749 int i, j;
24750
24751 do {
24752 expflag = false;
24753 for (i = 0; i < frontlist->len(); i++) {
24754
24755 front = * (triface *)(* frontlist)[i];
24756
24757 tspivot(front, frontsh);
24758 if (frontsh.sh == dummysh) {
24759
24760 adjustedgering(front, CW);
24761 pa = org(front);
24762 pb = dest(front);
24763 pc = apex(front);
24764 ori = orient3d(pa, pb, pc, steinpt);
24765 if (ori != 0.0) {
24766 if (iscoplanar(pa, pb, pc, steinpt, ori, eps)) {
24767 ori = 0.0;
24768 }
24769 }
24770 if (ori >= 0.0) {
24771
24772 if (b->verbose > 2) {
24773 printf(" Remove front (%d, %d, %d).\n", pointmark(pa),
24774 pointmark(pb), pointmark(pc));
24775 }
24776 frontlist->del(i, 1);
24777 expflag = true;
24778 break;
24779 }
24780 }
24781 }
24782 if (expflag) {
24783 assert(!infected(front) && (oppo(front) != NULL));
24784
24785 adjustedgering(front, CCW);
24786 for (i = 0; i < 3; i++) {
24787 newflag = true;
24788
24789 fnext(front, symfront);
24790 tspivot(symfront, frontsh);
24791 sym(symfront, newfront);
24792 if (frontsh.sh == dummysh) {
24793 assert(newfront.tet != dummytet);
24794
24795 if (infected(newfront)) {
24796 for (j = 0; j < frontlist->len(); j++) {
24797 oldfront = * (triface *)(* frontlist)[j];
24798 if ((oldfront.tet == symfront.tet) &&
24799 (oldfront.loc == symfront.loc)) {
24800
24801 if (b->verbose > 2) {
24802 printf(" Remove front (%d, %d, %d).\n",
24803 pointmark(org(oldfront)), pointmark(dest(oldfront)),
24804 pointmark(apex(oldfront)));
24805 }
24806 frontlist->del(j, 1);
24807 newflag = false;
24808 break;
24809 }
24810 }
24811 }
24812 } else {
24813
24814 if (newfront.tet == dummytet) {
24815 sesymself(frontsh);
24816
24817 maketetrahedron(&newfront);
24818 setorg(newfront, sorg(frontsh));
24819 setdest(newfront, sdest(frontsh));
24820 setapex(newfront, sapex(frontsh));
24821 setoppo(newfront, (point) NULL);
24822 tsbond(newfront, frontsh);
24823 } else {
24824
24825 assert(!infected(newfront));
24826 }
24827 }
24828 if (newflag) {
24829 if (b->verbose > 2) {
24830 printf(" Add front (%d, %d, %d).\n", pointmark(org(newfront)),
24831 pointmark(dest(newfront)), pointmark(apex(newfront)));
24832 }
24833 frontlist->append(&newfront);
24834 }
24835 enextself(front);
24836 }
24837
24838 infect(front);
24839 oldtetlist->append(&front);
24840 expcavcount++;
24841 }
24842 } while (expflag);
24843 }
24844
24846
24847
24848
24849
24850
24851
24853
24854 bool tetgenmesh::findrelocatepoint(point sp, point np, REAL* n,
24855 list* frontlist, list* oldtetlist)
24856 {
24857 triface front;
24858 point pa, pb, pc;
24859 REAL tp[3], tvol, mvol;
24860 REAL ori, eps;
24861 bool visible;
24862 int i, j, k;
24863
24864 if (b->verbose > 1) {
24865 printf(" Find new location for point %d.\n", pointmark(sp));
24866 }
24867
24868
24869 tvol = mvol = 0.0;
24870 visible = false;
24871
24872 eps = b->epsilon;
24873
24874 for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24875
24876 for (i = 0; i < 3; i++) tp[i] = np[i];
24877
24878 j = 0;
24879 do {
24880 for (i = 0; i < frontlist->len(); i++) {
24881
24882 front = * (triface *)(* frontlist)[i];
24883
24884 adjustedgering(front, CW);
24885 pa = org(front);
24886 pb = dest(front);
24887 pc = apex(front);
24888 ori = orient3d(pa, pb, pc, np);
24889 visible = (ori < 0.0);
24890 if (!visible) {
24891
24892 for (i = 0; i < 3; i++) np[i] = sp[i] + 0.5 * (sp[i] - np[i]);
24893
24894 if ((tp[0] == np[0]) && (tp[1] == np[1]) && (tp[2] == np[2])) {
24895
24896 expandsteinercavity(sp, eps, frontlist, oldtetlist);
24897 eps *= 10.0;
24898 if (eps > b->epsilon * 1000.0) {
24899
24900
24901 return false;
24902 }
24903
24904 for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24905 }
24906 if (j % 2) {
24907
24908 for (i = 0; i < 3; i++) tp[i] = np[i];
24909 }
24910 break;
24911 } else {
24912
24913 if (i == 0) {
24914 mvol = fabs(ori);
24915 } else {
24916 mvol = fabs(ori) < mvol ? fabs(ori) : mvol;
24917 }
24918 }
24919 }
24920 j++;
24921 } while (!visible);
24922
24923 if (b->verbose > 1) {
24924 printf(" %d iterations. minvol = %.12g.\n", j, mvol);
24925 }
24926
24927
24928
24929 k = 0;
24930 do {
24931 j = 0;
24932 do {
24933 if (k == 0) {
24934
24935 for (i = 0; i < 3; i++) tp[i] = sp[i] + 0.9 * (np[i] - sp[i]);
24936 } else {
24937
24938 for (i = 0; i < 3; i++) tp[i] = sp[i] + 1.1 * (np[i] - sp[i]);
24939 }
24940
24941 for (i = 0; i < frontlist->len(); i++) {
24942
24943 front = * (triface *)(* frontlist)[i];
24944
24945 adjustedgering(front, CW);
24946 pa = org(front);
24947 pb = dest(front);
24948 pc = apex(front);
24949 ori = orient3d(pa, pb, pc, tp);
24950 visible = (ori < 0.0);
24951 if (visible) {
24952
24953 if (i == 0) {
24954 tvol = fabs(ori);
24955 } else {
24956 tvol = fabs(ori) < tvol ? fabs(ori) : tvol;
24957 }
24958 } else {
24959
24960 tvol = 0.0;
24961 break;
24962 }
24963 }
24964 if (tvol > mvol) {
24965
24966 for (i = 0; i < 3; i++) np[i] = tp[i];
24967 mvol = tvol;
24968 } else {
24969
24970 break;
24971 }
24972
24973 j++;
24974 } while (true);
24975
24976 if (j > 0) break;
24977
24978 k++;
24979 } while (k < 2);
24980
24981 if (b->verbose > 1) {
24982 printf(" %d adjust iterations. minvol = %.12g.\n", j, mvol);
24983 }
24984 return true;
24985 }
24986
24988
24989
24990
24991
24992
24993
24994
24996
24997 void tetgenmesh::relocatepoint(point steinpt, triface* oldtet, list* frontlist,
24998 list* newtetlist, queue* flipque)
24999 {
25000 triface front, newtet, newface, neightet;
25001 face checksh;
25002 point pa, pb;
25003 REAL attrib, volume;
25004 bool bdflag;
25005 int i, j, k, l;
25006
25007 if (b->verbose > 1) {
25008 printf(" Insert Steiner point (%.12g, %.12g, %.12g) %d.\n",
25009 steinpt[0], steinpt[1], steinpt[2], pointmark(steinpt));
25010 }
25011
25012 newtetlist->clear();
25013
25014
25015 for (i = 0; i < frontlist->len(); i++) {
25016
25017 front = * (triface *)(* frontlist)[i];
25018
25019 adjustedgering(front, CW);
25020 if (b->verbose > 2) {
25021 printf(" Get front (%d, %d, %d).\n", pointmark(org(front)),
25022 pointmark(dest(front)), pointmark(apex(front)));
25023 }
25024 maketetrahedron(&newtet);
25025 newtetlist->append(&newtet);
25026 setorg(newtet, org(front));
25027 setdest(newtet, dest(front));
25028 setapex(newtet, apex(front));
25029 setoppo(newtet, steinpt);
25030 if (oldtet != (triface *) NULL) {
25031 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
25032 attrib = elemattribute(oldtet->tet, j);
25033 setelemattribute(newtet.tet, j, attrib);
25034 }
25035 if (b->varvolume) {
25036 volume = volumebound(oldtet->tet);
25037 setvolumebound(newtet.tet, volume);
25038 }
25039 }
25040
25041 tspivot(front, checksh);
25042 if (oppo(front) == (point) NULL) {
25043 if (checksh.sh != dummysh) {
25044 stdissolve(checksh);
25045 }
25046
25047 tetrahedrondealloc(front.tet);
25048
25049
25050
25051 dummytet[0] = encode(newtet);
25052 } else {
25053
25054 bond(newtet, front);
25055 }
25056 if (checksh.sh != dummysh) {
25057 sesymself(checksh);
25058 tsbond(newtet, checksh);
25059 }
25060 if (flipque != (queue *) NULL) {
25061
25062 enqueueflipface(newtet, flipque);
25063 }
25064
25065 }
25066
25067
25068 for (i = 0; i < newtetlist->len(); i++) {
25069 newtet = * (triface *)(* newtetlist)[i];
25070 newtet.ver = 0;
25071 for (j = 0; j < 3; j++) {
25072 fnext(newtet, newface);
25073 sym(newface, neightet);
25074 if (neightet.tet == dummytet) {
25075
25076 bdflag = false;
25077 pa = org(newface);
25078 pb = dest(newface);
25079 assert(apex(newface) == steinpt);
25080 for (k = i + 1; k < newtetlist->len() && !bdflag; k++) {
25081 neightet = * (triface *)(* newtetlist)[k];
25082 neightet.ver = 0;
25083 for (l = 0; l < 3; l++) {
25084 if ((org(neightet) == pa && dest(neightet) == pb) ||
25085 (org(neightet) == pb && dest(neightet) == pa)) {
25086
25087 fnextself(neightet);
25088 assert(apex(neightet) == steinpt);
25089
25090 bond(newface, neightet);
25091 bdflag = true;
25092 break;
25093 }
25094 enextself(neightet);
25095 }
25096 }
25097 assert(bdflag);
25098 }
25099 enextself(newtet);
25100 }
25101
25102 pa = org(newtet);
25103 setpoint2tet(pa, encode(newtet));
25104 pa = dest(newtet);
25105 setpoint2tet(pa, encode(newtet));
25106 pa = apex(newtet);
25107 setpoint2tet(pa, encode(newtet));
25108 pa = oppo(newtet);
25109 setpoint2tet(pa, encode(newtet));
25110 }
25111
25112 if (flipque != (queue *) NULL) {
25113
25114 flip(flipque, NULL);
25115 }
25116 }
25117
25119
25120
25121
25123
25124 bool tetgenmesh::findcollapseedge(point suppt, point *conpt, list* oldtetlist,
25125 list* ptlist)
25126 {
25127 triface front;
25128 point pt, pa, pb, pc;
25129 REAL *lenarray, ltmp, ori;
25130 bool visflag;
25131 int *idxarray, itmp;
25132 int n, i, j;
25133
25134 if (b->verbose > 2) {
25135 printf(" Search an edge (in %d edges) for collapse %d.\n",
25136 ptlist->len(), pointmark(suppt));
25137 }
25138
25139
25140 n = ptlist->len();
25141 lenarray = new REAL[n];
25142 idxarray = new int[n];
25143
25144 for (i = 0; i < n; i++) {
25145 pt = * (point *)(* ptlist)[i];
25146 lenarray[i] = distance(suppt, pt);
25147 idxarray[i] = i;
25148 }
25149
25150 for (i = 0; i < n - 1; i++) {
25151 for (j = 0; j < n - 1 - i; j++) {
25152 if (lenarray[j + 1] < lenarray[j]) {
25153 ltmp = lenarray[j];
25154 lenarray[j] = lenarray[j + 1];
25155 lenarray[j + 1] = ltmp;
25156 itmp = idxarray[j];
25157 idxarray[j] = idxarray[j + 1];
25158 idxarray[j + 1] = itmp;
25159 }
25160 }
25161 }
25162
25163 for (i = 0; i < n; i++) {
25164 pt = * (point *)(* ptlist)[idxarray[i]];
25165
25166 lenarray[i] = 0.0;
25167 visflag = true;
25168 for (j = 0; j < oldtetlist->len() && visflag; j++) {
25169 front = * (triface *)(* oldtetlist)[j];
25170
25171 adjustedgering(front, CCW);
25172 pa = org(front);
25173 pb = dest(front);
25174 pc = apex(front);
25175
25176 if ((pa != pt) && (pb != pt) && (pc != pt)) {
25177 ori = orient3d(pa, pb, pc, pt);
25178 if (ori != 0.0) {
25179 if (iscoplanar(pa, pb, pc, pt, ori, b->epsilon * 1e+2)) ori = 0.0;
25180 }
25181 visflag = ori < 0.0;
25182 if (visflag) {
25183
25184 if (j == 0) {
25185 lenarray[i] = fabs(ori);
25186 } else {
25187 lenarray[i] = fabs(ori) < lenarray[i] ? fabs(ori) : lenarray[i];
25188 }
25189 } else {
25190
25191 lenarray[i] = 0.0;
25192 }
25193 }
25194 }
25195 if ((b->verbose > 2) && visflag) {
25196 printf(" Got candidate %d vol(%g).\n", pointmark(pt), lenarray[i]);
25197 }
25198 }
25199
25200
25201 ltmp = lenarray[0];
25202 itmp = idxarray[0];
25203 for (i = 1; i < n; i++) {
25204 if (lenarray[i] != 0.0) {
25205 if (lenarray[i] > ltmp) {
25206 ltmp = lenarray[i];
25207 itmp = idxarray[i];
25208 }
25209 }
25210 }
25211
25212 delete [] lenarray;
25213 delete [] idxarray;
25214
25215 if (ltmp == 0.0) {
25216
25217 *conpt = (point) NULL;
25218 return false;
25219 } else {
25220 pt = * (point *)(* ptlist)[itmp];
25221 *conpt = pt;
25222 return true;
25223 }
25224 }
25225
25227
25228
25229
25231
25232 void tetgenmesh::collapseedge(point suppt, point conpt, list* oldtetlist,
25233 list* deadtetlist)
25234 {
25235 triface oldtet, deadtet;
25236 triface adjtet1, adjtet2;
25237 face adjsh;
25238 point pa, pb, pc;
25239 int i, j;
25240
25241 if (b->verbose > 2) {
25242 printf(" Collapse edge (%d,%d).\n", pointmark(suppt), pointmark(conpt));
25243 }
25244
25245
25246 for (i = 0; i < oldtetlist->len(); i++) {
25247 oldtet = * (triface *)(* oldtetlist)[i];
25248 uninfect(oldtet);
25249 pa = org(oldtet);
25250 pb = dest(oldtet);
25251 pc = apex(oldtet);
25252 assert(oppo(oldtet) == suppt);
25253 setoppo(oldtet, conpt);
25254 if ((pa == conpt) || (pb == conpt) || (pc == conpt)) {
25255 deadtetlist->append(&oldtet);
25256 }
25257 }
25258
25259 for (i = 0; i < deadtetlist->len(); i++) {
25260 deadtet = * (triface *)(* deadtetlist)[i];
25261
25262 sym(deadtet, adjtet1);
25263 tspivot(deadtet, adjsh);
25264
25265 adjustedgering(deadtet, CCW);
25266 for (j = 0; j < 3; j++) {
25267 if (apex(deadtet) == conpt) break;
25268 enextself(deadtet);
25269 }
25270 assert(j < 3);
25271
25272 fnext(deadtet, adjtet2);
25273 symself(adjtet2);
25274 assert(adjtet2.tet != dummytet);
25275 if (adjtet1.tet != dummytet) {
25276 bond(adjtet1, adjtet2);
25277 } else {
25278 dissolve(adjtet2);
25279 dummytet[0] = encode(adjtet2);
25280 }
25281 if (adjsh.sh != dummysh) {
25282 tsbond(adjtet2, adjsh);
25283 }
25284
25285 tetrahedrondealloc(deadtet.tet);
25286 }
25287 deadtetlist->clear();
25288 }
25289
25291
25292
25293
25294
25295
25296
25297
25299
25300 void tetgenmesh::deallocfaketets(list* frontlist)
25301 {
25302 triface front, neightet;
25303 face checksh;
25304 bool infectflag;
25305 int i;
25306
25307 for (i = 0; i < frontlist->len(); i++) {
25308
25309 front = * (triface *)(* frontlist)[i];
25310
25311 adjustedgering(front, CW);
25312 sym(front, neightet);
25313 tspivot(front, checksh);
25314 if (oppo(front) == (point) NULL) {
25315 if (b->verbose > 2) {
25316 printf(" Get fake tet (%d, %d, %d).\n", pointmark(org(front)),
25317 pointmark(dest(front)), pointmark(apex(front)));
25318 }
25319 if (neightet.tet != dummytet) {
25320
25321
25322 infectflag = infected(neightet);
25323 dissolve(neightet);
25324 if (infectflag) {
25325 infect(neightet);
25326 }
25327 }
25328 if (checksh.sh != dummysh) {
25329 infectflag = sinfected(checksh);
25330 stdissolve(checksh);
25331 if (infectflag) {
25332 sinfect(checksh);
25333 }
25334 }
25335
25336 tetrahedrondealloc(front.tet);
25337
25338
25339
25340 if (neightet.tet != dummytet) {
25341 dummytet[0] = encode(neightet);
25342 }
25343 }
25344 }
25345 }
25346
25348
25349
25350
25351
25352
25353
25354
25355
25356
25357
25358
25360
25361 void tetgenmesh::restorepolyhedron(list* oldtetlist)
25362 {
25363 triface oldtet, neightet, neineitet;
25364 face checksh;
25365 int i;
25366
25367 for (i = 0; i < oldtetlist->len(); i++) {
25368
25369 oldtet = * (triface *)(* oldtetlist)[i];
25370
25371 for (oldtet.loc = 0; oldtet.loc < 4; oldtet.loc++) {
25372 sym(oldtet, neightet);
25373 tspivot(oldtet, checksh);
25374 if (neightet.tet != dummytet) {
25375 sym(neightet, neineitet);
25376 if (neineitet.tet != oldtet.tet) {
25377
25378 bond(neightet, oldtet);
25379 if (checksh.sh != dummysh) {
25380 tsbond(oldtet, checksh);
25381 }
25382 }
25383 } else {
25384
25385 #ifdef SELF_CHECK
25386 assert(checksh.sh != dummysh);
25387 stpivot(checksh, neineitet);
25388 assert(neineitet.tet != oldtet.tet);
25389 #endif
25390 tsbond(oldtet, checksh);
25391
25392 dummytet[0] = encode(oldtet);
25393 }
25394 }
25395 }
25396 }
25397
25399
25400
25401
25402
25403
25404
25405
25406
25407
25408
25409
25410
25412
25413 bool tetgenmesh::suppressfacetpoint(face* supsh, list* frontlist,
25414 list* misfrontlist, list* ptlist, list* conlist, memorypool* viri,
25415 queue* flipque, bool noreloc, bool optflag)
25416 {
25417 list *oldtetlist[2], *newtetlist[2];
25418 list *oldshlist, *newshlist;
25419 triface oldtet, newtet;
25420 face oldsh, newsh;
25421 point suppt, newpt[2];
25422 point *cons;
25423 REAL norm[3];
25424 bool success;
25425 int shmark;
25426 int i, j;
25427
25428 suppt = sapex(*supsh);
25429 if (b->verbose > 1) {
25430 printf(" Suppress point %d in facet.\n", pointmark(suppt));
25431 }
25432
25433
25434 for (i = 0; i < 2; i++) {
25435 oldtetlist[i] = (list *) NULL;
25436 newtetlist[i] = (list *) NULL;
25437 newpt[i] = (point) NULL;
25438 }
25439 oldshlist = new list(sizeof(face), NULL, 256);
25440 newshlist = new list(sizeof(face), NULL, 256);
25441 success = true;
25442
25443
25444 oldshlist->append(supsh);
25445 formstarpolygon(suppt, oldshlist, ptlist);
25446
25447 for (i = 0; i < oldshlist->len(); i++) {
25448 oldsh = * (face *)(* oldshlist)[i];
25449 cons = (point *) conlist->append(NULL);
25450 cons[0] = sorg(oldsh);
25451 cons[1] = sdest(oldsh);
25452 }
25453
25454 shmark = shellmark(*supsh);
25455 triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25456
25457 retrievenewsubs(newshlist, true);
25458
25459 replacepolygonsubs(oldshlist, newshlist);
25460
25461 ptlist->clear();
25462 conlist->clear();
25463 flipque->clear();
25464 viri->restart();
25465
25466
25467
25468 for (i = 0; i < 2 && success; i++) {
25469 if (i == 1) sesymself(*supsh);
25470
25471 stpivot(*supsh, oldtet);
25472
25473 if (oldtet.tet == dummytet) continue;
25474
25475 oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25476 newtetlist[i] = new list(sizeof(triface), NULL, 256);
25477
25478 assert(!isdead(&oldtet));
25479 oldtetlist[i]->append(&oldtet);
25480 formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25481
25482 for (j = 0; j < oldtetlist[i]->len(); j++) {
25483 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25484 infect(oldtet);
25485 }
25486
25487 orientnewsubs(newshlist, supsh, norm);
25488
25489 success = constrainedcavity(&oldtet, newshlist, oldtetlist[i], ptlist,
25490 frontlist, misfrontlist, newtetlist[i], flipque);
25491
25492 if (!success && !noreloc) {
25493
25494 makepoint(&(newpt[i]));
25495 success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25496 oldtetlist[i]);
25497
25498
25499
25500 if (success) {
25501
25502
25503 relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25504 setpointtype(newpt[i], FREEVOLVERTEX);
25505 relverts++;
25506 } else {
25507
25508 deallocfaketets(frontlist);
25509 pointdealloc(newpt[i]);
25510 newpt[i] = (point) NULL;
25511 assert(newtetlist[i]->len() == 0);
25512 }
25513 }
25514 if (!success && noreloc) {
25515
25516 deallocfaketets(frontlist);
25517 }
25518
25519 ptlist->clear();
25520 frontlist->clear();
25521 misfrontlist->clear();
25522 flipque->clear();
25523 }
25524
25525 if (success) {
25526
25527 setpointtype(suppt, UNUSEDVERTEX);
25528 unuverts++;
25529
25530 for (i = 0; i < oldshlist->len(); i++) {
25531 oldsh = * (face *)(* oldshlist)[i];
25532 if (i == 0) {
25533
25534 stpivot(oldsh, oldtet);
25535 if (oldtet.tet != dummytet) {
25536 sesymself(oldsh);
25537 stpivot(oldsh, oldtet);
25538 }
25539 if (oldtet.tet == dummytet) {
25540
25541 j = oldshlist->len() - newshlist->len();
25542 assert(j > 0);
25543 hullsize -= j;
25544 }
25545 }
25546 shellfacedealloc(subfaces, oldsh.sh);
25547 }
25548
25549 for (i = 0; i < 2; i++) {
25550 if (oldtetlist[i] != (list *) NULL) {
25551
25552 for (j = 0; j < oldtetlist[i]->len(); j++) {
25553 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25554 assert(!isdead(&oldtet));
25555 tetrahedrondealloc(oldtet.tet);
25556 }
25557 }
25558 }
25559 if (optflag) {
25560
25561 for (i = 0; i < 2; i++) {
25562 if (newtetlist[i] != (list *) NULL) {
25563 for (j = 0; j < newtetlist[i]->len(); j++) {
25564 newtet = * (triface *)(* (newtetlist[i]))[j];
25565 if (!isdead(&newtet)) checktet4opt(&newtet, true);
25566 }
25567 }
25568 }
25569 }
25570 } else {
25571
25572 unsupverts++;
25573
25574 replacepolygonsubs(newshlist, oldshlist);
25575
25576 for (i = 0; i < newshlist->len(); i++) {
25577 newsh = * (face *)(* newshlist)[i];
25578 shellfacedealloc(subfaces, newsh.sh);
25579 }
25580
25581 for (i = 0; i < 2; i++) {
25582 if (oldtetlist[i] != (list *) NULL) {
25583
25584 for (j = 0; j < oldtetlist[i]->len(); j++) {
25585 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25586 assert(infected(oldtet));
25587 uninfect(oldtet);
25588 }
25589
25590 if (newtetlist[i]->len() > 0) {
25591
25592 restorepolyhedron(oldtetlist[i]);
25593
25594 for (j = 0; j < newtetlist[i]->len(); j++) {
25595 newtet = * (triface *)(* (newtetlist[i]))[j];
25596
25597 if (!isdead(&newtet)) {
25598 tetrahedrondealloc(newtet.tet);
25599 }
25600 }
25601 }
25602
25603 if (newpt[i] != (point) NULL) {
25604 pointdealloc(newpt[i]);
25605 relverts--;
25606 }
25607 }
25608 }
25609 }
25610
25611
25612 delete oldshlist;
25613 delete newshlist;
25614 for (i = 0; i < 2; i++) {
25615 if (oldtetlist[i] != (list *) NULL) {
25616 delete oldtetlist[i];
25617 delete newtetlist[i];
25618 }
25619 }
25620
25621 return success;
25622 }
25623
25625
25626
25627
25628
25629
25630
25631
25632
25633
25635
25636 bool tetgenmesh::suppresssegpoint(face* supseg, list* spinshlist,
25637 list* newsegshlist, list* frontlist, list* misfrontlist, list* ptlist,
25638 list* conlist, memorypool* viri, queue* flipque, bool noreloc, bool optflag)
25639 {
25640 list **oldtetlist, **newtetlist;
25641 list **oldshlist, **newshlist;
25642 list *pnewshlist, *dnewshlist;
25643 triface oldtet, newtet;
25644 face oldsh, newsh;
25645 face startsh, spinsh, segsh1, segsh2;
25646 face nsupseg, newseg, prevseg, nextseg;
25647 point suppt, *newpt;
25648 point pa, pb, *cons;
25649 REAL pnorm[2][3], norm[3];
25650 bool success;
25651 int shmark;
25652 int n, i, j, k;
25653
25654
25655 assert(supseg->shver < 2);
25656 suppt = sdest(*supseg);
25657
25658 senext(*supseg, nsupseg);
25659 spivotself(nsupseg);
25660 assert(nsupseg.sh != dummysh);
25661 nsupseg.shver = 0;
25662 if (sorg(nsupseg) != suppt) sesymself(nsupseg);
25663 assert(sorg(nsupseg) == suppt);
25664 pa = sorg(*supseg);
25665 pb = sdest(nsupseg);
25666 if (b->verbose > 1) {
25667 printf(" Remove point %d on segment (%d, %d).\n",
25668 pointmark(suppt), pointmark(pa), pointmark(pb));
25669 }
25670
25671
25672 spivot(*supseg, startsh);
25673 spinsh = startsh;
25674 do {
25675
25676 spinshlist->append(&spinsh);
25677
25678 spivotself(spinsh);
25679 } while (spinsh.sh != startsh.sh);
25680 if (spinshlist->len() == 1) {
25681
25682
25683 spinshlist->clear();
25684 unsupverts++;
25685 return false;
25686 }
25687
25688
25689
25690 n = spinshlist->len();
25691 oldtetlist = new list*[n];
25692 newtetlist = new list*[n];
25693 oldshlist = new list*[n];
25694 newshlist = new list*[n];
25695 newpt = new point[n];
25696 for (i = 0; i < n; i++) {
25697 oldtetlist[i] = (list *) NULL;
25698 newtetlist[i] = (list *) NULL;
25699 oldshlist[i] = (list *) NULL;
25700 newshlist[i] = (list *) NULL;
25701 newpt[i] = (point) NULL;
25702 }
25703
25704
25705 makeshellface(subsegs, &newseg);
25706 setsorg(newseg, pa);
25707 setsdest(newseg, pb);
25708
25709 setshellmark(newseg, shellmark(*supseg));
25710 setshelltype(newseg, shelltype(*supseg));
25711 if (b->quality && varconstraint) {
25712
25713 setareabound(newseg, areabound(*supseg));
25714 }
25715
25716 senext2(*supseg, prevseg);
25717 spivotself(prevseg);
25718 if (prevseg.sh != dummysh) {
25719 prevseg.shver = 0;
25720 if (sdest(prevseg) != pa) sesymself(prevseg);
25721 assert(sdest(prevseg) == pa);
25722 senextself(prevseg);
25723 senext2self(newseg);
25724 sbond(newseg, prevseg);
25725 newseg.shver = 0;
25726 }
25727
25728 senext(nsupseg, nextseg);
25729 spivotself(nextseg);
25730 if (nextseg.sh != dummysh) {
25731 nextseg.shver = 0;
25732 if (sorg(nextseg) != pb) sesymself(nextseg);
25733 assert(sorg(nextseg) == pb);
25734 senext2self(nextseg);
25735 senextself(newseg);
25736 sbond(newseg, nextseg);
25737 newseg.shver = 0;
25738 }
25739
25740
25741 for (i = 0; i < spinshlist->len(); i++) {
25742 spinsh = * (face *)(* spinshlist)[i];
25743
25744 oldshlist[i] = new list(sizeof(face), NULL, 256);
25745 newshlist[i] = new list(sizeof(face), NULL, 256);
25746
25747 oldshlist[i]->append(&spinsh);
25748 formstarpolygon(suppt, oldshlist[i], ptlist);
25749
25750 for (j = 0; j < oldshlist[i]->len(); j++) {
25751 oldsh = * (face *)(* (oldshlist[i]))[j];
25752 cons = (point *) conlist->append(NULL);
25753 cons[0] = sorg(oldsh);
25754 cons[1] = sdest(oldsh);
25755 }
25756
25757 cons = (point *) conlist->append(NULL);
25758 cons[0] = pa;
25759 cons[1] = pb;
25760
25761 shmark = shellmark(spinsh);
25762 triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25763
25764 retrievenewsubs(newshlist[i], true);
25765
25766 replacepolygonsubs(oldshlist[i], newshlist[i]);
25767
25768 for (j = 0; j < newshlist[i]->len(); j++) {
25769 segsh1 = * (face *)(* (newshlist[i]))[j];
25770 for (k = 0; k < 3; k++) {
25771 if (((sorg(segsh1) == pa) && (sdest(segsh1) == pb)) ||
25772 ((sorg(segsh1) == pb) && (sdest(segsh1) == pa))) break;
25773 senextself(segsh1);
25774 }
25775 if (k < 3) break;
25776 }
25777 assert(j < newshlist[i]->len());
25778
25779 ssbond(segsh1, newseg);
25780
25781 newsegshlist->append(&segsh1);
25782
25783 ptlist->clear();
25784 conlist->clear();
25785 flipque->clear();
25786 viri->restart();
25787 }
25788
25789 for (i = 0; i < newsegshlist->len(); i++) {
25790 segsh1 = * (face *)(* newsegshlist)[i];
25791 if ((i + 1) == newsegshlist->len()) {
25792 segsh2 = * (face *)(* newsegshlist)[0];
25793 } else {
25794 segsh2 = * (face *)(* newsegshlist)[i + 1];
25795 }
25796 sbond1(segsh1, segsh2);
25797 }
25798
25799
25800 dnewshlist = new list(sizeof(face), NULL, 256);
25801 success = true;
25802
25803
25804 for (i = 0; i < spinshlist->len() && success; i++) {
25805
25806 spinsh = * (face *)(* spinshlist)[i];
25807
25808
25809 if (sorg(spinsh) != pa) sesymself(spinsh);
25810
25811 stpivot(spinsh, oldtet);
25812
25813 if (oldtet.tet == dummytet) continue;
25814
25815 oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25816 newtetlist[i] = new list(sizeof(triface), NULL, 256);
25817
25818 oldtetlist[i]->append(&oldtet);
25819 formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25820
25821 for (j = 0; j < oldtetlist[i]->len(); j++) {
25822 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25823 infect(oldtet);
25824 }
25825
25826 for (k = 0; k < 2; k++) {
25827 if ((i + k) < spinshlist->len()) {
25828 pnewshlist = newshlist[i + k];
25829 segsh1 = * (face *)(* spinshlist)[i + k];
25830 } else {
25831 pnewshlist = newshlist[0];
25832 segsh1 = * (face *)(* spinshlist)[0];
25833 }
25834
25835 if (k == 0) {
25836 if (sorg(segsh1) != pa) sesymself(segsh1);
25837 assert(sorg(segsh1) == pa);
25838 } else {
25839 if (sdest(segsh1) != pa) sesymself(segsh1);
25840 assert(sdest(segsh1) == pa);
25841 }
25842
25843 orientnewsubs(pnewshlist, &segsh1, pnorm[k]);
25844 for (j = 0; j < pnewshlist->len(); j++) {
25845 dnewshlist->append((face *)(* pnewshlist)[j]);
25846 }
25847 }
25848
25849 success = constrainedcavity(&oldtet, dnewshlist, oldtetlist[i], ptlist,
25850 frontlist, misfrontlist, newtetlist[i], flipque);
25851 if (!success && !noreloc) {
25852
25853 makepoint(&(newpt[i]));
25854 for (j = 0; j < 3; j++) norm[j] = 0.5 * (pnorm[0][j] + pnorm[1][j]);
25855 success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25856 oldtetlist[i]);
25857
25858
25859 if (success) {
25860
25861
25862 relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25863 setpointtype(newpt[i], FREEVOLVERTEX);
25864 relverts++;
25865 } else {
25866
25867 deallocfaketets(frontlist);
25868 pointdealloc(newpt[i]);
25869 newpt[i] = (point) NULL;
25870 assert(newtetlist[i]->len() == 0);
25871 }
25872 }
25873 if (!success && noreloc) {
25874
25875 deallocfaketets(frontlist);
25876 }
25877
25878 dnewshlist->clear();
25879 ptlist->clear();
25880 frontlist->clear();
25881 misfrontlist->clear();
25882 flipque->clear();
25883 }
25884
25885 if (success) {
25886
25887 setpointtype(suppt, UNUSEDVERTEX);
25888 unuverts++;
25889
25890 setpoint2sh(pa, sencode(newseg));
25891 setpoint2sh(pb, sencode(newseg));
25892
25893 shellfacedealloc(subsegs, supseg->sh);
25894 shellfacedealloc(subsegs, nsupseg.sh);
25895
25896 for (i = 0; i < spinshlist->len(); i++) {
25897 for (j = 0; j < oldshlist[i]->len(); j++) {
25898 oldsh = * (face *)(* (oldshlist[i]))[j];
25899 if (j == 0) {
25900
25901 stpivot(oldsh, oldtet);
25902 if (oldtet.tet != dummytet) {
25903 sesymself(oldsh);
25904 stpivot(oldsh, oldtet);
25905 }
25906 if (oldtet.tet == dummytet) {
25907
25908 k = oldshlist[i]->len() - newshlist[i]->len();
25909 assert(k > 0);
25910 hullsize -= k;
25911 }
25912 }
25913 shellfacedealloc(subfaces, oldsh.sh);
25914 }
25915 }
25916
25917 for (i = 0; i < spinshlist->len(); i++) {
25918
25919 if (oldtetlist[i] != (list *) NULL) {
25920 for (j = 0; j < oldtetlist[i]->len(); j++) {
25921 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25922 assert(!isdead(&oldtet));
25923 tetrahedrondealloc(oldtet.tet);
25924 }
25925 }
25926 }
25927 if (optflag) {
25928 for (i = 0; i < spinshlist->len(); i++) {
25929
25930 if (newtetlist[i] != (list *) NULL) {
25931 for (j = 0; j < newtetlist[i]->len(); j++) {
25932 newtet = * (triface *)(* (newtetlist[i]))[j];
25933 if (!isdead(&newtet)) checktet4opt(&newtet, true);
25934 }
25935 }
25936 }
25937 }
25938 } else {
25939
25940 unsupverts++;
25941
25942 senext2(*supseg, prevseg);
25943 spivotself(prevseg);
25944 if (prevseg.sh != dummysh) {
25945 prevseg.shver = 0;
25946 if (sdest(prevseg) != pa) sesymself(prevseg);
25947 assert(sdest(prevseg) == pa);
25948 senextself(prevseg);
25949 senext2self(*supseg);
25950 sbond(*supseg, prevseg);
25951 senextself(*supseg);
25952 assert(supseg->shver < 2);
25953 }
25954
25955 senext(nsupseg, nextseg);
25956 spivotself(nextseg);
25957 if (nextseg.sh != dummysh) {
25958 nextseg.shver = 0;
25959 if (sorg(nextseg) != pb) sesymself(nextseg);
25960 assert(sorg(nextseg) == pb);
25961 senext2self(nextseg);
25962 senextself(nsupseg);
25963 sbond(nsupseg, nextseg);
25964
25965 senext2self(nsupseg);
25966 assert(nsupseg.shver < 2);
25967 }
25968
25969 shellfacedealloc(subsegs, newseg.sh);
25970
25971 for (i = 0; i < spinshlist->len(); i++) {
25972 replacepolygonsubs(newshlist[i], oldshlist[i]);
25973
25974 for (j = 0; j < newshlist[i]->len(); j++) {
25975 newsh = * (face *)(* (newshlist[i]))[j];
25976 shellfacedealloc(subfaces, newsh.sh);
25977 }
25978 }
25979
25980 for (i = 0; i < spinshlist->len(); i++) {
25981 if (oldtetlist[i] != (list *) NULL) {
25982
25983 for (j = 0; j < oldtetlist[i]->len(); j++) {
25984 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25985 assert(infected(oldtet));
25986 uninfect(oldtet);
25987 }
25988
25989 if (newtetlist[i]->len() > 0) {
25990
25991 restorepolyhedron(oldtetlist[i]);
25992
25993 for (j = 0; j < newtetlist[i]->len(); j++) {
25994 newtet = * (triface *)(* (newtetlist[i]))[j];
25995
25996 if (!isdead(&newtet)) {
25997 tetrahedrondealloc(newtet.tet);
25998 }
25999 }
26000 }
26001
26002 if (newpt[i] != (point) NULL) {
26003 pointdealloc(newpt[i]);
26004 relverts--;
26005 }
26006 }
26007 }
26008 }
26009
26010
26011 delete dnewshlist;
26012 for (i = 0; i < spinshlist->len(); i++) {
26013 delete oldshlist[i];
26014 delete newshlist[i];
26015 }
26016 delete [] oldshlist;
26017 delete [] newshlist;
26018 for (i = 0; i < spinshlist->len(); i++) {
26019 if (oldtetlist[i] != (list *) NULL) {
26020 delete oldtetlist[i];
26021 delete newtetlist[i];
26022 }
26023 }
26024 delete [] oldtetlist;
26025 delete [] newtetlist;
26026
26027 newsegshlist->clear();
26028 spinshlist->clear();
26029
26030 return success;
26031 }
26032
26034
26035
26036
26037
26038
26039
26040
26041
26042
26044
26045 bool tetgenmesh::suppressvolpoint(triface* suptet, list* frontlist,
26046 list* misfrontlist, list* ptlist, queue* flipque, bool optflag)
26047 {
26048 list *myfrontlist, *mymisfrontlist, *myptlist;
26049 list *oldtetlist, *newtetlist;
26050 list *newshlist;
26051 queue *myflipque;
26052 triface oldtet, newtet;
26053 point suppt, conpt;
26054 bool success;
26055 int j;
26056
26057
26058 oldtetlist = new list(sizeof(triface), NULL, 256);
26059 newtetlist = new list(sizeof(triface), NULL, 256);
26060 newshlist = new list(sizeof(face), NULL, 256);
26061
26062 myfrontlist = mymisfrontlist = myptlist = (list *) NULL;
26063 myflipque = (queue *) NULL;
26064 if (frontlist == (list *) NULL) {
26065 myfrontlist = new list(sizeof(triface), NULL, 256);
26066 frontlist = myfrontlist;
26067 mymisfrontlist = new list(sizeof(triface), NULL, 256);
26068 misfrontlist = mymisfrontlist;
26069 myptlist = new list(sizeof(point *), NULL, 256);
26070 ptlist = myptlist;
26071 myflipque = new queue(sizeof(badface));
26072 flipque = myflipque;
26073 }
26074
26075 suppt = org(*suptet);
26076 oldtet = *suptet;
26077 success = true;
26078
26079 if (b->verbose > 1) {
26080 printf(" Remove point %d in mesh.\n", pointmark(suppt));
26081 }
26082
26083
26084 oldtetlist->append(&oldtet);
26085 formstarpolyhedron(suppt, oldtetlist, ptlist, false);
26086
26087 for (j = 0; j < oldtetlist->len(); j++) {
26088 oldtet = * (triface *)(* oldtetlist)[j];
26089 infect(oldtet);
26090 }
26091
26092 success = constrainedcavity(&oldtet, newshlist, oldtetlist, ptlist,
26093 frontlist, misfrontlist, newtetlist, flipque);
26094 if (!success) {
26095
26096 deallocfaketets(frontlist);
26097
26098 conpt = (point) NULL;
26099 assert(newtetlist->len() == 0);
26100 if (findcollapseedge(suppt, &conpt, oldtetlist, ptlist)) {
26101
26102 collapseedge(suppt, conpt, oldtetlist, newtetlist);
26103
26104 if (optflag) {
26105 assert(newtetlist->len() == 0);
26106 for (j = 0; j < oldtetlist->len(); j++) {
26107 newtet = * (triface *)(* oldtetlist)[j];
26108 newtetlist->append(&newtet);
26109 }
26110 }
26111 oldtetlist->clear();
26112 collapverts++;
26113 success = true;
26114 }
26115 }
26116 if (success) {
26117
26118 setpointtype(suppt, UNUSEDVERTEX);
26119 unuverts++;
26120 suprelverts++;
26121
26122 for (j = 0; j < oldtetlist->len(); j++) {
26123 oldtet = * (triface *)(* oldtetlist)[j];
26124 assert(!isdead(&oldtet));
26125 tetrahedrondealloc(oldtet.tet);
26126 }
26127 if (optflag) {
26128
26129 for (j = 0; j < newtetlist->len(); j++) {
26130 newtet = * (triface *)(* newtetlist)[j];
26131 if (!isdead(&newtet)) checktet4opt(&newtet, true);
26132 }
26133 }
26134 } else {
26135
26136
26137 for (j = 0; j < oldtetlist->len(); j++) {
26138 oldtet = * (triface *)(* oldtetlist)[j];
26139 assert(infected(oldtet));
26140 uninfect(oldtet);
26141 }
26142 }
26143
26144
26145 ptlist->clear();
26146 frontlist->clear();
26147 misfrontlist->clear();
26148 flipque->clear();
26149
26150 if (myfrontlist != (list *) NULL) {
26151 delete myfrontlist;
26152 delete mymisfrontlist;
26153 delete myptlist;
26154 delete myflipque;
26155 }
26156 delete oldtetlist;
26157 delete newtetlist;
26158 delete newshlist;
26159
26160 return success;
26161 }
26162
26164
26165
26166
26167
26168
26169
26170
26171
26172
26173
26174
26175
26176
26177
26179
26180 bool tetgenmesh::smoothpoint(point smthpt, point e1, point e2, list *starlist,
26181 bool invtori, REAL *key)
26182 {
26183 triface starttet;
26184 point pa, pb, pc;
26185 REAL fcent[3], startpt[3], nextpt[3], bestpt[3];
26186 REAL iniTmax, oldTmax, newTmax;
26187 REAL ori, aspT, aspTmax, imprate;
26188 REAL cosd, maxcosd;
26189 bool segflag, randflag;
26190 int numdirs;
26191 int iter, i, j;
26192
26193
26194 segflag = (e1 != (point) NULL);
26195
26196 numdirs = segflag ? 2 : starlist->len();
26197 randflag = numdirs > 10;
26198 if (randflag) {
26199 numdirs = 10;
26200 }
26201
26202 aspTmax = 0.0;
26203
26204 for (i = 0; i < starlist->len(); i++) {
26205 starttet = * (triface *)(* starlist)[i];
26206 adjustedgering(starttet, !invtori ? CCW : CW);
26207 pa = org(starttet);
26208 pb = dest(starttet);
26209 pc = apex(starttet);
26210 aspT = tetaspectratio(pa, pb, pc, smthpt);
26211 if (i == 0) {
26212 aspTmax = aspT;
26213 } else {
26214 aspTmax = aspT > aspTmax ? aspT : aspTmax;
26215 }
26216 }
26217 iniTmax = aspTmax;
26218
26219 if (b->verbose > 1) {
26220 printf(" Smooth %s point %d (%g, %g, %g).\n", segflag ? "seg" : "vol",
26221 pointmark(smthpt), smthpt[0], smthpt[1], smthpt[2]);
26222 printf(" Initial max L/h = %g.\n", iniTmax);
26223 }
26224 for (i = 0; i < 3; i++) {
26225 bestpt[i] = startpt[i] = smthpt[i];
26226 }
26227
26228
26229 newTmax = iniTmax;
26230 iter = 0;
26231 while (true) {
26232
26233 oldTmax = newTmax;
26234 for (i = 0; i < numdirs; i++) {
26235
26236 if (!segflag) {
26237 if (randflag) {
26238
26239 j = (int) randomnation(starlist->len());
26240 } else {
26241 j = i;
26242 }
26243 starttet = * (triface *)(* starlist)[j];
26244 adjustedgering(starttet, !invtori ? CCW : CW);
26245 pa = org(starttet);
26246 pb = dest(starttet);
26247 pc = apex(starttet);
26248 for (j = 0; j < 3; j++) {
26249 fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0;
26250 }
26251 } else {
26252 for (j = 0; j < 3; j++) {
26253 fcent[j] = (i == 0 ? e1[j] : e2[j]);
26254 }
26255 }
26256 for (j = 0; j < 3; j++) {
26257 nextpt[j] = startpt[j] + 0.01 * (fcent[j] - startpt[j]);
26258 }
26259
26260 for (j = 0; j < starlist->len(); j++) {
26261 starttet = * (triface *)(* starlist)[j];
26262 adjustedgering(starttet, !invtori ? CCW : CW);
26263 pa = org(starttet);
26264 pb = dest(starttet);
26265 pc = apex(starttet);
26266 ori = orient3d(pa, pb, pc, nextpt);
26267 if (ori < 0.0) {
26268 aspT = tetaspectratio(pa, pb, pc, nextpt);
26269 if (j == 0) {
26270 aspTmax = aspT;
26271 } else {
26272 aspTmax = aspT > aspTmax ? aspT : aspTmax;
26273 }
26274 } else {
26275
26276 aspTmax = newTmax;
26277 }
26278
26279 if (aspTmax >= newTmax) break;
26280 }
26281 if (aspTmax < newTmax) {
26282
26283 newTmax = aspTmax;
26284 for (j = 0; j < 3; j++) bestpt[j] = nextpt[j];
26285 }
26286 }
26287
26288 imprate = fabs(oldTmax - newTmax) / oldTmax;
26289 if (imprate < 1e-3) break;
26290
26291 for (j = 0; j < 3; j++) startpt[j] = bestpt[j];
26292 iter++;
26293 }
26294
26295 if (iter > 0) {
26296
26297 if (key) {
26298
26299 maxcosd = 0.0;
26300 for (j = 0; j < starlist->len(); j++) {
26301 starttet = * (triface *)(* starlist)[j];
26302 adjustedgering(starttet, !invtori ? CCW : CW);
26303 pa = org(starttet);
26304 pb = dest(starttet);
26305 pc = apex(starttet);
26306 tetalldihedral(pa, pb, pc, startpt, NULL, &cosd, NULL);
26307 if (cosd < *key) {
26308
26309 iter = 0; break;
26310 } else {
26311
26312 maxcosd = maxcosd < cosd ? maxcosd : cosd;
26313 }
26314 }
26315 if (iter > 0) *key = maxcosd;
26316 }
26317 }
26318
26319 if (iter > 0) {
26320 segflag ? smoothsegverts++ : smoothvolverts++;
26321 for (i = 0; i < 3; i++) smthpt[i] = startpt[i];
26322 if (b->verbose > 1) {
26323 printf(" Move to new location (%g, %g, %g).\n", smthpt[0], smthpt[1],
26324 smthpt[2]);
26325 printf(" Final max L/h = %g. (%d iterations)\n", newTmax, iter);
26326 if (key) {
26327 printf(" Max. dihed = %g (degree).\n", acos(*key) / PI * 180.0);
26328 }
26329 }
26330 return true;
26331 } else {
26332 if (b->verbose > 1) {
26333 printf(" Not smoothed.\n");
26334 }
26335 return false;
26336 }
26337 }
26338
26340
26341
26342
26344
26345 void tetgenmesh::removesteiners(bool coarseflag)
26346 {
26347 list *frontlist, *misfrontlist;
26348 list *spinshlist, *newsegshlist;
26349 list *ptlist, *conlist;
26350 memorypool *viri;
26351 queue *flipque;
26352 triface checktet;
26353 face shloop;
26354 face segloop, nextseg;
26355 point pa, neipt;
26356 REAL len;
26357 bool remflag;
26358 int *worklist;
26359 int oldnum, rmstein;
26360 int i, j;
26361
26362 if (!b->quiet) {
26363 if (!coarseflag) {
26364 printf("Removing Steiner points.\n");
26365 } else {
26366 printf("Coarsening mesh.\n");
26367 }
26368 }
26369
26370
26371 frontlist = new list(sizeof(triface), NULL);
26372 misfrontlist = new list(sizeof(triface), NULL);
26373 spinshlist = new list(sizeof(face), NULL);
26374 newsegshlist = new list(sizeof(face), NULL);
26375 ptlist = new list(sizeof(point *), NULL);
26376 conlist = new list(sizeof(point *) * 2, NULL);
26377 flipque = new queue(sizeof(badface));
26378 viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
26379 oldnum = unuverts;
26380 relverts = suprelverts = collapverts = unsupverts;
26381 smoothvolverts = 0;
26382 expcavcount = 0;
26383
26384
26385 do {
26386 rmstein = unuverts;
26387 subfaces->traversalinit();
26388 shloop.sh = shellfacetraverse(subfaces);
26389 while (shloop.sh != (shellface *) NULL) {
26390 remflag = false;
26391
26392 shloop.shver = 0;
26393 for (i = 0; i < 3; i++) {
26394 pa = sapex(shloop);
26395 if (pointtype(pa) == FREESUBVERTEX) {
26396 if (!coarseflag) {
26397
26398 j = pointmark(pa) - in->firstnumber;
26399 if (j >= in->numberofpoints) {
26400 if (b->nobisect == 1) {
26401
26402 stpivot(shloop, checktet);
26403 if (checktet.tet != dummytet) {
26404 sesymself(shloop);
26405 stpivot(shloop, checktet);
26406 }
26407 remflag = (checktet.tet == dummytet);
26408 } else {
26409
26410 remflag = true;
26411 }
26412 }
26413 } else {
26414
26415 if (b->nobisect == 0) {
26416
26417 if (b->metric) {
26418
26419
26420 spinshlist->append(&shloop);
26421 formstarpolygon(pa, spinshlist, ptlist);
26422 len = 0.0;
26423 for (j = 0; j < ptlist->len(); j++) {
26424 neipt = * (point *)(* ptlist)[j];
26425 len += distance(pa, neipt);
26426 }
26427 len /= ptlist->len();
26428
26429 remflag = len < pa[pointmtrindex];
26430 spinshlist->clear();
26431 ptlist->clear();
26432 } else {
26433
26434
26435 remflag = true;
26436 j = pointmark(pa) - in->firstnumber;
26437 if (j < in->numberofpoints) {
26438 remflag = (in->pointmarkerlist[j] == 0);
26439 }
26440 }
26441 }
26442 }
26443 if (remflag) break;
26444 }
26445 senextself(shloop);
26446 }
26447 if (remflag) {
26448 suppressfacetpoint(&shloop, frontlist, misfrontlist, ptlist, conlist,
26449 viri, flipque, coarseflag, false);
26450 }
26451 shloop.sh = shellfacetraverse(subfaces);
26452 }
26453
26454 } while (unuverts > rmstein);
26455
26456 if (coarseflag) {
26457 shellface **segsperverlist;
26458 int *idx2seglist;
26459 face seg1, seg2;
26460 point e1, e2;
26461
26462
26463 makesegmentmap(idx2seglist, segsperverlist);
26464 subsegs->traversalinit();
26465 segloop.sh = shellfacetraverse(subsegs);
26466 while (segloop.sh != (shellface *) NULL) {
26467 for (i = 0; i < 2; i++) {
26468 segloop.shver = i;
26469 senext(segloop, nextseg);
26470 spivotself(nextseg);
26471 if ((nextseg.sh == dummysh) || (nextseg.sh > segloop.sh)) {
26472
26473 pa = sdest(segloop);
26474 j = pointmark(pa) - in->firstnumber;
26475 if (idx2seglist[j + 1] - idx2seglist[j] == 2) {
26476
26477 nextseg.sh = segsperverlist[idx2seglist[j]];
26478 if (nextseg.sh == segloop.sh) {
26479 nextseg.sh = segsperverlist[idx2seglist[j] + 1];
26480 }
26481 nextseg.shver = 0;
26482 if (sorg(nextseg) != pa) sesymself(nextseg);
26483
26484 e1 = sorg(segloop);
26485 e2 = sdest(nextseg);
26486 if (iscollinear(e1, pa, e2, b->epsilon)) {
26487
26488 if (b->verbose > 1) {
26489 printf(" Glue two insegs (%d, %d) at %d.\n", pointmark(e1),
26490 pointmark(e2), pointmark(pa));
26491 }
26492 senext(segloop, seg1);
26493 senext2(nextseg, seg2);
26494 sbond(seg1, seg2);
26495 }
26496 }
26497 }
26498 }
26499 segloop.sh = shellfacetraverse(subsegs);
26500 }
26501 delete [] segsperverlist;
26502 delete [] idx2seglist;
26503 }
26504
26505
26506 do {
26507 rmstein = unuverts;
26508 subsegs->traversalinit();
26509 segloop.sh = shellfacetraverse(subsegs);
26510 while (segloop.sh != (shellface *) NULL) {
26511 remflag = false;
26512
26513
26514
26515 segloop.shver = 0;
26516 senext(segloop, nextseg);
26517 spivotself(nextseg);
26518 if (nextseg.sh != dummysh) {
26519 pa = sdest(segloop);
26520 nextseg.shver = 0;
26521 if (sorg(nextseg) != pa) sesymself(nextseg);
26522 assert(sorg(nextseg) == pa);
26523 if (!coarseflag) {
26524
26525 j = pointmark(pa) - in->firstnumber;
26526 if (j >= in->numberofpoints) {
26527 if (b->nobisect == 1) {
26528
26529 sstpivot(&segloop, &checktet);
26530 assert(checktet.tet != dummytet);
26531 pa = apex(checktet);
26532 do {
26533 if (!fnextself(checktet)) {
26534
26535 remflag = true; break;
26536 }
26537 } while (pa != apex(checktet));
26538 } else {
26539
26540 remflag = true;
26541 }
26542 }
26543 } else {
26544
26545 if (b->nobisect == 0) {
26546 if (b->metric) {
26547
26548 len = 0.0;
26549 neipt = sorg(segloop);
26550 for (j = 0; j < 2; j++) {
26551 len += distance(pa, neipt);
26552
26553
26554
26555
26556
26557 neipt = sdest(nextseg);
26558 }
26559 len /= 2.0;
26560
26561 remflag = len < pa[pointmtrindex];
26562 } else {
26563
26564
26565 remflag = true;
26566 j = pointmark(pa) - in->firstnumber;
26567 if (j < in->numberofpoints) {
26568 remflag = (in->pointmarkerlist[j] == 0);
26569 }
26570 }
26571 }
26572 }
26573 }
26574
26575
26576 if (remflag) {
26577 suppresssegpoint(&segloop, spinshlist, newsegshlist, frontlist,
26578 misfrontlist, ptlist, conlist, viri, flipque, coarseflag, false);
26579 }
26580 segloop.sh = shellfacetraverse(subsegs);
26581 }
26582
26583 } while (unuverts > rmstein);
26584
26585 if ((relverts > 0) || coarseflag) {
26586 worklist = new int[points->items + 1];
26587
26588 do {
26589
26590
26591 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26592 rmstein = unuverts;
26593 tetrahedrons->traversalinit();
26594 checktet.tet = tetrahedrontraverse();
26595 while (checktet.tet != (tetrahedron *) NULL) {
26596 remflag = false;
26597 for (i = 0; i < 4; i++) {
26598 pa = (point) checktet.tet[4 + i];
26599 if (pointtype(pa) == FREEVOLVERTEX) {
26600
26601
26602
26603
26604
26605
26606 if (worklist[pointmark(pa)] < 3) {
26607 worklist[pointmark(pa)]++;
26608 if (!coarseflag) {
26609
26610 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26611 remflag = true;
26612 }
26613 } else {
26614 if (b->metric) {
26615
26616
26617 frontlist->append(&checktet);
26618 formstarpolyhedron(pa, frontlist, ptlist, true);
26619 len = 0.0;
26620 for (j = 0; j < ptlist->len(); j++) {
26621 neipt = * (point *)(* ptlist)[j];
26622 len += distance(pa, neipt);
26623 }
26624 len /= ptlist->len();
26625
26626 remflag = len < pa[pointmtrindex];
26627 frontlist->clear();
26628 ptlist->clear();
26629 } else {
26630
26631
26632 remflag = true;
26633 j = pointmark(pa) - in->firstnumber;
26634 if (j < in->numberofpoints) {
26635 remflag = (in->pointmarkerlist[j] == 0);
26636 }
26637 }
26638 }
26639 if (remflag) break;
26640 }
26641 }
26642 }
26643 if (remflag) {
26644 findorg(&checktet, pa);
26645 assert(org(checktet) == pa);
26646 suppressvolpoint(&checktet, frontlist, misfrontlist, ptlist, flipque,
26647 false);
26648 }
26649 checktet.tet = tetrahedrontraverse();
26650 }
26651
26652 } while (unuverts > rmstein);
26653
26654
26655
26656 if (!coarseflag && (relverts > suprelverts)) {
26657 if (b->verbose) {
26658 printf(" Smoothing relocated points.\n");
26659 }
26660 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26661 tetrahedrons->traversalinit();
26662 checktet.tet = tetrahedrontraverse();
26663 while (checktet.tet != (tetrahedron *) NULL) {
26664 for (i = 0; i < 4; i++) {
26665 pa = (point) checktet.tet[4 + i];
26666 if (pointtype(pa) == FREEVOLVERTEX) {
26667 if (worklist[pointmark(pa)] == 0) {
26668 worklist[pointmark(pa)] = 1;
26669 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26670
26671 findorg(&checktet, pa);
26672 frontlist->append(&checktet);
26673 formstarpolyhedron(pa, frontlist, NULL, false);
26674 smoothpoint(pa, NULL, NULL, frontlist, false, NULL);
26675 frontlist->clear();
26676 }
26677 }
26678 }
26679 }
26680 checktet.tet = tetrahedrontraverse();
26681 }
26682 }
26683 delete [] worklist;
26684 }
26685
26686 if (b->verbose > 0) {
26687 if (!coarseflag) {
26688 printf(" %d points removed from boundary", unuverts - oldnum);
26689 if (expcavcount > 0) {
26690 printf(" (%d cavity corrections)", expcavcount);
26691 }
26692 printf("\n");
26693 if (relverts > 0) {
26694 printf(" %d points relocated (%d suppressed, %d collapsed).\n",
26695 relverts, suprelverts - collapverts, collapverts);
26696 if (smoothvolverts > 0) {
26697 printf(" %d points are smoothed.\n", smoothvolverts);
26698 }
26699 }
26700 if (unsupverts > 0) {
26701 printf(" !! %d points are unsuppressed.\n", unsupverts);
26702 }
26703 } else {
26704 printf(" %d points are removed.\n", unuverts - oldnum);
26705 }
26706 }
26707
26708
26709 delete frontlist;
26710 delete misfrontlist;
26711 delete spinshlist;
26712 delete newsegshlist;
26713 delete ptlist;
26714 delete conlist;
26715 delete flipque;
26716 delete viri;
26717 }
26718
26719
26720
26721
26722
26724
26725
26726
26727
26728
26729
26730
26731
26732
26733
26734
26735
26736
26737
26738
26739
26740
26741
26742
26743
26744
26745
26746
26747
26748
26749
26750
26751
26752
26753
26754
26755
26756
26757
26759
26760 long tetgenmesh::reconstructmesh()
26761 {
26762 tetrahedron **tetsperverlist;
26763 shellface **facesperverlist;
26764 triface tetloop, neightet, neineightet, spintet;
26765 face subloop, neighsh, neineighsh, subseg;
26766 face sface1, sface2;
26767 point *idx2verlist;
26768 point torg, tdest, tapex, toppo;
26769 point norg, ndest, napex;
26770 list *neighshlist, *markerlist;
26771 REAL sign, attrib, volume;
26772 REAL da1, da2;
26773 bool bondflag, insertsegflag;
26774 int *idx2tetlist;
26775 int *idx2facelist;
26776 int *worklist;
26777 int facetidx, marker;
26778 int iorg, idest, iapex, ioppo;
26779 int inorg, indest, inapex;
26780 int index, i, j;
26781
26782 if (!b->quiet) {
26783 printf("Reconstructing mesh.\n");
26784 }
26785
26786
26787 makeindex2pointmap(idx2verlist);
26788
26789
26790 for (i = 0; i < in->numberoftetrahedra; i++) {
26791
26792
26793 maketetrahedron(&tetloop);
26794 index = i * in->numberofcorners;
26795
26796 iorg = in->tetrahedronlist[index] - in->firstnumber;
26797 idest = in->tetrahedronlist[index + 1] - in->firstnumber;
26798 iapex = in->tetrahedronlist[index + 2] - in->firstnumber;
26799 ioppo = in->tetrahedronlist[index + 3] - in->firstnumber;
26800 torg = idx2verlist[iorg];
26801 tdest = idx2verlist[idest];
26802 tapex = idx2verlist[iapex];
26803 toppo = idx2verlist[ioppo];
26804 sign = orient3d(torg, tdest, tapex, toppo);
26805 if (sign > 0.0) {
26806 norg = torg; torg = tdest; tdest = norg;
26807 } else if (sign == 0.0) {
26808 if (!b->quiet) {
26809 printf("Warning: Tet %d is degenerate.\n", i + in->firstnumber);
26810 }
26811 }
26812 setorg(tetloop, torg);
26813 setdest(tetloop, tdest);
26814 setapex(tetloop, tapex);
26815 setoppo(tetloop, toppo);
26816
26817
26818 setpointtype(torg, FREEVOLVERTEX);
26819 setpointtype(tdest, FREEVOLVERTEX);
26820 setpointtype(tapex, FREEVOLVERTEX);
26821 setpointtype(toppo, FREEVOLVERTEX);
26822
26823 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
26824 index = i * in->numberoftetrahedronattributes;
26825 attrib = in->tetrahedronattributelist[index + j];
26826 setelemattribute(tetloop.tet, j, attrib);
26827 }
26828
26829
26830 if (b->varvolume) {
26831 if (in->tetrahedronvolumelist != (REAL *) NULL) {
26832 volume = in->tetrahedronvolumelist[i];
26833 } else {
26834 volume = -1.0;
26835 }
26836 setvolumebound(tetloop.tet, volume);
26837 }
26838 }
26839
26840
26841 hullsize = 0l;
26842
26843 maketetrahedronmap(idx2tetlist, tetsperverlist);
26844
26845 worklist = new int[points->items];
26846 for (i = 0; i < points->items; i++) worklist[i] = 0;
26847
26848
26849 tetrahedrons->traversalinit();
26850 tetloop.tet = tetrahedrontraverse();
26851 while (tetloop.tet != (tetrahedron *) NULL) {
26852
26853 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26854 sym(tetloop, neightet);
26855 if (neightet.tet != dummytet) continue;
26856 torg = org(tetloop);
26857 tdest = dest(tetloop);
26858 tapex = apex(tetloop);
26859 iorg = pointmark(torg) - in->firstnumber;
26860 idest = pointmark(tdest) - in->firstnumber;
26861 iapex = pointmark(tapex) - in->firstnumber;
26862 worklist[iorg] = 1;
26863 worklist[idest] = 1;
26864 worklist[iapex] = 1;
26865 bondflag = false;
26866
26867 for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26868 j++) {
26869 if (tetsperverlist[j] == tetloop.tet) continue;
26870 neightet.tet = tetsperverlist[j];
26871 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26872 sym(neightet, neineightet);
26873 if (neineightet.tet == dummytet) {
26874 norg = org(neightet);
26875 ndest = dest(neightet);
26876 napex = apex(neightet);
26877 inorg = pointmark(norg) - in->firstnumber;
26878 indest = pointmark(ndest) - in->firstnumber;
26879 inapex = pointmark(napex) - in->firstnumber;
26880 if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26881
26882 bond(tetloop, neightet);
26883 bondflag = true;
26884 break;
26885 }
26886 }
26887 }
26888 }
26889 if (!bondflag) {
26890 hullsize++;
26891
26892 dummytet[0] = encode(tetloop);
26893 if ((in->pointmarkerlist != (int *) NULL) && !b->coarse) {
26894
26895 if (in->pointmarkerlist[iorg] == 0) {
26896 in->pointmarkerlist[iorg] = 1;
26897 }
26898 if (in->pointmarkerlist[idest] == 0) {
26899 in->pointmarkerlist[idest] = 1;
26900 }
26901 if (in->pointmarkerlist[iapex] == 0) {
26902 in->pointmarkerlist[iapex] = 1;
26903 }
26904 }
26905 }
26906 worklist[iorg] = 0;
26907 worklist[idest] = 0;
26908 worklist[iapex] = 0;
26909 }
26910 tetloop.tet = tetrahedrontraverse();
26911 }
26912
26913
26914
26915
26916
26917
26918
26919 if (in->trifacelist != (int *) NULL) {
26920
26921 for (i = 0; i < in->numberoftrifaces; i++) {
26922 index = i * 3;
26923 iorg = in->trifacelist[index] - in->firstnumber;
26924 idest = in->trifacelist[index + 1] - in->firstnumber;
26925 iapex = in->trifacelist[index + 2] - in->firstnumber;
26926
26927 worklist[iorg] = 1;
26928 worklist[idest] = 1;
26929 worklist[iapex] = 1;
26930 bondflag = false;
26931
26932 for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26933 j++) {
26934 neightet.tet = tetsperverlist[j];
26935 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26936 norg = org(neightet);
26937 ndest = dest(neightet);
26938 napex = apex(neightet);
26939 inorg = pointmark(norg) - in->firstnumber;
26940 indest = pointmark(ndest) - in->firstnumber;
26941 inapex = pointmark(napex) - in->firstnumber;
26942 if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26943 bondflag = true;
26944 break;
26945 }
26946 }
26947 }
26948 if (bondflag) {
26949
26950 makeshellface(subfaces, &subloop);
26951 torg = idx2verlist[iorg];
26952 tdest = idx2verlist[idest];
26953 tapex = idx2verlist[iapex];
26954 setsorg(subloop, torg);
26955 setsdest(subloop, tdest);
26956 setsapex(subloop, tapex);
26957
26958
26959 setpointtype(torg, FREESUBVERTEX);
26960 setpointtype(tdest, FREESUBVERTEX);
26961 setpointtype(tapex, FREESUBVERTEX);
26962 if (in->trifacemarkerlist != (int *) NULL) {
26963 setshellmark(subloop, in->trifacemarkerlist[i]);
26964 }
26965 adjustedgering(neightet, CCW);
26966 findedge(&subloop, org(neightet), dest(neightet));
26967 tsbond(neightet, subloop);
26968 sym(neightet, neineightet);
26969 if (neineightet.tet != dummytet) {
26970 sesymself(subloop);
26971 tsbond(neineightet, subloop);
26972 }
26973 } else {
26974 if (!b->quiet) {
26975 printf("Warning: Subface %d is discarded.\n", i + in->firstnumber);
26976 }
26977 }
26978 worklist[iorg] = 0;
26979 worklist[idest] = 0;
26980 worklist[iapex] = 0;
26981 }
26982 }
26983
26984
26985 tetrahedrons->traversalinit();
26986 tetloop.tet = tetrahedrontraverse();
26987 while (tetloop.tet != (tetrahedron *) NULL) {
26988
26989 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26990 tspivot(tetloop, subloop);
26991 if (subloop.sh != dummysh) continue;
26992 bondflag = false;
26993 sym(tetloop, neightet);
26994 if (neightet.tet == dummytet) {
26995
26996 bondflag = true;
26997 } else {
26998
26999
27000 if (in->numberoftetrahedronattributes > 0) {
27001 if (elemattribute(neightet.tet,
27002 in->numberoftetrahedronattributes - 1) !=
27003 elemattribute(tetloop.tet,
27004 in->numberoftetrahedronattributes - 1)) {
27005 bondflag = true;
27006 }
27007 }
27008 }
27009 if (bondflag) {
27010 adjustedgering(tetloop, CCW);
27011 makeshellface(subfaces, &subloop);
27012 torg = org(tetloop);
27013 tdest = dest(tetloop);
27014 tapex = apex(tetloop);
27015 setsorg(subloop, torg);
27016 setsdest(subloop, tdest);
27017 setsapex(subloop, tapex);
27018
27019
27020 setpointtype(torg, FREESUBVERTEX);
27021 setpointtype(tdest, FREESUBVERTEX);
27022 setpointtype(tapex, FREESUBVERTEX);
27023 tsbond(tetloop, subloop);
27024 if (neightet.tet != dummytet) {
27025 sesymself(subloop);
27026 tsbond(neightet, subloop);
27027 }
27028 }
27029 }
27030 tetloop.tet = tetrahedrontraverse();
27031 }
27032
27033
27034
27035
27036 neighshlist = new list(sizeof(face), NULL);
27037
27038 makesubfacemap(idx2facelist, facesperverlist);
27039
27040
27041 subfaces->traversalinit();
27042 subloop.sh = shellfacetraverse(subfaces);
27043 while (subloop.sh != (shellface *) NULL) {
27044 for (i = 0; i < 3; i++) {
27045 spivot(subloop, neighsh);
27046 if (neighsh.sh == dummysh) {
27047
27048 torg = sorg(subloop);
27049 tdest = sdest(subloop);
27050 tapex = sapex(subloop);
27051 neighshlist->append(&subloop);
27052 iorg = pointmark(torg) - in->firstnumber;
27053
27054 for (j = idx2facelist[iorg]; j < idx2facelist[iorg + 1]; j++) {
27055 neighsh.sh = facesperverlist[j];
27056 if (neighsh.sh == subloop.sh) continue;
27057 neighsh.shver = 0;
27058 if (isfacehasedge(&neighsh, torg, tdest)) {
27059 findedge(&neighsh, torg, tdest);
27060
27061 if (neighshlist->len() < 2) {
27062 neighshlist->append(&neighsh);
27063 } else {
27064 for (index = 0; index < neighshlist->len() - 1; index++) {
27065 sface1 = * (face *)(* neighshlist)[index];
27066 sface2 = * (face *)(* neighshlist)[index + 1];
27067 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(neighsh));
27068 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
27069 if (da1 < da2) {
27070 break;
27071 }
27072 }
27073 neighshlist->insert(index + 1, &neighsh);
27074 }
27075 }
27076 }
27077
27078 if (neighshlist->len() > 1) {
27079 neighsh = * (face *)(* neighshlist)[0];
27080 for (j = 1; j <= neighshlist->len(); j++) {
27081 if (j < neighshlist->len()) {
27082 neineighsh = * (face *)(* neighshlist)[j];
27083 } else {
27084 neineighsh = * (face *)(* neighshlist)[0];
27085 }
27086 sbond1(neighsh, neineighsh);
27087 neighsh = neineighsh;
27088 }
27089 } else {
27090
27091 sbond(subloop, subloop);
27092 }
27093 neighshlist->clear();
27094 }
27095 senextself(subloop);
27096 }
27097 subloop.sh = shellfacetraverse(subfaces);
27098 }
27099
27100
27101 marker = 1;
27102 subfaces->traversalinit();
27103 subloop.sh = shellfacetraverse(subfaces);
27104 while (subloop.sh != (shellface *) NULL) {
27105 for (i = 0; i < 3; i++) {
27106 sspivot(subloop, subseg);
27107 if (subseg.sh == dummysh) {
27108
27109 torg = sorg(subloop);
27110 tdest = sdest(subloop);
27111 tapex = sapex(subloop);
27112 spivot(subloop, neighsh);
27113 spivot(neighsh, neineighsh);
27114 insertsegflag = false;
27115 if (subloop.sh == neighsh.sh || subloop.sh != neineighsh.sh) {
27116
27117
27118 insertsegflag = true;
27119 } else {
27120
27121 #ifdef SELF_CHECK
27122 assert(subloop.sh != neighsh.sh);
27123 #endif
27124 napex = sapex(neighsh);
27125 sign = orient3d(torg, tdest, tapex, napex);
27126 if (iscoplanar(torg, tdest, tapex, napex, sign, b->epsilon)) {
27127
27128
27129 insertsegflag = (shellmark(subloop) != shellmark(neighsh));
27130 } else {
27131
27132 insertsegflag = true;
27133 }
27134 }
27135 if (insertsegflag) {
27136
27137 makeshellface(subsegs, &subseg);
27138 setsorg(subseg, torg);
27139 setsdest(subseg, tdest);
27140
27141
27142 setpointtype(torg, NACUTEVERTEX);
27143 setpointtype(tdest, NACUTEVERTEX);
27144 setshellmark(subseg, marker);
27145 marker++;
27146
27147 neighsh = subloop;
27148 do {
27149 ssbond(neighsh, subseg);
27150 spivotself(neighsh);
27151 } while (neighsh.sh != subloop.sh);
27152 }
27153 }
27154 senextself(subloop);
27155 }
27156 subloop.sh = shellfacetraverse(subfaces);
27157 }
27158
27159 insegments = subsegs->items;
27160
27161
27162
27163 markerlist = new list((char*)"int");
27164
27165 subfaces->traversalinit();
27166 subloop.sh = shellfacetraverse(subfaces);
27167 while (subloop.sh != (shellface *) NULL) {
27168
27169 if (!sinfected(subloop)) {
27170
27171 marker = shellmark(subloop);
27172 markerlist->append(&marker);
27173 facetidx = markerlist->len();
27174 setshellmark(subloop, facetidx);
27175 sinfect(subloop);
27176 neighshlist->append(&subloop);
27177
27178 for (i = 0; i < neighshlist->len(); i++) {
27179 neighsh = * (face *) (* neighshlist)[i];
27180 for (j = 0; j < 3; j++) {
27181 sspivot(neighsh, subseg);
27182 if (subseg.sh == dummysh) {
27183 spivot(neighsh, neineighsh);
27184 if (!sinfected(neineighsh)) {
27185
27186 #ifdef SELF_CHECK
27187 assert(shellmark(neineighsh) == marker);
27188 #endif
27189 setshellmark(neineighsh, facetidx);
27190 sinfect(neineighsh);
27191 neighshlist->append(&neineighsh);
27192 }
27193 }
27194 senextself(neighsh);
27195 }
27196 }
27197 neighshlist->clear();
27198 }
27199 subloop.sh = shellfacetraverse(subfaces);
27200 }
27201
27202 subfaces->traversalinit();
27203 subloop.sh = shellfacetraverse(subfaces);
27204 while (subloop.sh != (shellface *) NULL) {
27205 #ifdef SELF_CHECK
27206 assert(sinfected(subloop));
27207 #endif
27208 suninfect(subloop);
27209 subloop.sh = shellfacetraverse(subfaces);
27210 }
27211
27212 in->numberoffacets = markerlist->len();
27213 in->facetmarkerlist = new int[in->numberoffacets];
27214 for (i = 0; i < in->numberoffacets; i++) {
27215 marker = * (int *) (* markerlist)[i];
27216 in->facetmarkerlist[i] = marker;
27217 }
27218
27219 facetabovepointarray = new point[in->numberoffacets + 1];
27220 for (i = 0; i < in->numberoffacets + 1; i++) {
27221 facetabovepointarray[i] = (point) NULL;
27222 }
27223
27224
27225 checksubfaces = 1;
27226
27227 nonconvex = 1;
27228
27229
27230 if (checkpbcs) {
27231 tetgenio::pbcgroup *pg;
27232 pbcdata *pd;
27233
27234 createsubpbcgrouptable();
27235
27236 for (i = 0; i < in->numberofpbcgroups; i++) {
27237 pg = &(in->pbcgrouplist[i]);
27238 pd = &(subpbcgrouptable[i]);
27239
27240 for (j = 0; j < 2; j++) {
27241 subfaces->traversalinit();
27242 subloop.sh = shellfacetraverse(subfaces);
27243 while (subloop.sh != (shellface *) NULL) {
27244 facetidx = shellmark(subloop);
27245 marker = in->facetmarkerlist[facetidx - 1];
27246 if (marker == pd->fmark[j]) {
27247 setshellpbcgroup(subloop, i);
27248 pd->ss[j] = subloop;
27249 }
27250 subloop.sh = shellfacetraverse(subfaces);
27251 }
27252 }
27253 if (pg->pointpairlist != (int *) NULL) {
27254
27255 for (j = 0; j < pg->numberofpointpairs; j++) {
27256 iorg = pg->pointpairlist[j * 2] - in->firstnumber;
27257 idest = pg->pointpairlist[j * 2 + 1] - in->firstnumber;
27258 torg = idx2verlist[iorg];
27259 tdest = idx2verlist[idest];
27260 setpoint2pbcpt(torg, tdest);
27261 setpoint2pbcpt(tdest, torg);
27262 }
27263 }
27264 }
27265
27266 createsegpbcgrouptable();
27267 }
27268
27269 delete markerlist;
27270 delete neighshlist;
27271 delete [] worklist;
27272 delete [] idx2tetlist;
27273 delete [] tetsperverlist;
27274 delete [] idx2facelist;
27275 delete [] facesperverlist;
27276 delete [] idx2verlist;
27277
27278 return hullsize;
27279 }
27280
27282
27283
27284
27286
27287 void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
27288 {
27289 queue *flipqueue;
27290 triface searchtet;
27291 face checksh, checkseg;
27292 point newpoint;
27293 enum locateresult loc;
27294 REAL *attr;
27295 bool insertflag;
27296 int covertices, outvertices;
27297 int index;
27298 int i, j;
27299
27300 if (!b->quiet) {
27301 printf("Insert additional points into mesh.\n");
27302 }
27303
27304 flipqueue = new queue(sizeof(badface));
27305 recenttet.tet = dummytet;
27306 covertices = outvertices = 0;
27307
27308 index = 0;
27309 for (i = 0; i < addio->numberofpoints; i++) {
27310
27311 makepoint(&newpoint);
27312 newpoint[0] = addio->pointlist[index++];
27313 newpoint[1] = addio->pointlist[index++];
27314 newpoint[2] = addio->pointlist[index++];
27315
27316 if ((addio->numberofpointattributes > 0) &&
27317 (in->numberofpointattributes > 0)) {
27318 attr = addio->pointattributelist + addio->numberofpointattributes * i;
27319 for (j = 0; j < in->numberofpointattributes; j++) {
27320 if (j < addio->numberofpointattributes) {
27321 newpoint[3 + j] = attr[j];
27322 }
27323 }
27324 }
27325
27326 searchtet = recenttet;
27327 loc = locate(newpoint, &searchtet);
27328 if (loc != ONVERTEX) {
27329 loc = adjustlocate(newpoint, &searchtet, loc, b->epsilon2);
27330 }
27331 if (loc == OUTSIDE) {
27332 loc = hullwalk(newpoint, &searchtet);
27333 if (loc == OUTSIDE) {
27334
27335 tetrahedrons->traversalinit();
27336 searchtet.tet = tetrahedrontraverse();
27337 while (searchtet.tet != (tetrahedron *) NULL) {
27338 loc = adjustlocate(newpoint, &searchtet, OUTSIDE, b->epsilon2);
27339 if (loc != OUTSIDE) break;
27340 searchtet.tet = tetrahedrontraverse();
27341 }
27342 }
27343 }
27344
27345 insertflag = true;
27346 switch (loc) {
27347 case INTETRAHEDRON:
27348 setpointtype(newpoint, FREEVOLVERTEX);
27349 splittetrahedron(newpoint, &searchtet, flipqueue);
27350 break;
27351 case ONFACE:
27352 tspivot(searchtet, checksh);
27353 if (checksh.sh != dummysh) {
27354
27355 if (b->nobisect) {
27356 insertflag = false;
27357 } else {
27358 setpointtype(newpoint, FREESUBVERTEX);
27359 }
27360 } else {
27361 setpointtype(newpoint, FREEVOLVERTEX);
27362 }
27363 if (insertflag) {
27364 splittetface(newpoint, &searchtet, flipqueue);
27365 }
27366 break;
27367 case ONEDGE:
27368 tsspivot(&searchtet, &checkseg);
27369 if (checkseg.sh != dummysh) {
27370 if (b->nobisect) {
27371 insertflag = false;
27372 } else {
27373 setpointtype(newpoint, FREESEGVERTEX);
27374 setpoint2sh(newpoint, sencode(checkseg));
27375 }
27376 } else {
27377 tspivot(searchtet, checksh);
27378 if (checksh.sh != dummysh) {
27379 if (b->nobisect) {
27380 insertflag = false;
27381 } else {
27382 setpointtype(newpoint, FREESUBVERTEX);
27383 }
27384 } else {
27385 setpointtype(newpoint, FREEVOLVERTEX);
27386 }
27387 }
27388 if (insertflag) {
27389 splittetedge(newpoint, &searchtet, flipqueue);
27390 }
27391 break;
27392 case ONVERTEX:
27393 insertflag = false;
27394 covertices++;
27395 break;
27396 case OUTSIDE:
27397 insertflag = false;
27398 outvertices++;
27399 break;
27400 }
27401
27402 recenttet = searchtet;
27403 if (!insertflag) {
27404 pointdealloc(newpoint);
27405 } else {
27406 flip(flipqueue, NULL);
27407 }
27408 }
27409
27410 if (b->verbose) {
27411 if (covertices > 0) {
27412 printf(" %d constrained points already exist.\n", covertices);
27413 }
27414 if (outvertices > 0) {
27415 printf(" %d constrained points lie outside the mesh.\n", outvertices);
27416 }
27417 printf(" %d constrained points have been inserted.\n",
27418 addio->numberofpoints - covertices - outvertices);
27419 }
27420
27421 delete flipqueue;
27422 }
27423
27425
27426
27427
27428
27429
27430
27432
27433 bool tetgenmesh::p1interpolatebgm(point pt, triface* bgmtet, long *scount)
27434 {
27435 point bgmpt[4];
27436 enum locateresult loc;
27437 REAL vol, volpt[4], weights[4];
27438 int i;
27439
27440 loc = bgm->preciselocate(pt, bgmtet, bgm->tetrahedrons->items);
27441 if (loc == OUTSIDE) {
27442 loc = bgm->hullwalk(pt, bgmtet);
27443 if (loc == OUTSIDE) {
27444
27445 if (b->verbose) {
27446 printf("Warning: Global point location.\n");
27447 }
27448 if (scount) (*scount)++;
27449 bgm->tetrahedrons->traversalinit();
27450 bgmtet->tet = bgm->tetrahedrontraverse();
27451 while (bgmtet->tet != (tetrahedron *) NULL) {
27452 loc = bgm->adjustlocate(pt, bgmtet, OUTSIDE, b->epsilon);
27453 if (loc != OUTSIDE) break;
27454 bgmtet->tet = bgm->tetrahedrontraverse();
27455 }
27456 }
27457 }
27458 if (loc != OUTSIDE) {
27459
27460 setpoint2bgmtet(pt, encode(*bgmtet));
27461
27462 for (i = 0; i < 4; i++) bgmpt[i] = (point) bgmtet->tet[4 + i];
27463
27464 vol = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], bgmpt[3]);
27465 volpt[0] = orient3d(pt, bgmpt[1], bgmpt[2], bgmpt[3]);
27466 volpt[1] = orient3d(bgmpt[0], pt, bgmpt[2], bgmpt[3]);
27467 volpt[2] = orient3d(bgmpt[0], bgmpt[1], pt, bgmpt[3]);
27468 volpt[3] = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], pt);
27469 for (i = 0; i < 4; i++) weights[i] = fabs(volpt[i] / vol);
27470
27471 for (i = 0; i < bgm->in->numberofpointmtrs; i++) {
27472 pt[pointmtrindex + i] = weights[0] * bgmpt[0][bgm->pointmtrindex + i]
27473 + weights[1] * bgmpt[1][bgm->pointmtrindex + i]
27474 + weights[2] * bgmpt[2][bgm->pointmtrindex + i]
27475 + weights[3] * bgmpt[3][bgm->pointmtrindex + i];
27476 }
27477 } else {
27478 setpoint2bgmtet(pt, (tetrahedron) NULL);
27479 }
27480 return loc != OUTSIDE;
27481 }
27482
27484
27485
27486
27487
27488
27489
27490
27491
27492
27493
27495
27496 void tetgenmesh::interpolatesizemap()
27497 {
27498 list *adjtetlist;
27499 triface tetloop, neightet, bgmtet;
27500 point searchpt;
27501 long scount;
27502 int *worklist;
27503 int sepcount;
27504 int i;
27505
27506 if (b->verbose) {
27507 printf(" Interpolating size map.\n");
27508 }
27509
27510 worklist = new int[points->items + 1];
27511 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
27512 sepcount = 0;
27513 scount = 0l;
27514
27515 tetrahedrons->traversalinit();
27516 tetloop.tet = tetrahedrontraverse();
27517 while (tetloop.tet != (tetrahedron *) NULL) {
27518 if (!infected(tetloop)) {
27519
27520 adjtetlist = new list(sizeof(triface), NULL, 1024);
27521 infect(tetloop);
27522
27523 for (i = 0; i < 4; i++) {
27524 searchpt = (point) tetloop.tet[4 + i];
27525
27526
27527 worklist[pointmark(searchpt)] = 1;
27528
27529 bgm->decode(point2bgmtet(searchpt), bgmtet);
27530 if (bgm->isdead(&bgmtet)) {
27531 bgmtet = bgm->recenttet;
27532 }
27533 if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27534 bgm->recenttet = bgmtet;
27535 }
27536 }
27537
27538 adjtetlist->append(&tetloop);
27539
27540 for (i = 0; i < adjtetlist->len(); i++) {
27541 tetloop = * (triface *)(* adjtetlist)[i];
27542 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27543 sym(tetloop, neightet);
27544 if ((neightet.tet != dummytet) && !infected(neightet)) {
27545
27546 searchpt = oppo(neightet);
27547 if (worklist[pointmark(searchpt)] == 0) {
27548 worklist[pointmark(searchpt)] = 1;
27549 decode(point2bgmtet(searchpt), bgmtet);
27550 if (bgm->isdead(&bgmtet)) {
27551 bgmtet = bgm->recenttet;
27552 }
27553 if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27554 bgm->recenttet = bgmtet;
27555 }
27556 }
27557 infect(neightet);
27558 adjtetlist->append(&neightet);
27559 }
27560 }
27561 }
27562
27563 sepcount++;
27564 delete adjtetlist;
27565 }
27566 tetloop.tet = tetrahedrontraverse();
27567 }
27568
27569
27570 tetrahedrons->traversalinit();
27571 tetloop.tet = tetrahedrontraverse();
27572 while (tetloop.tet != (tetrahedron *) NULL) {
27573 assert(infected(tetloop));
27574 uninfect(tetloop);
27575 tetloop.tet = tetrahedrontraverse();
27576 }
27577 delete [] worklist;
27578
27579 #ifdef SELF_CHECK
27580 if (b->verbose && scount > 0l) {
27581 printf(" %ld brute-force searches.\n", scount);
27582 }
27583 if (b->verbose && sepcount > 0) {
27584 printf(" %d separate domains.\n", sepcount);
27585 }
27586 #endif
27587 }
27588
27590
27591
27592
27593
27594
27595
27597
27598 void tetgenmesh::duplicatebgmesh()
27599 {
27600 triface tetloop, btetloop;
27601 triface symtet, bsymtet;
27602 face bhullsh, bneighsh;
27603 point *idx2bplist, *tetptbaklist;
27604 point ploop, bploop;
27605 int idx, i;
27606
27607 if (!b->quiet) {
27608 printf("Duplicating background mesh.\n");
27609 }
27610
27611
27612
27613
27614
27615
27616
27617 idx2bplist = new point[points->items + 1];
27618 idx = in->firstnumber;
27619 points->traversalinit();
27620 ploop = pointtraverse();
27621 while (ploop != (point) NULL) {
27622 bgm->makepoint(&bploop);
27623
27624 for (i = 0; i < 3 + in->numberofpointattributes; i++) {
27625 bploop[i] = ploop[i];
27626 }
27627
27628 for (i = 0; i < bgm->sizeoftensor; i++) {
27629 bploop[bgm->pointmtrindex + i] = ploop[pointmtrindex + i];
27630
27631 if (bploop[bgm->pointmtrindex + i] <= 0.0) {
27632 printf("Error: Point %d has non-positive size %g (-m option).\n",
27633 bgm->pointmark(bploop), bploop[bgm->pointmtrindex + i]);
27634 terminatetetgen(1);
27635 }
27636 }
27637
27638 idx2bplist[idx++] = bploop;
27639 ploop = pointtraverse();
27640 }
27641
27642
27643 tetptbaklist = new point[tetrahedrons->items + 1];
27644 idx = in->firstnumber;
27645 tetrahedrons->traversalinit();
27646 tetloop.tet = tetrahedrontraverse();
27647 while (tetloop.tet != (tetrahedron *) NULL) {
27648 bgm->maketetrahedron(&btetloop);
27649
27650 for (i = 0; i < 4; i++) {
27651 ploop = (point) tetloop.tet[4 + i];
27652 bploop = idx2bplist[pointmark(ploop)];
27653 btetloop.tet[4 + i] = (tetrahedron) bploop;
27654 }
27655
27656 tetptbaklist[idx++] = (point) tetloop.tet[4];
27657 tetloop.tet[4] = (tetrahedron) btetloop.tet;
27658 tetloop.tet = tetrahedrontraverse();
27659 }
27660
27661
27662
27663 idx = in->firstnumber;
27664 tetrahedrons->traversalinit();
27665 tetloop.tet = tetrahedrontraverse();
27666 while (tetloop.tet != (tetrahedron *) NULL) {
27667
27668 btetloop.tet = (tetrahedron *) tetloop.tet[4];
27669
27670 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27671 btetloop.loc = tetloop.loc;
27672 sym(tetloop, symtet);
27673 if ((symtet.tet != dummytet) && (symtet.tet > tetloop.tet)) {
27674
27675 bsymtet.tet = (tetrahedron *) symtet.tet[4];
27676 bsymtet.loc = symtet.loc;
27677 bgm->bond(btetloop, bsymtet);
27678 } else if (symtet.tet == dummytet) {
27679
27680 bgm->makeshellface(bgm->subfaces, &bhullsh);
27681 bgm->adjustedgering(btetloop, CCW);
27682 bgm->setsorg(bhullsh, bgm->org(btetloop));
27683 bgm->setsdest(bhullsh, bgm->dest(btetloop));
27684 bgm->setsapex(bhullsh, bgm->apex(btetloop));
27685 bgm->tsbond(btetloop, bhullsh);
27686
27687 bgm->dummytet[0] = bgm->encode(btetloop);
27688 }
27689 }
27690
27691 tetloop.tet[4] = (tetrahedron) tetptbaklist[idx++];
27692
27693 btetloop.loc = 0;
27694 for (i = 0; i < 4; i++) {
27695 ploop = (point) tetloop.tet[4 + i];
27696 setpoint2bgmtet(ploop, bgm->encode(btetloop));
27697 }
27698
27699 tetloop.tet = tetrahedrontraverse();
27700 }
27701
27702
27703 bgm->subfaces->traversalinit();
27704 bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27705 while (bhullsh.sh != (shellface *) NULL) {
27706 bhullsh.shver = 0;
27707 bgm->stpivot(bhullsh, btetloop);
27708 assert(btetloop.tet != bgm->dummytet);
27709 bgm->adjustedgering(btetloop, CCW);
27710 for (i = 0; i < 3; i++) {
27711 bgm->spivot(bhullsh, bneighsh);
27712 if (bneighsh.sh == bgm->dummysh) {
27713
27714 bsymtet = btetloop;
27715 while (bgm->fnextself(bsymtet));
27716 bgm->tspivot(bsymtet, bneighsh);
27717 bgm->findedge(&bneighsh, bgm->sdest(bhullsh), bgm->sorg(bhullsh));
27718 bgm->sbond(bhullsh, bneighsh);
27719 }
27720 bgm->enextself(btetloop);
27721 bgm->senextself(bhullsh);
27722 }
27723 bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27724 }
27725
27726 delete [] tetptbaklist;
27727 delete [] idx2bplist;
27728 }
27729
27730
27731
27732
27733
27735
27736
27737
27738
27739
27740
27741
27742
27743
27744
27745
27746
27747
27748
27749
27751
27752 void tetgenmesh::marksharpsegments(REAL sharpangle)
27753 {
27754 triface adjtet;
27755 face startsh, spinsh, neighsh;
27756 face segloop, prevseg, nextseg;
27757 point eorg, edest;
27758 REAL ang, smallang;
27759 bool issharp;
27760 int sharpsegcount;
27761
27762 if (b->verbose > 0) {
27763 printf(" Marking sharp segments.\n");
27764 }
27765
27766 smallang = sharpangle * PI / 180.;
27767 sharpsegcount = 0;
27768 eorg = edest = (point) NULL;
27769
27770
27771
27772 subsegs->traversalinit();
27773 segloop.sh = shellfacetraverse(subsegs);
27774 while (segloop.sh != (shellface *) NULL) {
27775 segloop.shver = 0;
27776 senext2(segloop, prevseg);
27777 spivotself(prevseg);
27778 if (prevseg.sh == dummysh) {
27779
27780 assert(shelltype(segloop) != SHARP);
27781 issharp = false;
27782 spivot(segloop, startsh);
27783 if (startsh.sh != dummysh) {
27784
27785 eorg = sorg(segloop);
27786 edest = sdest(segloop);
27787 spinsh = startsh;
27788 do {
27789 if (sorg(spinsh) != eorg) {
27790 sesymself(spinsh);
27791 }
27792
27793 stpivot(spinsh, adjtet);
27794 if (adjtet.tet != dummytet) {
27795
27796 spivot(spinsh, neighsh);
27797
27798 if (neighsh.sh != spinsh.sh) {
27799
27800 ang = facedihedral(eorg, edest, sapex(spinsh), sapex(neighsh));
27801
27802 if (!issharp) issharp = (ang < smallang);
27803
27804 minfacetdihed = minfacetdihed < ang ? minfacetdihed : ang;
27805 }
27806 }
27807
27808 spivotself(spinsh);
27809 } while (spinsh.sh != startsh.sh);
27810
27811
27812 spinsh = startsh;
27813 do {
27814 if (sorg(spinsh) != eorg) {
27815 sesymself(spinsh);
27816 }
27817
27818 neighsh = spinsh;
27819
27820
27821
27822
27823 ang = 0.0;
27824 do {
27825 ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27826 senext2self(neighsh);
27827 sspivot(neighsh, nextseg);
27828 if (nextseg.sh != dummysh) break;
27829
27830 spivotself(neighsh);
27831 assert(neighsh.sh != dummysh);
27832 if (sorg(neighsh) != eorg) {
27833 sesymself(neighsh);
27834 }
27835 } while (true);
27836
27837 if (!issharp) issharp = (ang < smallang);
27838
27839 minfaceang = minfaceang < ang ? minfaceang : ang;
27840
27841 spivotself(spinsh);
27842 } while (spinsh.sh != startsh.sh);
27843
27844 }
27845 if (issharp) {
27846 setshelltype(segloop, SHARP);
27847
27848 senext(segloop, nextseg);
27849 spivotself(nextseg);
27850 while (nextseg.sh != dummysh) {
27851 nextseg.shver = 0;
27852 setshelltype(nextseg, SHARP);
27853 senextself(nextseg);
27854 spivotself(nextseg);
27855 }
27856 sharpsegcount++;
27857 }
27858 }
27859 segloop.sh = shellfacetraverse(subsegs);
27860 }
27861
27862
27863
27864
27865 subsegs->traversalinit();
27866 segloop.sh = shellfacetraverse(subsegs);
27867 while (segloop.sh != (shellface *) NULL) {
27868
27869 segloop.shver = 0;
27870 senext(segloop, nextseg);
27871 spivotself(nextseg);
27872
27873 if (nextseg.sh == dummysh) {
27874
27875 issharp = (shelltype(segloop) == SHARP);
27876 spivot(segloop, startsh);
27877 if (startsh.sh != dummysh) {
27878
27879 eorg = sdest(segloop);
27880 spinsh = startsh;
27881 do {
27882 if (sorg(spinsh) != eorg) {
27883 sesymself(spinsh);
27884 }
27885
27886 neighsh = spinsh;
27887 ang = 0.0;
27888 do {
27889 ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27890 senext2self(neighsh);
27891 sspivot(neighsh, nextseg);
27892 if (nextseg.sh != dummysh) break;
27893
27894 spivotself(neighsh);
27895 assert(neighsh.sh != dummysh);
27896 if (sorg(neighsh) != eorg) {
27897 sesymself(neighsh);
27898 }
27899 } while (true);
27900
27901 if (!issharp) issharp = (ang < smallang);
27902
27903 minfaceang = minfaceang < ang ? minfaceang : ang;
27904
27905 spivotself(spinsh);
27906 } while (spinsh.sh != startsh.sh);
27907 }
27908 if (issharp) {
27909 setshelltype(segloop, SHARP);
27910
27911 senext2(segloop, prevseg);
27912 spivotself(prevseg);
27913 while (prevseg.sh != dummysh) {
27914 prevseg.shver = 0;
27915 setshelltype(prevseg, SHARP);
27916 senext2self(prevseg);
27917 spivotself(prevseg);
27918 }
27919 sharpsegcount++;
27920 }
27921 }
27922 segloop.sh = shellfacetraverse(subsegs);
27923 }
27924
27925 if ((b->verbose > 0) && (sharpsegcount > 0)) {
27926 printf(" %d sharp segments.\n", sharpsegcount);
27927 }
27928 }
27929
27931
27932
27933
27934
27935
27936
27937
27938
27939
27940
27941
27942
27943
27944
27945
27946
27947
27949
27950 void tetgenmesh::decidefeaturepointsizes()
27951 {
27952 list *tetlist, *verlist;
27953 shellface **segsperverlist;
27954 triface starttet;
27955 face shloop;
27956 face checkseg, prevseg, nextseg, testseg;
27957 point ploop, adjpt, e1, e2;
27958 REAL lfs_0, len, vol, maxlen, varlen;
27959 bool isfeature;
27960 int *idx2seglist;
27961 int featurecount;
27962 int idx, i, j;
27963
27964 maxlen = 0.0;
27965
27966 if (b->verbose > 0) {
27967 printf(" Deciding feature-point sizes.\n");
27968 }
27969
27970
27971 makesegmentmap(idx2seglist, segsperverlist);
27972
27973 tetlist = new list(sizeof(triface), NULL, 256);
27974 verlist = new list(sizeof(point *), NULL, 256);
27975
27976 if (b->fixedvolume) {
27977
27978
27979 maxlen = pow(6.0 * b->maxvolume, 1.0/3.0);
27980 }
27981
27982 if (!b->refine) {
27983
27984 featurecount = 0;
27985 points->traversalinit();
27986 ploop = pointtraverse();
27987 while (ploop != (point) NULL) {
27988 if (pointtype(ploop) == NACUTEVERTEX) {
27989 if (point2sh(ploop) != (shellface) NULL) {
27990 setpointtype(ploop, FREESEGVERTEX);
27991 featurecount++;
27992 }
27993 }
27994 ploop = pointtraverse();
27995 }
27996 #ifdef SELF_CHECK
27997 if ((b->verbose > 0) && (featurecount > 0)) {
27998 printf(" %d Steiner points correction.\n", featurecount);
27999 }
28000 #endif
28001 }
28002
28003
28004
28005
28006 featurecount = 0;
28007 points->traversalinit();
28008 ploop = pointtraverse();
28009 while (ploop != (point) NULL) {
28010 if (pointtype(ploop) != FREESEGVERTEX) {
28011
28012 isfeature = false;
28013 idx = pointmark(ploop) - in->firstnumber;
28014 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; i++) {
28015 checkseg.sh = segsperverlist[i];
28016 isfeature = (shelltype(checkseg) == SHARP);
28017 }
28018
28019 if (isfeature) {
28020
28021 sstpivot(&checkseg, &starttet);
28022
28023 tetlist->append(&starttet);
28024 formstarpolyhedron(ploop, tetlist, verlist, true);
28025
28026 if (ploop[pointmtrindex] == 0.0) {
28027
28028 lfs_0 = longest;
28029 for (i = 0; i < verlist->len(); i++) {
28030 adjpt = * (point *)(* verlist)[i];
28031 if (pointtype(adjpt) == FREESEGVERTEX) {
28032
28033 sdecode(point2sh(adjpt), checkseg);
28034 assert(checkseg.sh != dummysh);
28035 checkseg.shver = 0;
28036
28037 prevseg = checkseg;
28038 do {
28039 senext2(prevseg, testseg);
28040 spivotself(testseg);
28041 if (testseg.sh == dummysh) break;
28042 prevseg = testseg;
28043 prevseg.shver = 0;
28044 } while (true);
28045
28046 nextseg = checkseg;
28047 do {
28048 senext(nextseg, testseg);
28049 spivotself(testseg);
28050 if (testseg.sh == dummysh) break;
28051 nextseg = testseg;
28052 nextseg.shver = 0;
28053 } while (true);
28054 e1 = sorg(prevseg);
28055 e2 = sdest(nextseg);
28056
28057 if (ploop == e1) {
28058
28059 adjpt = e2;
28060 } else if (ploop == e2) {
28061
28062 adjpt = e1;
28063 }
28064 }
28065 len = distance(ploop, adjpt);
28066 if (lfs_0 > len) lfs_0 = len;
28067 }
28068 ploop[pointmtrindex] = lfs_0;
28069 }
28070 if (b->fixedvolume) {
28071
28072 if (ploop[pointmtrindex] > maxlen) {
28073 ploop[pointmtrindex] = maxlen;
28074 }
28075 }
28076 if (b->varvolume) {
28077
28078 for (i = 0; i < tetlist->len(); i++) {
28079 starttet = * (triface *)(* tetlist)[i];
28080 vol = volumebound(starttet.tet);
28081 if (vol > 0.0) {
28082 varlen = pow(6 * vol, 1.0/3.0);
28083 if (ploop[pointmtrindex] > varlen) {
28084 ploop[pointmtrindex] = varlen;
28085 }
28086 }
28087 }
28088 }
28089
28090 tetlist->clear();
28091 verlist->clear();
28092 featurecount++;
28093 } else {
28094
28095 ploop[pointmtrindex] = 0.0;
28096 }
28097 }
28098 ploop = pointtraverse();
28099 }
28100
28101 if (b->verbose > 0) {
28102 printf(" %d feature points.\n", featurecount);
28103 }
28104
28105 if (!b->refine) {
28106
28107
28108
28109 featurecount = 0;
28110 points->traversalinit();
28111 ploop = pointtraverse();
28112 while (ploop != (point) NULL) {
28113 if (pointtype(ploop) == FREESEGVERTEX) {
28114 if (ploop[pointmtrindex] == 0.0) {
28115 sdecode(point2sh(ploop), checkseg);
28116 assert(checkseg.sh != dummysh);
28117 if (shelltype(checkseg) == SHARP) {
28118 checkseg.shver = 0;
28119
28120 prevseg = checkseg;
28121 do {
28122 senext2(prevseg, testseg);
28123 spivotself(testseg);
28124 if (testseg.sh == dummysh) break;
28125 prevseg = testseg;
28126 prevseg.shver = 0;
28127 } while (true);
28128
28129 nextseg = checkseg;
28130 do {
28131 senext(nextseg, testseg);
28132 spivotself(testseg);
28133 if (testseg.sh == dummysh) break;
28134 nextseg = testseg;
28135 nextseg.shver = 0;
28136 } while (true);
28137 e1 = sorg(prevseg);
28138 e2 = sdest(nextseg);
28139 len = distance(e1, e2);
28140 lfs_0 = distance(e1, ploop);
28141
28142 if (b->nobisect == 0) {
28143 assert(lfs_0 < len);
28144 }
28145 ploop[pointmtrindex] = e1[pointmtrindex]
28146 + (lfs_0 / len) * (e2[pointmtrindex] - e1[pointmtrindex]);
28147 featurecount++;
28148 } else {
28149
28150 ploop[pointmtrindex] = 0.0;
28151 }
28152 }
28153 }
28154 ploop = pointtraverse();
28155 }
28156 if ((b->verbose > 0) && (featurecount > 0)) {
28157 printf(" %d Steiner feature points.\n", featurecount);
28158 }
28159 }
28160
28161 if (varconstraint) {
28162
28163 if (in->facetconstraintlist) {
28164
28165 subfaces->traversalinit();
28166 shloop.sh = shellfacetraverse(subfaces);
28167 while (shloop.sh != (shellface *) NULL) {
28168 varlen = areabound(shloop);
28169 if (varlen > 0.0) {
28170
28171 varlen = sqrt(varlen);
28172 for (j = 0; j < 3; j++) {
28173 ploop = (point) shloop.sh[3 + j];
28174 isfeature = false;
28175 idx = pointmark(ploop) - in->firstnumber;
28176 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28177 i++) {
28178 checkseg.sh = segsperverlist[i];
28179 isfeature = (shelltype(checkseg) == SHARP);
28180 }
28181 if (isfeature) {
28182 assert(ploop[pointmtrindex] > 0.0);
28183 if (ploop[pointmtrindex] > varlen) {
28184 ploop[pointmtrindex] = varlen;
28185 }
28186 }
28187 }
28188 }
28189 shloop.sh = shellfacetraverse(subfaces);
28190 }
28191 }
28192 if (in->segmentconstraintlist) {
28193
28194 subsegs->traversalinit();
28195 shloop.sh = shellfacetraverse(subsegs);
28196 while (shloop.sh != (shellface *) NULL) {
28197 varlen = areabound(shloop);
28198 if (varlen > 0.0) {
28199
28200 for (j = 0; j < 2; j++) {
28201 ploop = (point) shloop.sh[3 + j];
28202 isfeature = false;
28203 idx = pointmark(ploop) - in->firstnumber;
28204 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28205 i++) {
28206 checkseg.sh = segsperverlist[i];
28207 isfeature = (shelltype(checkseg) == SHARP);
28208 }
28209 if (isfeature) {
28210 assert(ploop[pointmtrindex] > 0.0);
28211 if (ploop[pointmtrindex] > varlen) {
28212 ploop[pointmtrindex] = varlen;
28213 }
28214 }
28215 }
28216 }
28217 shloop.sh = shellfacetraverse(subsegs);
28218 }
28219 }
28220 }
28221
28222 delete [] segsperverlist;
28223 delete [] idx2seglist;
28224 delete tetlist;
28225 delete verlist;
28226 }
28227
28229
28230
28231
28233
28234 void tetgenmesh::enqueueencsub(face* testsub, point encpt, int quenumber,
28235 REAL* cent)
28236 {
28237 badface *encsub;
28238 int i;
28239
28240 encsub = (badface *) badsubfaces->alloc();
28241 encsub->ss = *testsub;
28242 encsub->forg = sorg(*testsub);
28243 encsub->fdest = sdest(*testsub);
28244 encsub->fapex = sapex(*testsub);
28245 encsub->foppo = (point) encpt;
28246 for (i = 0; i < 3; i++) encsub->cent[i] = cent[i];
28247 encsub->nextitem = (badface *) NULL;
28248
28249
28250 setshell2badface(encsub->ss, encsub);
28251
28252 *subquetail[quenumber] = encsub;
28253
28254 subquetail[quenumber] = &encsub->nextitem;
28255 if (b->verbose > 2) {
28256 printf(" Queuing subface (%d, %d, %d) [%d].\n", pointmark(encsub->forg),
28257 pointmark(encsub->fdest), pointmark(encsub->fapex), quenumber);
28258 }
28259 }
28260
28262
28263
28264
28266
28267 tetgenmesh::badface* tetgenmesh::dequeueencsub(int* pquenumber)
28268 {
28269 badface *result;
28270 int quenumber;
28271
28272
28273 for (quenumber = 2; quenumber >= 0; quenumber--) {
28274 result = subquefront[quenumber];
28275 if (result != (badface *) NULL) {
28276
28277 subquefront[quenumber] = result->nextitem;
28278
28279 if (subquefront[quenumber] == (badface *) NULL) {
28280 subquetail[quenumber] = &subquefront[quenumber];
28281 }
28282 *pquenumber = quenumber;
28283 return result;
28284 }
28285 }
28286 return (badface *) NULL;
28287 }
28288
28290
28291
28292
28294
28295 void tetgenmesh::enqueuebadtet(triface* testtet, REAL ratio2, REAL* cent)
28296 {
28297 badface *newbadtet;
28298 int queuenumber;
28299 int i;
28300
28301
28302 newbadtet = (badface *) badtetrahedrons->alloc();
28303 newbadtet->tt = *testtet;
28304 newbadtet->key = ratio2;
28305 if (cent != NULL) {
28306 for (i = 0; i < 3; i++) newbadtet->cent[i] = cent[i];
28307 } else {
28308 for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
28309 }
28310 newbadtet->forg = org(*testtet);
28311 newbadtet->fdest = dest(*testtet);
28312 newbadtet->fapex = apex(*testtet);
28313 newbadtet->foppo = oppo(*testtet);
28314 newbadtet->nextitem = (badface *) NULL;
28315
28316 if (ratio2 > b->goodratio) {
28317
28318 queuenumber = (int) (64.0 - 64.0 / ratio2);
28319
28320 if ((queuenumber > 63) || (queuenumber < 0)) {
28321 queuenumber = 63;
28322 }
28323 } else {
28324
28325 queuenumber = 0;
28326 }
28327
28328
28329 if (tetquefront[queuenumber] == (badface *) NULL) {
28330
28331 if (queuenumber > firstnonemptyq) {
28332
28333 nextnonemptyq[queuenumber] = firstnonemptyq;
28334 firstnonemptyq = queuenumber;
28335 } else {
28336
28337 i = queuenumber + 1;
28338 while (tetquefront[i] == (badface *) NULL) {
28339 i++;
28340 }
28341
28342 nextnonemptyq[queuenumber] = nextnonemptyq[i];
28343 nextnonemptyq[i] = queuenumber;
28344 }
28345
28346 tetquefront[queuenumber] = newbadtet;
28347 } else {
28348
28349 tetquetail[queuenumber]->nextitem = newbadtet;
28350 }
28351
28352 tetquetail[queuenumber] = newbadtet;
28353
28354 if (b->verbose > 2) {
28355 printf(" Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
28356 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
28357 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
28358 sqrt(ratio2), queuenumber);
28359 }
28360 }
28361
28363
28364
28365
28367
28368 tetgenmesh::badface* tetgenmesh::topbadtetra()
28369 {
28370
28371
28372 recentq = firstnonemptyq;
28373
28374 if (firstnonemptyq < 0) {
28375 return (badface *) NULL;
28376 } else {
28377
28378 return tetquefront[firstnonemptyq];
28379 }
28380 }
28381
28382 void tetgenmesh::dequeuebadtet()
28383 {
28384 badface *deadbadtet;
28385 int i;
28386
28387
28388 if (recentq >= 0) {
28389
28390 deadbadtet = tetquefront[recentq];
28391
28392 tetquefront[recentq] = deadbadtet->nextitem;
28393
28394 if (deadbadtet == tetquetail[recentq]) {
28395
28396 if (firstnonemptyq == recentq) {
28397
28398 firstnonemptyq = nextnonemptyq[firstnonemptyq];
28399 } else {
28400
28401 i = recentq + 1;
28402 while (tetquefront[i] == (badface *) NULL) {
28403 i++;
28404 }
28405 nextnonemptyq[i] = nextnonemptyq[recentq];
28406 }
28407 }
28408
28409 badfacedealloc(badtetrahedrons, deadbadtet);
28410 }
28411 }
28412
28414
28415
28416
28417
28418
28419
28420
28421
28422
28423
28424
28425
28426
28428
28429 bool tetgenmesh::checkseg4encroach(face* testseg, point testpt, point* prefpt,
28430 bool enqflag)
28431 {
28432 badface *encsubseg;
28433 triface starttet, spintet;
28434 point eorg, edest, eapex, encpt;
28435 REAL cent[3], radius, dist, diff;
28436 REAL maxradius;
28437 bool enq;
28438 int hitbdry;
28439
28440 enq = false;
28441 eorg = sorg(*testseg);
28442 edest = sdest(*testseg);
28443 cent[0] = 0.5 * (eorg[0] + edest[0]);
28444 cent[1] = 0.5 * (eorg[1] + edest[1]);
28445 cent[2] = 0.5 * (eorg[2] + edest[2]);
28446 radius = distance(cent, eorg);
28447
28448 if (varconstraint && (areabound(*testseg) > 0.0)) {
28449 enq = (2.0 * radius) > areabound(*testseg);
28450 }
28451
28452 if (!enq) {
28453 maxradius = 0.0;
28454 if (testpt == (point) NULL) {
28455
28456 sstpivot(testseg, &starttet);
28457 eapex = apex(starttet);
28458 spintet = starttet;
28459 hitbdry = 0;
28460 do {
28461 dist = distance(cent, apex(spintet));
28462 diff = dist - radius;
28463 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28464 if (diff <= 0.0) {
28465
28466 enq = true;
28467 if (prefpt != (point *) NULL) {
28468
28469 encpt = apex(spintet);
28470 circumsphere(eorg, edest, encpt, NULL, NULL, &dist);
28471 if (dist > maxradius) {
28472
28473 *prefpt = encpt;
28474 maxradius = dist;
28475 }
28476 } else {
28477 break;
28478 }
28479 }
28480 if (!fnextself(spintet)) {
28481 hitbdry++;
28482 if (hitbdry < 2) {
28483 esym(starttet, spintet);
28484 if (!fnextself(spintet)) {
28485 hitbdry++;
28486 }
28487 }
28488 }
28489 } while (apex(spintet) != eapex && (hitbdry < 2));
28490 } else {
28491
28492 dist = distance(cent, testpt);
28493 diff = dist - radius;
28494 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28495 enq = (diff <= 0.0);
28496 }
28497 }
28498
28499 if (enq && enqflag) {
28500 if (b->verbose > 2) {
28501 printf(" Queuing encroaching subsegment (%d, %d).\n",
28502 pointmark(eorg), pointmark(edest));
28503 }
28504 encsubseg = (badface *) badsubsegs->alloc();
28505 encsubseg->ss = *testseg;
28506 encsubseg->forg = eorg;
28507 encsubseg->fdest = edest;
28508 encsubseg->foppo = (point) NULL;
28509
28510
28511 setshell2badface(encsubseg->ss, encsubseg);
28512 }
28513
28514 return enq;
28515 }
28516
28518
28519
28520
28521
28522
28523
28524
28525
28526
28527
28529
28530 bool tetgenmesh::checksub4encroach(face* testsub, point testpt, bool enqflag)
28531 {
28532 triface abuttet;
28533 point pa, pb, pc, encpt;
28534 REAL A[4][4], rhs[4], D;
28535 REAL cent[3], area;
28536 REAL radius, dist, diff;
28537 bool enq;
28538 int indx[4];
28539 int quenumber;
28540
28541 enq = false;
28542 radius = 0.0;
28543 encpt = (point) NULL;
28544
28545 pa = sorg(*testsub);
28546 pb = sdest(*testsub);
28547 pc = sapex(*testsub);
28548
28549
28550 A[0][0] = pb[0] - pa[0];
28551 A[0][1] = pb[1] - pa[1];
28552 A[0][2] = pb[2] - pa[2];
28553 A[1][0] = pc[0] - pa[0];
28554 A[1][1] = pc[1] - pa[1];
28555 A[1][2] = pc[2] - pa[2];
28556 cross(A[0], A[1], A[2]);
28557
28558 if (varconstraint && (areabound(*testsub) > 0.0)) {
28559
28560 area = 0.5 * sqrt(dot(A[2], A[2]));
28561 enq = area > areabound(*testsub);
28562 if (enq) {
28563 quenumber = 2;
28564 }
28565 }
28566
28567
28568 rhs[0] = 0.5 * dot(A[0], A[0]);
28569 rhs[1] = 0.5 * dot(A[1], A[1]);
28570 rhs[2] = 0.0;
28571
28572
28573 if (lu_decmp(A, 3, indx, &D, 0)) {
28574 lu_solve(A, 3, indx, rhs, 0);
28575 cent[0] = pa[0] + rhs[0];
28576 cent[1] = pa[1] + rhs[1];
28577 cent[2] = pa[2] + rhs[2];
28578 radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
28579 }
28580
28581 if (!enq) {
28582
28583 if (testpt == (point) NULL) {
28584 stpivot(*testsub, abuttet);
28585 if (abuttet.tet != dummytet) {
28586 dist = distance(cent, oppo(abuttet));
28587 diff = dist - radius;
28588 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28589 enq = (diff <= 0.0);
28590 if (enq) encpt = oppo(abuttet);
28591 }
28592 if (!enq) {
28593 sesymself(*testsub);
28594 stpivot(*testsub, abuttet);
28595 if (abuttet.tet != dummytet) {
28596 dist = distance(cent, oppo(abuttet));
28597 diff = dist - radius;
28598 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28599 enq = (diff <= 0.0);
28600 if (enq) encpt = oppo(abuttet);
28601 }
28602 }
28603 } else {
28604 dist = distance(cent, testpt);
28605 diff = dist - radius;
28606 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28607 enq = (diff <= 0.0);
28608 }
28609 if (enq) {
28610 quenumber = 0;
28611 }
28612 }
28613
28614 if (enq && enqflag) {
28615 enqueueencsub(testsub, encpt, quenumber, cent);
28616 }
28617
28618 return enq;
28619 }
28620
28622
28623
28624
28625
28626
28627
28628
28630
28631 bool tetgenmesh::checktet4badqual(triface* testtet, bool enqflag)
28632 {
28633 point pa, pb, pc, pd, pe1, pe2;
28634 REAL vda[3], vdb[3], vdc[3];
28635 REAL vab[3], vbc[3], vca[3];
28636 REAL N[4][3], A[4][4], rhs[4], D;
28637 REAL elen[6], circumcent[3];
28638 REAL bicent[3], offcent[3];
28639 offcent[0] = 0.0;
28640 offcent[1] = 0.0;
28641 offcent[2] = 0.0;
28642 REAL volume, L, cosd;
28643 REAL radius2, smlen2, ratio2;
28644 REAL dist, sdist, split;
28645 bool enq;
28646 int indx[4];
28647 int sidx, i, j;
28648
28649 pa = (point) testtet->tet[4];
28650 pb = (point) testtet->tet[5];
28651 pc = (point) testtet->tet[6];
28652 pd = (point) testtet->tet[7];
28653
28654
28655
28656 for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
28657 for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
28658 for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
28659
28660 for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
28661 for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i];
28662 for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i];
28663
28664
28665 lu_decmp(A, 3, indx, &D, 0);
28666
28667 volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
28668 if (volume < 0.0) volume = -volume;
28669
28670 rhs[0] = 0.5 * dot(vda, vda);
28671 rhs[1] = 0.5 * dot(vdb, vdb);
28672 rhs[2] = 0.5 * dot(vdc, vdc);
28673 lu_solve(A, 3, indx, rhs, 0);
28674
28675 for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
28676
28677 radius2 = dot(rhs, rhs);
28678
28679 elen[0] = dot(vda, vda);
28680 elen[1] = dot(vdb, vdb);
28681 elen[2] = dot(vdc, vdc);
28682 elen[3] = dot(vab, vab);
28683 elen[4] = dot(vbc, vbc);
28684 elen[5] = dot(vca, vca);
28685 smlen2 = elen[0]; sidx = 0;
28686 for (i = 1; i < 6; i++) {
28687 if (smlen2 > elen[i]) { smlen2 = elen[i]; sidx = i; }
28688 }
28689
28690 ratio2 = radius2 / smlen2;
28691
28692 enq = ratio2 > b->goodratio;
28693 if (!enq) {
28694
28695
28696
28697
28698
28699 for (j = 0; j < 3; j++) {
28700 for (i = 0; i < 3; i++) rhs[i] = 0.0;
28701 rhs[j] = 1.0;
28702 lu_solve(A, 3, indx, rhs, 0);
28703 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
28704 }
28705
28706 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
28707
28708 for (i = 0; i < 4; i++) {
28709 L = sqrt(dot(N[i], N[i]));
28710 if (L > 0.0) {
28711 for (j = 0; j < 3; j++) N[i][j] /= L;
28712 }
28713 }
28714
28715
28716 for (i = 1; i < 4 && !enq; i++) {
28717 cosd = -dot(N[0], N[i]);
28718 enq = cosd > cosmindihed;
28719 }
28720 if (!enq) {
28721 for (i = 2; i < 4 && !enq; i++) {
28722 cosd = -dot(N[1], N[i]);
28723 enq = cosd > cosmindihed;
28724 }
28725 if (!enq) {
28726 cosd = -dot(N[2], N[3]);
28727 enq = cosd > cosmindihed;
28728 }
28729 }
28730
28731 } else if (b->offcenter) {
28732
28733 switch (sidx) {
28734 case 0:
28735 pe1 = pd; pe2 = pa; break;
28736 case 1:
28737 pe1 = pd; pe2 = pb; break;
28738 case 2:
28739 pe1 = pd; pe2 = pc; break;
28740 case 3:
28741 pe1 = pa; pe2 = pb; break;
28742 case 4:
28743 pe1 = pb; pe2 = pc; break;
28744 case 5:
28745 pe1 = pc; pe2 = pa; break;
28746 default:
28747 pe1 = pe2 = (point) NULL;
28748 }
28749
28750 for (i = 0; i < 3; i++) bicent[i] = 0.5 * (pe1[i] + pe2[i]);
28751 dist = distance(bicent, circumcent);
28752
28753
28754 sdist = b->alpha3 * (b->minratio+sqrt(b->goodratio-0.25))* sqrt(smlen2);
28755 split = sdist / dist;
28756 if (split > 1.0) split = 1.0;
28757
28758 for (i = 0; i < 3; i++) {
28759 offcent[i] = bicent[i] + split * (circumcent[i] - bicent[i]);
28760 }
28761 }
28762
28763 if (!enq && (b->varvolume || b->fixedvolume)) {
28764
28765 enq = b->fixedvolume && (volume > b->maxvolume);
28766 if (!enq && b->varvolume) {
28767 enq = (volume > volumebound(testtet->tet)) &&
28768 (volumebound(testtet->tet) > 0.0);
28769 }
28770 }
28771
28772 if (!enq) {
28773
28774 if (b->metric) {
28775
28776 sdist = sqrt(radius2) / b->alpha1;
28777 for (i = 0; i < 4; i++) {
28778 pa = (point) testtet->tet[4 + i];
28779
28780 dist = pa[pointmtrindex];
28781 enq = ((dist < sdist) && (dist > 0.0));
28782 if (enq) break;
28783
28784
28785 }
28786
28787
28788 }
28789 }
28790
28791 if (enq && enqflag) {
28792 if (b->offcenter && (ratio2 > b->goodratio)) {
28793 for (i = 0; i < 3; i++) circumcent[i] = offcent[i];
28794 }
28795 enqueuebadtet(testtet, ratio2, circumcent);
28796 }
28797
28798 return enq;
28799 }
28800
28802
28803
28804
28805
28806
28807
28808
28809
28810
28811
28812
28813
28814
28815
28817
28818 bool tetgenmesh::acceptsegpt(point segpt, point refpt, face* splitseg)
28819 {
28820 point p[2];
28821 REAL L, lfs;
28822 int i, j;
28823
28824 if (b->nobisect == 1) {
28825
28826 triface spintet;
28827 point pc;
28828 sstpivot(splitseg, &spintet);
28829 assert(spintet.tet != dummytet);
28830 pc = apex(spintet);
28831 do {
28832 if (!fnextself(spintet)) {
28833
28834 return false;
28835 }
28836 } while (pc != apex(spintet));
28837 } else if (b->nobisect > 1) {
28838
28839 return false;
28840 }
28841
28842 p[0] = sorg(*splitseg);
28843 p[1] = sdest(*splitseg);
28844 if (varconstraint && (areabound(*splitseg) > 0)) {
28845 lfs = areabound(*splitseg);
28846 L = distance(p[0], p[1]);
28847 if (L > lfs) {
28848 return true;
28849 }
28850 }
28851
28852 j = 0;
28853 for (i = 0; i < 2; i++) {
28854
28855 if (p[i][pointmtrindex] > 0.0) {
28856 lfs = b->alpha2 * p[i][pointmtrindex];
28857 L = distance(p[i], segpt);
28858 if (L < lfs) j++;
28859 }
28860 }
28861 if (j == 0) return true;
28862
28863
28864 if (refpt != (point) NULL) {
28865 cdtenforcesegpts++;
28866 return true;
28867 }
28868
28869
28870 rejsegpts++;
28871 return false;
28872 }
28873
28875
28876
28877
28878
28879
28880
28881
28882
28883
28884
28885
28887
28888 bool tetgenmesh::acceptfacpt(point facpt, list* subceillist, list* verlist)
28889 {
28890 face *testsh;
28891 point p[2], ploop;
28892 REAL L, lfs;
28893 int idx, i, j;
28894
28895 if (b->nobisect == 1) {
28896
28897 triface testtet;
28898 testsh = (face *)(* subceillist)[0];
28899 stpivot(*testsh, testtet);
28900 if (testtet.tet != dummytet) {
28901 sesymself(*testsh);
28902 stpivot(*testsh, testtet);
28903 }
28904 if (testtet.tet == dummytet) return false;
28905 } else if (b->nobisect > 1) {
28906
28907 return false;
28908 }
28909
28910
28911 for (i = 0; i < subceillist->len(); i++) {
28912 testsh = (face *)(* subceillist)[i];
28913 p[0] = sorg(*testsh);
28914 p[1] = sdest(*testsh);
28915 for (j = 0; j < 2; j++) {
28916 idx = pointmark(p[j]);
28917 if (idx >= 0) {
28918 setpointmark(p[j], -idx - 1);
28919 verlist->append(&(p[j]));
28920 }
28921 }
28922 }
28923
28924 j = 0;
28925 for (i = 0; i < verlist->len(); i++) {
28926 ploop = * (point *)(* verlist)[i];
28927
28928 idx = pointmark(ploop);
28929 setpointmark(ploop, -(idx + 1));
28930
28931 if (ploop[pointmtrindex] > 0.0) {
28932 lfs = b->alpha2 * ploop[pointmtrindex];
28933 L = distance(ploop, facpt);
28934 if (L < lfs) j++;
28935 }
28936 }
28937 verlist->clear();
28938
28939 if (j == 0) return true;
28940
28941 rejsubpts++;
28942 return false;
28943 }
28944
28946
28947
28948
28949
28950
28951
28952
28953
28955
28956 bool tetgenmesh::acceptvolpt(point volpt, list* ceillist, list* verlist)
28957 {
28958 triface* testtet;
28959 point p[3], ploop;
28960 REAL L, lfs;
28961 int idx, i, j;
28962
28963
28964 for (i = 0; i < ceillist->len(); i++) {
28965 testtet = (triface *)(* ceillist)[i];
28966 p[0] = org(*testtet);
28967 p[1] = dest(*testtet);
28968 p[2] = apex(*testtet);
28969 for (j = 0; j < 3; j++) {
28970 idx = pointmark(p[j]);
28971 if (idx >= 0) {
28972 setpointmark(p[j], -idx - 1);
28973 verlist->append(&(p[j]));
28974 }
28975 }
28976 }
28977
28978 j = 0;
28979 for (i = 0; i < verlist->len(); i++) {
28980 ploop = * (point *)(* verlist)[i];
28981
28982 idx = pointmark(ploop);
28983 setpointmark(ploop, -(idx + 1));
28984
28985 if (ploop[pointmtrindex] > 0.0) {
28986 lfs = b->alpha2 * ploop[pointmtrindex];
28987 L = distance(ploop, volpt);
28988 if (L < lfs) j++;
28989 }
28990 }
28991 verlist->clear();
28992
28993 if (j == 0) return true;
28994
28995 rejtetpts++;
28996 return false;
28997 }
28998
29000
29001
29002
29004
29005 void tetgenmesh::getsplitpoint(point e1, point e2, point refpt, point newpt)
29006 {
29007 point ei, ej;
29008 REAL split, L, d1, d2, ps, rs;
29009 bool acutea, acuteb;
29010 int i;
29011
29012 if (refpt != (point) NULL) {
29013
29014 acutea = (pointtype(e1) == ACUTEVERTEX);
29015 acuteb = (pointtype(e2) == ACUTEVERTEX);
29016 if (acutea ^ acuteb) {
29017
29018 ei = acutea ? e1 : e2;
29019 ej = acutea ? e2 : e1;
29020 L = distance(ei, ej);
29021
29022 d1 = distance(ei, refpt);
29023 split = d1 / L;
29024 for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29025
29026 d2 = distance(refpt, newpt);
29027 if (d2 > (L - d1)) {
29028
29029 if ((d1 - d2) > (0.5 * d1)) {
29030 split = (d1 - d2) / L;
29031 } else {
29032 split = 0.5 * d1 / L;
29033 }
29034 for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29035 if (b->verbose > 1) {
29036 printf(" Found by rule-3:");
29037 }
29038 r3count++;
29039 } else {
29040 if (b->verbose > 1) {
29041 printf(" Found by rule-2:");
29042 }
29043 r2count++;
29044 }
29045 if (b->verbose > 1) {
29046 printf(" center %d, split = %.12g.\n", pointmark(ei), split);
29047 }
29048
29049 d1 = distance(ei, newpt);
29050 d2 = distance(newpt, refpt);
29051 ps = randgenerator(d2 * b->epsilon2 * 1e+2);
29052 rs = ps / d1;
29053
29054 for (i = 0; i < 3; i++) newpt[i] = ei[i] + (1.0+rs) * (newpt[i] - ei[i]);
29055 } else {
29056
29057 for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29058
29059 d1 = 0.5 * distance(e1, e2);
29060 ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29061 rs = ps / d1;
29062 for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29063 }
29064 } else {
29065
29066 for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29067
29068 d1 = 0.5 * distance(e1, e2);
29069 ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29070 rs = ps / d1;
29071 for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29072 }
29073 }
29074
29076
29077
29078
29079
29080
29081
29082
29083
29085
29086 void tetgenmesh::shepardinterpolate(point newpt, list *verlist)
29087 {
29088 point neipt;
29089 REAL *weights, sumweight;
29090 REAL vec[3];
29091 int i, j;
29092
29093 weights = new REAL[verlist->len()];
29094 sumweight = 0.0;
29095
29096
29097 for (i = 0; i < verlist->len(); i++) {
29098 neipt = * (point *)(* verlist)[i];
29099 for (j = 0; j < 3; j++) vec[j] = neipt[j] - newpt[j];
29100 weights[i] = 1.0 / dot(vec, vec);
29101 sumweight += weights[i];
29102 }
29103
29104 newpt[pointmtrindex] = 0.0;
29105 for (i = 0; i < verlist->len(); i++) {
29106 neipt = * (point *)(* verlist)[i];
29107 newpt[pointmtrindex] += (weights[i] * neipt[pointmtrindex]) / sumweight;
29108 }
29109
29110 delete [] weights;
29111 }
29112
29114
29115
29116
29117
29118
29119
29121
29122 void tetgenmesh::setnewpointsize(point newpt, point e1, point e2)
29123 {
29124 if (b->metric) {
29125
29126 triface bgmtet;
29127
29128 decode(point2bgmtet(e1), bgmtet);
29129 p1interpolatebgm(newpt, &bgmtet, NULL);
29130 } else {
29131 if (e2 != (point) NULL) {
29132
29133 REAL split, l, d;
29134 l = distance(e1, e2);
29135 d = distance(e1, newpt);
29136 split = d / l;
29137 #ifdef SELF_CHECK
29138
29139 assert(e1[pointmtrindex] > 0.0);
29140 assert(e2[pointmtrindex] > 0.0);
29141 #endif
29142 newpt[pointmtrindex] = (1.0 - split) * e1[pointmtrindex]
29143 + split * e2[pointmtrindex];
29144 }
29145 }
29146 }
29147
29149
29150
29151
29153
29154 void tetgenmesh::splitencseg(point newpt, face* splitseg, list* tetlist,
29155 list* sublist, list* verlist, queue* flipque, bool chkencsub, bool chkbadtet,
29156 bool optflag)
29157 {
29158 list *mytetlist;
29159 queue *myflipque;
29160 triface starttet;
29161 face startsh, spinsh, checksh;
29162 int i;
29163
29164 mytetlist = NULL;
29165 myflipque = NULL;
29166
29167 if (optflag) {
29168 mytetlist = new list(sizeof(triface), NULL, 1024);
29169 myflipque = new queue(sizeof(badface));
29170 tetlist = mytetlist;
29171 flipque = myflipque;
29172 }
29173
29174
29175 splitseg->shver = 0;
29176
29177 sstpivot(splitseg, &starttet);
29178 splittetedge(newpt, &starttet, flipque);
29179
29180 flip(flipque, NULL);
29181
29182 if (!optflag) {
29183
29184 for (i = 0; i < 2; i++) {
29185 if (!shell2badface(*splitseg)) {
29186 checkseg4encroach(splitseg, NULL, NULL, true);
29187 }
29188 if (i == 1) break;
29189 senextself(*splitseg);
29190 spivotself(*splitseg);
29191 #ifdef SELF_CHECK
29192 assert(splitseg->sh != (shellface *) NULL);
29193 #endif
29194 splitseg->shver = 0;
29195 }
29196
29197 if (chkencsub) {
29198 spivot(*splitseg, startsh);
29199 spinsh = startsh;
29200 do {
29201 sublist->append(&spinsh);
29202 formstarpolygon(newpt, sublist, verlist);
29203 for (i = 0; i < sublist->len(); i++) {
29204 checksh = * (face *)(* sublist)[i];
29205 if (!shell2badface(checksh)) {
29206 checksub4encroach(&checksh, NULL, true);
29207 }
29208 }
29209 sublist->clear();
29210 if (verlist) verlist->clear();
29211 spivotself(spinsh);
29212 } while (spinsh.sh != startsh.sh);
29213 }
29214 }
29215
29216
29217 sstpivot(splitseg, &starttet);
29218 tetlist->append(&starttet);
29219 formstarpolyhedron(newpt, tetlist, verlist, true);
29220
29221 if (!optflag) {
29222
29223 tallencsegs(newpt, 1, &tetlist);
29224 if (chkencsub) {
29225
29226 tallencsubs(newpt, 1, &tetlist);
29227 }
29228 if (chkbadtet) {
29229
29230 for (i = 0; i < tetlist->len(); i++) {
29231 starttet = * (triface *)(* tetlist)[i];
29232 checktet4badqual(&starttet, true);
29233 }
29234 }
29235 tetlist->clear();
29236 } else {
29237
29238 for (i = 0; i < tetlist->len(); i++) {
29239 starttet = * (triface *)(* tetlist)[i];
29240 checktet4opt(&starttet, true);
29241 }
29242 delete mytetlist;
29243 delete myflipque;
29244 }
29245 }
29246
29248
29249
29250
29251
29252
29253
29254
29255
29256
29257
29259
29260 bool tetgenmesh::tallencsegs(point testpt, int n, list **ceillists)
29261 {
29262 list *ceillist;
29263 triface ceiltet;
29264 face checkseg;
29265 long oldencnum;
29266 int i, j, k;
29267
29268
29269 oldencnum = badsubsegs->items;
29270
29271 if (ceillists != (list **) NULL) {
29272 for (k = 0; k < n; k++) {
29273 ceillist = ceillists[k];
29274
29275 for (i = 0; i < ceillist->len(); i++) {
29276 ceiltet = * (triface *)(* ceillist)[i];
29277 ceiltet.ver = 0;
29278 for (j = 0; j < 3; j++) {
29279 tsspivot(&ceiltet, &checkseg);
29280 if (checkseg.sh != dummysh) {
29281
29282 if (!shell2badface(checkseg)) {
29283 checkseg4encroach(&checkseg, testpt, NULL, true);
29284 }
29285 }
29286 enextself(ceiltet);
29287 }
29288 }
29289 }
29290 } else {
29291
29292 subsegs->traversalinit();
29293 checkseg.sh = shellfacetraverse(subsegs);
29294 while (checkseg.sh != (shellface *) NULL) {
29295
29296 if (!shell2badface(checkseg)) {
29297 checkseg4encroach(&checkseg, testpt, NULL, true);
29298 }
29299 checkseg.sh = shellfacetraverse(subsegs);
29300 }
29301 }
29302
29303 return (badsubsegs->items > oldencnum);
29304 }
29305
29307
29308
29309
29310
29311
29312
29313
29314
29315
29316
29318
29319 bool tetgenmesh::tallencsubs(point testpt, int n, list** ceillists)
29320 {
29321 list *ceillist;
29322 triface ceiltet;
29323 face checksh;
29324 long oldencnum;
29325 int i, k;
29326
29327
29328 oldencnum = badsubfaces->items;
29329
29330 if (ceillists != (list **) NULL) {
29331 for (k = 0; k < n; k++) {
29332 ceillist = ceillists[k];
29333
29334 for (i = 0; i < ceillist->len(); i++) {
29335 ceiltet = * (triface *)(* ceillist)[i];
29336 tspivot(ceiltet, checksh);
29337 if (checksh.sh != dummysh) {
29338
29339 if (!shell2badface(checksh)) {
29340 checksub4encroach(&checksh, testpt, true);
29341 }
29342 }
29343 }
29344 }
29345 } else {
29346
29347 subfaces->traversalinit();
29348 checksh.sh = shellfacetraverse(subfaces);
29349 while (checksh.sh != (shellface *) NULL) {
29350
29351 if (!shell2badface(checksh)) {
29352 checksub4encroach(&checksh, testpt, true);
29353 }
29354 checksh.sh = shellfacetraverse(subfaces);
29355 }
29356 }
29357
29358 return (badsubfaces->items > oldencnum);
29359 }
29360
29362
29363
29364
29366
29367 void tetgenmesh::tallbadtetrahedrons()
29368 {
29369 triface tetloop;
29370
29371 tetrahedrons->traversalinit();
29372 tetloop.tet = tetrahedrontraverse();
29373 while (tetloop.tet != (tetrahedron *) NULL) {
29374 checktet4badqual(&tetloop, true);
29375 tetloop.tet = tetrahedrontraverse();
29376 }
29377 }
29378
29380
29381
29382
29383
29384
29385
29386
29387
29388
29389
29390
29392
29393 void tetgenmesh::repairencsegs(bool chkencsub, bool chkbadtet)
29394 {
29395 list **tetlists, **ceillists;
29396 list **sublists, **subceillists;
29397 list *tetlist, *sublist;
29398 queue *flipque;
29399 badface *encloop;
29400 face splitseg, symsplitseg;
29401 point newpt, sympt, refpt;
29402 point e1, e2;
29403 enum locateresult symloc;
29404 int nmax, n, i, j;
29405
29406 ceillists = NULL;
29407 flipque = NULL;
29408 subceillists = NULL;
29409 sublist = NULL;
29410 sublists = NULL;
29411 tetlist = NULL;
29412 tetlists = NULL;
29413
29414 n = 0;
29415 nmax = 128;
29416 if (!b->fliprepair) {
29417 tetlists = new list*[nmax];
29418 ceillists = new list*[nmax];
29419 sublists = new list*[nmax];
29420 subceillists = new list*[nmax];
29421 } else {
29422 tetlist = new list(sizeof(triface), NULL, 1024);
29423 sublist = new list(sizeof(face), NULL, 256);
29424 flipque = new queue(sizeof(badface));
29425 }
29426
29427
29428
29429 while ((badsubsegs->items > 0) && (steinerleft != 0)) {
29430 badsubsegs->traversalinit();
29431 encloop = badfacetraverse(badsubsegs);
29432 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
29433
29434 splitseg = encloop->ss;
29435
29436 setshell2badface(splitseg, NULL);
29437 if ((sorg(splitseg) == encloop->forg) &&
29438 (sdest(splitseg) == encloop->fdest)) {
29439 if (b->verbose > 1) {
29440 printf(" Get an enc-seg (%d, %d)\n", pointmark(encloop->forg),
29441 pointmark(encloop->fdest));
29442 }
29443 refpt = (point) NULL;
29444 if (b->conformdel) {
29445
29446 checkseg4encroach(&splitseg, NULL, &refpt, false);
29447 }
29448
29449 makepoint(&newpt);
29450 getsplitpoint(encloop->forg, encloop->fdest, refpt, newpt);
29451 setpointtype(newpt, FREESEGVERTEX);
29452 setpoint2sh(newpt, sencode(splitseg));
29453
29454 if (acceptsegpt(newpt, refpt, &splitseg)) {
29455
29456 if (checkpbcs) {
29457
29458 i = shellmark(splitseg) - 1;
29459 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
29460 makepoint(&sympt);
29461 symloc = getsegpbcsympoint(newpt, &splitseg, sympt, &symsplitseg,
29462 segpglist[j]);
29463 if (symloc == ONEDGE) {
29464 if (symsplitseg.sh != splitseg.sh) {
29465
29466 setpointtype(sympt, FREESEGVERTEX);
29467 setpoint2sh(sympt, sencode(symsplitseg));
29468
29469 e1 = sorg(symsplitseg);
29470 if (shelltype(symsplitseg) == SHARP) {
29471 e2 = sdest(symsplitseg);
29472 } else {
29473 e2 = (point) NULL;
29474 }
29475 if (!b->fliprepair) {
29476
29477 formbowatcavity(sympt, &symsplitseg, NULL, &n, &nmax,
29478 sublists, subceillists, tetlists, ceillists);
29479
29480 if (trimbowatcavity(sympt, &symsplitseg, n, sublists,
29481 subceillists, tetlists, ceillists, -1.0)) {
29482 bowatinsertsite(sympt, &symsplitseg, n, sublists,
29483 subceillists, tetlists, ceillists, NULL, flipque,
29484 true, chkencsub, chkbadtet);
29485 setnewpointsize(sympt, e1, e2);
29486 if (steinerleft > 0) steinerleft--;
29487 } else {
29488
29489 pointdealloc(sympt);
29490 }
29491
29492 releasebowatcavity(&symsplitseg, n, sublists, subceillists,
29493 tetlists, ceillists);
29494 } else {
29495 splitencseg(sympt, &symsplitseg, tetlist, sublist, NULL,
29496 flipque, chkencsub, chkbadtet, false);
29497 setnewpointsize(sympt, e1, e2);
29498 if (steinerleft > 0) steinerleft--;
29499 }
29500 } else {
29501
29502
29503 pointdealloc(sympt);
29504 }
29505 } else if (symloc == ONVERTEX) {
29506
29507
29508 pointdealloc(sympt);
29509 } else {
29510
29511
29512 pointdealloc(sympt);
29513 }
29514 }
29515 }
29516
29517 e1 = sorg(splitseg);
29518 if (shelltype(splitseg) == SHARP) {
29519 e2 = sdest(splitseg);
29520 } else {
29521 e2 = (point) NULL;
29522 }
29523 if (!b->fliprepair) {
29524
29525 formbowatcavity(newpt, &splitseg, NULL, &n, &nmax, sublists,
29526 subceillists, tetlists, ceillists);
29527
29528 if (trimbowatcavity(newpt, &splitseg, n, sublists, subceillists,
29529 tetlists, ceillists, -1.0)) {
29530 bowatinsertsite(newpt, &splitseg, n, sublists, subceillists,
29531 tetlists, ceillists, NULL, flipque, true,
29532 chkencsub, chkbadtet);
29533 setnewpointsize(newpt, e1, e2);
29534 if (steinerleft > 0) steinerleft--;
29535 } else {
29536
29537 pointdealloc(newpt);
29538 }
29539
29540 releasebowatcavity(&splitseg, n, sublists, subceillists, tetlists,
29541 ceillists);
29542 } else {
29543 splitencseg(newpt, &splitseg, tetlist, sublist, NULL, flipque,
29544 chkencsub, chkbadtet, false);
29545 setnewpointsize(newpt, e1, e2);
29546 if (steinerleft > 0) steinerleft--;
29547 }
29548 } else {
29549
29550 pointdealloc(newpt);
29551 }
29552 }
29553 badfacedealloc(badsubsegs, encloop);
29554 encloop = badfacetraverse(badsubsegs);
29555 }
29556 }
29557
29558 if (!b->fliprepair) {
29559 delete [] tetlists;
29560 delete [] ceillists;
29561 delete [] sublists;
29562 delete [] subceillists;
29563 } else {
29564 delete tetlist;
29565 delete sublist;
29566 delete flipque;
29567 }
29568 }
29569
29571
29572
29573
29574
29575
29576
29577
29578
29579
29580
29582
29583 void tetgenmesh::repairencsubs(bool chkbadtet)
29584 {
29585 list *tetlists[2], *ceillists[2];
29586 list *sublist, *subceillist;
29587 list *verlist;
29588 badface *encloop;
29589 face splitsub, symsplitsub;
29590 point newpt, sympt, e1;
29591 enum locateresult loc, symloc;
29592 bool reject;
29593 long oldptnum;
29594 int quenumber, n, i;
29595
29596 quenumber = 0;
29597 n = 0;
29598 sublist = (list *) NULL;
29599 subceillist = (list *) NULL;
29600 verlist = new list(sizeof(point *), NULL, 256);
29601
29602
29603
29604 while ((badsubfaces->items > 0) && (steinerleft != 0)) {
29605
29606 encloop = dequeueencsub(&quenumber);
29607 splitsub = encloop->ss;
29608
29609 setshell2badface(splitsub, NULL);
29610
29611 if (!isdead(&splitsub)
29612 && (sorg(splitsub) == encloop->forg)
29613 && (sdest(splitsub) == encloop->fdest)
29614 && (sapex(splitsub) == encloop->fapex)) {
29615 if (b->verbose > 1) {
29616 printf(" Dequeuing ensub (%d, %d, %d) [%d].\n",
29617 pointmark(encloop->forg), pointmark(encloop->fdest),
29618 pointmark(encloop->fapex), quenumber);
29619 }
29620
29621 makepoint(&newpt);
29622 for (i = 0; i < 3; i++) newpt[i] = encloop->cent[i];
29623 setpointtype(newpt, FREESUBVERTEX);
29624 setpoint2sh(newpt, sencode(splitsub));
29625
29626 abovepoint = facetabovepointarray[shellmark(splitsub)];
29627 if (abovepoint == (point) NULL) {
29628 getfacetabovepoint(&splitsub);
29629 }
29630
29631
29632 loc = locatesub(newpt, &splitsub, 1, b->epsilon * 1e+2);
29633 if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29634
29635 formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29636 &subceillist, tetlists, ceillists);
29637
29638 reject = tallencsegs(newpt, 2, ceillists);
29639
29640 if (!reject) {
29641 reject = !acceptfacpt(newpt, subceillist, verlist);
29642 }
29643 if (!reject) {
29644
29645 reject = !trimbowatcavity(newpt, NULL, n, &sublist, &subceillist,
29646 tetlists, ceillists, -1.0);
29647 }
29648 if (!reject) {
29649
29650
29651
29652
29653 reject = !sinfected(encloop->ss);
29654 }
29655 if (!reject) {
29656 if (checkpbcs) {
29657 if (shellpbcgroup(splitsub) >= 0) {
29658
29659 makepoint(&sympt);
29660 symloc = getsubpbcsympoint(newpt,&splitsub,sympt,&symsplitsub);
29661 if (symloc != ONVERTEX) {
29662
29663 releasebowatcavity(NULL, 2, &sublist, &subceillist, tetlists,
29664 ceillists);
29665
29666 formbowatcavity(sympt, NULL, &symsplitsub, &n, NULL, &sublist,
29667 &subceillist, tetlists, ceillists);
29668 reject = tallencsegs(sympt, 2, ceillists);
29669 if (!reject) {
29670 reject = !acceptfacpt(sympt, subceillist, verlist);
29671 }
29672 if (!reject) {
29673 reject = !trimbowatcavity(sympt,NULL,n,&sublist,&subceillist,
29674 tetlists, ceillists, -1.0);
29675 }
29676 if (!reject) {
29677
29678 setpoint2pbcpt(newpt, sympt);
29679 setpoint2pbcpt(sympt, newpt);
29680 setpointtype(sympt, FREESUBVERTEX);
29681 setpoint2sh(sympt, sencode(symsplitsub));
29682
29683 e1 = sorg(symsplitsub);
29684 bowatinsertsite(sympt, NULL, n, &sublist, &subceillist,
29685 tetlists,ceillists,NULL,NULL,false,true,chkbadtet);
29686 setnewpointsize(sympt, e1, NULL);
29687 if (steinerleft > 0) steinerleft--;
29688
29689 releasebowatcavity(NULL, n, &sublist, &subceillist, tetlists,
29690 ceillists);
29691 } else {
29692
29693
29694
29695
29696 pointdealloc(sympt);
29697
29698 }
29699 } else {
29700
29701 pointdealloc(sympt);
29702
29703 reject = true;
29704 }
29705 }
29706 }
29707 }
29708 if (!reject) {
29709
29710 if (checkpbcs) {
29711 if (shellpbcgroup(splitsub) >= 0) {
29712
29713 formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29714 &subceillist, tetlists, ceillists);
29715 trimbowatcavity(newpt, NULL, n, &sublist, &subceillist, tetlists,
29716 ceillists, -1.0);
29717 }
29718 }
29719
29720 e1 = sorg(splitsub);
29721 bowatinsertsite(newpt, NULL, n, &sublist, &subceillist, tetlists,
29722 ceillists, NULL, NULL, true, true, chkbadtet);
29723 setnewpointsize(newpt, e1, NULL);
29724 if (steinerleft > 0) steinerleft--;
29725 } else {
29726
29727
29728
29729
29730
29731
29732 pointdealloc(newpt);
29733 }
29734
29735 releasebowatcavity(NULL,n,&sublist,&subceillist,tetlists,ceillists);
29736 if (reject) {
29737
29738 if (badsubsegs->items > 0) {
29739
29740 oldptnum = points->items;
29741 repairencsegs(true, chkbadtet);
29742 if (points->items > oldptnum) {
29743
29744 splitsub = encloop->ss;
29745 if (!isdead(&splitsub)) {
29746 if (!shell2badface(splitsub)) {
29747 checksub4encroach(&splitsub, NULL, true);
29748 }
29749 }
29750 }
29751 }
29752 }
29753 } else {
29754
29755
29756
29757
29758
29759
29760
29761
29762
29763 if (loc == ONVERTEX) {
29764 printf("Internal error in repairencsubs():\n");
29765 printf(" During repairing encroached subface (%d, %d, %d)\n",
29766 pointmark(encloop->forg), pointmark(encloop->fdest),
29767 pointmark(encloop->fapex));
29768 printf(" New point %d is coincident with an existing vertex %d\n",
29769 pointmark(newpt), pointmark(sorg(splitsub)));
29770 internalerror();
29771 }
29772
29773
29774
29775 pointdealloc(newpt);
29776 }
29777 } else {
29778 if (!isdead(&splitsub)) {
29779
29780 checksub4encroach(&splitsub, NULL, true);
29781 }
29782 }
29783
29784 badfacedealloc(badsubfaces, encloop);
29785 }
29786
29787 delete verlist;
29788 }
29789
29791
29792
29793
29794
29795
29796
29797
29798
29799
29801
29802 void tetgenmesh::repairbadtets()
29803 {
29804 list *tetlist, *ceillist;
29805 list *verlist;
29806 badface *badtet;
29807 triface starttet;
29808 point newpt, e1;
29809 enum locateresult loc;
29810 bool reject;
29811 long oldptnum;
29812 int i;
29813
29814 tetlist = new list(sizeof(triface), NULL, 1024);
29815 ceillist = new list(sizeof(triface), NULL, 1024);
29816 verlist = new list(sizeof(point *), NULL, 256);
29817
29818
29819
29820 while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
29821
29822 badtet = topbadtetra();
29823
29824
29825 if ((badtet != (badface *) NULL) && !isdead(&badtet->tt)
29826 && org(badtet->tt) == badtet->forg
29827 && dest(badtet->tt) == badtet->fdest
29828 && apex(badtet->tt) == badtet->fapex
29829 && oppo(badtet->tt) == badtet->foppo) {
29830 if (b->verbose > 1) {
29831 printf(" Dequeuing btet (%d, %d, %d, %d).\n",
29832 pointmark(badtet->forg), pointmark(badtet->fdest),
29833 pointmark(badtet->fapex), pointmark(badtet->foppo));
29834 }
29835
29836 makepoint(&newpt);
29837 for (i = 0; i < 3; i++) newpt[i] = badtet->cent[i];
29838 setpointtype(newpt, FREEVOLVERTEX);
29839
29840 starttet = badtet->tt;
29841 loc = preciselocate(newpt, &starttet, tetrahedrons->items);
29842 if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29843
29844 infect(starttet);
29845 tetlist->append(&starttet);
29846 formbowatcavityquad(newpt, tetlist, ceillist);
29847
29848 reject = tallencsegs(newpt, 1, &ceillist);
29849 if (!reject) {
29850
29851 reject = tallencsubs(newpt, 1, &ceillist);
29852 }
29853
29854
29855 if (!reject) {
29856 reject = !acceptvolpt(newpt, ceillist, verlist);
29857 }
29858 if (!reject) {
29859 reject = !trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist,
29860 &ceillist, -1.0);
29861 }
29862 if (!reject) {
29863
29864
29865
29866
29867 reject = !infected(badtet->tt);
29868 if (reject) outbowatcircumcount++;
29869 }
29870 if (!reject) {
29871
29872 e1 = org(starttet);
29873
29874 bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist,
29875 NULL, NULL, false, false, true);
29876 setnewpointsize(newpt, e1, NULL);
29877 if (steinerleft > 0) steinerleft--;
29878 } else {
29879
29880
29881
29882
29883
29884
29885 pointdealloc(newpt);
29886
29887 for (i = 0; i < tetlist->len(); i++) {
29888 starttet = * (triface *)(* tetlist)[i];
29889 uninfect(starttet);
29890 }
29891 }
29892 tetlist->clear();
29893 ceillist->clear();
29894
29895 if (reject) {
29896 oldptnum = points->items;
29897 if (badsubsegs->items > 0) {
29898 repairencsegs(true, true);
29899 }
29900 if (badsubfaces->items > 0) {
29901 repairencsubs(true);
29902 }
29903 if (points->items > oldptnum) {
29904
29905
29906 starttet = badtet->tt;
29907 if (!isdead(&starttet)) {
29908 checktet4badqual(&starttet, true);
29909 }
29910 }
29911 }
29912 } else {
29913
29914
29915
29916
29917
29918
29919
29920
29921
29922 if (loc == ONVERTEX) {
29923 printf("Internal error in repairbadtets():\n");
29924 printf(" During repairing bad tet (%d, %d, %d, %d)\n",
29925 pointmark(badtet->forg), pointmark(badtet->fdest),
29926 pointmark(badtet->fapex), pointmark(badtet->foppo));
29927 printf(" New point %d is coincident with an existing vertex %d\n",
29928 pointmark(newpt), pointmark(org(starttet)));
29929 internalerror();
29930 }
29931
29932
29933
29934
29935 pointdealloc(newpt);
29936 }
29937 }
29938
29939 dequeuebadtet();
29940 }
29941
29942 delete tetlist;
29943 delete ceillist;
29944 delete verlist;
29945 }
29946
29948
29949
29950
29952
29953 void tetgenmesh::enforcequality()
29954 {
29955 long total, vertcount;
29956 int i;
29957
29958 if (!b->quiet) {
29959 printf("Adding Steiner points to enforce quality.\n");
29960 }
29961
29962 total = vertcount = 0l;
29963 if (b->conformdel) {
29964 r2count = r3count = 0l;
29965 }
29966
29967
29968 if (b->conformdel && b->refine) {
29969 markacutevertices(65.0);
29970 }
29971
29972 if (!b->metric) {
29973
29974 marksharpsegments(65.0);
29975
29976 decidefeaturepointsizes();
29977 }
29978
29979
29980 badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29981
29982 tallencsegs(NULL, 0, NULL);
29983 if (b->verbose && badsubsegs->items > 0) {
29984 printf(" Splitting encroached subsegments.\n");
29985 }
29986 vertcount = points->items;
29987
29988 repairencsegs(false, false);
29989 if (b->verbose > 0) {
29990 printf(" %ld split points.\n", points->items - vertcount);
29991 }
29992 total += points->items - vertcount;
29993
29994
29995 badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29996
29997 for (i = 0; i < 3; i++) subquefront[i] = (badface *) NULL;
29998 for (i = 0; i < 3; i++) subquetail[i] = &subquefront[i];
29999
30000 tallencsubs(NULL, 0, NULL);
30001 if (b->verbose && badsubfaces->items > 0) {
30002 printf(" Splitting encroached subfaces.\n");
30003 }
30004 vertcount = points->items;
30005
30006 repairencsubs(false);
30007 if (b->verbose > 0) {
30008 printf(" %ld split points.\n", points->items - vertcount);
30009 }
30010 total += points->items - vertcount;
30011
30012
30013
30014
30015 if ((b->minratio > 0.0) || b->varvolume || b->fixedvolume) {
30016
30017 badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30018
30019 for (i = 0; i < 64; i++) tetquefront[i] = (badface *) NULL;
30020 firstnonemptyq = -1;
30021 recentq = -1;
30022
30023 cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30024 cosmindihed = cos(b->mindihedral * PI / 180.0);
30025 tallbadtetrahedrons();
30026 if (b->verbose && badtetrahedrons->items > 0) {
30027 printf(" Splitting bad tetrahedra.\n");
30028 }
30029 vertcount = points->items;
30030 repairbadtets();
30031 if (b->verbose > 0) {
30032 printf(" %ld refinement points.\n", points->items - vertcount);
30033 }
30034 total += points->items - vertcount;
30035 delete badtetrahedrons;
30036 }
30037
30038 if (b->verbose > 0) {
30039 printf(" Totally added %ld points.\n", total);
30040 }
30041
30042 delete badsubfaces;
30043 delete badsubsegs;
30044 }
30045
30046
30047
30048
30049
30050
30051
30052
30053
30054 void tetgenmesh::dumpbadtets()
30055 {
30056 FILE *fout;
30057 badface *remtet;
30058
30059
30060 printf(" Writing bad tets to file bad-dump.lua.\n");
30061 fout = fopen("bad-dump.lua", "w");
30062 fprintf(fout, "-- %ld remaining bad tets (> %g degree).\n",
30063 badtetrahedrons->items, b->maxdihedral);
30064 badtetrahedrons->traversalinit();
30065 remtet = badfacetraverse(badtetrahedrons);
30066 while (remtet != (badface *) NULL) {
30067 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30068 dest(remtet->tt) == remtet->fdest &&
30069 apex(remtet->tt) == remtet->fapex &&
30070 oppo(remtet->tt) == remtet->foppo) {
30071 fprintf(fout, "p:draw_tet(%d, %d, %d, %d) -- %g\n",
30072 pointmark(remtet->forg), pointmark(remtet->fdest),
30073 pointmark(remtet->fapex), pointmark(remtet->foppo),
30074 acos(remtet->key) * 180.0 / PI);
30075 }
30076 remtet = badfacetraverse(badtetrahedrons);
30077 }
30078 fclose(fout);
30079 }
30080
30082
30083
30084
30085
30086
30087
30088
30089
30090
30092
30093 bool tetgenmesh::checktet4ill(triface* testtet, bool enqflag)
30094 {
30095 badface *newbadtet;
30096 triface checktet;
30097 face checksh1, checksh2;
30098 face checkseg;
30099 bool illflag;
30100 int i;
30101
30102 illflag = false;
30103 for (testtet->loc = 0; testtet->loc < 4; testtet->loc++) {
30104 tspivot(*testtet, checksh1);
30105 if (checksh1.sh != dummysh) {
30106 testtet->ver = 0;
30107 findedge(&checksh1, org(*testtet), dest(*testtet));
30108 for (i = 0; i < 3; i++) {
30109 fnext(*testtet, checktet);
30110 tspivot(checktet, checksh2);
30111 if (checksh2.sh != dummysh) {
30112
30113 sspivot(checksh1, checkseg);
30114 if (checkseg.sh == dummysh) {
30115
30116
30117 enextfnextself(*testtet);
30118 enextself(*testtet);
30119 illflag = true;
30120 break;
30121 }
30122 }
30123 enextself(*testtet);
30124 senextself(checksh1);
30125 }
30126 }
30127 if (illflag) break;
30128 }
30129
30130 if (illflag && enqflag) {
30131
30132 newbadtet = (badface *) badtetrahedrons->alloc();
30133 newbadtet->tt = *testtet;
30134 newbadtet->key = -1.0;
30135 for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
30136 newbadtet->forg = org(*testtet);
30137 newbadtet->fdest = dest(*testtet);
30138 newbadtet->fapex = apex(*testtet);
30139 newbadtet->foppo = oppo(*testtet);
30140 newbadtet->nextitem = (badface *) NULL;
30141 if (b->verbose > 2) {
30142 printf(" Queueing illtet: (%d, %d, %d, %d).\n",
30143 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30144 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo));
30145 }
30146 }
30147
30148 return illflag;
30149 }
30150
30152
30153
30154
30155
30156
30157
30158
30159
30160
30161
30162
30163
30164
30165
30166
30168
30169 bool tetgenmesh::checktet4opt(triface* testtet, bool enqflag)
30170 {
30171 badface *newbadtet;
30172 point pa, pb, pc, pd;
30173 REAL N[4][3], len;
30174 REAL cosd;
30175 bool enq;
30176 int i, j;
30177
30178 cosd = 0.0;
30179 enq = false;
30180 pa = (point) testtet->tet[4];
30181 pb = (point) testtet->tet[5];
30182 pc = (point) testtet->tet[6];
30183 pd = (point) testtet->tet[7];
30184
30185 tetallnormal(pa, pb, pc, pd, N, NULL);
30186
30187 for (i = 0; i < 4; i++) {
30188 len = sqrt(dot(N[i], N[i]));
30189 if (len != 0.0) {
30190 for (j = 0; j < 3; j++) N[i][j] /= len;
30191 }
30192 }
30193
30194 for (i = 0; i < 6; i++) {
30195
30196 testtet->loc = 0;
30197 testtet->ver = 0;
30198 switch (i) {
30199 case 0:
30200 cosd = -dot(N[2], N[3]);
30201 break;
30202 case 1:
30203 enextfnextself(*testtet);
30204 enextself(*testtet);
30205 cosd = -dot(N[0], N[1]);
30206 break;
30207 case 2:
30208 enextfnextself(*testtet);
30209 enext2self(*testtet);
30210 cosd = -dot(N[0], N[2]);
30211 break;
30212 case 3:
30213 enextself(*testtet);
30214 cosd = -dot(N[0], N[3]);
30215 break;
30216 case 4:
30217 enext2fnextself(*testtet);
30218 enextself(*testtet);
30219 cosd = -dot(N[1], N[2]);
30220 break;
30221 case 5:
30222 enext2self(*testtet);
30223 cosd = -dot(N[1], N[3]);
30224 break;
30225 }
30226 if (cosd < cosmaxdihed) {
30227
30228 if (enqflag) {
30229
30230 newbadtet = (badface *) badtetrahedrons->alloc();
30231 newbadtet->tt = *testtet;
30232 newbadtet->key = cosd;
30233 for (j = 0; j < 3; j++) newbadtet->cent[j] = 0.0;
30234 newbadtet->forg = org(*testtet);
30235 newbadtet->fdest = dest(*testtet);
30236 newbadtet->fapex = apex(*testtet);
30237 newbadtet->foppo = oppo(*testtet);
30238 newbadtet->nextitem = (badface *) NULL;
30239 if (b->verbose > 2) {
30240 printf(" Queueing tet: (%d, %d, %d, %d), dihed %g (degree).\n",
30241 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30242 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
30243 acos(cosd) * 180.0 / PI);
30244 }
30245 }
30246 enq = true;
30247 }
30248 }
30249
30250 return enq;
30251 }
30252
30254
30255
30256
30257
30258
30259
30260
30261
30262
30263
30264
30265
30266
30267
30268
30269
30270
30271
30272
30273
30275
30276 bool tetgenmesh::removeedge(badface* remedge, bool optflag)
30277 {
30278 triface abcd, badc;
30279 triface baccasing, abdcasing;
30280 triface abtetlist[11];
30281 triface bftetlist[11];
30282 triface newtetlist[33];
30283 face checksh;
30284 enum fliptype fty;
30285 REAL key;
30286 bool remflag, subflag;
30287 int n, n1, m, i, j;
30288
30289
30290
30291 abcd = remedge->tt;
30292 adjustedgering(abcd, CCW);
30293 i = 0;
30294 do {
30295 sym(abcd, baccasing);
30296
30297 if (baccasing.tet == dummytet) {
30298 fnext(abcd, badc);
30299 sym(badc, abdcasing);
30300 if (abdcasing.tet == dummytet) {
30301
30302 if (removetetbypeeloff(&abcd)) {
30303 if (b->verbose > 1) {
30304 printf(" Stripped tet from the mesh.\n");
30305 }
30306 optcount[0]++;
30307 return true;
30308 }
30309 }
30310 }
30311
30312 enext2fnextself(abcd);
30313 enext2self(abcd);
30314 esymself(abcd);
30315 i++;
30316 } while (i < 2);
30317
30318
30319 subflag = false;
30320 abcd = remedge->tt;
30321 adjustedgering(abcd, CW);
30322 n = 0;
30323 abtetlist[n] = abcd;
30324 do {
30325
30326 if (n == 10) break;
30327
30328 tspivot(abtetlist[n], checksh);
30329 if (checksh.sh != dummysh) {
30330
30331
30332 subflag = true; break;
30333 }
30334
30335 fnext(abtetlist[n], abtetlist[n + 1]);
30336 n++;
30337 } while (apex(abtetlist[n]) != apex(abcd));
30338
30339 remflag = false;
30340 key = remedge->key;
30341
30342 if (subflag && optflag) {
30343 abcd = remedge->tt;
30344 adjustedgering(abcd, CCW);
30345
30346 for (j = 0; j < 2; j++) {
30347 if (j == 0) {
30348 enext2fnext(abcd, abtetlist[0]);
30349 } else {
30350 enextfnext(abcd, abtetlist[0]);
30351 }
30352 fty = categorizeface(abtetlist[0]);
30353 if (fty == T23) {
30354
30355 sym(abtetlist[0], abtetlist[1]);
30356 assert(abtetlist[1].tet != dummytet);
30357 n = 2;
30358 m = 3;
30359 remflag = removefacebyflip23(&key, abtetlist, newtetlist, NULL);
30360 } else if (fty == T22) {
30361
30362 n = 2;
30363 newtetlist[0] = abtetlist[0];
30364 adjustedgering(newtetlist[0], CW);
30365 fnext(newtetlist[0], newtetlist[1]);
30366 assert(newtetlist[1].tet != dummytet);
30367
30368 if (fnext(newtetlist[1], newtetlist[2])) {
30369 fnext(newtetlist[2], newtetlist[3]);
30370 assert(newtetlist[3].tet != dummytet);
30371 n = 4;
30372 }
30373 m = n;
30374 remflag = removeedgebyflip22(&key, n, newtetlist, NULL);
30375 }
30376
30377 if (remflag) {
30378 if (b->verbose > 1) {
30379 printf(" Done flip %d-to-%d. Qual: %g -> %g.\n", n, m,
30380 acos(remedge->key) / PI * 180.0, acos(key) / PI * 180.0);
30381 }
30382
30383 if (m == 3) {
30384 for (i = 0; i < n; i++) {
30385 tetrahedrondealloc(abtetlist[i].tet);
30386 }
30387 }
30388 for (i = 0; i < m; i++) {
30389 checktet4opt(&(newtetlist[i]), true);
30390 }
30391 optcount[1]++;
30392 return true;
30393 }
30394 }
30395
30396 return false;
30397 }
30398
30399
30400 if (n == 3) {
30401
30402 remflag = removeedgebyflip32(&key, abtetlist, newtetlist, NULL);
30403 } else if ((n == 4) || (n == 5) || (n == 6)) {
30404
30405 remflag = removeedgebytranNM(&key,n,abtetlist,newtetlist,NULL,NULL,NULL);
30406 } else {
30407 if (b->verbose > 1) {
30408 printf(" !! Unhandled case: n = %d.\n", n);
30409 }
30410 }
30411 if (remflag) {
30412 optcount[n]++;
30413
30414 for (i = 0; i < n; i++) {
30415 tetrahedrondealloc(abtetlist[i].tet);
30416 }
30417 m = (n - 2) * 2;
30418 if (b->verbose > 1) {
30419 printf(" Done flip %d-to-%d. ", n, m);
30420 if (optflag) {
30421 printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30422 acos(key) / PI * 180.0);
30423 }
30424 printf("\n");
30425 }
30426 }
30427
30428 if (!remflag && (key == remedge->key) && (n < 7)) {
30429
30430 n1 = 0;
30431 remflag = removeedgebycombNM(&key, n, abtetlist, &n1, bftetlist,
30432 newtetlist, NULL);
30433 if (remflag) {
30434 optcount[9]++;
30435
30436 for (i = 0; i < n; i++) {
30437 tetrahedrondealloc(abtetlist[i].tet);
30438 }
30439 for (i = 0; i < n1; i++) {
30440 if (!isdead(&(bftetlist[i]))) {
30441 tetrahedrondealloc(bftetlist[i].tet);
30442 }
30443 }
30444 m = ((n1 - 2) * 2 - 1) + (n - 3) * 2;
30445 if (b->verbose > 1) {
30446 printf(" Done flip %d-to-%d (n-1=%d, n1=%d). ", n+n1-2, m, n-1,n1);
30447 if (optflag) {
30448 printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30449 acos(key) / PI * 180.0);
30450 }
30451 printf("\n");
30452 }
30453 }
30454 }
30455
30456 if (remflag) {
30457
30458 for (i = 0; i < m; i++) {
30459 if (optflag) {
30460 checktet4opt(&(newtetlist[i]), true);
30461 } else {
30462 checktet4ill(&(newtetlist[i]), true);
30463 }
30464 }
30465 }
30466
30467 return remflag;
30468 }
30469
30471
30472
30473
30474
30475
30476
30478
30479 bool tetgenmesh::smoothsliver(badface* remedge, list *starlist)
30480 {
30481 triface checktet;
30482 point smthpt;
30483 bool smthed;
30484 int idx, i, j;
30485
30486
30487 smthed = false;
30488 for (i = 0; i < 4 && !smthed; i++) {
30489 smthpt = (point) remedge->tt.tet[4 + i];
30490
30491 if (pointtype(smthpt) == FREEVOLVERTEX) {
30492
30493 idx = pointmark(smthpt) - in->firstnumber;
30494 if (!(idx < in->numberofpoints)) {
30495
30496 starlist->append(&(remedge->tt.tet));
30497 formstarpolyhedron(smthpt, starlist, NULL, false);
30498 smthed = smoothpoint(smthpt,NULL,NULL,starlist,false,&remedge->key);
30499
30500 if (smthed) {
30501 for (j = 0; j < starlist->len(); j++) {
30502 checktet = * (triface *)(* starlist)[j];
30503 checktet4opt(&checktet, true);
30504 }
30505 }
30506 starlist->clear();
30507 }
30508 }
30509 }
30510
30511
30512
30513
30514
30515
30516
30517
30518
30519
30520
30521
30522
30523
30524
30525
30526
30527
30528
30529
30530
30531
30532
30533
30534
30535
30536
30537
30538
30539
30540
30541
30542
30543
30544
30545
30546
30547
30548
30549
30550 return smthed;
30551 }
30552
30554
30555
30556
30557
30558
30559
30561
30562 bool tetgenmesh::splitsliver(badface *remedge, list *tetlist, list *ceillist)
30563 {
30564 triface starttet;
30565 face checkseg;
30566 point newpt, pt[4];
30567 bool remflag;
30568 int i;
30569
30570 starttet = remedge->tt;
30571
30572
30573 adjustedgering(starttet, CCW);
30574 enextfnextself(starttet);
30575 enextself(starttet);
30576 tsspivot(&starttet, &checkseg);
30577 if (b->nobisect == 0) {
30578 if (checkseg.sh != dummysh) {
30579
30580
30581 checkseg.shver = 0;
30582 pt[0] = sorg(checkseg);
30583 pt[1] = sdest(checkseg);
30584 makepoint(&newpt);
30585 getsplitpoint(pt[0], pt[1], NULL, newpt);
30586 setpointtype(newpt, FREESEGVERTEX);
30587 setpoint2sh(newpt, sencode(checkseg));
30588
30589 sstpivot(&checkseg, &starttet);
30590 splittetedge(newpt, &starttet, NULL);
30591
30592 sstpivot(&checkseg, &starttet);
30593 ceillist->append(&starttet);
30594 formstarpolyhedron(newpt, ceillist, NULL, true);
30595 setnewpointsize(newpt, pt[0], NULL);
30596 if (steinerleft > 0) steinerleft--;
30597
30598 smoothpoint(newpt, pt[0], pt[1], ceillist, false, NULL);
30599
30600 for (i = 0; i < ceillist->len(); i++) {
30601 starttet = * (triface *)(* ceillist)[i];
30602 checktet4opt(&starttet, true);
30603 }
30604 ceillist->clear();
30605 return true;
30606 }
30607 }
30608
30609
30610 for (i = 0; i < 4; i++) {
30611 pt[i] = (point) starttet.tet[4 + i];
30612 }
30613
30614 makepoint(&newpt);
30615 for (i = 0; i < 3; i++) {
30616 newpt[i] = 0.25 * (pt[0][i] + pt[1][i] + pt[2][i] + pt[3][i]);
30617 }
30618 setpointtype(newpt, FREEVOLVERTEX);
30619
30620
30621 remflag = false;
30622 infect(starttet);
30623 tetlist->append(&starttet);
30624 formbowatcavityquad(newpt, tetlist, ceillist);
30625 if (trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, -1.0)) {
30626
30627 if (smoothpoint( newpt, NULL, NULL, ceillist, false, &remedge->key)) {
30628
30629 bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, NULL,
30630 NULL, false, false, false);
30631 setnewpointsize(newpt, pt[0], NULL);
30632 if (steinerleft > 0) steinerleft--;
30633
30634 for (i = 0; i < ceillist->len(); i++) {
30635 starttet = * (triface *)(* ceillist)[i];
30636 checktet4opt(&starttet, true);
30637 }
30638 remflag = true;
30639 }
30640 }
30641
30642 if (!remflag) {
30643
30644 pointdealloc(newpt);
30645
30646 for (i = 0; i < tetlist->len(); i++) {
30647 starttet = * (triface *)(* tetlist)[i];
30648 uninfect(starttet);
30649 }
30650 }
30651 tetlist->clear();
30652 ceillist->clear();
30653
30654 return remflag;
30655 }
30656
30658
30659
30660
30662
30663 void tetgenmesh::tallslivers(bool optflag)
30664 {
30665 triface tetloop;
30666
30667 tetrahedrons->traversalinit();
30668 tetloop.tet = tetrahedrontraverse();
30669 while (tetloop.tet != (tetrahedron *) NULL) {
30670 if (optflag) {
30671 checktet4opt(&tetloop, true);
30672 } else {
30673 checktet4ill(&tetloop, true);
30674 }
30675 tetloop.tet = tetrahedrontraverse();
30676 }
30677 }
30678
30680
30681
30682
30683
30684
30685
30686
30687
30688
30689
30690
30692
30693 void tetgenmesh::optimizemesh(bool optflag)
30694 {
30695 list *splittetlist, *tetlist, *ceillist;
30696 badface *remtet, *lastentry;
30697
30698 REAL objdihed, curdihed;
30699 long oldnum;
30700 int iter, i;
30701
30702 objdihed = 0.0;
30703
30704 if (!b->quiet) {
30705 if (optflag) {
30706 printf("Optimizing mesh.\n");
30707 } else {
30708 printf("Repairing mesh.\n");
30709 }
30710 }
30711
30712 #ifdef SELF_CHECK
30713 if (optflag && (b->verbose)) {
30714 printf(" level = %d.\n", b->optlevel);
30715 }
30716 #endif
30717
30718
30719 badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30720 if (optflag) {
30721 cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30722 cosmindihed = cos(b->mindihedral * PI / 180.0);
30723
30724
30725
30726 objdihed = b->maxdihedral + 5.0;
30727 if (objdihed < 170.0) objdihed = 170.0;
30728 objdihed = objdihed / 180.0 * PI;
30729 }
30730
30731 tallslivers(optflag);
30732
30733 optcount[0] = 0l;
30734 optcount[1] = 0l;
30735 optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l;
30736 optcount[9] = 0l;
30737
30738
30739 lastentry = (badface *) NULL;
30740
30741 while (badtetrahedrons->items > 0) {
30742 badtetrahedrons->traversalinit();
30743 remtet = badfacetraverse(badtetrahedrons);
30744 while (remtet != (badface *) NULL) {
30745
30746
30747 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30748 dest(remtet->tt) == remtet->fdest &&
30749 apex(remtet->tt) == remtet->fapex &&
30750 oppo(remtet->tt) == remtet->foppo) {
30751 if (b->verbose > 1) {
30752 printf(" Repair tet (%d, %d, %d, %d) %g (degree).\n",
30753 pointmark(remtet->forg), pointmark(remtet->fdest),
30754 pointmark(remtet->fapex), pointmark(remtet->foppo),
30755 acos(remtet->key) / PI * 180.0);
30756 }
30757 if (!removeedge(remtet, optflag)) {
30758
30759 if (lastentry != (badface *) NULL) {
30760 if (remtet == lastentry) break;
30761 } else {
30762
30763 lastentry = remtet;
30764 }
30765 } else {
30766
30767 lastentry = (badface *) NULL;
30768
30769 badfacedealloc(badtetrahedrons, remtet);
30770 }
30771 } else {
30772
30773 badfacedealloc(badtetrahedrons, remtet);
30774 }
30775 remtet = badfacetraverse(badtetrahedrons);
30776 }
30777
30778 if (remtet != (badface *) NULL) break;
30779 }
30780
30781 if (b->verbose) {
30782 if (optcount[0] > 0l) {
30783 printf(" %ld tets are peeled off.\n", optcount[0]);
30784 }
30785 if (optcount[1] > 0l) {
30786 printf(" %ld faces are flipped.\n", optcount[1]);
30787 }
30788 if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30789 optcount[9] > 0l) {
30790 printf(" %ld edges are flipped.\n", optcount[3] + optcount[4] +
30791 optcount[5] + optcount[6] + optcount[9]);
30792 }
30793
30794
30795
30796 }
30797
30798 if ((badtetrahedrons->items > 0l) && optflag && (b->optlevel > 2)) {
30799 splittetlist = new list(sizeof(badface), NULL, 256);
30800 tetlist = new list(sizeof(triface), NULL, 256);
30801 ceillist = new list(sizeof(triface), NULL, 256);
30802 oldnum = points->items;
30803 smoothsegverts = smoothvolverts = 0;
30804 optcount[1] = 0l;
30805 optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l;
30806 optcount[9] = 0l;
30807 iter = 0;
30808
30809 do {
30810
30811 badtetrahedrons->traversalinit();
30812 remtet = badfacetraverse(badtetrahedrons);
30813 while (remtet != (badface *) NULL) {
30814 splittetlist->append(remtet);
30815
30816 badfacedealloc(badtetrahedrons, remtet);
30817 remtet = badfacetraverse(badtetrahedrons);
30818 }
30819 for (i = 0; i < splittetlist->len(); i++) {
30820 remtet = (badface *)(* splittetlist)[i];
30821
30822
30823 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30824 dest(remtet->tt) == remtet->fdest &&
30825 apex(remtet->tt) == remtet->fapex &&
30826 oppo(remtet->tt) == remtet->foppo) {
30827
30828 curdihed = facedihedral(remtet->forg, remtet->fdest, remtet->fapex,
30829 remtet->foppo);
30830
30831 if (curdihed > PI) curdihed = 2 * PI - curdihed;
30832
30833 if (curdihed > objdihed) {
30834 remtet->key = cos(curdihed);
30835 if (b->verbose > 1) {
30836 printf(" Get sliver (%d, %d, %d, %d) %g (degree).\n",
30837 pointmark(remtet->forg), pointmark(remtet->fdest),
30838 pointmark(remtet->fapex), pointmark(remtet->foppo),
30839 acos(remtet->key) / PI * 180.0);
30840 }
30841 if (!removeedge(remtet, optflag)) {
30842 if (!smoothsliver(remtet, tetlist)) {
30843 splitsliver(remtet, tetlist, ceillist);
30844 }
30845 }
30846 }
30847 }
30848 }
30849 iter++;
30850 } while ((badtetrahedrons->items > 0l) && (iter < b->optpasses));
30851
30852 if (b->verbose) {
30853 printf(" %d passes.\n", iter);
30854 if ((points->items - oldnum) > 0l) {
30855 printf(" %ld points are inserted (%d on segment).\n",
30856 points->items - oldnum, smoothsegverts);
30857 }
30858 if (optcount[1] > 0l) {
30859 printf(" %ld faces are flipped.\n", optcount[1]);
30860 }
30861 if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30862 optcount[9] > 0l) {
30863 printf(" %ld edges are flipped.\n", optcount[3] + optcount[4] +
30864 optcount[5] + optcount[6] + optcount[9]);
30865 }
30866
30867
30868
30869 }
30870 delete tetlist;
30871 delete ceillist;
30872 delete splittetlist;
30873 }
30874
30875 delete badtetrahedrons;
30876 badtetrahedrons = (memorypool *) NULL;
30877 }
30878
30879
30880
30881
30882
30883
30884
30885
30886
30888
30889
30890
30891
30892
30893
30894
30895
30897
30898 void tetgenmesh::transfernodes()
30899 {
30900 point pointloop;
30901 REAL x, y, z;
30902 int coordindex;
30903 int attribindex;
30904 int mtrindex;
30905 int i, j;
30906
30907
30908 coordindex = 0;
30909 attribindex = 0;
30910 mtrindex = 0;
30911 for (i = 0; i < in->numberofpoints; i++) {
30912 makepoint(&pointloop);
30913
30914 x = pointloop[0] = in->pointlist[coordindex++];
30915 y = pointloop[1] = in->pointlist[coordindex++];
30916 z = pointloop[2] = in->pointlist[coordindex++];
30917
30918 for (j = 0; j < in->numberofpointattributes; j++) {
30919 pointloop[3 + j] = in->pointattributelist[attribindex++];
30920 }
30921
30922 for (j = 0; j < in->numberofpointmtrs; j++) {
30923 pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
30924 }
30925
30926 if (i == 0) {
30927 xmin = xmax = x;
30928 ymin = ymax = y;
30929 zmin = zmax = z;
30930 } else {
30931 xmin = (x < xmin) ? x : xmin;
30932 xmax = (x > xmax) ? x : xmax;
30933 ymin = (y < ymin) ? y : ymin;
30934 ymax = (y > ymax) ? y : ymax;
30935 zmin = (z < zmin) ? z : zmin;
30936 zmax = (z > zmax) ? z : zmax;
30937 }
30938 }
30939
30940 x = xmax - xmin;
30941 y = ymax - ymin;
30942 z = zmax - zmin;
30943 longest = sqrt(x * x + y * y + z * z);
30944 if (longest == 0.0) {
30945 printf("Error: The point set is trivial.\n");
30946 terminatetetgen(1);
30947 }
30948
30949 lengthlimit = longest * b->epsilon * 1e+2;
30950 }
30951
30953
30954
30955
30956
30957
30958
30959
30960
30961
30963
30964 void tetgenmesh::jettisonnodes()
30965 {
30966 point pointloop;
30967 bool jetflag;
30968 int oldidx, newidx;
30969 int remcount;
30970
30971 if (!b->quiet) {
30972 printf("Jettisoning redundants points.\n");
30973 }
30974
30975 points->traversalinit();
30976 pointloop = pointtraverse();
30977 oldidx = newidx = 0;
30978 remcount = 0;
30979 while (pointloop != (point) NULL) {
30980 jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) ||
30981 (pointtype(pointloop) == UNUSEDVERTEX);
30982 if (jetflag) {
30983
30984 pointdealloc(pointloop);
30985 remcount++;
30986 } else {
30987
30988 setpointmark(pointloop, newidx + in->firstnumber);
30989 if (in->pointmarkerlist != (int *) NULL) {
30990 if (oldidx < in->numberofpoints) {
30991
30992 in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
30993 }
30994 }
30995 newidx++;
30996 }
30997 oldidx++;
30998 if (oldidx == in->numberofpoints) {
30999
31000 in->numberofpoints -= remcount;
31001
31002 jettisoninverts = remcount;
31003 }
31004 pointloop = pointtraverse();
31005 }
31006 if (b->verbose) {
31007 printf(" %d duplicated vertices have been removed.\n", dupverts);
31008 printf(" %d unused vertices have been removed.\n", unuverts);
31009 }
31010 dupverts = 0;
31011 unuverts = 0;
31012
31013
31014
31015
31016 points->deaditemstack = (void *) NULL;
31017 }
31018
31020
31021
31022
31023
31024
31025
31026
31028
31029 void tetgenmesh::highorder()
31030 {
31031 triface tetloop, worktet;
31032 triface spintet, adjtet;
31033 point torg, tdest, tapex;
31034 point *extralist, *adjextralist;
31035 point newpoint;
31036 int hitbdry, ptmark;
31037 int i, j;
31038
31039 if (!b->quiet) {
31040 printf("Adding vertices for second-order tetrahedra.\n");
31041 }
31042
31043
31044 highordertable = new point[tetrahedrons->items * 6];
31045 if (highordertable == (point *) NULL) {
31046 printf("Error: Out of memory.\n");
31047 terminatetetgen(1);
31048 }
31049
31050
31051
31052
31053
31054
31055 points->deaditemstack = (void *) NULL;
31056
31057
31058
31059 i = 0;
31060 tetrahedrons->traversalinit();
31061 tetloop.tet = tetrahedrontraverse();
31062 while (tetloop.tet != (tetrahedron *) NULL) {
31063 tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
31064 for (j = 0; j < 6; j++) {
31065 highordertable[i + j] = (point) NULL;
31066 }
31067 i += 6;
31068 tetloop.tet = tetrahedrontraverse();
31069 }
31070
31071
31072
31073
31074
31075
31076 tetrahedrons->traversalinit();
31077 tetloop.tet = tetrahedrontraverse();
31078 while (tetloop.tet != (tetrahedron *) NULL) {
31079
31080 extralist = (point *) tetloop.tet[highorderindex];
31081 worktet.tet = tetloop.tet;
31082 for (i = 0; i < 6; i++) {
31083 if (extralist[i] == (point) NULL) {
31084
31085 worktet.loc = edge2locver[i][0];
31086 worktet.ver = edge2locver[i][1];
31087
31088 torg = org(worktet);
31089 tdest = dest(worktet);
31090
31091 newpoint = (point) points->alloc();
31092
31093 for (j = 0; j < 3 + in->numberofpointattributes; j++) {
31094 newpoint[j] = 0.5 * (torg[j] + tdest[j]);
31095 }
31096 ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
31097 setpointmark(newpoint, ptmark);
31098
31099 extralist[i] = newpoint;
31100
31101
31102 tapex = apex(worktet);
31103 spintet = worktet;
31104 hitbdry = 0;
31105 while (hitbdry < 2) {
31106 if (fnextself(spintet)) {
31107
31108 adjextralist = (point *) spintet.tet[highorderindex];
31109
31110 j = locver2edge[spintet.loc][spintet.ver];
31111
31112
31113 if (adjextralist[j] == (point) NULL) {
31114 adjextralist[j] = newpoint;
31115 }
31116 if (apex(spintet) == tapex) {
31117 break;
31118 }
31119 } else {
31120 hitbdry++;
31121 if (hitbdry < 2) {
31122 esym(worktet, spintet);
31123 }
31124 }
31125 }
31126 }
31127 }
31128 tetloop.tet = tetrahedrontraverse();
31129 }
31130 }
31131
31133
31134
31135
31136
31137
31138
31140
31141 void tetgenmesh::outnodes(tetgenio* out)
31142 {
31143 FILE *outfile;
31144 char outnodefilename[FILENAMESIZE];
31145 shellface subptr;
31146 triface adjtet;
31147 face subloop;
31148 point pointloop;
31149 point *extralist, ep[3];
31150 int nextras, bmark, shmark, marker;
31151 int coordindex, attribindex;
31152 int pointnumber, firstindex;
31153 int index, i;
31154
31155 if (out == (tetgenio *) NULL) {
31156 strcpy(outnodefilename, b->outfilename);
31157 strcat(outnodefilename, ".node");
31158 }
31159
31160 if (!b->quiet) {
31161 if (out == (tetgenio *) NULL) {
31162 printf("Writing %s.\n", outnodefilename);
31163 } else {
31164 printf("Writing nodes.\n");
31165 }
31166 }
31167
31168 nextras = in->numberofpointattributes;
31169 bmark = !b->nobound && in->pointmarkerlist;
31170
31171
31172 outfile = (FILE *) NULL;
31173 marker = coordindex = 0;
31174
31175 if (out == (tetgenio *) NULL) {
31176 outfile = fopen(outnodefilename, "w");
31177 if (outfile == (FILE *) NULL) {
31178 printf("File I/O Error: Cannot create file %s.\n", outnodefilename);
31179 terminatetetgen(1);
31180 }
31181
31182
31183 fprintf(outfile, "%ld %d %d %d\n", points->items, 3, nextras, bmark);
31184 } else {
31185
31186 out->pointlist = new REAL[points->items * 3];
31187 if (out->pointlist == (REAL *) NULL) {
31188 printf("Error: Out of memory.\n");
31189 terminatetetgen(1);
31190 }
31191
31192 if (nextras > 0) {
31193 out->pointattributelist = new REAL[points->items * nextras];
31194 if (out->pointattributelist == (REAL *) NULL) {
31195 printf("Error: Out of memory.\n");
31196 terminatetetgen(1);
31197 }
31198 }
31199
31200 if (bmark) {
31201 out->pointmarkerlist = new int[points->items];
31202 if (out->pointmarkerlist == (int *) NULL) {
31203 printf("Error: Out of memory.\n");
31204 terminatetetgen(1);
31205 }
31206 }
31207 out->numberofpoints = points->items;
31208 out->numberofpointattributes = nextras;
31209 coordindex = 0;
31210 attribindex = 0;
31211 }
31212
31213 if (bmark && (b->plc || b->refine)) {
31214
31215 points->traversalinit();
31216 pointloop = pointtraverse();
31217 while (pointloop != (point) NULL) {
31218 setpoint2tet(pointloop, (tetrahedron) NULL);
31219 pointloop = pointtraverse();
31220 }
31221
31222
31223 subfaces->traversalinit();
31224 subloop.sh = shellfacetraverse(subfaces);
31225 while (subloop.sh != (shellface *) NULL) {
31226 subloop.shver = 0;
31227
31228 for (i = 0; i < 3; i++) {
31229 pointloop = (point) subloop.sh[3 + i];
31230 setpoint2tet(pointloop, (tetrahedron) sencode(subloop));
31231 }
31232 if (b->order == 2) {
31233
31234 stpivot(subloop, adjtet);
31235 if (adjtet.tet == dummytet) {
31236 sesymself(subloop);
31237 stpivot(subloop, adjtet);
31238 }
31239 assert(adjtet.tet != dummytet);
31240 extralist = (point *) adjtet.tet[highorderindex];
31241 switch (adjtet.loc) {
31242 case 0:
31243 ep[0] = extralist[0];
31244 ep[1] = extralist[1];
31245 ep[2] = extralist[2];
31246 break;
31247 case 1:
31248 ep[0] = extralist[0];
31249 ep[1] = extralist[4];
31250 ep[2] = extralist[3];
31251 break;
31252 case 2:
31253 ep[0] = extralist[1];
31254 ep[1] = extralist[5];
31255 ep[2] = extralist[4];
31256 break;
31257 case 3:
31258 ep[0] = extralist[2];
31259 ep[1] = extralist[3];
31260 ep[2] = extralist[5];
31261 break;
31262 default: break;
31263 }
31264 for (i = 0; i < 3; i++) {
31265 setpoint2tet(ep[i], (tetrahedron) sencode(subloop));
31266 }
31267 }
31268 subloop.sh = shellfacetraverse(subfaces);
31269 }
31270 }
31271
31272
31273 firstindex = b->zeroindex ? 0 : in->firstnumber;
31274
31275 points->traversalinit();
31276 pointloop = pointtraverse();
31277 pointnumber = firstindex;
31278 index = 0;
31279 while (pointloop != (point) NULL) {
31280 if (bmark) {
31281
31282 marker = 0;
31283
31284 if (index < in->numberofpoints) {
31285
31286 marker = in->pointmarkerlist[index];
31287 }
31288
31289 if ((marker == 0) && (b->plc || b->refine)) {
31290 subptr = (shellface) point2tet(pointloop);
31291 if (subptr != (shellface) NULL) {
31292
31293 marker = 1;
31294 if (in->facetmarkerlist != (int *) NULL) {
31295
31296 sdecode(subptr, subloop);
31297 shmark = shellmark(subloop);
31298 marker = in->facetmarkerlist[shmark - 1];
31299 }
31300 }
31301 }
31302 }
31303 if (out == (tetgenio *) NULL) {
31304
31305 fprintf(outfile, "%4d %.17g %.17g %.17g", pointnumber,
31306 pointloop[0], pointloop[1], pointloop[2]);
31307 for (i = 0; i < nextras; i++) {
31308
31309 fprintf(outfile, " %.17g", pointloop[3 + i]);
31310 }
31311 if (bmark) {
31312
31313 fprintf(outfile, " %d", marker);
31314 }
31315 fprintf(outfile, "\n");
31316 } else {
31317
31318 out->pointlist[coordindex++] = pointloop[0];
31319 out->pointlist[coordindex++] = pointloop[1];
31320 out->pointlist[coordindex++] = pointloop[2];
31321
31322 for (i = 0; i < nextras; i++) {
31323
31324 out->pointattributelist[attribindex++] = pointloop[3 + i];
31325 }
31326 if (bmark) {
31327
31328 out->pointmarkerlist[index] = marker;
31329 }
31330 }
31331 pointloop = pointtraverse();
31332 pointnumber++;
31333 index++;
31334 }
31335
31336 if (out == (tetgenio *) NULL) {
31337 fprintf(outfile, "# Generated by %s\n", b->commandline);
31338 fclose(outfile);
31339 }
31340 }
31341
31343
31344
31345
31347
31348 void tetgenmesh::outmetrics(tetgenio* out)
31349 {
31350 FILE *outfile;
31351 char outmtrfilename[FILENAMESIZE];
31352 list *tetlist, *ptlist;
31353 triface tetloop;
31354 point ptloop, neipt;
31355 REAL lave, len;
31356 int mtrindex;
31357 int i;
31358
31359 lave = 0.0;
31360
31361 if (out == (tetgenio *) NULL) {
31362 strcpy(outmtrfilename, b->outfilename);
31363 strcat(outmtrfilename, ".mtr");
31364 }
31365
31366 if (!b->quiet) {
31367 if (out == (tetgenio *) NULL) {
31368 printf("Writing %s.\n", outmtrfilename);
31369 } else {
31370 printf("Writing metrics.\n");
31371 }
31372 }
31373
31374
31375 outfile = (FILE *) NULL;
31376 mtrindex = 0;
31377
31378 if (out == (tetgenio *) NULL) {
31379 outfile = fopen(outmtrfilename, "w");
31380 if (outfile == (FILE *) NULL) {
31381 printf("File I/O Error: Cannot create file %s.\n", outmtrfilename);
31382 terminatetetgen(1);
31383 }
31384
31385
31386 fprintf(outfile, "%ld %d\n", points->items, 1);
31387 } else {
31388
31389
31390 out->pointmtrlist = new REAL[points->items];
31391 if (out->pointmtrlist == (REAL *) NULL) {
31392 printf("Error: Out of memory.\n");
31393 terminatetetgen(1);
31394 }
31395 out->numberofpointmtrs = 1;
31396 mtrindex = 0;
31397 }
31398
31399
31400 points->traversalinit();
31401 ptloop = pointtraverse();
31402 while (ptloop != (point) NULL) {
31403 setpoint2tet(ptloop, (tetrahedron) NULL);
31404 ptloop = pointtraverse();
31405 }
31406
31407 tetrahedrons->traversalinit();
31408 tetloop.tet = tetrahedrontraverse();
31409 while (tetloop.tet != (tetrahedron *) NULL) {
31410 for (i = 0; i < 4; i++) {
31411 ptloop = (point) tetloop.tet[4 + i];
31412 setpoint2tet(ptloop, encode(tetloop));
31413 }
31414 tetloop.tet = tetrahedrontraverse();
31415 }
31416
31417 tetlist = new list(sizeof(triface), NULL, 256);
31418 ptlist = new list(sizeof(point *), NULL, 256);
31419
31420 points->traversalinit();
31421 ptloop = pointtraverse();
31422 while (ptloop != (point) NULL) {
31423 decode(point2tet(ptloop), tetloop);
31424 if (!isdead(&tetloop)) {
31425
31426 tetlist->append(&tetloop);
31427 formstarpolyhedron(ptloop, tetlist, ptlist, true);
31428
31429
31430 lave = 0.0;
31431 for (i = 0; i < ptlist->len(); i++) {
31432 neipt = * (point *)(* ptlist)[i];
31433 len = distance(ptloop, neipt);
31434
31435
31436 lave += len;
31437 }
31438 lave /= ptlist->len();
31439 }
31440 if (out == (tetgenio *) NULL) {
31441
31442
31443
31444 if (ptlist->len() > 0) {
31445
31446 fprintf(outfile, "%-16.8e ", lave);
31447 } else {
31448 fprintf(outfile, "0.0 ");
31449 }
31450 fprintf(outfile, "\n");
31451 } else {
31452
31453
31454
31455 if (ptlist->len() > 0) {
31456
31457
31458 out->pointmtrlist[mtrindex++] = lave;
31459 } else {
31460
31461
31462 out->pointmtrlist[mtrindex++] = 0.0;
31463 }
31464 }
31465 tetlist->clear();
31466 ptlist->clear();
31467 ptloop = pointtraverse();
31468 }
31469
31470 delete tetlist;
31471 delete ptlist;
31472
31473 if (out == (tetgenio *) NULL) {
31474 fprintf(outfile, "# Generated by %s\n", b->commandline);
31475 fclose(outfile);
31476 }
31477 }
31478
31480
31481
31482
31483
31485
31486 void tetgenmesh::outelements(tetgenio* out)
31487 {
31488 FILE *outfile;
31489 char outelefilename[FILENAMESIZE];
31490 tetrahedron* tptr;
31491 int *tlist;
31492 REAL *talist;
31493 int firstindex, shift;
31494 int pointindex;
31495 int attribindex;
31496 point p1, p2, p3, p4;
31497 point *extralist;
31498 int elementnumber;
31499 int eextras;
31500 int i;
31501
31502 if (out == (tetgenio *) NULL) {
31503 strcpy(outelefilename, b->outfilename);
31504 strcat(outelefilename, ".ele");
31505 }
31506
31507 if (!b->quiet) {
31508 if (out == (tetgenio *) NULL) {
31509 printf("Writing %s.\n", outelefilename);
31510 } else {
31511 printf("Writing elements.\n");
31512 }
31513 }
31514
31515
31516 outfile = (FILE *) NULL;
31517 tlist = (int *) NULL;
31518 talist = (double *) NULL;
31519 pointindex = attribindex = 0;
31520
31521 eextras = in->numberoftetrahedronattributes;
31522 if (out == (tetgenio *) NULL) {
31523 outfile = fopen(outelefilename, "w");
31524 if (outfile == (FILE *) NULL) {
31525 printf("File I/O Error: Cannot create file %s.\n", outelefilename);
31526 terminatetetgen(1);
31527 }
31528
31529 fprintf(outfile, "%ld %d %d\n", tetrahedrons->items,
31530 b->order == 1 ? 4 : 10, eextras);
31531 } else {
31532
31533 out->tetrahedronlist = new int[tetrahedrons->items *
31534 (b->order == 1 ? 4 : 10)];
31535 if (out->tetrahedronlist == (int *) NULL) {
31536 printf("Error: Out of memory.\n");
31537 terminatetetgen(1);
31538 }
31539
31540 if (eextras > 0) {
31541 out->tetrahedronattributelist = new REAL[tetrahedrons->items * eextras];
31542 if (out->tetrahedronattributelist == (REAL *) NULL) {
31543 printf("Error: Out of memory.\n");
31544 terminatetetgen(1);
31545 }
31546 }
31547 out->numberoftetrahedra = tetrahedrons->items;
31548 out->numberofcorners = b->order == 1 ? 4 : 10;
31549 out->numberoftetrahedronattributes = eextras;
31550 tlist = out->tetrahedronlist;
31551 talist = out->tetrahedronattributelist;
31552 pointindex = 0;
31553 attribindex = 0;
31554 }
31555
31556
31557 firstindex = b->zeroindex ? 0 : in->firstnumber;
31558 shift = 0;
31559 if ((in->firstnumber == 1) && (firstindex == 0)) {
31560 shift = 1;
31561 }
31562
31563 tetrahedrons->traversalinit();
31564 tptr = tetrahedrontraverse();
31565 elementnumber = firstindex;
31566 while (tptr != (tetrahedron *) NULL) {
31567 p1 = (point) tptr[4];
31568 p2 = (point) tptr[5];
31569 p3 = (point) tptr[6];
31570 p4 = (point) tptr[7];
31571 if (out == (tetgenio *) NULL) {
31572
31573 fprintf(outfile, "%5d %5d %5d %5d %5d", elementnumber,
31574 pointmark(p1) - shift, pointmark(p2) - shift,
31575 pointmark(p3) - shift, pointmark(p4) - shift);
31576 if (b->order == 2) {
31577 extralist = (point *) tptr[highorderindex];
31578
31579 fprintf(outfile, " %5d %5d %5d %5d %5d %5d",
31580 pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
31581 pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
31582 pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
31583 }
31584 for (i = 0; i < eextras; i++) {
31585 fprintf(outfile, " %.17g", elemattribute(tptr, i));
31586 }
31587 fprintf(outfile, "\n");
31588 } else {
31589 tlist[pointindex++] = pointmark(p1) - shift;
31590 tlist[pointindex++] = pointmark(p2) - shift;
31591 tlist[pointindex++] = pointmark(p3) - shift;
31592 tlist[pointindex++] = pointmark(p4) - shift;
31593 if (b->order == 2) {
31594 extralist = (point *) tptr[highorderindex];
31595 tlist[pointindex++] = pointmark(extralist[0]) - shift;
31596 tlist[pointindex++] = pointmark(extralist[1]) - shift;
31597 tlist[pointindex++] = pointmark(extralist[2]) - shift;
31598 tlist[pointindex++] = pointmark(extralist[3]) - shift;
31599 tlist[pointindex++] = pointmark(extralist[4]) - shift;
31600 tlist[pointindex++] = pointmark(extralist[5]) - shift;
31601 }
31602 for (i = 0; i < eextras; i++) {
31603 talist[attribindex++] = elemattribute(tptr, i);
31604 }
31605 }
31606 if (b->neighout) {
31607
31608 * (int *) (tptr + elemmarkerindex) = elementnumber;
31609 }
31610 tptr = tetrahedrontraverse();
31611 elementnumber++;
31612 }
31613 if (b->neighout) {
31614
31615 * (int *) (dummytet + elemmarkerindex) = -1;
31616 }
31617
31618 if (out == (tetgenio *) NULL) {
31619 fprintf(outfile, "# Generated by %s\n", b->commandline);
31620 fclose(outfile);
31621 }
31622 }
31623
31625
31626
31627
31628
31629
31630
31632
31633 void tetgenmesh::outfaces(tetgenio* out)
31634 {
31635 FILE *outfile;
31636 char facefilename[FILENAMESIZE];
31637 int *elist;
31638 int *emlist;
31639 int neigh1, neigh2;
31640 int index;
31641 triface tface, tsymface;
31642 face checkmark;
31643 point torg, tdest, tapex;
31644 long faces;
31645 int bmark, faceid, marker;
31646 int firstindex, shift;
31647 int facenumber;
31648
31649 neigh1 = 0;
31650 neigh2 = 0;
31651
31652 if (out == (tetgenio *) NULL) {
31653 strcpy(facefilename, b->outfilename);
31654 strcat(facefilename, ".face");
31655 }
31656
31657 if (!b->quiet) {
31658 if (out == (tetgenio *) NULL) {
31659 printf("Writing %s.\n", facefilename);
31660 } else {
31661 printf("Writing faces.\n");
31662 }
31663 }
31664
31665
31666 outfile = (FILE *) NULL;
31667 elist = (int *) NULL;
31668 emlist = (int *) NULL;
31669 index = marker = 0;
31670
31671 faces = (4l * tetrahedrons->items + hullsize) / 2l;
31672 bmark = !b->nobound && in->facetmarkerlist;
31673
31674 if (out == (tetgenio *) NULL) {
31675 outfile = fopen(facefilename, "w");
31676 if (outfile == (FILE *) NULL) {
31677 printf("File I/O Error: Cannot create file %s.\n", facefilename);
31678 terminatetetgen(1);
31679 }
31680 fprintf(outfile, "%ld %d\n", faces, bmark);
31681 } else {
31682
31683 out->trifacelist = new int[faces * 3];
31684 if (out->trifacelist == (int *) NULL) {
31685 printf("Error: Out of memory.\n");
31686 terminatetetgen(1);
31687 }
31688
31689 if (bmark) {
31690 out->trifacemarkerlist = new int[faces];
31691 if (out->trifacemarkerlist == (int *) NULL) {
31692 printf("Error: Out of memory.\n");
31693 terminatetetgen(1);
31694 }
31695 }
31696 if (b->neighout > 1) {
31697
31698 out->adjtetlist = new int[subfaces->items * 2];
31699 if (out->adjtetlist == (int *) NULL) {
31700 printf("Error: Out of memory.\n");
31701 terminatetetgen(1);
31702 }
31703 }
31704 out->numberoftrifaces = faces;
31705 elist = out->trifacelist;
31706 emlist = out->trifacemarkerlist;
31707 index = 0;
31708 }
31709
31710
31711 firstindex = b->zeroindex ? 0 : in->firstnumber;
31712 shift = 0;
31713 if ((in->firstnumber == 1) && (firstindex == 0)) {
31714 shift = 1;
31715 }
31716
31717 tetrahedrons->traversalinit();
31718 tface.tet = tetrahedrontraverse();
31719 facenumber = firstindex;
31720
31721
31722
31723
31724
31725
31726 while (tface.tet != (tetrahedron *) NULL) {
31727 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31728 sym(tface, tsymface);
31729 if ((tsymface.tet == dummytet) || (tface.tet < tsymface.tet)) {
31730 torg = org(tface);
31731 tdest = dest(tface);
31732 tapex = apex(tface);
31733 if (bmark) {
31734
31735
31736 if (b->useshelles) {
31737
31738 tspivot(tface, checkmark);
31739 if (checkmark.sh == dummysh) {
31740 marker = 0;
31741 } else {
31742 faceid = shellmark(checkmark) - 1;
31743 marker = in->facetmarkerlist[faceid];
31744 }
31745 } else {
31746
31747 marker = tsymface.tet != dummytet ? 1 : 0;
31748 }
31749 }
31750 if (b->neighout > 1) {
31751
31752 neigh1 = * (int *)(tface.tet + elemmarkerindex);
31753 if (tsymface.tet != dummytet) {
31754 neigh2 = * (int *)(tsymface.tet + elemmarkerindex);
31755 } else {
31756 neigh2 = -1;
31757 }
31758 }
31759 if (out == (tetgenio *) NULL) {
31760
31761 fprintf(outfile, "%5d %4d %4d %4d", facenumber,
31762 pointmark(torg) - shift, pointmark(tdest) - shift,
31763 pointmark(tapex) - shift);
31764 if (bmark) {
31765
31766 fprintf(outfile, " %d", marker);
31767 }
31768 if (b->neighout > 1) {
31769 fprintf(outfile, " %5d %5d", neigh1, neigh2);
31770 }
31771 fprintf(outfile, "\n");
31772 } else {
31773
31774 elist[index++] = pointmark(torg) - shift;
31775 elist[index++] = pointmark(tdest) - shift;
31776 elist[index++] = pointmark(tapex) - shift;
31777 if (bmark) {
31778 emlist[facenumber - in->firstnumber] = marker;
31779 }
31780 if (b->neighout > 1) {
31781 out->adjtetlist[(facenumber - in->firstnumber) * 2] = neigh1;
31782 out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
31783 }
31784 }
31785 facenumber++;
31786 }
31787 }
31788 tface.tet = tetrahedrontraverse();
31789 }
31790
31791 if (out == (tetgenio *) NULL) {
31792 fprintf(outfile, "# Generated by %s\n", b->commandline);
31793 fclose(outfile);
31794 }
31795 }
31796
31798
31799
31800
31801
31802
31803
31804
31805
31807
31808 void tetgenmesh::outhullfaces(tetgenio* out)
31809 {
31810 FILE *outfile;
31811 char facefilename[FILENAMESIZE];
31812 int *elist;
31813 int index;
31814 triface tface, tsymface;
31815 face checkmark;
31816 point torg, tdest, tapex;
31817 int firstindex, shift;
31818 int facenumber;
31819
31820 if (out == (tetgenio *) NULL) {
31821 strcpy(facefilename, b->outfilename);
31822 strcat(facefilename, ".face");
31823 }
31824
31825 if (!b->quiet) {
31826 if (out == (tetgenio *) NULL) {
31827 printf("Writing %s.\n", facefilename);
31828 } else {
31829 printf("Writing faces.\n");
31830 }
31831 }
31832
31833
31834 outfile = (FILE *) NULL;
31835 elist = (int *) NULL;
31836 index = 0;
31837
31838 if (out == (tetgenio *) NULL) {
31839 outfile = fopen(facefilename, "w");
31840 if (outfile == (FILE *) NULL) {
31841 printf("File I/O Error: Cannot create file %s.\n", facefilename);
31842 terminatetetgen(1);
31843 }
31844 fprintf(outfile, "%ld 0\n", hullsize);
31845 } else {
31846
31847 out->trifacelist = new int[hullsize * 3];
31848 if (out->trifacelist == (int *) NULL) {
31849 printf("Error: Out of memory.\n");
31850 terminatetetgen(1);
31851 }
31852 out->numberoftrifaces = hullsize;
31853 elist = out->trifacelist;
31854 index = 0;
31855 }
31856
31857
31858 firstindex = b->zeroindex ? 0 : in->firstnumber;
31859 shift = 0;
31860 if ((in->firstnumber == 1) && (firstindex == 0)) {
31861 shift = 1;
31862 }
31863
31864 tetrahedrons->traversalinit();
31865 tface.tet = tetrahedrontraverse();
31866 facenumber = firstindex;
31867
31868
31869
31870 while (tface.tet != (tetrahedron *) NULL) {
31871 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31872 sym(tface, tsymface);
31873 if (tsymface.tet == dummytet) {
31874 torg = org(tface);
31875 tdest = dest(tface);
31876 tapex = apex(tface);
31877 if (out == (tetgenio *) NULL) {
31878
31879 fprintf(outfile, "%5d %4d %4d %4d", facenumber,
31880 pointmark(torg) - shift, pointmark(tdest) - shift,
31881 pointmark(tapex) - shift);
31882 fprintf(outfile, "\n");
31883 } else {
31884
31885 elist[index++] = pointmark(torg) - shift;
31886 elist[index++] = pointmark(tdest) - shift;
31887 elist[index++] = pointmark(tapex) - shift;
31888 }
31889 facenumber++;
31890 }
31891 }
31892 tface.tet = tetrahedrontraverse();
31893 }
31894
31895 if (out == (tetgenio *) NULL) {
31896 fprintf(outfile, "# Generated by %s\n", b->commandline);
31897 fclose(outfile);
31898 }
31899 }
31900
31902
31903
31904
31905
31906
31907
31908
31909
31911
31912 void tetgenmesh::outsubfaces(tetgenio* out)
31913 {
31914 FILE *outfile;
31915 char facefilename[FILENAMESIZE];
31916 int *elist;
31917 int *emlist;
31918 int index, index1, index2;
31919 triface abuttingtet;
31920 face faceloop;
31921 point torg, tdest, tapex;
31922 int bmark, faceid, marker;
31923 int firstindex, shift;
31924 int neigh1, neigh2;
31925 int facenumber;
31926
31927 if (out == (tetgenio *) NULL) {
31928 strcpy(facefilename, b->outfilename);
31929 strcat(facefilename, ".face");
31930 }
31931
31932 if (!b->quiet) {
31933 if (out == (tetgenio *) NULL) {
31934 printf("Writing %s.\n", facefilename);
31935 } else {
31936 printf("Writing faces.\n");
31937 }
31938 }
31939
31940
31941 outfile = (FILE *) NULL;
31942 elist = (int *) NULL;
31943 emlist = (int *) NULL;
31944 index = index1 = index2 = 0;
31945 faceid = marker = 0;
31946 neigh1 = neigh2 = 0;
31947
31948 bmark = !b->nobound && in->facetmarkerlist;
31949
31950 if (out == (tetgenio *) NULL) {
31951 outfile = fopen(facefilename, "w");
31952 if (outfile == (FILE *) NULL) {
31953 printf("File I/O Error: Cannot create file %s.\n", facefilename);
31954 terminatetetgen(1);
31955 }
31956
31957 fprintf(outfile, "%ld %d\n", subfaces->items, bmark);
31958 } else {
31959
31960 out->trifacelist = new int[subfaces->items * 3];
31961 if (out->trifacelist == (int *) NULL) {
31962 printf("Error: Out of memory.\n");
31963 terminatetetgen(1);
31964 }
31965 if (bmark) {
31966
31967 out->trifacemarkerlist = new int[subfaces->items];
31968 if (out->trifacemarkerlist == (int *) NULL) {
31969 printf("Error: Out of memory.\n");
31970 terminatetetgen(1);
31971 }
31972 }
31973 if (b->neighout > 1) {
31974
31975 out->adjtetlist = new int[subfaces->items * 2];
31976 if (out->adjtetlist == (int *) NULL) {
31977 printf("Error: Out of memory.\n");
31978 terminatetetgen(1);
31979 }
31980 }
31981 out->numberoftrifaces = subfaces->items;
31982 elist = out->trifacelist;
31983 emlist = out->trifacemarkerlist;
31984 }
31985
31986
31987 firstindex = b->zeroindex ? 0 : in->firstnumber;
31988 shift = 0;
31989 if ((in->firstnumber == 1) && (firstindex == 0)) {
31990 shift = 1;
31991 }
31992
31993 subfaces->traversalinit();
31994 faceloop.sh = shellfacetraverse(subfaces);
31995 facenumber = firstindex;
31996 while (faceloop.sh != (shellface *) NULL) {
31997 stpivot(faceloop, abuttingtet);
31998 if (abuttingtet.tet == dummytet) {
31999 sesymself(faceloop);
32000 stpivot(faceloop, abuttingtet);
32001 }
32002 if (abuttingtet.tet != dummytet) {
32003
32004
32005
32006 adjustedgering(abuttingtet, CCW);
32007 torg = org(abuttingtet);
32008 tdest = dest(abuttingtet);
32009 tapex = apex(abuttingtet);
32010 } else {
32011
32012 torg = sorg(faceloop);
32013 tdest = sdest(faceloop);
32014 tapex = sapex(faceloop);
32015 }
32016 if (bmark) {
32017 faceid = shellmark(faceloop) - 1;
32018 marker = in->facetmarkerlist[faceid];
32019 }
32020 if (b->neighout > 1) {
32021
32022 neigh1 = -1;
32023 stpivot(faceloop, abuttingtet);
32024 if (abuttingtet.tet != dummytet) {
32025 neigh1 = * (int *)(abuttingtet.tet + elemmarkerindex);
32026 }
32027 neigh2 = -1;
32028 sesymself(faceloop);
32029 stpivot(faceloop, abuttingtet);
32030 if (abuttingtet.tet != dummytet) {
32031 neigh2 = * (int *)(abuttingtet.tet + elemmarkerindex);
32032 }
32033 }
32034 if (out == (tetgenio *) NULL) {
32035 fprintf(outfile, "%5d %4d %4d %4d", facenumber,
32036 pointmark(torg) - shift, pointmark(tdest) - shift,
32037 pointmark(tapex) - shift);
32038 if (bmark) {
32039 fprintf(outfile, " %d", marker);
32040 }
32041 if (b->neighout > 1) {
32042 fprintf(outfile, " %5d %5d", neigh1, neigh2);
32043 }
32044 fprintf(outfile, "\n");
32045 } else {
32046
32047 elist[index++] = pointmark(torg) - shift;
32048 elist[index++] = pointmark(tdest) - shift;
32049 elist[index++] = pointmark(tapex) - shift;
32050 if (bmark) {
32051 emlist[index1++] = marker;
32052 }
32053 if (b->neighout > 1) {
32054 out->adjtetlist[index2++] = neigh1;
32055 out->adjtetlist[index2++] = neigh2;
32056 }
32057 }
32058 facenumber++;
32059 faceloop.sh = shellfacetraverse(subfaces);
32060 }
32061
32062 if (out == (tetgenio *) NULL) {
32063 fprintf(outfile, "# Generated by %s\n", b->commandline);
32064 fclose(outfile);
32065 }
32066 }
32067
32069
32070
32071
32073
32074 void tetgenmesh::outedges(tetgenio* out)
32075 {
32076 FILE *outfile;
32077 char edgefilename[FILENAMESIZE];
32078 int *elist, *emlist;
32079 int index, index1;
32080 triface tetloop, worktet, spintet;
32081 face checksh;
32082 point torg, tdest;
32083 long faces, edges;
32084 int firstindex, shift;
32085 int edgenumber, faceid, marker;
32086 int hitbdry, i;
32087
32088 if (out == (tetgenio *) NULL) {
32089 strcpy(edgefilename, b->outfilename);
32090 strcat(edgefilename, ".edge");
32091 }
32092
32093 if (!b->quiet) {
32094 if (out == (tetgenio *) NULL) {
32095 printf("Writing %s.\n", edgefilename);
32096 } else {
32097 printf("Writing edges.\n");
32098 }
32099 }
32100
32101
32102 outfile = (FILE *) NULL;
32103 elist = (int *) NULL;
32104 emlist = (int *) NULL;
32105 index = index1 = 0;
32106 faceid = marker = 0;
32107
32108
32109 faces = (4l * tetrahedrons->items + hullsize) / 2l;
32110 edges = points->items + faces - tetrahedrons->items - 1l;
32111
32112 if (out == (tetgenio *) NULL) {
32113 outfile = fopen(edgefilename, "w");
32114 if (outfile == (FILE *) NULL) {
32115 printf("File I/O Error: Cannot create file %s.\n", edgefilename);
32116 terminatetetgen(1);
32117 }
32118
32119 fprintf(outfile, "%ld %d\n", edges, !b->nobound);
32120 } else {
32121
32122 out->edgelist = new int[edges * 2];
32123 if (out->edgelist == (int *) NULL) {
32124 printf("Error: Out of memory.\n");
32125 terminatetetgen(1);
32126 }
32127 if (!b->nobound) {
32128 out->edgemarkerlist = new int[edges];
32129 }
32130 out->numberofedges = edges;
32131 elist = out->edgelist;
32132 emlist = out->edgemarkerlist;
32133 }
32134
32135
32136 firstindex = b->zeroindex ? 0 : in->firstnumber;
32137 shift = 0;
32138 if ((in->firstnumber == 1) && (firstindex == 0)) {
32139 shift = 1;
32140 }
32141
32142 tetrahedrons->traversalinit();
32143 tetloop.tet = tetrahedrontraverse();
32144 edgenumber = firstindex;
32145 while (tetloop.tet != (tetrahedron *) NULL) {
32146
32147
32148
32149 worktet.tet = tetloop.tet;
32150 for (i = 0; i < 6; i++) {
32151 worktet.loc = edge2locver[i][0];
32152 worktet.ver = edge2locver[i][1];
32153 adjustedgering(worktet, CW);
32154 spintet = worktet;
32155 hitbdry = 0;
32156 while (hitbdry < 2) {
32157 if (fnextself(spintet)) {
32158 if (apex(spintet) == apex(worktet)) break;
32159 if (spintet.tet < worktet.tet) break;
32160 } else {
32161 hitbdry++;
32162 if (hitbdry < 2) {
32163 esym(worktet, spintet);
32164 fnextself(spintet);
32165 }
32166 }
32167 }
32168
32169 if (spintet.tet >= worktet.tet) {
32170 torg = org(worktet);
32171 tdest = dest(worktet);
32172 if (out == (tetgenio *) NULL) {
32173 fprintf(outfile, "%5d %4d %4d", edgenumber,
32174 pointmark(torg) - shift, pointmark(tdest) - shift);
32175 } else {
32176
32177 elist[index++] = pointmark(torg) - shift;
32178 elist[index++] = pointmark(tdest) - shift;
32179 }
32180 if (!b->nobound) {
32181 if (hitbdry > 0) {
32182
32183
32184
32185 if ((b->plc || b->refine) && in->facetmarkerlist) {
32186 tspivot(spintet, checksh);
32187 faceid = shellmark(checksh) - 1;
32188 marker = in->facetmarkerlist[faceid];
32189 } else {
32190 marker = 1;
32191 }
32192 } else {
32193 marker = 0;
32194 }
32195 if (out == (tetgenio *) NULL) {
32196 fprintf(outfile, " %d", marker);
32197 } else {
32198 emlist[index1++] = marker;
32199 }
32200 }
32201 if (out == (tetgenio *) NULL) {
32202 fprintf(outfile, "\n");
32203 }
32204 edgenumber++;
32205 }
32206 }
32207 tetloop.tet = tetrahedrontraverse();
32208 }
32209
32210 if (out == (tetgenio *) NULL) {
32211 fprintf(outfile, "# Generated by %s\n", b->commandline);
32212 fclose(outfile);
32213 }
32214 }
32215
32217
32218
32219
32221
32222 void tetgenmesh::outsubsegments(tetgenio* out)
32223 {
32224 FILE *outfile;
32225 char edgefilename[FILENAMESIZE];
32226 int *elist;
32227 int index;
32228 face edgeloop;
32229 point torg, tdest;
32230 int firstindex, shift;
32231 int edgenumber;
32232
32233 if (out == (tetgenio *) NULL) {
32234 strcpy(edgefilename, b->outfilename);
32235 strcat(edgefilename, ".edge");
32236 }
32237
32238 if (!b->quiet) {
32239 if (out == (tetgenio *) NULL) {
32240 printf("Writing %s.\n", edgefilename);
32241 } else {
32242 printf("Writing edges.\n");
32243 }
32244 }
32245
32246
32247 outfile = (FILE *) NULL;
32248 elist = (int *) NULL;
32249 index = 0;
32250
32251 if (out == (tetgenio *) NULL) {
32252 outfile = fopen(edgefilename, "w");
32253 if (outfile == (FILE *) NULL) {
32254 printf("File I/O Error: Cannot create file %s.\n", edgefilename);
32255 terminatetetgen(1);
32256 }
32257
32258 fprintf(outfile, "%ld\n", subsegs->items);
32259 } else {
32260
32261 out->edgelist = new int[subsegs->items * 2];
32262 if (out->edgelist == (int *) NULL) {
32263 printf("Error: Out of memory.\n");
32264 terminatetetgen(1);
32265 }
32266 out->numberofedges = subsegs->items;
32267 elist = out->edgelist;
32268 }
32269
32270
32271 firstindex = b->zeroindex ? 0 : in->firstnumber;
32272 shift = 0;
32273 if ((in->firstnumber == 1) && (firstindex == 0)) {
32274 shift = 1;
32275 }
32276
32277 subsegs->traversalinit();
32278 edgeloop.sh = shellfacetraverse(subsegs);
32279 edgenumber = firstindex;
32280 while (edgeloop.sh != (shellface *) NULL) {
32281 torg = sorg(edgeloop);
32282 tdest = sdest(edgeloop);
32283 if (out == (tetgenio *) NULL) {
32284 fprintf(outfile, "%5d %4d %4d\n", edgenumber,
32285 pointmark(torg) - shift, pointmark(tdest) - shift);
32286 } else {
32287
32288 elist[index++] = pointmark(torg) - shift;
32289 elist[index++] = pointmark(tdest) - shift;
32290 }
32291 edgenumber++;
32292 edgeloop.sh = shellfacetraverse(subsegs);
32293 }
32294
32295 if (out == (tetgenio *) NULL) {
32296 fprintf(outfile, "# Generated by %s\n", b->commandline);
32297 fclose(outfile);
32298 }
32299 }
32300
32302
32303
32304
32306
32307 void tetgenmesh::outneighbors(tetgenio* out)
32308 {
32309 FILE *outfile;
32310 char neighborfilename[FILENAMESIZE];
32311 int *nlist;
32312 int index;
32313 triface tetloop, tetsym;
32314 int neighbor1, neighbor2, neighbor3, neighbor4;
32315 int firstindex;
32316 int elementnumber;
32317
32318 if (out == (tetgenio *) NULL) {
32319 strcpy(neighborfilename, b->outfilename);
32320 strcat(neighborfilename, ".neigh");
32321 }
32322
32323 if (!b->quiet) {
32324 if (out == (tetgenio *) NULL) {
32325 printf("Writing %s.\n", neighborfilename);
32326 } else {
32327 printf("Writing neighbors.\n");
32328 }
32329 }
32330
32331
32332 outfile = (FILE *) NULL;
32333 nlist = (int *) NULL;
32334 index = 0;
32335
32336 if (out == (tetgenio *) NULL) {
32337 outfile = fopen(neighborfilename, "w");
32338 if (outfile == (FILE *) NULL) {
32339 printf("File I/O Error: Cannot create file %s.\n", neighborfilename);
32340 terminatetetgen(1);
32341 }
32342
32343 fprintf(outfile, "%ld %d\n", tetrahedrons->items, 4);
32344 } else {
32345
32346 out->neighborlist = new int[tetrahedrons->items * 4];
32347 if (out->neighborlist == (int *) NULL) {
32348 printf("Error: Out of memory.\n");
32349 terminatetetgen(1);
32350 }
32351 nlist = out->neighborlist;
32352 }
32353
32354
32355 firstindex = b->zeroindex ? 0 : in->firstnumber;
32356
32357 tetrahedrons->traversalinit();
32358 tetloop.tet = tetrahedrontraverse();
32359 elementnumber = firstindex;
32360 while (tetloop.tet != (tetrahedron *) NULL) {
32361 tetloop.loc = 2;
32362 sym(tetloop, tetsym);
32363 neighbor1 = * (int *) (tetsym.tet + elemmarkerindex);
32364 tetloop.loc = 3;
32365 sym(tetloop, tetsym);
32366 neighbor2 = * (int *) (tetsym.tet + elemmarkerindex);
32367 tetloop.loc = 1;
32368 sym(tetloop, tetsym);
32369 neighbor3 = * (int *) (tetsym.tet + elemmarkerindex);
32370 tetloop.loc = 0;
32371 sym(tetloop, tetsym);
32372 neighbor4 = * (int *) (tetsym.tet + elemmarkerindex);
32373 if (out == (tetgenio *) NULL) {
32374
32375 fprintf(outfile, "%4d %4d %4d %4d %4d\n", elementnumber,
32376 neighbor1, neighbor2, neighbor3, neighbor4);
32377 } else {
32378 nlist[index++] = neighbor1;
32379 nlist[index++] = neighbor2;
32380 nlist[index++] = neighbor3;
32381 nlist[index++] = neighbor4;
32382 }
32383 tetloop.tet = tetrahedrontraverse();
32384 elementnumber++;
32385 }
32386
32387 if (out == (tetgenio *) NULL) {
32388 fprintf(outfile, "# Generated by %s\n", b->commandline);
32389 fclose(outfile);
32390 }
32391 }
32392
32394
32395
32396
32397
32398
32399
32400
32401
32402
32403
32404
32405
32406
32407
32408
32410
32411 void tetgenmesh::outvoronoi(tetgenio* out)
32412 {
32413 FILE *outfile;
32414 char outfilename[FILENAMESIZE];
32415 tetgenio::voroedge *vedge;
32416 tetgenio::vorofacet *vfacet;
32417 list *tetlist, *ptlist;
32418 triface tetloop, worktet, spintet;
32419 point pt[4], ptloop, neipt;
32420 REAL ccent[3], infvec[3], vec1[3], vec2[3], L;
32421 long faces, edges;
32422 int *tetfaceindexarray, *tetedgeindexarray;
32423 int arraysize, *vertarray;
32424 int vpointcount, vedgecount, vfacecount, tcount;
32425 int index, shift;
32426 int end1, end2;
32427 int hitbdry, i, j, k;
32428
32429 vedge = NULL;
32430 vertarray = NULL;
32431 vfacet = NULL;
32432 k = 0;
32433
32434
32435 if (out == (tetgenio *) NULL) {
32436 strcpy(outfilename, b->outfilename);
32437 strcat(outfilename, ".v.node");
32438 }
32439
32440 if (!b->quiet) {
32441 if (out == (tetgenio *) NULL) {
32442 printf("Writing %s.\n", outfilename);
32443 } else {
32444 printf("Writing Voronoi vertices.\n");
32445 }
32446 }
32447
32448
32449 shift = (b->zeroindex ? 0 : in->firstnumber);
32450
32451 faces = (4l * tetrahedrons->items + hullsize) / 2l;
32452
32453 edges = points->items + faces - tetrahedrons->items - 1;
32454 outfile = (FILE *) NULL;
32455
32456 if (out == (tetgenio *) NULL) {
32457 outfile = fopen(outfilename, "w");
32458 if (outfile == (FILE *) NULL) {
32459 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32460 terminatetetgen(1);
32461 }
32462
32463 fprintf(outfile, "%ld 3 0 0\n", tetrahedrons->items);
32464 } else {
32465
32466 out->numberofvpoints = (int) tetrahedrons->items;
32467 out->vpointlist = new REAL[out->numberofvpoints * 3];
32468 if (out->vpointlist == (REAL *) NULL) {
32469 printf("Error: Out of memory.\n");
32470 terminatetetgen(1);
32471 }
32472 }
32473
32474
32475
32476
32477 tetrahedrons->traversalinit();
32478 tetloop.tet = tetrahedrontraverse();
32479 vpointcount = 0;
32480 index = 0;
32481 while (tetloop.tet != (tetrahedron *) NULL) {
32482
32483 for (i = 0; i < 4; i++) {
32484 pt[i] = (point) tetloop.tet[4 + i];
32485 setpoint2tet(pt[i], encode(tetloop));
32486 }
32487 circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
32488 if (out == (tetgenio *) NULL) {
32489 fprintf(outfile, "%4d %16.8e %16.8e %16.8e\n", vpointcount + shift,
32490 ccent[0], ccent[1], ccent[2]);
32491 } else {
32492 out->vpointlist[index++] = ccent[0];
32493 out->vpointlist[index++] = ccent[1];
32494 out->vpointlist[index++] = ccent[2];
32495 }
32496
32497 * (int *) (tetloop.tet + elemmarkerindex) = vpointcount;
32498 vpointcount++;
32499 tetloop.tet = tetrahedrontraverse();
32500 }
32501
32502 * (int *) (dummytet + elemmarkerindex) = -1;
32503
32504 if (out == (tetgenio *) NULL) {
32505 fprintf(outfile, "# Generated by %s\n", b->commandline);
32506 fclose(outfile);
32507 }
32508
32509
32510 if (out == (tetgenio *) NULL) {
32511 strcpy(outfilename, b->outfilename);
32512 strcat(outfilename, ".v.edge");
32513 }
32514
32515 if (!b->quiet) {
32516 if (out == (tetgenio *) NULL) {
32517 printf("Writing %s.\n", outfilename);
32518 } else {
32519 printf("Writing Voronoi edges.\n");
32520 }
32521 }
32522
32523 if (out == (tetgenio *) NULL) {
32524 outfile = fopen(outfilename, "w");
32525 if (outfile == (FILE *) NULL) {
32526 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32527 terminatetetgen(1);
32528 }
32529
32530 fprintf(outfile, "%ld 0\n", faces);
32531 } else {
32532
32533 out->numberofedges = (int) faces;
32534 out->vedgelist = new tetgenio::voroedge[out->numberofvedges];
32535 }
32536
32537
32538
32539
32540
32541
32542 tetfaceindexarray = new int[tetrahedrons->items * 4];
32543 tetrahedrons->traversalinit();
32544 tetloop.tet = tetrahedrontraverse();
32545 vedgecount = 0;
32546 index = 0;
32547 while (tetloop.tet != (tetrahedron *) NULL) {
32548
32549
32550
32551 end1 = * (int *) (tetloop.tet + elemmarkerindex);
32552 for (i = 0; i < 4; i++) {
32553 decode(tetloop.tet[i], worktet);
32554 if ((worktet.tet == dummytet) || (tetloop.tet < worktet.tet)) {
32555 if (out == (tetgenio *) NULL) {
32556 fprintf(outfile, "%4d %4d", vedgecount + shift, end1 + shift);
32557 } else {
32558 vedge = &(out->vedgelist[index++]);
32559 vedge->v1 = end1 + shift;
32560 }
32561 end2 = * (int *) (worktet.tet + elemmarkerindex);
32562
32563 if (end2 == -1) {
32564
32565 worktet.tet = tetloop.tet;
32566 worktet.loc = i;
32567 worktet.ver = 1;
32568 pt[0] = org(worktet);
32569 pt[1] = dest(worktet);
32570 pt[2] = apex(worktet);
32571 for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j];
32572 for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j];
32573 cross(vec1, vec2, infvec);
32574
32575 L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1]
32576 + infvec[2] * infvec[2]);
32577 if (L > 0) for (j = 0; j < 3; j++) infvec[j] /= L;
32578 if (out == (tetgenio *) NULL) {
32579 fprintf(outfile, " -1");
32580 fprintf(outfile, " %g %g %g\n", infvec[0], infvec[1], infvec[2]);
32581 } else {
32582 vedge->v2 = -1;
32583 vedge->vnormal[0] = infvec[0];
32584 vedge->vnormal[1] = infvec[1];
32585 vedge->vnormal[2] = infvec[2];
32586 }
32587 } else {
32588 if (out == (tetgenio *) NULL) {
32589 fprintf(outfile, " %4d\n", end2 + shift);
32590 } else {
32591 vedge->v2 = end2 + shift;
32592 vedge->vnormal[0] = 0.0;
32593 vedge->vnormal[1] = 0.0;
32594 vedge->vnormal[2] = 0.0;
32595 }
32596 }
32597
32598 tetfaceindexarray[end1 * 4 + i] = vedgecount;
32599 if (end2 != -1) {
32600 tetfaceindexarray[end2 * 4 + worktet.loc] = vedgecount;
32601 }
32602 vedgecount++;
32603 }
32604 }
32605 tetloop.tet = tetrahedrontraverse();
32606 }
32607
32608 if (out == (tetgenio *) NULL) {
32609 fprintf(outfile, "# Generated by %s\n", b->commandline);
32610 fclose(outfile);
32611 }
32612
32613
32614 if (out == (tetgenio *) NULL) {
32615 strcpy(outfilename, b->outfilename);
32616 strcat(outfilename, ".v.face");
32617 }
32618
32619 if (!b->quiet) {
32620 if (out == (tetgenio *) NULL) {
32621 printf("Writing %s.\n", outfilename);
32622 } else {
32623 printf("Writing Voronoi faces.\n");
32624 }
32625 }
32626
32627 if (out == (tetgenio *) NULL) {
32628 outfile = fopen(outfilename, "w");
32629 if (outfile == (FILE *) NULL) {
32630 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32631 terminatetetgen(1);
32632 }
32633
32634 fprintf(outfile, "%ld 0\n", edges);
32635 } else {
32636 out->numberofvfacets = edges;
32637 out->vfacetlist = new tetgenio::vorofacet[out->numberofvfacets];
32638 if (out->vfacetlist == (tetgenio::vorofacet *) NULL) {
32639 printf("Error: Out of memory.\n");
32640 terminatetetgen(1);
32641 }
32642 }
32643
32644
32645
32646
32647
32648
32649 tetedgeindexarray = new int[tetrahedrons->items * 6];
32650 tetrahedrons->traversalinit();
32651 tetloop.tet = tetrahedrontraverse();
32652 vfacecount = 0;
32653 while (tetloop.tet != (tetrahedron *) NULL) {
32654
32655
32656
32657 worktet = tetloop;
32658 for (i = 0; i < 6; i++) {
32659 worktet.loc = edge2locver[i][0];
32660 worktet.ver = edge2locver[i][1];
32661
32662 tcount = 1;
32663 adjustedgering(worktet, CW);
32664 spintet = worktet;
32665 hitbdry = 0;
32666 while (hitbdry < 2) {
32667 if (fnextself(spintet)) {
32668 if (apex(spintet) == apex(worktet)) break;
32669 if (spintet.tet < worktet.tet) break;
32670 tcount++;
32671 } else {
32672 hitbdry++;
32673 if (hitbdry < 2) {
32674 esym(worktet, spintet);
32675 fnextself(spintet);
32676 }
32677 }
32678 }
32679
32680 if (spintet.tet >= worktet.tet) {
32681
32682 pt[0] = org(worktet);
32683 pt[1] = dest(worktet);
32684 end1 = pointmark(pt[0]) - in->firstnumber;
32685 end2 = pointmark(pt[1]) - in->firstnumber;
32686 if (out == (tetgenio *) NULL) {
32687 fprintf(outfile, "%4d %4d %4d %-2d ", vfacecount + shift,
32688 end1 + shift, end2 + shift, tcount + (hitbdry > 0));
32689 } else {
32690 vfacet = &(out->vfacetlist[vfacecount]);
32691 vfacet->c1 = end1 + shift;
32692 vfacet->c2 = end2 + shift;
32693 vfacet->elist = new int[tcount + (hitbdry > 0) + 1];
32694 vfacet->elist[0] = tcount + (hitbdry > 0);
32695 index = 1;
32696 }
32697
32698 if (hitbdry > 0) {
32699
32700 vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32701 vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32702 if (out == (tetgenio *) NULL) {
32703 fprintf(outfile, " %d", vedgecount + shift);
32704 } else {
32705 vfacet->elist[index++] = vedgecount + shift;
32706 }
32707
32708 tetedgeindexarray[vpointcount * 6 +
32709 locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32710 esymself(spintet);
32711 fnextself(spintet);
32712 }
32713
32714 for (j = 0; j < tcount; j++) {
32715 vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32716 vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32717 if (out == (tetgenio *) NULL) {
32718 fprintf(outfile, " %d", vedgecount + shift);
32719 } else {
32720 vfacet->elist[index++] = vedgecount + shift;
32721 }
32722
32723 tetedgeindexarray[vpointcount * 6 +
32724 locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32725 fnextself(spintet);
32726 }
32727 if (out == (tetgenio *) NULL) {
32728 fprintf(outfile, "\n");
32729 }
32730 vfacecount++;
32731 }
32732 }
32733 tetloop.tet = tetrahedrontraverse();
32734 }
32735
32736 if (out == (tetgenio *) NULL) {
32737 fprintf(outfile, "# Generated by %s\n", b->commandline);
32738 fclose(outfile);
32739 }
32740
32741
32742 if (out == (tetgenio *) NULL) {
32743 strcpy(outfilename, b->outfilename);
32744 strcat(outfilename, ".v.cell");
32745 }
32746
32747 if (!b->quiet) {
32748 if (out == (tetgenio *) NULL) {
32749 printf("Writing %s.\n", outfilename);
32750 } else {
32751 printf("Writing Voronoi cells.\n");
32752 }
32753 }
32754
32755 if (out == (tetgenio *) NULL) {
32756 outfile = fopen(outfilename, "w");
32757 if (outfile == (FILE *) NULL) {
32758 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32759 terminatetetgen(1);
32760 }
32761
32762 fprintf(outfile, "%ld\n", points->items);
32763 } else {
32764 out->numberofvcells = points->items;
32765 out->vcelllist = new int*[out->numberofvcells];
32766 if (out->vcelllist == (int **) NULL) {
32767 printf("Error: Out of memory.\n");
32768 terminatetetgen(1);
32769 }
32770 }
32771
32772
32773 tetlist = new list(sizeof(triface), NULL, 256);
32774 ptlist = new list(sizeof(point *), NULL, 256);
32775 points->traversalinit();
32776 ptloop = pointtraverse();
32777 vpointcount = 0;
32778 while (ptloop != (point) NULL) {
32779 decode(point2tet(ptloop), tetloop);
32780
32781 if (!isdead(&tetloop)) {
32782
32783 tetlist->append(&tetloop);
32784 formstarpolyhedron(ptloop, tetlist, ptlist, true);
32785 tcount = ptlist->len();
32786 if (out == (tetgenio *) NULL) {
32787 fprintf(outfile, "%4d %-2d ", vpointcount + shift, tcount);
32788 } else {
32789 arraysize = tcount;
32790 vertarray = out->vcelllist[vpointcount];
32791 vertarray = new int[arraysize + 1];
32792 vertarray[0] = arraysize;
32793 index = 1;
32794 }
32795
32796 for (i = 0; i < ptlist->len(); i++) {
32797 neipt = * (point *)(* ptlist)[i];
32798
32799 for (j = 0; j < tetlist->len(); j++) {
32800 tetloop = * (triface *)(* tetlist)[j];
32801 for (k = 0; k < 6; k++) {
32802 tetloop.loc = edge2locver[k][0];
32803 tetloop.ver = edge2locver[k][1];
32804 if (org(tetloop) == ptloop) {
32805 if (dest(tetloop) == neipt) break;
32806 } else if (org(tetloop) == neipt) {
32807 if (dest(tetloop) == ptloop) break;
32808 }
32809 }
32810 if (k < 6) break;
32811 }
32812 assert(j < tetlist->len());
32813
32814 end1 = * (int *) (tetloop.tet + elemmarkerindex);
32815 vfacecount = tetedgeindexarray[end1 * 6 + k];
32816 if (out == (tetgenio *) NULL) {
32817 fprintf(outfile, " %d", vfacecount + shift);
32818 } else {
32819 vertarray[index++] = vfacecount + shift;
32820 }
32821 }
32822 if (out == (tetgenio *) NULL) {
32823 fprintf(outfile, "\n");
32824 }
32825 vpointcount++;
32826 }
32827 tetlist->clear();
32828 ptlist->clear();
32829 ptloop = pointtraverse();
32830 }
32831 delete tetlist;
32832 delete ptlist;
32833 delete [] tetfaceindexarray;
32834 delete [] tetedgeindexarray;
32835
32836 if (out == (tetgenio *) NULL) {
32837 fprintf(outfile, "# Generated by %s\n", b->commandline);
32838 fclose(outfile);
32839 }
32840 }
32841
32843
32844
32845
32847
32848 void tetgenmesh::outpbcnodes(tetgenio* out)
32849 {
32850 FILE *outfile;
32851 char pbcfilename[FILENAMESIZE];
32852 list *ptpairlist;
32853 tetgenio::pbcgroup *pgi, *pgo;
32854 pbcdata *pd;
32855 face faceloop;
32856 face checkseg, symseg;
32857 point *ptpair, pa, pb;
32858 enum locateresult loc;
32859 REAL sympt[3], d1, d2;
32860 int *worklist;
32861 int firstindex, shift;
32862 int index, idx;
32863 int i, j, k, l;
32864
32865 if (out == (tetgenio *) NULL) {
32866 strcpy(pbcfilename, b->outfilename);
32867 strcat(pbcfilename, ".pbc");
32868 }
32869
32870 if (!b->quiet) {
32871 if (out == (tetgenio *) NULL) {
32872 printf("Writing %s.\n", pbcfilename);
32873 } else {
32874 printf("Writing pbc nodes.\n");
32875 }
32876 }
32877
32878
32879 outfile = (FILE *) NULL;
32880 pgo = (tetgenio::pbcgroup *) NULL;
32881 index = 0;
32882
32883 if (out == (tetgenio *) NULL) {
32884 outfile = fopen(pbcfilename, "w");
32885 if (outfile == (FILE *) NULL) {
32886 printf("File I/O Error: Cannot create file %s.\n", pbcfilename);
32887 terminatetetgen(1);
32888 }
32889
32890 fprintf(outfile, "# number of PBCs.\n");
32891 fprintf(outfile, "%d\n\n", in->numberofpbcgroups);
32892 } else {
32893 out->numberofpbcgroups = in->numberofpbcgroups;
32894
32895 out->pbcgrouplist = new tetgenio::pbcgroup[in->numberofpbcgroups];
32896
32897 if (out->pbcgrouplist == (tetgenio::pbcgroup *) NULL) {
32898 printf("Error: Out of memory.\n");
32899 terminatetetgen(1);
32900 }
32901 }
32902
32903 ptpairlist = new list(2 * sizeof(point *), NULL, 256);
32904 worklist = new int[points->items + 1];
32905 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
32906
32907
32908 firstindex = b->zeroindex ? 0 : in->firstnumber;
32909 shift = 0;
32910 if ((in->firstnumber == 1) && (firstindex == 0)) {
32911 shift = 1;
32912 }
32913
32914 for (i = 0; i < in->numberofpbcgroups; i++) {
32915
32916 pgi = &(in->pbcgrouplist[i]);
32917 if (out == (tetgenio *) NULL) {
32918 fprintf(outfile, "# PBC %d\n", in->firstnumber + i);
32919
32920 fprintf(outfile, "%d %d\n", pgi->fmark1, pgi->fmark2);
32921
32922 fprintf(outfile, "[\n");
32923 for (j = 0; j < 4; j++) {
32924 fprintf(outfile, " %.12g %.12g %.12g %.12g\n", pgi->transmat[j][0],
32925 pgi->transmat[j][1], pgi->transmat[j][2], pgi->transmat[j][3]);
32926 }
32927 fprintf(outfile, "]\n");
32928 } else {
32929 pgo = &(out->pbcgrouplist[i]);
32930
32931 pgo->fmark1 = pgi->fmark1;
32932 pgo->fmark2 = pgi->fmark2;
32933 for (j = 0; j < 4; j++) {
32934 for (k = 0; k < 4; k++) pgo->transmat[j][k] = pgi->transmat[j][k];
32935 }
32936 }
32937
32938
32939 subfaces->traversalinit();
32940 faceloop.sh = shellfacetraverse(subfaces);
32941 while (faceloop.sh != (shellface *) NULL) {
32942 if (shellpbcgroup(faceloop) == i) {
32943
32944 idx = shellmark(faceloop) - 1;
32945 if (in->facetmarkerlist[idx] == pgi->fmark1) {
32946
32947 for (j = 0; j < 3; j++) {
32948 sspivot(faceloop, checkseg);
32949
32950 for (k = 0; k < 2; k++) {
32951 if (k == 0) pa = sorg(faceloop);
32952 else pa = sdest(faceloop);
32953 if (worklist[pointmark(pa)] == 0) {
32954 pb = (point) NULL;
32955 if (checkseg.sh != dummysh) {
32956
32957
32958 idx = shellmark(checkseg) - 1;
32959 for (l = idx2segpglist[idx]; l < idx2segpglist[idx + 1];
32960 l++) {
32961 pd = (pbcdata *)(* segpbcgrouptable)[segpglist[l]];
32962 if (((pd->fmark[0] == pgi->fmark1) &&
32963 (pd->fmark[1] == pgi->fmark2)) ||
32964 ((pd->fmark[0] == pgi->fmark2) &&
32965 (pd->fmark[1] == pgi->fmark1))) break;
32966 }
32967 #ifdef SELF_CHECK
32968 assert(l < idx2segpglist[idx + 1]);
32969 #endif
32970 loc = getsegpbcsympoint(pa, &checkseg, sympt, &symseg,
32971 segpglist[l]);
32972 if (loc != ONVERTEX) {
32973
32974
32975
32976 d1 = distance(sympt, sorg(symseg));
32977 d2 = distance(sympt, sdest(symseg));
32978 if (d1 > d2) sesymself(symseg);
32979 }
32980 pb = sorg(symseg);
32981 } else {
32982
32983 if (pointtype(pa) == FREESUBVERTEX) {
32984 pb = point2pbcpt(pa);
32985 }
32986 }
32987 if (pb != (point) NULL) {
32988
32989 ptpair = (point *) ptpairlist->append(NULL);
32990 ptpair[0] = pa;
32991 ptpair[1] = pb;
32992
32993 worklist[pointmark(pa)] = 1;
32994 }
32995 }
32996 }
32997
32998 senextself(faceloop);
32999 }
33000 }
33001 }
33002 faceloop.sh = shellfacetraverse(subfaces);
33003 }
33004
33005
33006 if (out == (tetgenio *) NULL) {
33007 fprintf(outfile, "%d\n", ptpairlist->len());
33008 } else {
33009 pgo->numberofpointpairs = ptpairlist->len();
33010 pgo->pointpairlist = new int[pgo->numberofpointpairs * 2];
33011 index = 0;
33012 }
33013 for (j = 0; j < ptpairlist->len(); j++) {
33014 ptpair = (point *)(* ptpairlist)[j];
33015 pa = ptpair[0];
33016 pb = ptpair[1];
33017 if (out == (tetgenio *) NULL) {
33018 fprintf(outfile, " %4d %4d\n", pointmark(pa) - shift,
33019 pointmark(pb) - shift);
33020 } else {
33021 pgo->pointpairlist[index++] = pointmark(pa) - shift;
33022 pgo->pointpairlist[index++] = pointmark(pb) - shift;
33023 }
33024
33025 worklist[pointmark(pa)] = 0;
33026 }
33027 if (out == (tetgenio *) NULL) {
33028 fprintf(outfile, "\n");
33029 }
33030 ptpairlist->clear();
33031 }
33032
33033 delete [] worklist;
33034 delete ptpairlist;
33035
33036 if (out == (tetgenio *) NULL) {
33037 fprintf(outfile, "# Generated by %s\n", b->commandline);
33038 fclose(outfile);
33039 }
33040 }
33041
33043
33044
33045
33046
33047
33048
33049
33050
33052
33053 void tetgenmesh::outsmesh(char* smfilename)
33054 {
33055 FILE *outfile;
33056 char nodfilename[FILENAMESIZE];
33057 char smefilename[FILENAMESIZE];
33058 face faceloop;
33059 point p1, p2, p3;
33060 int firstindex, shift;
33061 int bmark;
33062 int faceid, marker;
33063 int i;
33064
33065 if (smfilename != (char *) NULL && smfilename[0] != '\0') {
33066 strcpy(smefilename, smfilename);
33067 } else if (b->outfilename[0] != '\0') {
33068 strcpy(smefilename, b->outfilename);
33069 } else {
33070 strcpy(smefilename, "unnamed");
33071 }
33072 strcpy(nodfilename, smefilename);
33073 strcat(smefilename, ".smesh");
33074 strcat(nodfilename, ".node");
33075
33076 if (!b->quiet) {
33077 printf("Writing %s.\n", smefilename);
33078 }
33079 outfile = fopen(smefilename, "w");
33080 if (outfile == (FILE *) NULL) {
33081 printf("File I/O Error: Cannot create file %s.\n", smefilename);
33082 return;
33083 }
33084
33085
33086 firstindex = b->zeroindex ? 0 : in->firstnumber;
33087 shift = 0;
33088 if ((in->firstnumber == 1) && (firstindex == 0)) {
33089 shift = 1;
33090 }
33091
33092 fprintf(outfile, "# %s. TetGen's input file.\n", smefilename);
33093 fprintf(outfile, "\n# part 1: node list.\n");
33094 fprintf(outfile, "0 3 0 0 # nodes are found in %s.\n", nodfilename);
33095
33096 marker = 0;
33097 bmark = !b->nobound && in->facetmarkerlist;
33098
33099 fprintf(outfile, "\n# part 2: facet list.\n");
33100
33101 fprintf(outfile, "%ld %d\n", subfaces->items, bmark);
33102
33103 subfaces->traversalinit();
33104 faceloop.sh = shellfacetraverse(subfaces);
33105 while (faceloop.sh != (shellface *) NULL) {
33106 p1 = sorg(faceloop);
33107 p2 = sdest(faceloop);
33108 p3 = sapex(faceloop);
33109 if (bmark) {
33110 faceid = shellmark(faceloop) - 1;
33111 if (faceid >= 0) {
33112 marker = in->facetmarkerlist[faceid];
33113 } else {
33114 marker = 0;
33115 }
33116 }
33117 fprintf(outfile, "3 %4d %4d %4d", pointmark(p1) - shift,
33118 pointmark(p2) - shift, pointmark(p3) - shift);
33119 if (bmark) {
33120 fprintf(outfile, " %d", marker);
33121 }
33122 fprintf(outfile, "\n");
33123 faceloop.sh = shellfacetraverse(subfaces);
33124 }
33125
33126
33127 fprintf(outfile, "\n# part 3: hole list.\n");
33128 fprintf(outfile, "%d\n", in->numberofholes);
33129 for (i = 0; i < in->numberofholes; i++) {
33130 fprintf(outfile, "%d %g %g %g\n", i + in->firstnumber,
33131 in->holelist[i * 3], in->holelist[i * 3 + 1],
33132 in->holelist[i * 3 + 2]);
33133 }
33134
33135
33136 fprintf(outfile, "\n# part 4: region list.\n");
33137 fprintf(outfile, "%d\n", in->numberofregions);
33138 for (i = 0; i < in->numberofregions; i++) {
33139 fprintf(outfile, "%d %g %g %g %d %g\n", i + in->firstnumber,
33140 in->regionlist[i * 5], in->regionlist[i * 5 + 1],
33141 in->regionlist[i * 5 + 2], (int) in->regionlist[i * 5 + 3],
33142 in->regionlist[i * 5 + 4]);
33143 }
33144
33145 fprintf(outfile, "# Generated by %s\n", b->commandline);
33146 fclose(outfile);
33147 }
33148
33150
33151
33152
33153
33154
33155
33156
33157
33159
33160 void tetgenmesh::outmesh2medit(char* mfilename)
33161 {
33162 FILE *outfile;
33163 char mefilename[FILENAMESIZE];
33164 tetrahedron* tetptr;
33165 triface tface, tsymface;
33166 face segloop, checkmark;
33167 point ptloop, p1, p2, p3, p4;
33168 long faces;
33169 int pointnumber;
33170 int i;
33171
33172 if (mfilename != (char *) NULL && mfilename[0] != '\0') {
33173 strcpy(mefilename, mfilename);
33174 } else if (b->outfilename[0] != '\0') {
33175 strcpy(mefilename, b->outfilename);
33176 } else {
33177 strcpy(mefilename, "unnamed");
33178 }
33179 strcat(mefilename, ".mesh");
33180
33181 if (!b->quiet) {
33182 printf("Writing %s.\n", mefilename);
33183 }
33184 outfile = fopen(mefilename, "w");
33185 if (outfile == (FILE *) NULL) {
33186 printf("File I/O Error: Cannot create file %s.\n", mefilename);
33187 return;
33188 }
33189
33190 fprintf(outfile, "MeshVersionFormatted 1\n");
33191 fprintf(outfile, "\n");
33192 fprintf(outfile, "Dimension\n");
33193 fprintf(outfile, "3\n");
33194 fprintf(outfile, "\n");
33195
33196 fprintf(outfile, "\n# Set of mesh vertices\n");
33197 fprintf(outfile, "Vertices\n");
33198 fprintf(outfile, "%ld\n", points->items);
33199
33200 points->traversalinit();
33201 ptloop = pointtraverse();
33202 pointnumber = 1;
33203 while (ptloop != (point) NULL) {
33204
33205 fprintf(outfile, "%.17g %.17g %.17g", ptloop[0], ptloop[1], ptloop[2]);
33206 if (in->numberofpointattributes > 0) {
33207
33208 fprintf(outfile, " %.17g\n", ptloop[3]);
33209 } else {
33210 fprintf(outfile, " 0\n");
33211 }
33212 setpointmark(ptloop, pointnumber);
33213 ptloop = pointtraverse();
33214 pointnumber++;
33215 }
33216
33217
33218 faces = (4l * tetrahedrons->items + hullsize) / 2l;
33219
33220 fprintf(outfile, "\n# Set of Triangles\n");
33221 fprintf(outfile, "Triangles\n");
33222 fprintf(outfile, "%ld\n", faces);
33223
33224 tetrahedrons->traversalinit();
33225 tface.tet = tetrahedrontraverse();
33226
33227
33228
33229
33230
33231
33232 while (tface.tet != (tetrahedron *) NULL) {
33233 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33234 sym(tface, tsymface);
33235 if (tface.tet < tsymface.tet || tsymface.tet == dummytet) {
33236 p1 = org (tface);
33237 p2 = dest(tface);
33238 p3 = apex(tface);
33239 fprintf(outfile, "%5d %5d %5d",
33240 pointmark(p1), pointmark(p2), pointmark(p3));
33241 fprintf(outfile, " 0\n");
33242 }
33243 }
33244 tface.tet = tetrahedrontraverse();
33245 }
33246
33247 fprintf(outfile, "\n# Set of Tetrahedra\n");
33248 fprintf(outfile, "Tetrahedra\n");
33249 fprintf(outfile, "%ld\n", tetrahedrons->items);
33250
33251 tetrahedrons->traversalinit();
33252 tetptr = tetrahedrontraverse();
33253 while (tetptr != (tetrahedron *) NULL) {
33254 p1 = (point) tetptr[4];
33255 p2 = (point) tetptr[5];
33256 p3 = (point) tetptr[6];
33257 p4 = (point) tetptr[7];
33258 fprintf(outfile, "%5d %5d %5d %5d",
33259 pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33260 if (in->numberoftetrahedronattributes > 0) {
33261 fprintf(outfile, " %.17g", elemattribute(tetptr, 0));
33262 } else {
33263 fprintf(outfile, " 0");
33264 }
33265 fprintf(outfile, "\n");
33266 tetptr = tetrahedrontraverse();
33267 }
33268
33269 fprintf(outfile, "\nCorners\n");
33270 fprintf(outfile, "%d\n", in->numberofpoints);
33271
33272 for (i = 0; i < in->numberofpoints; i++) {
33273 fprintf(outfile, "%4d\n", i + 1);
33274 }
33275
33276 if (b->useshelles) {
33277 fprintf(outfile, "\nEdges\n");
33278 fprintf(outfile, "%ld\n", subsegs->items);
33279
33280 subsegs->traversalinit();
33281 segloop.sh = shellfacetraverse(subsegs);
33282 while (segloop.sh != (shellface *) NULL) {
33283 p1 = sorg(segloop);
33284 p2 = sdest(segloop);
33285 fprintf(outfile, "%5d %5d", pointmark(p1), pointmark(p2));
33286 fprintf(outfile, " 0\n");
33287 segloop.sh = shellfacetraverse(subsegs);
33288 }
33289 }
33290
33291 fprintf(outfile, "\nEnd\n");
33292 fclose(outfile);
33293 }
33294
33296
33297
33298
33299
33300
33301
33302
33303
33304
33306
33307 void tetgenmesh::outmesh2gid(char* gfilename)
33308 {
33309 FILE *outfile;
33310 char gidfilename[FILENAMESIZE];
33311 tetrahedron* tetptr;
33312 triface tface, tsymface;
33313 face sface;
33314 point ptloop, p1, p2, p3, p4;
33315 int pointnumber;
33316 int elementnumber;
33317
33318 if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33319 strcpy(gidfilename, gfilename);
33320 } else if (b->outfilename[0] != '\0') {
33321 strcpy(gidfilename, b->outfilename);
33322 } else {
33323 strcpy(gidfilename, "unnamed");
33324 }
33325 strcat(gidfilename, ".ele.msh");
33326
33327 if (!b->quiet) {
33328 printf("Writing %s.\n", gidfilename);
33329 }
33330 outfile = fopen(gidfilename, "w");
33331 if (outfile == (FILE *) NULL) {
33332 printf("File I/O Error: Cannot create file %s.\n", gidfilename);
33333 return;
33334 }
33335
33336 fprintf(outfile, "mesh dimension = 3 elemtype tetrahedron nnode = 4\n");
33337 fprintf(outfile, "coordinates\n");
33338
33339 points->traversalinit();
33340 ptloop = pointtraverse();
33341 pointnumber = 1;
33342 while (ptloop != (point) NULL) {
33343
33344 fprintf(outfile, "%4d %.17g %.17g %.17g", pointnumber,
33345 ptloop[0], ptloop[1], ptloop[2]);
33346 if (in->numberofpointattributes > 0) {
33347
33348 fprintf(outfile, " %.17g", ptloop[3]);
33349 }
33350 fprintf(outfile, "\n");
33351 setpointmark(ptloop, pointnumber);
33352 ptloop = pointtraverse();
33353 pointnumber++;
33354 }
33355
33356 fprintf(outfile, "end coordinates\n");
33357 fprintf(outfile, "elements\n");
33358
33359 tetrahedrons->traversalinit();
33360 tetptr = tetrahedrontraverse();
33361 elementnumber = 1;
33362 while (tetptr != (tetrahedron *) NULL) {
33363 p1 = (point) tetptr[4];
33364 p2 = (point) tetptr[5];
33365 p3 = (point) tetptr[6];
33366 p4 = (point) tetptr[7];
33367 fprintf(outfile, "%5d %5d %5d %5d %5d", elementnumber,
33368 pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33369 if (in->numberoftetrahedronattributes > 0) {
33370 fprintf(outfile, " %.17g", elemattribute(tetptr, 0));
33371 }
33372 fprintf(outfile, "\n");
33373 tetptr = tetrahedrontraverse();
33374 elementnumber++;
33375 }
33376
33377 fprintf(outfile, "end elements\n");
33378 fclose(outfile);
33379
33380 if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33381 strcpy(gidfilename, gfilename);
33382 } else if (b->outfilename[0] != '\0') {
33383 strcpy(gidfilename, b->outfilename);
33384 } else {
33385 strcpy(gidfilename, "unnamed");
33386 }
33387 strcat(gidfilename, ".face.msh");
33388
33389 if (!b->quiet) {
33390 printf("Writing %s.\n", gidfilename);
33391 }
33392 outfile = fopen(gidfilename, "w");
33393 if (outfile == (FILE *) NULL) {
33394 printf("File I/O Error: Cannot create file %s.\n", gidfilename);
33395 return;
33396 }
33397
33398 fprintf(outfile, "mesh dimension = 3 elemtype triangle nnode = 3\n");
33399 fprintf(outfile, "coordinates\n");
33400
33401 points->traversalinit();
33402 ptloop = pointtraverse();
33403 pointnumber = 1;
33404 while (ptloop != (point) NULL) {
33405
33406 fprintf(outfile, "%4d %.17g %.17g %.17g", pointnumber,
33407 ptloop[0], ptloop[1], ptloop[2]);
33408 if (in->numberofpointattributes > 0) {
33409
33410 fprintf(outfile, " %.17g", ptloop[3]);
33411 }
33412 fprintf(outfile, "\n");
33413 setpointmark(ptloop, pointnumber);
33414 ptloop = pointtraverse();
33415 pointnumber++;
33416 }
33417
33418 fprintf(outfile, "end coordinates\n");
33419 fprintf(outfile, "elements\n");
33420
33421 tetrahedrons->traversalinit();
33422 tface.tet = tetrahedrontraverse();
33423 elementnumber = 1;
33424 while (tface.tet != (tetrahedron *) NULL) {
33425 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33426 sym(tface, tsymface);
33427 if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33428 p1 = org(tface);
33429 p2 = dest(tface);
33430 p3 = apex(tface);
33431 if (tsymface.tet == dummytet) {
33432
33433 fprintf(outfile, "%5d %d %d %d\n", elementnumber,
33434 pointmark(p1), pointmark(p2), pointmark(p3));
33435 elementnumber++;
33436 } else if (b->useshelles) {
33437
33438 tspivot(tface, sface);
33439 if (sface.sh != dummysh) {
33440 fprintf(outfile, "%5d %d %d %d\n", elementnumber,
33441 pointmark(p1), pointmark(p2), pointmark(p3));
33442 elementnumber++;
33443 }
33444 }
33445 }
33446 }
33447 tface.tet = tetrahedrontraverse();
33448 }
33449
33450 fprintf(outfile, "end elements\n");
33451 fclose(outfile);
33452 }
33453
33455
33456
33457
33458
33459
33460
33462
33463 void tetgenmesh::outmesh2off(char* ofilename)
33464 {
33465 FILE *outfile;
33466 char offfilename[FILENAMESIZE];
33467 triface tface, tsymface;
33468 point ptloop, p1, p2, p3;
33469 long faces;
33470 int shift;
33471
33472 if (ofilename != (char *) NULL && ofilename[0] != '\0') {
33473 strcpy(offfilename, ofilename);
33474 } else if (b->outfilename[0] != '\0') {
33475 strcpy(offfilename, b->outfilename);
33476 } else {
33477 strcpy(offfilename, "unnamed");
33478 }
33479 strcat(offfilename, ".off");
33480
33481 if (!b->quiet) {
33482 printf("Writing %s.\n", offfilename);
33483 }
33484 outfile = fopen(offfilename, "w");
33485 if (outfile == (FILE *) NULL) {
33486 printf("File I/O Error: Cannot create file %s.\n", offfilename);
33487 return;
33488 }
33489
33490
33491 faces = (4l * tetrahedrons->items + hullsize) / 2l;
33492
33493
33494 fprintf(outfile, "OFF\n%ld %ld %ld\n", points->items, faces, hullsize);
33495
33496
33497 points->traversalinit();
33498 ptloop = pointtraverse();
33499 while (ptloop != (point) NULL) {
33500 fprintf(outfile, " %.17g %.17g %.17g\n",ptloop[0], ptloop[1], ptloop[2]);
33501 ptloop = pointtraverse();
33502 }
33503
33504
33505 shift = in->firstnumber == 1 ? 1 : 0;
33506
33507 tetrahedrons->traversalinit();
33508 tface.tet = tetrahedrontraverse();
33509
33510
33511
33512
33513
33514
33515 while (tface.tet != (tetrahedron *) NULL) {
33516 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33517 sym(tface, tsymface);
33518 if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33519 p1 = org(tface);
33520 p2 = dest(tface);
33521 p3 = apex(tface);
33522
33523 fprintf(outfile, "3 %4d %4d %4d\n", pointmark(p1) - shift,
33524 pointmark(p2) - shift, pointmark(p3) - shift);
33525 }
33526 }
33527 tface.tet = tetrahedrontraverse();
33528 }
33529
33530 fprintf(outfile, "# Generated by %s\n", b->commandline);
33531 fclose(outfile);
33532 }
33533
33534
33535
33536
33537
33538
33539
33540
33541
33543
33544
33545
33547
33548 void tetgenmesh::internalerror()
33549 {
33550 printf(" Please report this bug to sihang@mail.berlios.de. Include the\n");
33551 printf(" message above, your input data set, and the exact command\n");
33552 printf(" line you used to run this program, thank you.\n");
33553 terminatetetgen(2);
33554 }
33555
33557
33558
33559
33561
33562 void tetgenmesh::checkmesh()
33563 {
33564 triface tetraloop;
33565 triface oppotet, oppooppotet;
33566 point tetorg, tetdest, tetapex, tetoppo;
33567 REAL oritest;
33568 int horrors;
33569
33570 if (!b->quiet) {
33571 printf(" Checking consistency of mesh...\n");
33572 }
33573
33574 horrors = 0;
33575
33576 tetrahedrons->traversalinit();
33577 tetraloop.tet = tetrahedrontraverse();
33578 while (tetraloop.tet != (tetrahedron *) NULL) {
33579
33580 for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33581 tetorg = org(tetraloop);
33582 tetdest = dest(tetraloop);
33583 tetapex = apex(tetraloop);
33584 tetoppo = oppo(tetraloop);
33585 if (tetraloop.loc == 0) {
33586 oritest = orient3d(tetorg, tetdest, tetapex, tetoppo);
33587 if (oritest >= 0.0) {
33588 printf(" !! !! %s ", oritest > 0.0 ? "Inverted" : "Degenerated");
33589 printtet(&tetraloop);
33590 printf(" orient3d = %.17g.\n", oritest);
33591 horrors++;
33592 }
33593 }
33594
33595 sym(tetraloop, oppotet);
33596 if (oppotet.tet != dummytet) {
33597
33598 sym(oppotet, oppooppotet);
33599 if ((tetraloop.tet != oppooppotet.tet)
33600 || (tetraloop.loc != oppooppotet.loc)) {
33601 printf(" !! !! Asymmetric tetra-tetra bond:\n");
33602 if (tetraloop.tet == oppooppotet.tet) {
33603 printf(" (Right tetrahedron, wrong orientation)\n");
33604 }
33605 printf(" First ");
33606 printtet(&tetraloop);
33607 printf(" Second (nonreciprocating) ");
33608 printtet(&oppotet);
33609 horrors++;
33610 }
33611 }
33612 }
33613 tetraloop.tet = tetrahedrontraverse();
33614 }
33615 if (horrors == 0) {
33616 if (!b->quiet) {
33617 printf(" In my studied opinion, the mesh appears to be consistent.\n");
33618 }
33619 } else if (horrors == 1) {
33620 printf(" !! !! !! !! Precisely one festering wound discovered.\n");
33621 } else {
33622 printf(" !! !! !! !! %d abominations witnessed.\n", horrors);
33623 }
33624 }
33625
33627
33628
33629
33631
33632 void tetgenmesh::checkshells()
33633 {
33634 triface oppotet, oppooppotet, testtet;
33635 face shloop, segloop, spin;
33636 face testsh, testseg, testshsh;
33637 point shorg, shdest, segorg, segdest;
33638 REAL checksign;
33639 bool same;
33640 int horrors;
33641 int i;
33642
33643 if (!b->quiet) {
33644 printf(" Checking consistency of the mesh boundary...\n");
33645 }
33646 horrors = 0;
33647
33648
33649 subfaces->traversalinit();
33650 shloop.sh = shellfacetraverse(subfaces);
33651 while (shloop.sh != (shellface *) NULL) {
33652
33653 shloop.shver = 0;
33654 stpivot(shloop, oppotet);
33655 if (oppotet.tet != dummytet) {
33656 tspivot(oppotet, testsh);
33657 if (testsh.sh != shloop.sh) {
33658 printf(" !! !! Wrong tetra-subface connection.\n");
33659 printf(" Tetra: ");
33660 printtet(&oppotet);
33661 printf(" Subface: ");
33662 printsh(&shloop);
33663 horrors++;
33664 }
33665 if (oppo(oppotet) != (point) NULL) {
33666 adjustedgering(oppotet, CCW);
33667 checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33668 oppo(oppotet));
33669 if (checksign >= 0.0) {
33670 printf(" !! !! Wrong subface orientation.\n");
33671 printf(" Subface: ");
33672 printsh(&shloop);
33673 horrors++;
33674 }
33675 }
33676 }
33677 sesymself(shloop);
33678 stpivot(shloop, oppooppotet);
33679 if (oppooppotet.tet != dummytet) {
33680 tspivot(oppooppotet, testsh);
33681 if (testsh.sh != shloop.sh) {
33682 printf(" !! !! Wrong tetra-subface connection.\n");
33683 printf(" Tetra: ");
33684 printtet(&oppooppotet);
33685 printf(" Subface: ");
33686 printsh(&shloop);
33687 horrors++;
33688 }
33689 if (oppotet.tet != dummytet) {
33690 sym(oppotet, testtet);
33691 if (testtet.tet != oppooppotet.tet) {
33692 printf(" !! !! Wrong tetra-subface-tetra connection.\n");
33693 printf(" Tetra 1: ");
33694 printtet(&oppotet);
33695 printf(" Subface: ");
33696 printsh(&shloop);
33697 printf(" Tetra 2: ");
33698 printtet(&oppooppotet);
33699 horrors++;
33700 }
33701 }
33702 if (oppo(oppooppotet) != (point) NULL) {
33703 adjustedgering(oppooppotet, CCW);
33704 checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33705 oppo(oppooppotet));
33706 if (checksign >= 0.0) {
33707 printf(" !! !! Wrong subface orientation.\n");
33708 printf(" Subface: ");
33709 printsh(&shloop);
33710 horrors++;
33711 }
33712 }
33713 }
33714
33715 shloop.shver = 0;
33716 for (i = 0; i < 3; i++) {
33717 shorg = sorg(shloop);
33718 shdest = sdest(shloop);
33719 sspivot(shloop, testseg);
33720 if (testseg.sh != dummysh) {
33721 segorg = sorg(testseg);
33722 segdest = sdest(testseg);
33723 same = ((shorg == segorg) && (shdest == segdest))
33724 || ((shorg == segdest) && (shdest == segorg));
33725 if (!same) {
33726 printf(" !! !! Wrong subface-subsegment connection.\n");
33727 printf(" Subface: ");
33728 printsh(&shloop);
33729 printf(" Subsegment: ");
33730 printsh(&testseg);
33731 horrors++;
33732 }
33733 }
33734 spivot(shloop, testsh);
33735 if (testsh.sh != dummysh) {
33736 segorg = sorg(testsh);
33737 segdest = sdest(testsh);
33738 same = ((shorg == segorg) && (shdest == segdest))
33739 || ((shorg == segdest) && (shdest == segorg));
33740 if (!same) {
33741 printf(" !! !! Wrong subface-subface connection.\n");
33742 printf(" Subface 1: ");
33743 printsh(&shloop);
33744 printf(" Subface 2: ");
33745 printsh(&testsh);
33746 horrors++;
33747 }
33748 spivot(testsh, testshsh);
33749 shorg = sorg(testshsh);
33750 shdest = sdest(testshsh);
33751 same = ((shorg == segorg) && (shdest == segdest))
33752 || ((shorg == segdest) && (shdest == segorg));
33753 if (!same) {
33754 printf(" !! !! Wrong subface-subface connection.\n");
33755 printf(" Subface 1: ");
33756 printsh(&testsh);
33757 printf(" Subface 2: ");
33758 printsh(&testshsh);
33759 horrors++;
33760 }
33761 if (testseg.sh == dummysh) {
33762 if (testshsh.sh != shloop.sh) {
33763 printf(" !! !! Wrong subface-subface connection.\n");
33764 printf(" Subface 1: ");
33765 printsh(&shloop);
33766 printf(" Subface 2: ");
33767 printsh(&testsh);
33768 horrors++;
33769 }
33770 }
33771 }
33772 senextself(shloop);
33773 }
33774 shloop.sh = shellfacetraverse(subfaces);
33775 }
33776
33777
33778 subsegs->traversalinit();
33779 segloop.sh = shellfacetraverse(subsegs);
33780 while (segloop.sh != (shellface *) NULL) {
33781 segorg = sorg(segloop);
33782 segdest = sdest(segloop);
33783 spivot(segloop, testsh);
33784 if (testsh.sh == dummysh) {
33785 printf(" !! !! Wrong subsegment-subface connection.\n");
33786 printf(" Subsegment: ");
33787 printsh(&segloop);
33788 horrors++;
33789 segloop.sh = shellfacetraverse(subsegs);
33790 continue;
33791 }
33792 shorg = sorg(testsh);
33793 shdest = sdest(testsh);
33794 same = ((shorg == segorg) && (shdest == segdest))
33795 || ((shorg == segdest) && (shdest == segorg));
33796 if (!same) {
33797 printf(" !! !! Wrong subsegment-subface connection.\n");
33798 printf(" Subsegment : ");
33799 printsh(&segloop);
33800 printf(" Subface : ");
33801 printsh(&testsh);
33802 horrors++;
33803 segloop.sh = shellfacetraverse(subsegs);
33804 continue;
33805 }
33806
33807 spin = testsh;
33808 i = 0;
33809 do {
33810 spivotself(spin);
33811 shorg = sorg(spin);
33812 shdest = sdest(spin);
33813 same = ((shorg == segorg) && (shdest == segdest))
33814 || ((shorg == segdest) && (shdest == segorg));
33815 if (!same) {
33816 printf(" !! !! Wrong subsegment-subface connection.\n");
33817 printf(" Subsegment : ");
33818 printsh(&segloop);
33819 printf(" Subface : ");
33820 printsh(&testsh);
33821 horrors++;
33822 break;
33823 }
33824 i++;
33825 } while (spin.sh != testsh.sh && i < 1000);
33826 if (i >= 1000) {
33827 printf(" !! !! Wrong subsegment-subface connection.\n");
33828 printf(" Subsegment : ");
33829 printsh(&segloop);
33830 horrors++;
33831 }
33832 segloop.sh = shellfacetraverse(subsegs);
33833 }
33834 if (horrors == 0) {
33835 if (!b->quiet) {
33836 printf(" Mesh boundaries connected correctly.\n");
33837 }
33838 } else {
33839 printf(" !! !! !! !! %d boundary connection viewed with horror.\n",
33840 horrors);
33841 return;
33842 }
33843 }
33844
33846
33847
33848
33849
33850
33852
33853 void tetgenmesh::checkdelaunay(REAL eps, queue* flipqueue)
33854 {
33855 triface tetraloop;
33856 triface oppotet;
33857 face opposhelle;
33858 point tetorg, tetdest, tetapex, tetoppo;
33859 point oppooppo;
33860 enum fliptype fc;
33861 REAL sign;
33862 int shouldbedelaunay;
33863 int horrors;
33864
33865 if (!b->quiet) {
33866 printf(" Checking Delaunay property of the mesh...\n");
33867 }
33868 horrors = 0;
33869
33870 tetrahedrons->traversalinit();
33871 tetraloop.tet = tetrahedrontraverse();
33872 while (tetraloop.tet != (tetrahedron *) NULL) {
33873
33874 for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33875 tetorg = org(tetraloop);
33876 tetdest = dest(tetraloop);
33877 tetapex = apex(tetraloop);
33878 tetoppo = oppo(tetraloop);
33879 sym(tetraloop, oppotet);
33880 oppooppo = oppo(oppotet);
33881
33882
33883 shouldbedelaunay = (oppotet.tet != dummytet)
33884 && (tetoppo != (point) NULL)
33885 && (oppooppo != (point) NULL)
33886 && (tetraloop.tet < oppotet.tet);
33887 if (checksubfaces && shouldbedelaunay) {
33888
33889
33890 tspivot(tetraloop, opposhelle);
33891 if (opposhelle.sh != dummysh){
33892 shouldbedelaunay = 0;
33893 }
33894 }
33895 if (shouldbedelaunay) {
33896 sign = insphere(tetdest, tetorg, tetapex, tetoppo, oppooppo);
33897 if ((sign > 0.0) && (eps > 0.0)) {
33898 if (iscospheric(tetdest, tetorg, tetapex, tetoppo, oppooppo, sign,
33899 eps)) sign = 0.0;
33900 }
33901 if (sign > 0.0) {
33902 if (flipqueue) {
33903 enqueueflipface(tetraloop, flipqueue);
33904 } else {
33905 printf(" !! Non-locally Delaunay face (%d, %d, %d) ",
33906 pointmark(tetorg), pointmark(tetdest), pointmark(tetapex));
33907 fc = categorizeface(tetraloop);
33908 switch (fc) {
33909 case T23: printf("\"T23\""); break;
33910 case T32: printf("\"T32\""); break;
33911 case T22: printf("\"T22\""); break;
33912 case T44: printf("\"T44\""); break;
33913 case N32: printf("\"N32\""); break;
33914 case N40: printf("\"N40\""); break;
33915 case FORBIDDENFACE:printf("\"FORBIDDENFACE\""); break;
33916 case FORBIDDENEDGE:printf("\"FORBIDDENEDGE\""); break;
33917 }
33918 printf("\n");
33919 }
33920 horrors++;
33921 }
33922 }
33923 }
33924 tetraloop.tet = tetrahedrontraverse();
33925 }
33926 if (flipqueue == (queue *) NULL) {
33927 if (horrors == 0) {
33928 if (!b->quiet) {
33929 printf(" The mesh is %s.\n",
33930 checksubfaces ? "constrained Delaunay" : "Delaunay");
33931 }
33932 } else {
33933 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
33934 }
33935 }
33936 }
33937
33939
33940
33941
33943
33944 void tetgenmesh::checkconforming()
33945 {
33946 face segloop, shloop;
33947 int encsubsegs, encsubfaces;
33948
33949 if (!b->quiet) {
33950 printf(" Checking conforming Delaunay property of mesh...\n");
33951 }
33952 encsubsegs = encsubfaces = 0;
33953
33954 subsegs->traversalinit();
33955 segloop.sh = shellfacetraverse(subsegs);
33956 while (segloop.sh != (shellface *) NULL) {
33957 if (checkseg4encroach(&segloop, NULL, NULL, false)) {
33958 printf(" !! !! Non-conforming subsegment: (%d, %d)\n",
33959 pointmark(sorg(segloop)), pointmark(sdest(segloop)));
33960 encsubsegs++;
33961 }
33962 segloop.sh = shellfacetraverse(subsegs);
33963 }
33964
33965 subfaces->traversalinit();
33966 shloop.sh = shellfacetraverse(subfaces);
33967 while (shloop.sh != (shellface *) NULL) {
33968 if (checksub4encroach(&shloop, NULL, false)) {
33969 printf(" !! !! Non-conforming subface: (%d, %d, %d)\n",
33970 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
33971 pointmark(sapex(shloop)));
33972 encsubfaces++;
33973 }
33974 shloop.sh = shellfacetraverse(subfaces);
33975 }
33976 if (encsubsegs == 0 && encsubfaces == 0) {
33977 if (!b->quiet) {
33978 printf(" The mesh is conforming Delaunay.\n");
33979 }
33980 } else {
33981 if (encsubsegs > 0) {
33982 printf(" !! !! %d subsegments are non-conforming.\n", encsubsegs);
33983 }
33984 if (encsubfaces > 0) {
33985 printf(" !! !! %d subfaces are non-conforming.\n", encsubfaces);
33986 }
33987 }
33988 }
33989
33991
33992
33993
33995
33996 #ifdef SELF_CHECK
33997
33998 void tetgenmesh::algorithmicstatistics()
33999 {
34000
34001
34002
34003
34004
34005
34006
34007
34008
34009
34010
34011
34012
34013
34014
34015
34016
34017
34018
34019
34020
34021
34022
34023
34024
34025
34026
34027
34028
34029
34030
34031
34032
34033
34034
34035
34036 }
34037
34038 #endif // #ifdef SELF_CHECK
34039
34041
34042
34043
34045
34046 void tetgenmesh::qualitystatistics()
34047 {
34048 triface tetloop, neightet;
34049 point p[4];
34050 char sbuf[128];
34051 REAL radiusratiotable[12];
34052 REAL aspectratiotable[12];
34053 REAL A[4][4], rhs[4], D;
34054 REAL V[6][3], N[4][3], H[4];
34055 REAL edgelength[6], alldihed[6], faceangle[3];
34056 REAL shortest, longest;
34057 REAL smallestvolume, biggestvolume;
34058 REAL smallestdiangle, biggestdiangle;
34059 REAL smallestfaangle, biggestfaangle;
34060 REAL tetvol, minaltitude;
34061 REAL cirradius, minheightinv;
34062 REAL shortlen, longlen;
34063 REAL tetaspect, tetradius;
34064 REAL smalldiangle, bigdiangle;
34065 REAL smallfaangle, bigfaangle;
34066 int radiustable[12];
34067 int aspecttable[16];
34068 int dihedangletable[18];
34069 int faceangletable[18];
34070 int indx[4];
34071 int radiusindex;
34072 int aspectindex;
34073 int tendegree;
34074 int i, j;
34075
34076 smallfaangle = 0.0;
34077 bigfaangle = 0.0;
34078
34079 printf("Mesh quality statistics:\n\n");
34080
34081
34082 shortlen = longlen = 0.0;
34083 smalldiangle = bigdiangle = 0.0;
34084
34085 radiusratiotable[0] = 0.707; radiusratiotable[1] = 1.0;
34086 radiusratiotable[2] = 1.1; radiusratiotable[3] = 1.2;
34087 radiusratiotable[4] = 1.4; radiusratiotable[5] = 1.6;
34088 radiusratiotable[6] = 1.8; radiusratiotable[7] = 2.0;
34089 radiusratiotable[8] = 2.5; radiusratiotable[9] = 3.0;
34090 radiusratiotable[10] = 10.0; radiusratiotable[11] = 0.0;
34091
34092 aspectratiotable[0] = 1.5; aspectratiotable[1] = 2.0;
34093 aspectratiotable[2] = 2.5; aspectratiotable[3] = 3.0;
34094 aspectratiotable[4] = 4.0; aspectratiotable[5] = 6.0;
34095 aspectratiotable[6] = 10.0; aspectratiotable[7] = 15.0;
34096 aspectratiotable[8] = 25.0; aspectratiotable[9] = 50.0;
34097 aspectratiotable[10] = 100.0; aspectratiotable[11] = 0.0;
34098
34099 for (i = 0; i < 12; i++) radiustable[i] = 0;
34100 for (i = 0; i < 12; i++) aspecttable[i] = 0;
34101 for (i = 0; i < 18; i++) dihedangletable[i] = 0;
34102 for (i = 0; i < 18; i++) faceangletable[i] = 0;
34103
34104 minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
34105 minaltitude = minaltitude * minaltitude;
34106 shortest = minaltitude;
34107 longest = 0.0;
34108 smallestvolume = minaltitude;
34109 biggestvolume = 0.0;
34110 smallestdiangle = smallestfaangle = 180.0;
34111 biggestdiangle = biggestfaangle = 0.0;
34112
34113
34114 tetrahedrons->traversalinit();
34115 tetloop.tet = tetrahedrontraverse();
34116 while (tetloop.tet != (tetrahedron *) NULL) {
34117
34118
34119 for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i];
34120
34121 for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i];
34122 for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i];
34123 for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i];
34124 for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i];
34125 for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i];
34126 for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i];
34127
34128 for (j = 0; j < 3; j++) {
34129 for (i = 0; i < 3; i++) A[j][i] = V[j][i];
34130 }
34131
34132 lu_decmp(A, 3, indx, &D, 0);
34133
34134 tetvol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
34135
34136 for (j = 0; j < 3; j++) {
34137 for (i = 0; i < 3; i++) rhs[i] = 0.0;
34138 rhs[j] = 1.0;
34139 lu_solve(A, 3, indx, rhs, 0);
34140 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
34141 }
34142
34143 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
34144
34145 for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]);
34146 lu_solve(A, 3, indx, rhs, 0);
34147 cirradius = sqrt(dot(rhs, rhs));
34148
34149 for (i = 0; i < 4; i++) {
34150
34151 H[i] = sqrt(dot(N[i], N[i]));
34152 for (j = 0; j < 3; j++) N[i][j] /= H[i];
34153 }
34154
34155
34156
34157 minheightinv = H[0];
34158 for (i = 1; i < 3; i++) {
34159 if (H[i] > minheightinv) minheightinv = H[i];
34160 }
34161
34162 for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
34163
34164 j = 0;
34165 for (i = 1; i < 4; i++) {
34166 alldihed[j] = -dot(N[0], N[i]);
34167 if (alldihed[j] < -1.0) alldihed[j] = -1;
34168 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34169 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34170 j++;
34171 }
34172 for (i = 2; i < 4; i++) {
34173 alldihed[j] = -dot(N[1], N[i]);
34174 if (alldihed[j] < -1.0) alldihed[j] = -1;
34175 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34176 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34177 j++;
34178 }
34179 alldihed[j] = -dot(N[2], N[3]);
34180 if (alldihed[j] < -1.0) alldihed[j] = -1;
34181 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34182 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34183
34184
34185 for (i = 0; i < 6; i++) {
34186 if (i == 0) {
34187 shortlen = longlen = edgelength[i];
34188 } else {
34189 shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen;
34190 longlen = edgelength[i] > longlen ? edgelength[i] : longlen;
34191 }
34192 if (edgelength[i] > longest) {
34193 longest = edgelength[i];
34194 }
34195 if (edgelength[i] < shortest) {
34196 shortest = edgelength[i];
34197 }
34198 }
34199
34200
34201 if (tetvol < smallestvolume) {
34202 smallestvolume = tetvol;
34203 }
34204 if (tetvol > biggestvolume) {
34205 biggestvolume = tetvol;
34206 }
34207
34208
34209 for (i = 0; i < 6; i++) {
34210 if (i == 0) {
34211 smalldiangle = bigdiangle = alldihed[i];
34212 } else {
34213 smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle;
34214 bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle;
34215 }
34216 if (alldihed[i] < smallestdiangle) {
34217 smallestdiangle = alldihed[i];
34218 }
34219 if (alldihed[i] > biggestdiangle) {
34220 biggestdiangle = alldihed[i];
34221 }
34222 }
34223
34224 if (smalldiangle < 5.0) {
34225 tendegree = 0;
34226 } else if (smalldiangle >= 5.0 && smalldiangle < 10.0) {
34227 tendegree = 1;
34228 } else if (smalldiangle >= 80.0 && smalldiangle < 110.0) {
34229 tendegree = 9;
34230 } else {
34231 tendegree = (int) (smalldiangle / 10.);
34232 if (smalldiangle < 80.0) {
34233 tendegree++;
34234 } else {
34235 tendegree--;
34236 }
34237 }
34238 dihedangletable[tendegree]++;
34239 if (bigdiangle >= 80.0 && bigdiangle < 110.0) {
34240 tendegree = 9;
34241 } else if (bigdiangle >= 170.0 && bigdiangle < 175.0) {
34242 tendegree = 16;
34243 } else if (bigdiangle >= 175.0) {
34244 tendegree = 17;
34245 } else {
34246 tendegree = (int) (bigdiangle / 10.);
34247 if (bigdiangle < 80.0) {
34248 tendegree++;
34249 } else {
34250 tendegree--;
34251 }
34252 }
34253 dihedangletable[tendegree]++;
34254
34255
34256 tetloop.ver = 0;
34257 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
34258 sym(tetloop, neightet);
34259
34260 if ((neightet.tet == dummytet) || (tetloop.tet < neightet.tet)) {
34261 p[0] = org(tetloop);
34262 p[1] = dest(tetloop);
34263 p[2] = apex(tetloop);
34264 faceangle[0] = interiorangle(p[0], p[1], p[2], NULL);
34265 faceangle[1] = interiorangle(p[1], p[2], p[0], NULL);
34266 faceangle[2] = PI - (faceangle[0] + faceangle[1]);
34267
34268 for (i = 0; i < 3; i++) {
34269 faceangle[i] = (faceangle[i] * 180.0) / PI;
34270 }
34271
34272 for (i = 0; i < 3; i++) {
34273 if (i == 0) {
34274 smallfaangle = bigfaangle = faceangle[i];
34275 } else {
34276 smallfaangle = faceangle[i] < smallfaangle ?
34277 faceangle[i] : smallfaangle;
34278 bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle;
34279 }
34280 if (faceangle[i] < smallestfaangle) {
34281 smallestfaangle = faceangle[i];
34282 }
34283 if (faceangle[i] > biggestfaangle) {
34284 biggestfaangle = faceangle[i];
34285 }
34286 }
34287 tendegree = (int) (smallfaangle / 10.);
34288 faceangletable[tendegree]++;
34289 tendegree = (int) (bigfaangle / 10.);
34290 faceangletable[tendegree]++;
34291 }
34292 }
34293
34294
34295 tetradius = cirradius / sqrt(shortlen);
34296
34297 tetaspect = sqrt(longlen) * minheightinv;
34298 aspectindex = 0;
34299 while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) {
34300 aspectindex++;
34301 }
34302 aspecttable[aspectindex]++;
34303 radiusindex = 0;
34304 while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) {
34305 radiusindex++;
34306 }
34307 radiustable[radiusindex]++;
34308
34309 tetloop.tet = tetrahedrontraverse();
34310 }
34311
34312 shortest = sqrt(shortest);
34313 longest = sqrt(longest);
34314 minaltitude = sqrt(minaltitude);
34315
34316 printf(" Smallest volume: %16.5g | Largest volume: %16.5g\n",
34317 smallestvolume, biggestvolume);
34318 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n",
34319 shortest, longest);
34320 sprintf(sbuf, "%.17g", biggestfaangle);
34321 if (strlen(sbuf) > 8) {
34322 sbuf[8] = '\0';
34323 }
34324 printf(" Smallest facangle: %14.5g | Largest facangle: %s\n",
34325 smallestfaangle, sbuf);
34326 sprintf(sbuf, "%.17g", biggestdiangle);
34327 if (strlen(sbuf) > 8) {
34328 sbuf[8] = '\0';
34329 }
34330 printf(" Smallest dihedral: %14.5g | Largest dihedral: %s\n\n",
34331 smallestdiangle, sbuf);
34332
34333
34334
34335
34336
34337
34338
34339
34340
34341
34342
34343
34344
34345
34346
34347
34348
34349
34350
34351
34352 printf(" Aspect ratio histogram:\n");
34353 printf(" < %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
34354 aspectratiotable[0], aspecttable[0], aspectratiotable[5],
34355 aspectratiotable[6], aspecttable[6]);
34356 for (i = 1; i < 5; i++) {
34357 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
34358 aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i],
34359 aspectratiotable[i + 5], aspectratiotable[i + 6],
34360 aspecttable[i + 6]);
34361 }
34362 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
34363 aspectratiotable[4], aspectratiotable[5], aspecttable[5],
34364 aspectratiotable[10], aspecttable[11]);
34365 printf(" (A tetrahedron's aspect ratio is its longest edge length");
34366 printf(" divided by its\n");
34367 printf(" smallest side height)\n\n");
34368
34369 printf(" Face angle histogram:\n");
34370 for (i = 0; i < 9; i++) {
34371 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
34372 i * 10, i * 10 + 10, faceangletable[i],
34373 i * 10 + 90, i * 10 + 100, faceangletable[i + 9]);
34374 }
34375 if (minfaceang != PI) {
34376 printf(" Minimum input face angle is %g (degree).\n",
34377 minfaceang / PI * 180.0);
34378 }
34379 printf("\n");
34380
34381 printf(" Dihedral angle histogram:\n");
34382
34383 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34384 0, 5, dihedangletable[0], 80, 110, dihedangletable[9]);
34385 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34386 5, 10, dihedangletable[1], 110, 120, dihedangletable[10]);
34387
34388 for (i = 2; i < 7; i++) {
34389 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34390 (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i],
34391 (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]);
34392 }
34393
34394 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34395 60, 70, dihedangletable[7], 170, 175, dihedangletable[16]);
34396 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34397 70, 80, dihedangletable[8], 175, 180, dihedangletable[17]);
34398 if (minfacetdihed != PI) {
34399 printf(" Minimum input facet dihedral angle is %g (degree).\n",
34400 minfacetdihed / PI * 180.0);
34401 }
34402 printf("\n");
34403 }
34404
34406
34407
34408
34410
34411 void tetgenmesh::statistics()
34412 {
34413 printf("\nStatistics:\n\n");
34414 printf(" Input points: %d\n", in->numberofpoints + jettisoninverts);
34415 if (b->refine) {
34416 printf(" Input tetrahedra: %d\n", in->numberoftetrahedra);
34417 }
34418 if (b->plc) {
34419 printf(" Input facets: %d\n", in->numberoffacets);
34420 printf(" Input segments: %ld\n", insegments);
34421 printf(" Input holes: %d\n", in->numberofholes);
34422 printf(" Input regions: %d\n", in->numberofregions);
34423 }
34424
34425 printf("\n Mesh points: %ld\n", points->items);
34426 printf(" Mesh tetrahedra: %ld\n", tetrahedrons->items);
34427 if (b->plc || b->refine) {
34428 printf(" Mesh triangles: %ld\n", (4l*tetrahedrons->items+hullsize)/2l);
34429 }
34430 if (b->plc || b->refine) {
34431 printf(" Mesh subfaces: %ld\n", subfaces->items);
34432 printf(" Mesh subsegments: %ld\n\n", subsegs->items);
34433 } else {
34434 printf(" Convex hull triangles: %ld\n\n", hullsize);
34435 }
34436 if (b->verbose > 0) {
34437 qualitystatistics();
34438 unsigned long totalmeshbytes;
34439 printf("Memory allocation statistics:\n\n");
34440 printf(" Maximum number of vertices: %ld\n", points->maxitems);
34441 totalmeshbytes = points->maxitems * points->itembytes;
34442 printf(" Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems);
34443 totalmeshbytes += tetrahedrons->maxitems * tetrahedrons->itembytes;
34444 if (subfaces != (memorypool *) NULL) {
34445 printf(" Maximum number of subfaces: %ld\n", subfaces->maxitems);
34446 totalmeshbytes += subfaces->maxitems * subfaces->itembytes;
34447 }
34448 if (subsegs != (memorypool *) NULL) {
34449 printf(" Maximum number of segments: %ld\n", subsegs->maxitems);
34450 totalmeshbytes += subsegs->maxitems * subsegs->itembytes;
34451 }
34452 printf(" Approximate heap memory used by the mesh (K bytes): %g\n\n",
34453 (double) totalmeshbytes / 1024.0);
34454 #ifdef SELF_CHECK
34455 algorithmicstatistics();
34456 #endif
34457 }
34458 }
34459
34460
34461
34462
34463
34464
34465
34466
34467
34469
34470
34471
34473
34474 tetgenmesh::~tetgenmesh()
34475 {
34476 bgm = (tetgenmesh *) NULL;
34477 in = (tetgenio *) NULL;
34478 b = (tetgenbehavior *) NULL;
34479
34480 if (tetrahedrons != (memorypool *) NULL) {
34481 delete tetrahedrons;
34482 }
34483 if (subfaces != (memorypool *) NULL) {
34484 delete subfaces;
34485 }
34486 if (subsegs != (memorypool *) NULL) {
34487 delete subsegs;
34488 }
34489 if (points != (memorypool *) NULL) {
34490 delete points;
34491 }
34492 if (dummytetbase != (tetrahedron *) NULL) {
34493 delete [] dummytetbase;
34494 }
34495 if (dummyshbase != (shellface *) NULL) {
34496 delete [] dummyshbase;
34497 }
34498 if (facetabovepointarray != (point *) NULL) {
34499 delete [] facetabovepointarray;
34500 }
34501 if (highordertable != (point *) NULL) {
34502 delete [] highordertable;
34503 }
34504 if (subpbcgrouptable != (pbcdata *) NULL) {
34505 delete [] subpbcgrouptable;
34506 }
34507 if (segpbcgrouptable != (list *) NULL) {
34508 delete segpbcgrouptable;
34509 delete [] idx2segpglist;
34510 delete [] segpglist;
34511 }
34512 }
34513
34515
34516
34517
34519
34520 tetgenmesh::tetgenmesh()
34521 {
34522 bgm = (tetgenmesh *) NULL;
34523 in = (tetgenio *) NULL;
34524 b = (tetgenbehavior *) NULL;
34525
34526 tetrahedrons = (memorypool *) NULL;
34527 subfaces = (memorypool *) NULL;
34528 subsegs = (memorypool *) NULL;
34529 points = (memorypool *) NULL;
34530 badsubsegs = (memorypool *) NULL;
34531 badsubfaces = (memorypool *) NULL;
34532 badtetrahedrons = (memorypool *) NULL;
34533 flipstackers = (memorypool *) NULL;
34534
34535 dummytet = (tetrahedron *) NULL;
34536 dummytetbase = (tetrahedron *) NULL;
34537 dummysh = (shellface *) NULL;
34538 dummyshbase = (shellface *) NULL;
34539
34540 facetabovepointarray = (point *) NULL;
34541 abovepoint = (point) NULL;
34542 highordertable = (point *) NULL;
34543 subpbcgrouptable = (pbcdata *) NULL;
34544 segpbcgrouptable = (list *) NULL;
34545 idx2segpglist = (int *) NULL;
34546 segpglist = (int *) NULL;
34547
34548 xmax = xmin = ymax = ymin = zmax = zmin = 0.0;
34549 longest = 0.0;
34550 hullsize = 0l;
34551 insegments = 0l;
34552 pointmtrindex = 0;
34553 pointmarkindex = 0;
34554 point2simindex = 0;
34555 point2pbcptindex = 0;
34556 highorderindex = 0;
34557 elemattribindex = 0;
34558 volumeboundindex = 0;
34559 shmarkindex = 0;
34560 areaboundindex = 0;
34561 checksubfaces = 0;
34562 checksubsegs = 0;
34563 checkpbcs = 0;
34564 varconstraint = 0;
34565 nonconvex = 0;
34566 dupverts = 0;
34567 unuverts = 0;
34568 relverts = 0;
34569 suprelverts = 0;
34570 collapverts = 0;
34571 unsupverts = 0;
34572 jettisoninverts = 0;
34573 symbolic = 1;
34574 samples = 0l;
34575 randomseed = 1l;
34576 macheps = 0.0;
34577 minfaceang = minfacetdihed = PI;
34578 maxcavfaces = maxcavverts = 0;
34579 expcavcount = 0;
34580 abovecount = 0l;
34581 bowatvolcount = bowatsubcount = bowatsegcount = 0l;
34582 updvolcount = updsubcount = updsegcount = 0l;
34583 repairflipcount = 0l;
34584 outbowatcircumcount = 0l;
34585 failvolcount = failsubcount = failsegcount = 0l;
34586 r1count = r2count = r3count = 0l;
34587 cdtenforcesegpts = 0l;
34588 rejsegpts = rejsubpts = rejtetpts = 0l;
34589 flip23s = flip32s = flip22s = flip44s = 0l;
34590 tloctime = tfliptime = 0.0;
34591 }
34592
34593
34594
34595
34596
34597
34598
34599
34600
34602
34603
34604
34605
34606
34607
34608
34609
34610
34611
34612
34613
34614
34615
34616
34617
34618
34619
34620
34621
34622
34624
34625 void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
34626 tetgenio *addin, tetgenio *bgmin)
34627 {
34628 tetgenmesh m;
34629
34630 clock_t tv[14];
34631
34632 tv[0] = clock();
34633
34634 m.b = b;
34635 m.in = in;
34636 m.macheps = exactinit();
34637 m.steinerleft = b->steiner;
34638 if (b->metric) {
34639 m.bgm = new tetgenmesh();
34640 m.bgm->b = b;
34641 m.bgm->in = bgmin;
34642 m.bgm->macheps = exactinit();
34643 }
34644 m.initializepools();
34645 m.transfernodes();
34646
34647 tv[1] = clock();
34648
34649 if (b->refine) {
34650 m.reconstructmesh();
34651 } else {
34652 m.delaunizevertices();
34653 }
34654
34655 tv[2] = clock();
34656
34657 if (!b->quiet) {
34658 if (b->refine) {
34659 printf("Mesh reconstruction seconds:");
34660 } else {
34661 printf("Delaunay seconds:");
34662 }
34663 printf(" %g\n", (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
34664 }
34665
34666 if (b->metric) {
34667 if (bgmin != (tetgenio *) NULL) {
34668 m.bgm->initializepools();
34669 m.bgm->transfernodes();
34670 m.bgm->reconstructmesh();
34671 } else {
34672 m.bgm->in = in;
34673 m.bgm->initializepools();
34674 m.duplicatebgmesh();
34675 }
34676 }
34677
34678 tv[3] = clock();
34679
34680 if (!b->quiet) {
34681 if (b->metric) {
34682 printf("Background mesh reconstruct seconds: %g\n",
34683 (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
34684 }
34685 }
34686
34687 if (b->useshelles && !b->refine) {
34688 m.meshsurface();
34689 if (b->diagnose != 1) {
34690 m.markacutevertices(89.0);
34691 m.incrperturbvertices(b->epsilon);
34692 m.delaunizesegments();
34693 if (m.checkpbcs) {
34694 long oldnum;
34695 do {
34696 oldnum = m.points->items;
34697 m.incrperturbvertices(b->epsilon);
34698 if (m.points->items > oldnum) {
34699 oldnum = m.points->items;
34700 m.delaunizesegments();
34701 }
34702 } while (oldnum < m.points->items);
34703 }
34704 m.constrainedfacets();
34705 } else {
34706 m.detectinterfaces();
34707 }
34708 }
34709
34710 tv[4] = clock();
34711
34712 if (!b->quiet) {
34713 if (b->useshelles && !b->refine) {
34714 if (b->diagnose != 1) {
34715 printf("Segment and facet ");
34716 } else {
34717 printf("Intersection ");
34718 }
34719 printf("seconds: %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
34720 }
34721 }
34722
34723 if (b->plc && !(b->diagnose == 1)) {
34724 m.carveholes();
34725 }
34726
34727 tv[5] = clock();
34728
34729 if (!b->quiet) {
34730 if (b->plc && !(b->diagnose == 1)) {
34731 printf("Hole seconds: %g\n", (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
34732 }
34733 }
34734
34735 if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34736 m.optimizemesh(false);
34737 }
34738
34739 tv[6] = clock();
34740
34741 if (!b->quiet) {
34742 if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34743 printf("Repair seconds: %g\n", (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
34744 }
34745 }
34746
34747 if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34748 m.removesteiners(false);
34749 }
34750
34751 tv[7] = clock();
34752
34753 if (!b->quiet) {
34754 if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34755 printf("Steiner removal seconds: %g\n",
34756 (tv[7] - tv[6]) / (REAL) CLOCKS_PER_SEC);
34757 }
34758 }
34759
34760 if (b->insertaddpoints && (addin != (tetgenio *) NULL)) {
34761 if (addin->numberofpoints > 0) {
34762 m.insertconstrainedpoints(addin);
34763 }
34764 }
34765
34766 tv[8] = clock();
34767
34768 if (!b->quiet) {
34769 if ((b->plc || b->refine) && (b->insertaddpoints)) {
34770 printf("Constrained points seconds: %g\n",
34771 (tv[8] - tv[7]) / (REAL) CLOCKS_PER_SEC);
34772 }
34773 }
34774
34775 if (b->metric) {
34776 m.interpolatesizemap();
34777 }
34778
34779 tv[9] = clock();
34780
34781 if (!b->quiet) {
34782 if (b->metric) {
34783 printf("Size interpolating seconds: %g\n",
34784 (tv[9] - tv[8]) / (REAL) CLOCKS_PER_SEC);
34785 }
34786 }
34787
34788 if (b->coarse) {
34789 m.removesteiners(true);
34790 }
34791
34792 tv[10] = clock();
34793
34794 if (!b->quiet) {
34795 if (b->coarse) {
34796 printf("Mesh coarsening seconds: %g\n",
34797 (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
34798 }
34799 }
34800
34801 if (b->quality) {
34802 m.enforcequality();
34803 }
34804
34805 tv[11] = clock();
34806
34807 if (!b->quiet) {
34808 if (b->quality) {
34809 printf("Quality seconds: %g\n",
34810 (tv[11] - tv[10]) / (REAL) CLOCKS_PER_SEC);
34811 }
34812 }
34813
34814 if (b->quality && (b->optlevel > 0)) {
34815 m.optimizemesh(true);
34816 }
34817
34818 tv[12] = clock();
34819
34820 if (!b->quiet) {
34821 if (b->quality && (b->optlevel > 0)) {
34822 printf("Optimize seconds: %g\n",
34823 (tv[12] - tv[11]) / (REAL) CLOCKS_PER_SEC);
34824 }
34825 }
34826
34827 if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0)
34828 || (b->refine && (in->numberofcorners == 10)))) {
34829 m.jettisonnodes();
34830 }
34831
34832 if (b->order > 1) {
34833 m.highorder();
34834 }
34835
34836 if (!b->quiet) {
34837 printf("\n");
34838 }
34839
34840 if (out != (tetgenio *) NULL) {
34841 out->firstnumber = in->firstnumber;
34842 out->mesh_dim = in->mesh_dim;
34843 }
34844
34845 if (b->nonodewritten || b->noiterationnum) {
34846 if (!b->quiet) {
34847 printf("NOT writing a .node file.\n");
34848 }
34849 } else {
34850 if (b->diagnose == 1) {
34851 if (m.subfaces->items > 0l) {
34852 m.outnodes(out);
34853 }
34854 } else {
34855 m.outnodes(out);
34856 if (b->quality || b->metric) {
34857
34858 }
34859 }
34860 }
34861
34862 if (b->noelewritten) {
34863 if (!b->quiet) {
34864 printf("NOT writing an .ele file.\n");
34865 }
34866 } else {
34867 if (!(b->diagnose == 1)) {
34868 if (m.tetrahedrons->items > 0l) {
34869 m.outelements(out);
34870 }
34871 }
34872 }
34873
34874 if (b->nofacewritten) {
34875 if (!b->quiet) {
34876 printf("NOT writing an .face file.\n");
34877 }
34878 } else {
34879 if (b->facesout) {
34880 if (m.tetrahedrons->items > 0l) {
34881 m.outfaces(out);
34882 }
34883 } else {
34884 if (b->diagnose == 1) {
34885 if (m.subfaces->items > 0l) {
34886 m.outsubfaces(out);
34887 }
34888 } else if (b->plc || b->refine) {
34889 if (m.subfaces->items > 0l) {
34890 m.outsubfaces(out);
34891 }
34892 } else {
34893 if (m.tetrahedrons->items > 0l) {
34894 m.outhullfaces(out);
34895 }
34896 }
34897 }
34898 }
34899
34900 if (m.checkpbcs) {
34901 m.outpbcnodes(out);
34902 }
34903
34904 if (b->edgesout) {
34905 if (b->edgesout > 1) {
34906 m.outedges(out);
34907 } else {
34908 m.outsubsegments(out);
34909 }
34910 }
34911
34912 if (!out && b->plc &&
34913 ((b->object == tetgenbehavior::OFF) ||
34914 (b->object == tetgenbehavior::PLY) ||
34915 (b->object == tetgenbehavior::STL))) {
34916 m.outsmesh(b->outfilename);
34917 }
34918
34919 if (!out && b->meditview) {
34920 m.outmesh2medit(b->outfilename);
34921 }
34922
34923 if (!out && b->gidview) {
34924 m.outmesh2gid(b->outfilename);
34925 }
34926
34927 if (!out && b->geomview) {
34928 m.outmesh2off(b->outfilename);
34929 }
34930
34931 if (b->neighout) {
34932 m.outneighbors(out);
34933 }
34934
34935 if (b->voroout) {
34936 m.outvoronoi(out);
34937 }
34938
34939 tv[13] = clock();
34940
34941 if (!b->quiet) {
34942 printf("\nOutput seconds: %g\n",
34943 (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
34944 printf("Total running seconds: %g\n",
34945 (tv[13] - tv[0]) / (REAL) CLOCKS_PER_SEC);
34946 }
34947
34948 if (b->docheck) {
34949 m.checkmesh();
34950 if (m.checksubfaces) {
34951 m.checkshells();
34952 }
34953 if (b->docheck > 1) {
34954 m.checkdelaunay(0.0, NULL);
34955 if (b->docheck > 2) {
34956 if (b->quality || b->refine) {
34957 m.checkconforming();
34958 }
34959 }
34960 }
34961 }
34962
34963 if (!b->quiet) {
34964 m.statistics();
34965 }
34966
34967 if (b->metric) {
34968 delete m.bgm;
34969 }
34970 }
34971
34972 #ifndef TETLIBRARY
34973
34975
34976
34977
34979
34980 int main(int argc, char *argv[])
34981
34982 #else // with TETLIBRARY
34983
34985
34986
34987
34989
34990 void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
34991 tetgenio *addin, tetgenio *bgmin)
34992
34993 #endif // not TETLIBRARY
34994
34995 {
34996 tetgenbehavior b;
34997
34998 #ifndef TETLIBRARY
34999
35000 tetgenio in, addin, bgmin;
35001
35002 if (!b.parse_commandline(argc, argv)) {
35003 terminatetetgen(1);
35004 }
35005 if (b.refine) {
35006 if (!in.load_tetmesh(b.infilename)) {
35007 terminatetetgen(1);
35008 }
35009 } else {
35010 if (!in.load_plc(b.infilename, (int) b.object)) {
35011 terminatetetgen(1);
35012 }
35013 }
35014 if (b.insertaddpoints) {
35015 if (!addin.load_node(b.addinfilename)) {
35016 addin.numberofpoints = 0l;
35017 }
35018 }
35019 if (b.metric) {
35020 if (!bgmin.load_tetmesh(b.bgmeshfilename)) {
35021 bgmin.numberoftetrahedra = 0l;
35022 }
35023 }
35024
35025 if (bgmin.numberoftetrahedra > 0l) {
35026 tetrahedralize(&b, &in, NULL, &addin, &bgmin);
35027 } else {
35028 tetrahedralize(&b, &in, NULL, &addin, NULL);
35029 }
35030
35031 return 0;
35032
35033 #else // with TETLIBRARY
35034
35035 if (!b.parse_commandline(switches)) {
35036 terminatetetgen(1);
35037 }
35038 tetrahedralize(&b, in, out, addin, bgmin);
35039
35040 #endif // not TETLIBRARY
35041 }
35042
35043 }
35044
35045 #ifndef TETLIBRARY
35046
35047
35048 int main(int argc, char *argv[])
35049 {
35050 tetgen::main(argc, argv);
35051 }
35052 #endif // not TETLIBRARY