00001
00008
00009 #include "predicates.hpp"
00010
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00032
00034
00035
00036
00037
00038
00040
00041 #include "tetgen.h"
00042 namespace tetgen
00043 {
00044
00046
00047
00048
00050
00051 void terminatetetgen(int x)
00052 {
00053 #ifdef TETLIBRARY
00054 throw x;
00055 #else
00056 exit(x);
00057 #endif // #ifdef TETLIBRARY
00058 }
00059
00060
00061
00062
00063
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00076
00077 void tetgenio::initialize()
00078 {
00079 firstnumber = 0;
00080 mesh_dim = 3;
00081 useindex = true;
00082
00083 pointlist = (REAL *) NULL;
00084 pointattributelist = (REAL *) NULL;
00085 pointmtrlist = (REAL *) NULL;
00086 pointmarkerlist = (int *) NULL;
00087 numberofpoints = 0;
00088 numberofpointattributes = 0;
00089 numberofpointmtrs = 0;
00090
00091 tetrahedronlist = (int *) NULL;
00092 tetrahedronattributelist = (REAL *) NULL;
00093 tetrahedronvolumelist = (REAL *) NULL;
00094 neighborlist = (int *) NULL;
00095 numberoftetrahedra = 0;
00096 numberofcorners = 4;
00097 numberoftetrahedronattributes = 0;
00098
00099 trifacelist = (int *) NULL;
00100 adjtetlist = (int *) NULL;
00101 trifacemarkerlist = (int *) NULL;
00102 numberoftrifaces = 0;
00103
00104 facetlist = (facet *) NULL;
00105 facetmarkerlist = (int *) NULL;
00106 numberoffacets = 0;
00107
00108 edgelist = (int *) NULL;
00109 edgemarkerlist = (int *) NULL;
00110 numberofedges = 0;
00111
00112 holelist = (REAL *) NULL;
00113 numberofholes = 0;
00114
00115 regionlist = (REAL *) NULL;
00116 numberofregions = 0;
00117
00118 facetconstraintlist = (REAL *) NULL;
00119 numberoffacetconstraints = 0;
00120 segmentconstraintlist = (REAL *) NULL;
00121 numberofsegmentconstraints = 0;
00122
00123 pbcgrouplist = (pbcgroup *) NULL;
00124 numberofpbcgroups = 0;
00125
00126 vpointlist = (REAL *) NULL;
00127 vedgelist = (voroedge *) NULL;
00128 vfacetlist = (vorofacet *) NULL;
00129 vcelllist = (int **) NULL;
00130 numberofvpoints = 0;
00131 numberofvedges = 0;
00132 numberofvfacets = 0;
00133 numberofvcells = 0;
00134 }
00135
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00150
00151 void tetgenio::deinitialize()
00152 {
00153 facet *f;
00154 polygon *p;
00155 pbcgroup *pg;
00156 int i, j;
00157
00158 if (pointlist != (REAL *) NULL) {
00159 delete [] pointlist;
00160 }
00161 if (pointattributelist != (REAL *) NULL) {
00162 delete [] pointattributelist;
00163 }
00164 if (pointmtrlist != (REAL *) NULL) {
00165 delete [] pointmtrlist;
00166 }
00167 if (pointmarkerlist != (int *) NULL) {
00168 delete [] pointmarkerlist;
00169 }
00170
00171 if (tetrahedronlist != (int *) NULL) {
00172 delete [] tetrahedronlist;
00173 }
00174 if (tetrahedronattributelist != (REAL *) NULL) {
00175 delete [] tetrahedronattributelist;
00176 }
00177 if (tetrahedronvolumelist != (REAL *) NULL) {
00178 delete [] tetrahedronvolumelist;
00179 }
00180 if (neighborlist != (int *) NULL) {
00181 delete [] neighborlist;
00182 }
00183
00184 if (trifacelist != (int *) NULL) {
00185 delete [] trifacelist;
00186 }
00187 if (adjtetlist != (int *) NULL) {
00188 delete [] adjtetlist;
00189 }
00190 if (trifacemarkerlist != (int *) NULL) {
00191 delete [] trifacemarkerlist;
00192 }
00193
00194 if (edgelist != (int *) NULL) {
00195 delete [] edgelist;
00196 }
00197 if (edgemarkerlist != (int *) NULL) {
00198 delete [] edgemarkerlist;
00199 }
00200
00201 if (facetlist != (facet *) NULL) {
00202 for (i = 0; i < numberoffacets; i++) {
00203 f = &facetlist[i];
00204 for (j = 0; j < f->numberofpolygons; j++) {
00205 p = &f->polygonlist[j];
00206 delete [] p->vertexlist;
00207 }
00208 delete [] f->polygonlist;
00209 if (f->holelist != (REAL *) NULL) {
00210 delete [] f->holelist;
00211 }
00212 }
00213 delete [] facetlist;
00214 }
00215 if (facetmarkerlist != (int *) NULL) {
00216 delete [] facetmarkerlist;
00217 }
00218
00219 if (holelist != (REAL *) NULL) {
00220 delete [] holelist;
00221 }
00222 if (regionlist != (REAL *) NULL) {
00223 delete [] regionlist;
00224 }
00225 if (facetconstraintlist != (REAL *) NULL) {
00226 delete [] facetconstraintlist;
00227 }
00228 if (segmentconstraintlist != (REAL *) NULL) {
00229 delete [] segmentconstraintlist;
00230 }
00231 if (pbcgrouplist != (pbcgroup *) NULL) {
00232 for (i = 0; i < numberofpbcgroups; i++) {
00233 pg = &(pbcgrouplist[i]);
00234 if (pg->pointpairlist != (int *) NULL) {
00235 delete [] pg->pointpairlist;
00236 }
00237 }
00238 delete [] pbcgrouplist;
00239 }
00240 if (vpointlist != (REAL *) NULL) {
00241 delete [] vpointlist;
00242 }
00243 if (vedgelist != (voroedge *) NULL) {
00244 delete [] vedgelist;
00245 }
00246 if (vfacetlist != (vorofacet *) NULL) {
00247 for (i = 0; i < numberofvfacets; i++) {
00248 delete [] vfacetlist[i].elist;
00249 }
00250 delete [] vfacetlist;
00251 }
00252 if (vcelllist != (int **) NULL) {
00253 for (i = 0; i < numberofvcells; i++) {
00254 delete [] vcelllist[i];
00255 }
00256 delete [] vcelllist;
00257 }
00258 }
00259
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00274
00275 bool tetgenio::load_node_call(FILE* infile, int markers, char* infilename)
00276 {
00277 char inputline[INPUTLINESIZE];
00278 char *stringptr;
00279 REAL x, y, z, attrib;
00280 int firstnode, currentmarker;
00281 int index, attribindex;
00282 int i, j;
00283
00284
00285 pointlist = new REAL[numberofpoints * 3];
00286 if (pointlist == (REAL *) NULL) {
00287 printf("Error: Out of memory.\n");
00288 terminatetetgen(1);
00289 }
00290 if (numberofpointattributes > 0) {
00291 pointattributelist = new REAL[numberofpoints * numberofpointattributes];
00292 if (pointattributelist == (REAL *) NULL) {
00293 printf("Error: Out of memory.\n");
00294 terminatetetgen(1);
00295 }
00296 }
00297 if (markers) {
00298 pointmarkerlist = new int[numberofpoints];
00299 if (pointmarkerlist == (int *) NULL) {
00300 printf("Error: Out of memory.\n");
00301 terminatetetgen(1);
00302 }
00303 }
00304
00305
00306 index = 0;
00307 attribindex = 0;
00308 for (i = 0; i < numberofpoints; i++) {
00309 stringptr = readnumberline(inputline, infile, infilename);
00310 if (useindex) {
00311 if (i == 0) {
00312 firstnode = (int) strtol (stringptr, &stringptr, 0);
00313 if ((firstnode == 0) || (firstnode == 1)) {
00314 firstnumber = firstnode;
00315 }
00316 }
00317 stringptr = findnextnumber(stringptr);
00318 }
00319 if (*stringptr == '\0') {
00320 printf("Error: Point %d has no x coordinate.\n", firstnumber + i);
00321 break;
00322 }
00323 x = (REAL) strtod(stringptr, &stringptr);
00324 stringptr = findnextnumber(stringptr);
00325 if (*stringptr == '\0') {
00326 printf("Error: Point %d has no y coordinate.\n", firstnumber + i);
00327 break;
00328 }
00329 y = (REAL) strtod(stringptr, &stringptr);
00330 if (mesh_dim == 3) {
00331 stringptr = findnextnumber(stringptr);
00332 if (*stringptr == '\0') {
00333 printf("Error: Point %d has no z coordinate.\n", firstnumber + i);
00334 break;
00335 }
00336 z = (REAL) strtod(stringptr, &stringptr);
00337 } else {
00338 z = 0.0;
00339 }
00340 pointlist[index++] = x;
00341 pointlist[index++] = y;
00342 pointlist[index++] = z;
00343
00344 for (j = 0; j < numberofpointattributes; j++) {
00345 stringptr = findnextnumber(stringptr);
00346 if (*stringptr == '\0') {
00347 attrib = 0.0;
00348 } else {
00349 attrib = (REAL) strtod(stringptr, &stringptr);
00350 }
00351 pointattributelist[attribindex++] = attrib;
00352 }
00353 if (markers) {
00354
00355 stringptr = findnextnumber(stringptr);
00356 if (*stringptr == '\0') {
00357 currentmarker = 0;
00358 } else {
00359 currentmarker = (int) strtol (stringptr, &stringptr, 0);
00360 }
00361 pointmarkerlist[i] = currentmarker;
00362 }
00363 }
00364 if (i < numberofpoints) {
00365
00366 delete [] pointlist;
00367 pointlist = (REAL *) NULL;
00368 if (markers) {
00369 delete [] pointmarkerlist;
00370 pointmarkerlist = (int *) NULL;
00371 }
00372 if (numberofpointattributes > 0) {
00373 delete [] pointattributelist;
00374 pointattributelist = (REAL *) NULL;
00375 }
00376 numberofpoints = 0;
00377 return false;
00378 }
00379 return true;
00380 }
00381
00383
00384
00385
00386
00387
00388
00390
00391 bool tetgenio::load_node(char* filename)
00392 {
00393 FILE *infile;
00394 char innodefilename[FILENAMESIZE];
00395 char inputline[INPUTLINESIZE];
00396 char *stringptr;
00397 int markers;
00398
00399 markers = 0;
00400
00401 strcpy(innodefilename, filename);
00402 strcat(innodefilename, ".node");
00403
00404
00405 infile = fopen(innodefilename, "r");
00406 if (infile == (FILE *) NULL) {
00407 printf("File I/O Error: Cannot access file %s.\n", innodefilename);
00408 return false;
00409 }
00410 printf("Opening %s.\n", innodefilename);
00411
00412 stringptr = readnumberline(inputline, infile, innodefilename);
00413
00414 stringptr = strstr(inputline, "rbox");
00415 if (stringptr == NULL) {
00416
00417
00418 stringptr = inputline;
00419 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00420 stringptr = findnextnumber(stringptr);
00421 if (*stringptr == '\0') {
00422 mesh_dim = 3;
00423 } else {
00424 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00425 }
00426 stringptr = findnextnumber(stringptr);
00427 if (*stringptr == '\0') {
00428 numberofpointattributes = 0;
00429 } else {
00430 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00431 }
00432 stringptr = findnextnumber(stringptr);
00433 if (*stringptr == '\0') {
00434 markers = 0;
00435 } else {
00436 markers = (int) strtol (stringptr, &stringptr, 0);
00437 }
00438 } else {
00439
00440 stringptr = inputline;
00441
00442 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00443
00444 stringptr = readnumberline(inputline, infile, innodefilename);
00445 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00446
00447 useindex = 0;
00448 }
00449
00450
00451
00452
00453
00454
00455 if (numberofpoints < (mesh_dim + 1)) {
00456 printf("Input error: TetGen needs at least %d points.\n", mesh_dim + 1);
00457 fclose(infile);
00458 return false;
00459 }
00460
00461
00462 if (!load_node_call(infile, markers, innodefilename)) {
00463 fclose(infile);
00464 return false;
00465 }
00466 fclose(infile);
00467 return true;
00468 }
00469
00471
00472
00473
00474
00475
00476
00477
00478
00480
00481 bool tetgenio::load_pbc(char* filename)
00482 {
00483 FILE *infile;
00484 char pbcfilename[FILENAMESIZE];
00485 char inputline[INPUTLINESIZE];
00486 char *stringptr;
00487 pbcgroup *pg;
00488 int index, p1, p2;
00489 int i, j, k;
00490
00491
00492 strcpy(pbcfilename, filename);
00493 strcat(pbcfilename, ".pbc");
00494 infile = fopen(pbcfilename, "r");
00495 if (infile != (FILE *) NULL) {
00496 printf("Opening %s.\n", pbcfilename);
00497 } else {
00498
00499 return false;
00500 }
00501
00502
00503 stringptr = readnumberline(inputline, infile, pbcfilename);
00504 numberofpbcgroups = (int) strtol (stringptr, &stringptr, 0);
00505 if (numberofpbcgroups == 0) {
00506
00507 fclose(infile);
00508 return false;
00509 }
00510
00511 pbcgrouplist = new pbcgroup[numberofpbcgroups];
00512
00513
00514 for (i = 0; i < numberofpbcgroups; i++) {
00515 pg = &(pbcgrouplist[i]);
00516
00517 pg->numberofpointpairs = 0;
00518 pg->pointpairlist = (int *) NULL;
00519
00520 stringptr = readnumberline(inputline, infile, pbcfilename);
00521 if (*stringptr == '\0') break;
00522 pg->fmark1 = (int) strtol(stringptr, &stringptr, 0);
00523 stringptr = findnextnumber(stringptr);
00524 if (*stringptr == '\0') break;
00525 pg->fmark2 = (int) strtol(stringptr, &stringptr, 0);
00526
00527 do {
00528 stringptr = readline(inputline, infile, NULL);
00529 } while ((*stringptr != '[') && (*stringptr != '\0'));
00530 if (*stringptr == '\0') break;
00531 for (j = 0; j < 4; j++) {
00532 for (k = 0; k < 4; k++) {
00533
00534 stringptr = findnextnumber(stringptr);
00535 if (*stringptr == '\0') {
00536
00537 stringptr = readnumberline(inputline, infile, pbcfilename);
00538 if (*stringptr == '\0') break;
00539 }
00540 pg->transmat[j][k] = (REAL) strtod(stringptr, &stringptr);
00541 }
00542 if (k < 4) break;
00543 }
00544 if (j < 4) break;
00545
00546 stringptr = readnumberline(inputline, infile, pbcfilename);
00547 if (*stringptr == '\0') break;
00548 pg->numberofpointpairs = (int) strtol(stringptr, &stringptr, 0);
00549 if (pg->numberofpointpairs > 0) {
00550 pg->pointpairlist = new int[pg->numberofpointpairs * 2];
00551
00552 index = 0;
00553 for (j = 0; j < pg->numberofpointpairs; j++) {
00554 stringptr = readnumberline(inputline, infile, pbcfilename);
00555 p1 = (int) strtol(stringptr, &stringptr, 0);
00556 stringptr = findnextnumber(stringptr);
00557 p2 = (int) strtol(stringptr, &stringptr, 0);
00558 pg->pointpairlist[index++] = p1;
00559 pg->pointpairlist[index++] = p2;
00560 }
00561 }
00562 }
00563 fclose(infile);
00564
00565 if (i < numberofpbcgroups) {
00566
00567 delete [] pbcgrouplist;
00568 pbcgrouplist = (pbcgroup *) NULL;
00569 numberofpbcgroups = 0;
00570 return false;
00571 }
00572 return true;
00573 }
00574
00576
00577
00578
00579
00580
00581
00583
00584 bool tetgenio::load_var(char* filename)
00585 {
00586 FILE *infile;
00587 char varfilename[FILENAMESIZE];
00588 char inputline[INPUTLINESIZE];
00589 char *stringptr;
00590 int index;
00591 int i;
00592
00593
00594 strcpy(varfilename, filename);
00595 strcat(varfilename, ".var");
00596 infile = fopen(varfilename, "r");
00597 if (infile != (FILE *) NULL) {
00598 printf("Opening %s.\n", varfilename);
00599 } else {
00600
00601 return false;
00602 }
00603
00604
00605 stringptr = readnumberline(inputline, infile, varfilename);
00606 if (*stringptr != '\0') {
00607 numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0);
00608 } else {
00609 numberoffacetconstraints = 0;
00610 }
00611 if (numberoffacetconstraints > 0) {
00612
00613 facetconstraintlist = new REAL[numberoffacetconstraints * 2];
00614 index = 0;
00615 for (i = 0; i < numberoffacetconstraints; i++) {
00616 stringptr = readnumberline(inputline, infile, varfilename);
00617 stringptr = findnextnumber(stringptr);
00618 if (*stringptr == '\0') {
00619 printf("Error: facet constraint %d has no facet marker.\n",
00620 firstnumber + i);
00621 break;
00622 } else {
00623 facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00624 }
00625 stringptr = findnextnumber(stringptr);
00626 if (*stringptr == '\0') {
00627 printf("Error: facet constraint %d has no maximum area bound.\n",
00628 firstnumber + i);
00629 break;
00630 } else {
00631 facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00632 }
00633 }
00634 if (i < numberoffacetconstraints) {
00635
00636 fclose(infile);
00637 return false;
00638 }
00639 }
00640
00641
00642 stringptr = readnumberline(inputline, infile, varfilename);
00643 if (*stringptr != '\0') {
00644 numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0);
00645 } else {
00646 numberofsegmentconstraints = 0;
00647 }
00648 if (numberofsegmentconstraints > 0) {
00649
00650 segmentconstraintlist = new REAL[numberofsegmentconstraints * 3];
00651 index = 0;
00652 for (i = 0; i < numberofsegmentconstraints; i++) {
00653 stringptr = readnumberline(inputline, infile, varfilename);
00654 stringptr = findnextnumber(stringptr);
00655 if (*stringptr == '\0') {
00656 printf("Error: segment constraint %d has no frist endpoint.\n",
00657 firstnumber + i);
00658 break;
00659 } else {
00660 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00661 }
00662 stringptr = findnextnumber(stringptr);
00663 if (*stringptr == '\0') {
00664 printf("Error: segment constraint %d has no second endpoint.\n",
00665 firstnumber + i);
00666 break;
00667 } else {
00668 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00669 }
00670 stringptr = findnextnumber(stringptr);
00671 if (*stringptr == '\0') {
00672 printf("Error: segment constraint %d has no maximum length bound.\n",
00673 firstnumber + i);
00674 break;
00675 } else {
00676 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
00677 }
00678 }
00679 if (i < numberofsegmentconstraints) {
00680
00681 fclose(infile);
00682 return false;
00683 }
00684 }
00685
00686 fclose(infile);
00687 return true;
00688 }
00689
00691
00692
00693
00694
00695
00696
00698
00699 bool tetgenio::load_mtr(char* filename)
00700 {
00701 FILE *infile;
00702 char mtrfilename[FILENAMESIZE];
00703 char inputline[INPUTLINESIZE];
00704 char *stringptr;
00705 REAL mtr;
00706 int mtrindex;
00707 int i, j;
00708
00709 strcpy(mtrfilename, filename);
00710 strcat(mtrfilename, ".mtr");
00711 infile = fopen(mtrfilename, "r");
00712 if (infile != (FILE *) NULL) {
00713 printf("Opening %s.\n", mtrfilename);
00714 } else {
00715
00716 return false;
00717 }
00718
00719
00720 stringptr = readnumberline(inputline, infile, mtrfilename);
00721 stringptr = findnextnumber(stringptr);
00722 if (*stringptr != '\0') {
00723 numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0);
00724 }
00725 if (numberofpointmtrs == 0) {
00726
00727 numberofpointmtrs = 1;
00728 }
00729
00730
00731 pointmtrlist = new REAL[numberofpoints * numberofpointmtrs];
00732 if (pointmtrlist == (REAL *) NULL) {
00733 printf("Error: Out of memory.\n");
00734 terminatetetgen(1);
00735 }
00736 mtrindex = 0;
00737 for (i = 0; i < numberofpoints; i++) {
00738
00739 stringptr = readnumberline(inputline, infile, mtrfilename);
00740 for (j = 0; j < numberofpointmtrs; j++) {
00741 if (*stringptr == '\0') {
00742 printf("Error: Metric %d is missing value #%d in %s.\n",
00743 i + firstnumber, j + 1, mtrfilename);
00744 terminatetetgen(1);
00745 }
00746 mtr = (REAL) strtod(stringptr, &stringptr);
00747 pointmtrlist[mtrindex++] = mtr;
00748 stringptr = findnextnumber(stringptr);
00749 }
00750 }
00751
00752 fclose(infile);
00753 return true;
00754 }
00755
00757
00758
00759
00760
00761
00762
00763
00765
00766 bool tetgenio::load_poly(char* filename)
00767 {
00768 FILE *infile, *polyfile;
00769 char innodefilename[FILENAMESIZE];
00770 char inpolyfilename[FILENAMESIZE];
00771 char insmeshfilename[FILENAMESIZE];
00772 char inputline[INPUTLINESIZE];
00773 char *stringptr, *infilename;
00774 int smesh, markers, currentmarker;
00775 int readnodefile, index;
00776 int i, j, k;
00777
00778
00779 strcpy(innodefilename, filename);
00780 strcpy(inpolyfilename, filename);
00781 strcpy(insmeshfilename, filename);
00782 strcat(innodefilename, ".node");
00783 strcat(inpolyfilename, ".poly");
00784 strcat(insmeshfilename, ".smesh");
00785
00786
00787 smesh = 0;
00788
00789 polyfile = fopen(inpolyfilename, "r");
00790 if (polyfile == (FILE *) NULL) {
00791
00792 polyfile = fopen(insmeshfilename, "r");
00793 if (polyfile == (FILE *) NULL) {
00794 printf("File I/O Error: Cannot access file %s and %s.\n",
00795 inpolyfilename, insmeshfilename);
00796 return false;
00797 } else {
00798 printf("Opening %s.\n", insmeshfilename);
00799 }
00800 smesh = 1;
00801 } else {
00802 printf("Opening %s.\n", inpolyfilename);
00803 }
00804
00805 mesh_dim = 3;
00806 numberofpointattributes = 0;
00807 markers = 0;
00808
00809
00810 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00811 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00812 stringptr = findnextnumber(stringptr);
00813 if (*stringptr != '\0') {
00814 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00815 }
00816 stringptr = findnextnumber(stringptr);
00817 if (*stringptr != '\0') {
00818 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00819 }
00820 stringptr = findnextnumber(stringptr);
00821 if (*stringptr != '\0') {
00822 markers = (int) strtol (stringptr, &stringptr, 0);
00823 }
00824 if (numberofpoints > 0) {
00825 readnodefile = 0;
00826 if (smesh) {
00827 infilename = insmeshfilename;
00828 } else {
00829 infilename = inpolyfilename;
00830 }
00831 infile = polyfile;
00832 } else {
00833
00834
00835 readnodefile = 1;
00836 infilename = innodefilename;
00837 }
00838
00839 if (readnodefile) {
00840
00841 printf("Opening %s.\n", innodefilename);
00842 infile = fopen(innodefilename, "r");
00843 if (infile == (FILE *) NULL) {
00844 printf("File I/O Error: Cannot access file %s.\n", innodefilename);
00845 return false;
00846 }
00847
00848 mesh_dim = 3;
00849 numberofpointattributes = 0;
00850 markers = 0;
00851
00852
00853 stringptr = readnumberline(inputline, infile, innodefilename);
00854 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
00855 stringptr = findnextnumber(stringptr);
00856 if (*stringptr != '\0') {
00857 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
00858 }
00859 stringptr = findnextnumber(stringptr);
00860 if (*stringptr != '\0') {
00861 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
00862 }
00863 stringptr = findnextnumber(stringptr);
00864 if (*stringptr != '\0') {
00865 markers = (int) strtol (stringptr, &stringptr, 0);
00866 }
00867 }
00868
00869 if ((mesh_dim != 3) && (mesh_dim != 2)) {
00870 printf("Input error: TetGen only works for 2D & 3D point sets.\n");
00871 fclose(infile);
00872 return false;
00873 }
00874 if (numberofpoints < (mesh_dim + 1)) {
00875 printf("Input error: TetGen needs at least %d points.\n", mesh_dim + 1);
00876 fclose(infile);
00877 return false;
00878 }
00879
00880
00881 if (!load_node_call(infile, markers, infilename)) {
00882 fclose(infile);
00883 return false;
00884 }
00885
00886 if (readnodefile) {
00887 fclose(infile);
00888 }
00889
00890 facet *f;
00891 polygon *p;
00892
00893 if (mesh_dim == 3) {
00894
00895
00896 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00897 numberoffacets = (int) strtol (stringptr, &stringptr, 0);
00898 if (numberoffacets <= 0) {
00899
00900 fclose(polyfile);
00901 return true;
00902 }
00903 stringptr = findnextnumber(stringptr);
00904 if (*stringptr == '\0') {
00905 markers = 0;
00906 } else {
00907 markers = (int) strtol (stringptr, &stringptr, 0);
00908 }
00909
00910
00911 facetlist = new facet[numberoffacets];
00912 if (markers == 1) {
00913 facetmarkerlist = new int[numberoffacets];
00914 }
00915
00916
00917 if (smesh == 0) {
00918
00919 for (i = 1; i <= numberoffacets; i++) {
00920 f = &(facetlist[i - 1]);
00921 init(f);
00922 f->numberofholes = 0;
00923 currentmarker = 0;
00924
00925 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00926 f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
00927 stringptr = findnextnumber(stringptr);
00928 if (*stringptr != '\0') {
00929 f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
00930 if (markers == 1) {
00931 stringptr = findnextnumber(stringptr);
00932 if (*stringptr != '\0') {
00933 currentmarker = (int) strtol(stringptr, &stringptr, 0);
00934 }
00935 }
00936 }
00937
00938 if (markers == 1) {
00939 facetmarkerlist[i - 1] = currentmarker;
00940 }
00941
00942 if (f->numberofpolygons <= 0) {
00943 printf("Error: Wrong number of polygon in %d facet.\n", i);
00944 break;
00945 }
00946
00947 f->polygonlist = new polygon[f->numberofpolygons];
00948
00949 for (j = 1; j <= f->numberofpolygons; j++) {
00950 p = &(f->polygonlist[j - 1]);
00951 init(p);
00952
00953 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00954 p->numberofvertices = (int) strtol(stringptr, &stringptr, 0);
00955 if (p->numberofvertices < 1) {
00956 printf("Error: Wrong polygon %d in facet %d\n", j, i);
00957 break;
00958 }
00959
00960 p->vertexlist = new int[p->numberofvertices];
00961
00962 for (k = 1; k <= p->numberofvertices; k++) {
00963 stringptr = findnextnumber(stringptr);
00964 if (*stringptr == '\0') {
00965
00966
00967 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00968 if (*stringptr == '\0') {
00969 printf("Error: Missing %d endpoints of polygon %d in facet %d",
00970 p->numberofvertices - k, j, i);
00971 break;
00972 }
00973 }
00974 p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
00975 }
00976 }
00977 if (j <= f->numberofpolygons) {
00978
00979
00980 if (j == 1) {
00981
00982 delete [] f->polygonlist;
00983 }
00984 f->numberofpolygons = j - 1;
00985
00986 f->numberofholes = 0;
00987 break;
00988 }
00989
00990 if (f->numberofholes > 0) {
00991
00992 f->holelist = new REAL[f->numberofholes * 3];
00993
00994 index = 0;
00995 for (j = 1; j <= f->numberofholes; j++) {
00996 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
00997 for (k = 1; k <= 3; k++) {
00998 stringptr = findnextnumber(stringptr);
00999 if (*stringptr == '\0') {
01000 printf("Error: Hole %d in facet %d has no coordinates", j, i);
01001 break;
01002 }
01003 f->holelist[index++] = (REAL) strtod (stringptr, &stringptr);
01004 }
01005 if (k <= 3) {
01006
01007 break;
01008 }
01009 }
01010 if (j <= f->numberofholes) {
01011
01012 break;
01013 }
01014 }
01015 }
01016 if (i <= numberoffacets) {
01017
01018 numberoffacets = i - 1;
01019 fclose(polyfile);
01020 return false;
01021 }
01022 } else {
01023
01024 for (i = 1; i <= numberoffacets; i++) {
01025 f = &(facetlist[i - 1]);
01026 init(f);
01027
01028
01029 f->numberofpolygons = 1;
01030 f->polygonlist = new polygon[f->numberofpolygons];
01031 p = &(f->polygonlist[0]);
01032 init(p);
01033
01034 stringptr = readnumberline(inputline, polyfile, insmeshfilename);
01035 p->numberofvertices = (int) strtol (stringptr, &stringptr, 0);
01036 if (p->numberofvertices < 1) {
01037 printf("Error: Wrong number of vertex in facet %d\n", i);
01038 break;
01039 }
01040
01041 p->vertexlist = new int[p->numberofvertices];
01042 for (k = 1; k <= p->numberofvertices; k++) {
01043 stringptr = findnextnumber(stringptr);
01044 if (*stringptr == '\0') {
01045
01046
01047 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01048 if (*stringptr == '\0') {
01049 printf("Error: Missing %d endpoints in facet %d",
01050 p->numberofvertices - k, i);
01051 break;
01052 }
01053 }
01054 p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
01055 }
01056 if (k <= p->numberofvertices) {
01057
01058 break;
01059 }
01060
01061 if (markers == 1) {
01062 stringptr = findnextnumber(stringptr);
01063 if (*stringptr == '\0') {
01064 currentmarker = 0;
01065 } else {
01066 currentmarker = (int) strtol(stringptr, &stringptr, 0);
01067 }
01068 facetmarkerlist[i - 1] = currentmarker;
01069 }
01070 }
01071 if (i <= numberoffacets) {
01072
01073 numberoffacets = i - 1;
01074 fclose(polyfile);
01075 return false;
01076 }
01077 }
01078
01079
01080 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01081 if (*stringptr != '\0') {
01082 numberofholes = (int) strtol (stringptr, &stringptr, 0);
01083 } else {
01084 numberofholes = 0;
01085 }
01086 if (numberofholes > 0) {
01087
01088 holelist = new REAL[numberofholes * 3];
01089 for (i = 0; i < 3 * numberofholes; i += 3) {
01090 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01091 stringptr = findnextnumber(stringptr);
01092 if (*stringptr == '\0') {
01093 printf("Error: Hole %d has no x coord.\n", firstnumber + (i / 3));
01094 break;
01095 } else {
01096 holelist[i] = (REAL) strtod(stringptr, &stringptr);
01097 }
01098 stringptr = findnextnumber(stringptr);
01099 if (*stringptr == '\0') {
01100 printf("Error: Hole %d has no y coord.\n", firstnumber + (i / 3));
01101 break;
01102 } else {
01103 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
01104 }
01105 stringptr = findnextnumber(stringptr);
01106 if (*stringptr == '\0') {
01107 printf("Error: Hole %d has no z coord.\n", firstnumber + (i / 3));
01108 break;
01109 } else {
01110 holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
01111 }
01112 }
01113 if (i < 3 * numberofholes) {
01114
01115 fclose(polyfile);
01116 return false;
01117 }
01118 }
01119
01120
01121
01122 stringptr = readnumberline(inputline, polyfile, NULL);
01123 if (stringptr != (char *) NULL && *stringptr != '\0') {
01124 numberofregions = (int) strtol (stringptr, &stringptr, 0);
01125 } else {
01126 numberofregions = 0;
01127 }
01128 if (numberofregions > 0) {
01129
01130 regionlist = new REAL[numberofregions * 5];
01131 index = 0;
01132 for (i = 0; i < numberofregions; i++) {
01133 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01134 stringptr = findnextnumber(stringptr);
01135 if (*stringptr == '\0') {
01136 printf("Error: Region %d has no x coordinate.\n", firstnumber + i);
01137 break;
01138 } else {
01139 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01140 }
01141 stringptr = findnextnumber(stringptr);
01142 if (*stringptr == '\0') {
01143 printf("Error: Region %d has no y coordinate.\n", firstnumber + i);
01144 break;
01145 } else {
01146 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01147 }
01148 stringptr = findnextnumber(stringptr);
01149 if (*stringptr == '\0') {
01150 printf("Error: Region %d has no z coordinate.\n", firstnumber + i);
01151 break;
01152 } else {
01153 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01154 }
01155 stringptr = findnextnumber(stringptr);
01156 if (*stringptr == '\0') {
01157 printf("Error: Region %d has no region attrib.\n", firstnumber + i);
01158 break;
01159 } else {
01160 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
01161 }
01162 stringptr = findnextnumber(stringptr);
01163 if (*stringptr == '\0') {
01164 regionlist[index] = regionlist[index - 1];
01165 } else {
01166 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
01167 }
01168 index++;
01169 }
01170 if (i < numberofregions) {
01171
01172 fclose(polyfile);
01173 return false;
01174 }
01175 }
01176
01177 } else {
01178
01179
01180 assert(mesh_dim == 2);
01181
01182 numberoffacets = 1;
01183
01184 facetlist = new facet[numberoffacets];
01185 facetmarkerlist = (int *) NULL;
01186 f = &(facetlist[0]);
01187 init(f);
01188
01189 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01190
01191 f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
01192 if (f->numberofpolygons > 0) {
01193 f->polygonlist = new polygon[f->numberofpolygons];
01194 }
01195
01196 for (j = 0; j < f->numberofpolygons; j++) {
01197 p = &(f->polygonlist[j]);
01198 init(p);
01199
01200 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01201 stringptr = findnextnumber(stringptr);
01202 p->numberofvertices = 2;
01203 p->vertexlist = new int[p->numberofvertices];
01204 p->vertexlist[0] = (int) strtol (stringptr, &stringptr, 0);
01205 stringptr = findnextnumber(stringptr);
01206 p->vertexlist[1] = (int) strtol (stringptr, &stringptr, 0);
01207 }
01208
01209 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01210 f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
01211 if (f->numberofholes > 0) {
01212
01213 f->holelist = new REAL[f->numberofholes * 3];
01214
01215 for (j = 0; j < f->numberofholes; j++) {
01216
01217 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
01218 stringptr = findnextnumber(stringptr);
01219 f->holelist[j * 3] = (REAL) strtod (stringptr, &stringptr);
01220 stringptr = findnextnumber(stringptr);
01221 f->holelist[j * 3 + 1] = (REAL) strtod (stringptr, &stringptr);
01222 f->holelist[j * 3 + 2] = 0.0;
01223 }
01224 }
01225
01226
01227 }
01228
01229
01230 fclose(polyfile);
01231
01232
01233 load_var(filename);
01234
01235 load_mtr(filename);
01236
01237 load_pbc(filename);
01238
01239 return true;
01240 }
01241
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01255
01256 bool tetgenio::load_off(char* filename)
01257 {
01258 FILE *fp;
01259 tetgenio::facet *f;
01260 tetgenio::polygon *p;
01261 char infilename[FILENAMESIZE];
01262 char buffer[INPUTLINESIZE];
01263 char *bufferp;
01264 double *coord;
01265 int nverts = 0, iverts = 0;
01266 int nfaces = 0, ifaces = 0;
01267 int nedges = 0;
01268 int line_count = 0, i;
01269
01270 strncpy(infilename, filename, 1024 - 1);
01271 infilename[FILENAMESIZE - 1] = '\0';
01272 if (infilename[0] == '\0') {
01273 printf("Error: No filename.\n");
01274 return false;
01275 }
01276 if (strcmp(&infilename[strlen(infilename) - 4], ".off") != 0) {
01277 strcat(infilename, ".off");
01278 }
01279
01280 if (!(fp = fopen(infilename, "r"))) {
01281 printf("File I/O Error: Unable to open file %s\n", infilename);
01282 return false;
01283 }
01284 printf("Opening %s.\n", infilename);
01285
01286
01287 firstnumber = 0;
01288
01289 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01290
01291 if (nverts == 0) {
01292
01293 bufferp = strstr(bufferp, "OFF");
01294 if (bufferp != NULL) {
01295
01296 bufferp = findnextnumber(bufferp);
01297 if (*bufferp == '\0') {
01298
01299 bufferp = readline(buffer, fp, &line_count);
01300 }
01301 if ((sscanf(bufferp, "%d%d%d", &nverts, &nfaces, &nedges) != 3)
01302 || (nverts == 0)) {
01303 printf("Syntax error reading header on line %d in file %s\n",
01304 line_count, infilename);
01305 fclose(fp);
01306 return false;
01307 }
01308
01309 if (nverts > 0) {
01310 numberofpoints = nverts;
01311 pointlist = new REAL[nverts * 3];
01312 }
01313 if (nfaces > 0) {
01314 numberoffacets = nfaces;
01315 facetlist = new tetgenio::facet[nfaces];
01316 }
01317 }
01318 } else if (iverts < nverts) {
01319
01320 coord = &pointlist[iverts * 3];
01321 for (i = 0; i < 3; i++) {
01322 if (*bufferp == '\0') {
01323 printf("Syntax error reading vertex coords on line %d in file %s\n",
01324 line_count, infilename);
01325 fclose(fp);
01326 return false;
01327 }
01328 coord[i] = (REAL) strtod(bufferp, &bufferp);
01329 bufferp = findnextnumber(bufferp);
01330 }
01331 iverts++;
01332 } else if (ifaces < nfaces) {
01333
01334 f = &facetlist[ifaces];
01335 init(f);
01336
01337 f->numberofpolygons = 1;
01338 f->polygonlist = new tetgenio::polygon[1];
01339 p = &f->polygonlist[0];
01340 init(p);
01341
01342 p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01343 if (p->numberofvertices == 0) {
01344 printf("Syntax error reading polygon on line %d in file %s\n",
01345 line_count, infilename);
01346 fclose(fp);
01347 return false;
01348 }
01349
01350 p->vertexlist = new int[p->numberofvertices];
01351 for (i = 0; i < p->numberofvertices; i++) {
01352 bufferp = findnextnumber(bufferp);
01353 if (*bufferp == '\0') {
01354 printf("Syntax error reading polygon on line %d in file %s\n",
01355 line_count, infilename);
01356 fclose(fp);
01357 return false;
01358 }
01359 p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01360 }
01361 ifaces++;
01362 } else {
01363
01364 printf("Found extra text starting at line %d in file %s\n", line_count,
01365 infilename);
01366 break;
01367 }
01368 }
01369
01370
01371 fclose(fp);
01372
01373
01374 if (iverts != nverts) {
01375 printf("Expected %d vertices, but read only %d vertices in file %s\n",
01376 nverts, iverts, infilename);
01377 return false;
01378 }
01379
01380
01381 if (ifaces != nfaces) {
01382 printf("Expected %d faces, but read only %d faces in file %s\n",
01383 nfaces, ifaces, infilename);
01384 return false;
01385 }
01386
01387 return true;
01388 }
01389
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01408
01409 bool tetgenio::load_ply(char* filename)
01410 {
01411 FILE *fp;
01412 tetgenio::facet *f;
01413 tetgenio::polygon *p;
01414 char infilename[FILENAMESIZE];
01415 char buffer[INPUTLINESIZE];
01416 char *bufferp, *str;
01417 double *coord;
01418 int endheader = 0, format = 0;
01419 int nverts = 0, iverts = 0;
01420 int nfaces = 0, ifaces = 0;
01421 int line_count = 0, i;
01422
01423 strncpy(infilename, filename, FILENAMESIZE - 1);
01424 infilename[FILENAMESIZE - 1] = '\0';
01425 if (infilename[0] == '\0') {
01426 printf("Error: No filename.\n");
01427 return false;
01428 }
01429 if (strcmp(&infilename[strlen(infilename) - 4], ".ply") != 0) {
01430 strcat(infilename, ".ply");
01431 }
01432
01433 if (!(fp = fopen(infilename, "r"))) {
01434 printf("Error: Unable to open file %s\n", infilename);
01435 return false;
01436 }
01437 printf("Opening %s.\n", infilename);
01438
01439
01440 firstnumber = 0;
01441
01442 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01443 if (!endheader) {
01444
01445 str = strstr(bufferp, "end_header");
01446
01447 if (!str) str = strstr(bufferp, "End_header");
01448 if (!str) str = strstr(bufferp, "End_Header");
01449 if (str) {
01450
01451 endheader = 1;
01452 continue;
01453 }
01454
01455 if (nverts == 0 || nfaces == 0) {
01456
01457 str = strstr(bufferp, "element");
01458 if (!str) str = strstr(bufferp, "Element");
01459 if (str) {
01460 bufferp = findnextfield(str);
01461 if (*bufferp == '\0') {
01462 printf("Syntax error reading element type on line%d in file %s\n",
01463 line_count, infilename);
01464 fclose(fp);
01465 return false;
01466 }
01467 if (nverts == 0) {
01468
01469 str = strstr(bufferp, "vertex");
01470 if (!str) str = strstr(bufferp, "Vertex");
01471 if (str) {
01472 bufferp = findnextnumber(str);
01473 if (*bufferp == '\0') {
01474 printf("Syntax error reading vertex number on line");
01475 printf(" %d in file %s\n", line_count, infilename);
01476 fclose(fp);
01477 return false;
01478 }
01479 nverts = (int) strtol(bufferp, &bufferp, 0);
01480
01481 if (nverts > 0) {
01482 numberofpoints = nverts;
01483 pointlist = new REAL[nverts * 3];
01484 }
01485 }
01486 }
01487 if (nfaces == 0) {
01488
01489 str = strstr(bufferp, "face");
01490 if (!str) str = strstr(bufferp, "Face");
01491 if (str) {
01492 bufferp = findnextnumber(str);
01493 if (*bufferp == '\0') {
01494 printf("Syntax error reading face number on line");
01495 printf(" %d in file %s\n", line_count, infilename);
01496 fclose(fp);
01497 return false;
01498 }
01499 nfaces = (int) strtol(bufferp, &bufferp, 0);
01500
01501 if (nfaces > 0) {
01502 numberoffacets = nfaces;
01503 facetlist = new tetgenio::facet[nfaces];
01504 }
01505 }
01506 }
01507 }
01508 }
01509 if (format == 0) {
01510
01511 str = strstr(bufferp, "format");
01512 if (!str) str = strstr(bufferp, "Format");
01513 if (str) {
01514 format = 1;
01515 bufferp = findnextfield(str);
01516
01517 str = strstr(bufferp, "ascii");
01518 if (!str) str = strstr(bufferp, "ASCII");
01519 if (!str) {
01520 printf("This routine only reads ascii format of ply files.\n");
01521 printf("Hint: You can convert the binary to ascii format by\n");
01522 printf(" using the provided ply tools:\n");
01523 printf(" ply2ascii < %s > ascii_%s\n", infilename, infilename);
01524 fclose(fp);
01525 return false;
01526 }
01527 }
01528 }
01529 } else if (iverts < nverts) {
01530
01531 coord = &pointlist[iverts * 3];
01532 for (i = 0; i < 3; i++) {
01533 if (*bufferp == '\0') {
01534 printf("Syntax error reading vertex coords on line %d in file %s\n",
01535 line_count, infilename);
01536 fclose(fp);
01537 return false;
01538 }
01539 coord[i] = (REAL) strtod(bufferp, &bufferp);
01540 bufferp = findnextnumber(bufferp);
01541 }
01542 iverts++;
01543 } else if (ifaces < nfaces) {
01544
01545 f = &facetlist[ifaces];
01546 init(f);
01547
01548 f->numberofpolygons = 1;
01549 f->polygonlist = new tetgenio::polygon[1];
01550 p = &f->polygonlist[0];
01551 init(p);
01552
01553 p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
01554 if (p->numberofvertices == 0) {
01555 printf("Syntax error reading polygon on line %d in file %s\n",
01556 line_count, infilename);
01557 fclose(fp);
01558 return false;
01559 }
01560
01561 p->vertexlist = new int[p->numberofvertices];
01562 for (i = 0; i < p->numberofvertices; i++) {
01563 bufferp = findnextnumber(bufferp);
01564 if (*bufferp == '\0') {
01565 printf("Syntax error reading polygon on line %d in file %s\n",
01566 line_count, infilename);
01567 fclose(fp);
01568 return false;
01569 }
01570 p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
01571 }
01572 ifaces++;
01573 } else {
01574
01575 printf("Found extra text starting at line %d in file %s\n", line_count,
01576 infilename);
01577 break;
01578 }
01579 }
01580
01581
01582 fclose(fp);
01583
01584
01585 if (iverts != nverts) {
01586 printf("Expected %d vertices, but read only %d vertices in file %s\n",
01587 nverts, iverts, infilename);
01588 return false;
01589 }
01590
01591
01592 if (ifaces != nfaces) {
01593 printf("Expected %d faces, but read only %d faces in file %s\n",
01594 nfaces, ifaces, infilename);
01595 return false;
01596 }
01597
01598 return true;
01599 }
01600
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01618
01619 bool tetgenio::load_stl(char* filename)
01620 {
01621 FILE *fp;
01622 tetgenmesh::list *plist;
01623 tetgenio::facet *f;
01624 tetgenio::polygon *p;
01625 char infilename[FILENAMESIZE];
01626 char buffer[INPUTLINESIZE];
01627 char *bufferp, *str;
01628 double *coord;
01629 int solid = 0;
01630 int nverts = 0, iverts = 0;
01631 int nfaces = 0;
01632 int line_count = 0, i;
01633
01634 strncpy(infilename, filename, FILENAMESIZE - 1);
01635 infilename[FILENAMESIZE - 1] = '\0';
01636 if (infilename[0] == '\0') {
01637 printf("Error: No filename.\n");
01638 return false;
01639 }
01640 if (strcmp(&infilename[strlen(infilename) - 4], ".stl") != 0) {
01641 strcat(infilename, ".stl");
01642 }
01643
01644 if (!(fp = fopen(infilename, "r"))) {
01645 printf("Error: Unable to open file %s\n", infilename);
01646 return false;
01647 }
01648 printf("Opening %s.\n", infilename);
01649
01650
01651 plist = new tetgenmesh::list(sizeof(double) * 3, NULL, 1024);
01652
01653 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01654
01655
01656 if (solid == 0) {
01657
01658 bufferp = strstr(bufferp, "solid");
01659 if (bufferp != NULL) {
01660 solid = 1;
01661 }
01662 } else {
01663
01664 str = bufferp;
01665
01666 bufferp = strstr(bufferp, "endsolid");
01667 if (bufferp != NULL) {
01668 solid = 0;
01669 } else {
01670
01671 bufferp = str;
01672 bufferp = strstr(bufferp, "vertex");
01673 if (bufferp != NULL) {
01674 coord = (double *) plist->append(NULL);
01675 for (i = 0; i < 3; i++) {
01676 bufferp = findnextnumber(bufferp);
01677 if (*bufferp == '\0') {
01678 printf("Syntax error reading vertex coords on line %d\n",
01679 line_count);
01680 delete plist;
01681 fclose(fp);
01682 return false;
01683 }
01684 coord[i] = (REAL) strtod(bufferp, &bufferp);
01685 }
01686 }
01687 }
01688 }
01689 }
01690 fclose(fp);
01691
01692 nverts = plist->len();
01693
01694 if (nverts == 0 || (nverts % 3 != 0)) {
01695 printf("Error: Wrong number of vertices in file %s.\n", infilename);
01696 delete plist;
01697 return false;
01698 }
01699 numberofpoints = nverts;
01700 pointlist = new REAL[nverts * 3];
01701 for (i = 0; i < nverts; i++) {
01702 coord = (double *) (* plist)[i];
01703 iverts = i * 3;
01704 pointlist[iverts] = (REAL) coord[0];
01705 pointlist[iverts + 1] = (REAL) coord[1];
01706 pointlist[iverts + 2] = (REAL) coord[2];
01707 }
01708
01709 nfaces = (int) (nverts / 3);
01710 numberoffacets = nfaces;
01711 facetlist = new tetgenio::facet[nfaces];
01712
01713
01714 firstnumber = 1;
01715 iverts = firstnumber;
01716 for (i = 0; i < nfaces; i++) {
01717 f = &facetlist[i];
01718 init(f);
01719
01720 f->numberofpolygons = 1;
01721 f->polygonlist = new tetgenio::polygon[1];
01722 p = &f->polygonlist[0];
01723 init(p);
01724
01725 p->numberofvertices = 3;
01726 p->vertexlist = new int[p->numberofvertices];
01727 p->vertexlist[0] = iverts;
01728 p->vertexlist[1] = iverts + 1;
01729 p->vertexlist[2] = iverts + 2;
01730 iverts += 3;
01731 }
01732
01733 delete plist;
01734 return true;
01735 }
01736
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01749
01750 bool tetgenio::load_medit(char* filename)
01751 {
01752 FILE *fp;
01753 tetgenio::facet *tmpflist, *f;
01754 tetgenio::polygon *p;
01755 char infilename[FILENAMESIZE];
01756 char buffer[INPUTLINESIZE];
01757 char *bufferp, *str;
01758 double *coord;
01759 int *tmpfmlist;
01760 int dimension = 0;
01761 int nverts = 0;
01762 int nfaces = 0;
01763 int line_count = 0;
01764 int corners = 0;
01765 int i, j;
01766
01767 strncpy(infilename, filename, FILENAMESIZE - 1);
01768 infilename[FILENAMESIZE - 1] = '\0';
01769 if (infilename[0] == '\0') {
01770 printf("Error: No filename.\n");
01771 return false;
01772 }
01773 if (strcmp(&infilename[strlen(infilename) - 5], ".mesh") != 0) {
01774 strcat(infilename, ".mesh");
01775 }
01776
01777 if (!(fp = fopen(infilename, "r"))) {
01778 printf("Error: Unable to open file %s\n", infilename);
01779 return false;
01780 }
01781 printf("Opening %s.\n", infilename);
01782
01783
01784 firstnumber = 1;
01785
01786 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
01787 if (*bufferp == '#') continue;
01788 if (dimension == 0) {
01789
01790 str = strstr(bufferp, "Dimension");
01791 if (!str) str = strstr(bufferp, "dimension");
01792 if (!str) str = strstr(bufferp, "DIMENSION");
01793 if (str) {
01794
01795 bufferp = findnextnumber(str);
01796 if (*bufferp == '\0') {
01797
01798 bufferp = readline(buffer, fp, &line_count);
01799 }
01800 dimension = (int) strtol(bufferp, &bufferp, 0);
01801 if (dimension != 2 && dimension != 3) {
01802 printf("Unknown dimension in file on line %d in file %s\n",
01803 line_count, infilename);
01804 fclose(fp);
01805 return false;
01806 }
01807 mesh_dim = dimension;
01808 }
01809 }
01810 if (nverts == 0) {
01811
01812 str = strstr(bufferp, "Vertices");
01813 if (!str) str = strstr(bufferp, "vertices");
01814 if (!str) str = strstr(bufferp, "VERTICES");
01815 if (str) {
01816
01817 bufferp = findnextnumber(str);
01818 if (*bufferp == '\0') {
01819
01820 bufferp = readline(buffer, fp, &line_count);
01821 }
01822 nverts = (int) strtol(bufferp, &bufferp, 0);
01823
01824 if (nverts > 0) {
01825 numberofpoints = nverts;
01826 pointlist = new REAL[nverts * 3];
01827 }
01828
01829 for (i = 0; i < nverts; i++) {
01830 bufferp = readline(buffer, fp, &line_count);
01831 if (bufferp == NULL) {
01832 printf("Unexpected end of file on line %d in file %s\n",
01833 line_count, infilename);
01834 fclose(fp);
01835 return false;
01836 }
01837
01838 coord = &pointlist[i * 3];
01839 for (j = 0; j < 3; j++) {
01840 if (*bufferp == '\0') {
01841 printf("Syntax error reading vertex coords on line");
01842 printf(" %d in file %s\n", line_count, infilename);
01843 fclose(fp);
01844 return false;
01845 }
01846 if ((j < 2) || (dimension == 3)) {
01847 coord[j] = (REAL) strtod(bufferp, &bufferp);
01848 } else {
01849 assert((j == 2) && (dimension == 2));
01850 coord[j] = 0.0;
01851 }
01852 bufferp = findnextnumber(bufferp);
01853 }
01854 }
01855 continue;
01856 }
01857 }
01858 if (nfaces == 0) {
01859
01860 corners = 0;
01861 str = strstr(bufferp, "Triangles");
01862 if (!str) str = strstr(bufferp, "triangles");
01863 if (!str) str = strstr(bufferp, "TRIANGLES");
01864 if (str) {
01865 corners = 3;
01866 } else {
01867 str = strstr(bufferp, "Quadrilaterals");
01868 if (!str) str = strstr(bufferp, "quadrilaterals");
01869 if (!str) str = strstr(bufferp, "QUADRILATERALS");
01870 if (str) {
01871 corners = 4;
01872 }
01873 }
01874 if (corners == 3 || corners == 4) {
01875
01876 bufferp = findnextnumber(str);
01877 if (*bufferp == '\0') {
01878
01879 bufferp = readline(buffer, fp, &line_count);
01880 }
01881 nfaces = strtol(bufferp, &bufferp, 0);
01882
01883 if (nfaces > 0) {
01884 if (numberoffacets > 0) {
01885
01886 tmpflist = new tetgenio::facet[numberoffacets + nfaces];
01887 tmpfmlist = new int[numberoffacets + nfaces];
01888
01889 for (i = 0; i < numberoffacets; i++) {
01890 f = &(tmpflist[i]);
01891 tetgenio::init(f);
01892 *f = facetlist[i];
01893 tmpfmlist[i] = facetmarkerlist[i];
01894 }
01895
01896 delete [] facetlist;
01897 delete [] facetmarkerlist;
01898
01899 facetlist = tmpflist;
01900 facetmarkerlist = tmpfmlist;
01901 } else {
01902
01903 facetlist = new tetgenio::facet[nfaces];
01904 facetmarkerlist = new int[nfaces];
01905 }
01906 }
01907
01908 for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
01909 bufferp = readline(buffer, fp, &line_count);
01910 if (bufferp == NULL) {
01911 printf("Unexpected end of file on line %d in file %s\n",
01912 line_count, infilename);
01913 fclose(fp);
01914 return false;
01915 }
01916 f = &facetlist[i];
01917 tetgenio::init(f);
01918
01919 f->numberofpolygons = 1;
01920 f->polygonlist = new tetgenio::polygon[1];
01921 p = &f->polygonlist[0];
01922 tetgenio::init(p);
01923 p->numberofvertices = corners;
01924
01925 p->vertexlist = new int[p->numberofvertices];
01926
01927 for (j = 0; j < corners; j++) {
01928 if (*bufferp == '\0') {
01929 printf("Syntax error reading face on line %d in file %s\n",
01930 line_count, infilename);
01931 fclose(fp);
01932 return false;
01933 }
01934 p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0);
01935 if (firstnumber == 1) {
01936
01937 if (p->vertexlist[j] == 0) {
01938
01939 firstnumber = 0;
01940 }
01941 }
01942 bufferp = findnextnumber(bufferp);
01943 }
01944
01945 facetmarkerlist[i] = 0;
01946 if (*bufferp != '\0') {
01947 facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
01948 }
01949 }
01950
01951 numberoffacets += nfaces;
01952 nfaces = 0;
01953 }
01954 }
01955
01956 }
01957
01958
01959 fclose(fp);
01960
01961 return true;
01962 }
01963
01965
01966
01967
01968
01969
01970
01971
01973
01974 bool tetgenio::load_plc(char* filename, int object)
01975 {
01976 enum tetgenbehavior::objecttype type;
01977
01978 type = (enum tetgenbehavior::objecttype) object;
01979 switch (type) {
01980 case tetgenbehavior::NODES:
01981 return load_node(filename);
01982 case tetgenbehavior::POLY:
01983 return load_poly(filename);
01984 case tetgenbehavior::OFF:
01985 return load_off(filename);
01986 case tetgenbehavior::PLY:
01987 return load_ply(filename);
01988 case tetgenbehavior::STL:
01989 return load_stl(filename);
01990 case tetgenbehavior::MEDIT:
01991 return load_medit(filename);
01992 default:
01993 return load_poly(filename);
01994 }
01995 }
01996
01998
01999
02000
02001
02002
02003
02004
02006
02007 bool tetgenio::load_tetmesh(char* filename)
02008 {
02009 FILE *infile;
02010 char innodefilename[FILENAMESIZE];
02011 char inelefilename[FILENAMESIZE];
02012 char infacefilename[FILENAMESIZE];
02013 char inedgefilename[FILENAMESIZE];
02014 char involfilename[FILENAMESIZE];
02015 char inputline[INPUTLINESIZE];
02016 char *stringptr, *infilename;
02017 REAL attrib, volume;
02018 int volelements;
02019 int markers, corner;
02020 int index, attribindex;
02021 int i, j;
02022
02023 markers = 0;
02024
02025
02026 strcpy(innodefilename, filename);
02027 strcpy(inelefilename, filename);
02028 strcpy(infacefilename, filename);
02029 strcpy(inedgefilename, filename);
02030 strcpy(involfilename, filename);
02031 strcat(innodefilename, ".node");
02032 strcat(inelefilename, ".ele");
02033 strcat(infacefilename, ".face");
02034 strcat(inedgefilename, ".edge");
02035 strcat(involfilename, ".vol");
02036
02037
02038 infilename = innodefilename;
02039 printf("Opening %s.\n", infilename);
02040 infile = fopen(infilename, "r");
02041 if (infile == (FILE *) NULL) {
02042 printf("File I/O Error: Cannot access file %s.\n", infilename);
02043 return false;
02044 }
02045
02046 stringptr = readnumberline(inputline, infile, infilename);
02047
02048 stringptr = strstr(inputline, "rbox");
02049 if (stringptr == NULL) {
02050
02051
02052 stringptr = inputline;
02053 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02054 stringptr = findnextnumber(stringptr);
02055 if (*stringptr == '\0') {
02056 mesh_dim = 3;
02057 } else {
02058 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02059 }
02060 stringptr = findnextnumber(stringptr);
02061 if (*stringptr == '\0') {
02062 numberofpointattributes = 0;
02063 } else {
02064 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
02065 }
02066 stringptr = findnextnumber(stringptr);
02067 if (*stringptr == '\0') {
02068 markers = 0;
02069 } else {
02070 markers = (int) strtol (stringptr, &stringptr, 0);
02071 }
02072 } else {
02073
02074 stringptr = inputline;
02075
02076 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02077
02078 stringptr = readnumberline(inputline, infile, infilename);
02079 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
02080
02081 useindex = 0;
02082 }
02083
02084
02085 if (!load_node_call(infile, markers, infilename)) {
02086 fclose(infile);
02087 return false;
02088 }
02089 fclose(infile);
02090
02091
02092 if (mesh_dim == 3) {
02093 infilename = inelefilename;
02094 infile = fopen(infilename, "r");
02095 if (infile != (FILE *) NULL) {
02096 printf("Opening %s.\n", infilename);
02097
02098
02099 stringptr = readnumberline(inputline, infile, infilename);
02100 numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0);
02101 stringptr = findnextnumber(stringptr);
02102 if (*stringptr == '\0') {
02103 numberofcorners = 4;
02104 } else {
02105 numberofcorners = (int) strtol(stringptr, &stringptr, 0);
02106 }
02107 stringptr = findnextnumber(stringptr);
02108 if (*stringptr == '\0') {
02109 numberoftetrahedronattributes = 0;
02110 } else {
02111 numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0);
02112 }
02113 if (numberofcorners != 4 && numberofcorners != 10) {
02114 printf("Error: Wrong number of corners %d (should be 4 or 10).\n",
02115 numberofcorners);
02116 fclose(infile);
02117 return false;
02118 }
02119
02120 if (numberoftetrahedra > 0) {
02121 tetrahedronlist = new int[numberoftetrahedra * numberofcorners];
02122 if (tetrahedronlist == (int *) NULL) {
02123 printf("Error: Out of memory.\n");
02124 terminatetetgen(1);
02125 }
02126
02127 if (numberoftetrahedronattributes > 0) {
02128 tetrahedronattributelist = new REAL[numberoftetrahedra *
02129 numberoftetrahedronattributes];
02130 if (tetrahedronattributelist == (REAL *) NULL) {
02131 printf("Error: Out of memory.\n");
02132 terminatetetgen(1);
02133 }
02134 }
02135 }
02136
02137 index = 0;
02138 attribindex = 0;
02139 for (i = 0; i < numberoftetrahedra; i++) {
02140
02141 stringptr = readnumberline(inputline, infile, infilename);
02142 for (j = 0; j < numberofcorners; j++) {
02143 stringptr = findnextnumber(stringptr);
02144 if (*stringptr == '\0') {
02145 printf("Error: Tetrahedron %d is missing vertex %d in %s.\n",
02146 i + firstnumber, j + 1, infilename);
02147 terminatetetgen(1);
02148 }
02149 corner = (int) strtol(stringptr, &stringptr, 0);
02150 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02151 printf("Error: Tetrahedron %d has an invalid vertex index.\n",
02152 i + firstnumber);
02153 terminatetetgen(1);
02154 }
02155 tetrahedronlist[index++] = corner;
02156 }
02157
02158 for (j = 0; j < numberoftetrahedronattributes; j++) {
02159 stringptr = findnextnumber(stringptr);
02160 if (*stringptr == '\0') {
02161 attrib = 0.0;
02162 } else {
02163 attrib = (REAL) strtod(stringptr, &stringptr);
02164 }
02165 tetrahedronattributelist[attribindex++] = attrib;
02166 }
02167 }
02168 fclose(infile);
02169 }
02170 }
02171
02172
02173 if (mesh_dim == 3) {
02174 infilename = infacefilename;
02175 } else {
02176 infilename = inelefilename;
02177 }
02178 infile = fopen(infilename, "r");
02179 if (infile != (FILE *) NULL) {
02180 printf("Opening %s.\n", infilename);
02181
02182 stringptr = readnumberline(inputline, infile, infilename);
02183 numberoftrifaces = (int) strtol (stringptr, &stringptr, 0);
02184 stringptr = findnextnumber(stringptr);
02185 if (mesh_dim == 2) {
02186
02187 stringptr = findnextnumber(stringptr);
02188 }
02189 if (*stringptr == '\0') {
02190 markers = 0;
02191 } else {
02192 markers = (int) strtol (stringptr, &stringptr, 0);
02193 }
02194 if (numberoftrifaces > 0) {
02195 trifacelist = new int[numberoftrifaces * 3];
02196 if (trifacelist == (int *) NULL) {
02197 printf("Error: Out of memory.\n");
02198 terminatetetgen(1);
02199 }
02200 if (markers) {
02201 trifacemarkerlist = new int[numberoftrifaces * 3];
02202 if (trifacemarkerlist == (int *) NULL) {
02203 printf("Error: Out of memory.\n");
02204 terminatetetgen(1);
02205 }
02206 }
02207 }
02208
02209 index = 0;
02210 for (i = 0; i < numberoftrifaces; i++) {
02211
02212 stringptr = readnumberline(inputline, infile, infilename);
02213 for (j = 0; j < 3; j++) {
02214 stringptr = findnextnumber(stringptr);
02215 if (*stringptr == '\0') {
02216 printf("Error: Face %d is missing vertex %d in %s.\n",
02217 i + firstnumber, j + 1, infilename);
02218 terminatetetgen(1);
02219 }
02220 corner = (int) strtol(stringptr, &stringptr, 0);
02221 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02222 printf("Error: Face %d has an invalid vertex index.\n",
02223 i + firstnumber);
02224 terminatetetgen(1);
02225 }
02226 trifacelist[index++] = corner;
02227 }
02228
02229 if (markers) {
02230 stringptr = findnextnumber(stringptr);
02231 if (*stringptr == '\0') {
02232 attrib = 0.0;
02233 } else {
02234 attrib = (REAL) strtod(stringptr, &stringptr);
02235 }
02236 trifacemarkerlist[i] = (int) attrib;
02237 }
02238 }
02239 fclose(infile);
02240 }
02241
02242
02243 infilename = inedgefilename;
02244 infile = fopen(infilename, "r");
02245 if (infile != (FILE *) NULL) {
02246 printf("Opening %s.\n", infilename);
02247
02248 stringptr = readnumberline(inputline, infile, infilename);
02249 numberofedges = (int) strtol (stringptr, &stringptr, 0);
02250 if (numberofedges > 0) {
02251 edgelist = new int[numberofedges * 2];
02252 if (edgelist == (int *) NULL) {
02253 printf("Error: Out of memory.\n");
02254 terminatetetgen(1);
02255 }
02256 }
02257
02258 index = 0;
02259 for (i = 0; i < numberofedges; i++) {
02260
02261 stringptr = readnumberline(inputline, infile, infilename);
02262 for (j = 0; j < 2; j++) {
02263 stringptr = findnextnumber(stringptr);
02264 if (*stringptr == '\0') {
02265 printf("Error: Edge %d is missing vertex %d in %s.\n",
02266 i + firstnumber, j + 1, infilename);
02267 terminatetetgen(1);
02268 }
02269 corner = (int) strtol(stringptr, &stringptr, 0);
02270 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
02271 printf("Error: Edge %d has an invalid vertex index.\n",
02272 i + firstnumber);
02273 terminatetetgen(1);
02274 }
02275 edgelist[index++] = corner;
02276 }
02277 }
02278 fclose(infile);
02279 }
02280
02281
02282 infilename = involfilename;
02283 infile = fopen(infilename, "r");
02284 if (infile != (FILE *) NULL) {
02285 printf("Opening %s.\n", infilename);
02286
02287 stringptr = readnumberline(inputline, infile, infilename);
02288 volelements = (int) strtol (stringptr, &stringptr, 0);
02289 if (volelements != numberoftetrahedra) {
02290 printf("Warning: %s and %s disagree on number of tetrahedra.\n",
02291 inelefilename, involfilename);
02292 volelements = 0;
02293 }
02294 if (volelements > 0) {
02295 tetrahedronvolumelist = new REAL[volelements];
02296 if (tetrahedronvolumelist == (REAL *) NULL) {
02297 printf("Error: Out of memory.\n");
02298 terminatetetgen(1);
02299 }
02300 }
02301
02302 for (i = 0; i < volelements; i++) {
02303 stringptr = readnumberline(inputline, infile, infilename);
02304 stringptr = findnextnumber(stringptr);
02305 if (*stringptr == '\0') {
02306 volume = -1.0;
02307 } else {
02308 volume = (REAL) strtod(stringptr, &stringptr);
02309 }
02310 tetrahedronvolumelist[i] = volume;
02311 }
02312 fclose(infile);
02313 }
02314
02315
02316 load_mtr(filename);
02317
02318 load_pbc(filename);
02319
02320 return true;
02321 }
02322
02324
02325
02326
02327
02328
02329
02331
02332 bool tetgenio::load_voronoi(char* filename)
02333 {
02334 FILE *infile;
02335 char innodefilename[FILENAMESIZE];
02336 char inedgefilename[FILENAMESIZE];
02337 char inputline[INPUTLINESIZE];
02338 char *stringptr, *infilename;
02339 voroedge *vedge;
02340 REAL x, y, z;
02341 int firstnode, corner;
02342 int index;
02343 int i, j;
02344
02345
02346 strcpy(innodefilename, filename);
02347 strcpy(inedgefilename, filename);
02348 strcat(innodefilename, ".v.node");
02349 strcat(inedgefilename, ".v.edge");
02350
02351
02352 infilename = innodefilename;
02353 printf("Opening %s.\n", infilename);
02354 infile = fopen(infilename, "r");
02355 if (infile == (FILE *) NULL) {
02356 printf("File I/O Error: Cannot access file %s.\n", infilename);
02357 return false;
02358 }
02359
02360 stringptr = readnumberline(inputline, infile, infilename);
02361
02362 stringptr = strstr(inputline, "rbox");
02363 if (stringptr == NULL) {
02364
02365
02366 stringptr = inputline;
02367 numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02368 stringptr = findnextnumber(stringptr);
02369 if (*stringptr == '\0') {
02370 mesh_dim = 3;
02371 } else {
02372 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02373 }
02374 useindex = 1;
02375 } else {
02376
02377 stringptr = inputline;
02378
02379 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
02380
02381 stringptr = readnumberline(inputline, infile, infilename);
02382 numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
02383 useindex = 0;
02384 }
02385
02386 vpointlist = new REAL[numberofvpoints * 3];
02387 if (vpointlist == (REAL *) NULL) {
02388 printf("Error: Out of memory.\n");
02389 terminatetetgen(1);
02390 }
02391
02392 index = 0;
02393 for (i = 0; i < numberofvpoints; i++) {
02394 stringptr = readnumberline(inputline, infile, infilename);
02395 if (useindex) {
02396 if (i == 0) {
02397 firstnode = (int) strtol (stringptr, &stringptr, 0);
02398 if ((firstnode == 0) || (firstnode == 1)) {
02399 firstnumber = firstnode;
02400 }
02401 }
02402 stringptr = findnextnumber(stringptr);
02403 }
02404 if (*stringptr == '\0') {
02405 printf("Error: Point %d has no x coordinate.\n", firstnumber + i);
02406 terminatetetgen(1);
02407 }
02408 x = (REAL) strtod(stringptr, &stringptr);
02409 stringptr = findnextnumber(stringptr);
02410 if (*stringptr == '\0') {
02411 printf("Error: Point %d has no y coordinate.\n", firstnumber + i);
02412 terminatetetgen(1);
02413 }
02414 y = (REAL) strtod(stringptr, &stringptr);
02415 if (mesh_dim == 3) {
02416 stringptr = findnextnumber(stringptr);
02417 if (*stringptr == '\0') {
02418 printf("Error: Point %d has no z coordinate.\n", firstnumber + i);
02419 terminatetetgen(1);
02420 }
02421 z = (REAL) strtod(stringptr, &stringptr);
02422 } else {
02423 z = 0.0;
02424 }
02425 vpointlist[index++] = x;
02426 vpointlist[index++] = y;
02427 vpointlist[index++] = z;
02428 }
02429 fclose(infile);
02430
02431
02432 infilename = inedgefilename;
02433 infile = fopen(infilename, "r");
02434 if (infile != (FILE *) NULL) {
02435 printf("Opening %s.\n", infilename);
02436
02437 stringptr = readnumberline(inputline, infile, infilename);
02438 numberofvedges = (int) strtol (stringptr, &stringptr, 0);
02439 if (numberofvedges > 0) {
02440 vedgelist = new voroedge[numberofvedges];
02441 }
02442
02443 index = 0;
02444 for (i = 0; i < numberofvedges; i++) {
02445
02446 stringptr = readnumberline(inputline, infile, infilename);
02447 vedge = &(vedgelist[i]);
02448 for (j = 0; j < 2; j++) {
02449 stringptr = findnextnumber(stringptr);
02450 if (*stringptr == '\0') {
02451 printf("Error: Edge %d is missing vertex %d in %s.\n",
02452 i + firstnumber, j + 1, infilename);
02453 terminatetetgen(1);
02454 }
02455 corner = (int) strtol(stringptr, &stringptr, 0);
02456 j == 0 ? vedge->v1 = corner : vedge->v2 = corner;
02457 }
02458 if (vedge->v2 < 0) {
02459 for (j = 0; j < mesh_dim; j++) {
02460 stringptr = findnextnumber(stringptr);
02461 if (*stringptr == '\0') {
02462 printf("Error: Edge %d is missing normal in %s.\n",
02463 i + firstnumber, infilename);
02464 terminatetetgen(1);
02465 }
02466 vedge->vnormal[j] = (REAL) strtod(stringptr, &stringptr);
02467 }
02468 if (mesh_dim == 2) {
02469 vedge->vnormal[2] = 0.0;
02470 }
02471 } else {
02472 vedge->vnormal[0] = 0.0;
02473 vedge->vnormal[1] = 0.0;
02474 vedge->vnormal[2] = 0.0;
02475 }
02476 }
02477 fclose(infile);
02478 }
02479
02480 return true;
02481 }
02482
02484
02485
02486
02487
02488
02490
02491 void tetgenio::save_nodes(char* filename)
02492 {
02493 FILE *fout;
02494 char outnodefilename[FILENAMESIZE];
02495 char outmtrfilename[FILENAMESIZE];
02496 int i, j;
02497
02498 sprintf(outnodefilename, "%s.node", filename);
02499 printf("Saving nodes to %s\n", outnodefilename);
02500 fout = fopen(outnodefilename, "w");
02501 fprintf(fout, "%d %d %d %d\n", numberofpoints, mesh_dim,
02502 numberofpointattributes, pointmarkerlist != NULL ? 1 : 0);
02503 for (i = 0; i < numberofpoints; i++) {
02504 if (mesh_dim == 2) {
02505 fprintf(fout, "%d %.16g %.16g", i + firstnumber, pointlist[i * 2],
02506 pointlist[i * 2 + 1]);
02507 } else {
02508 fprintf(fout, "%d %.16g %.16g %.16g", i + firstnumber,
02509 pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
02510 }
02511 for (j = 0; j < numberofpointattributes; j++) {
02512 fprintf(fout, " %.16g",
02513 pointattributelist[i * numberofpointattributes + j]);
02514 }
02515 if (pointmarkerlist != NULL) {
02516 fprintf(fout, " %d", pointmarkerlist[i]);
02517 }
02518 fprintf(fout, "\n");
02519 }
02520 fclose(fout);
02521
02522
02523 if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
02524 sprintf(outmtrfilename, "%s.mtr", filename);
02525 printf("Saving metrics to %s\n", outmtrfilename);
02526 fout = fopen(outmtrfilename, "w");
02527 fprintf(fout, "%d %d\n", numberofpoints, numberofpointmtrs);
02528 for (i = 0; i < numberofpoints; i++) {
02529 for (j = 0; j < numberofpointmtrs; j++) {
02530 fprintf(fout, "%.16g ", pointmtrlist[i * numberofpointmtrs + j]);
02531 }
02532 fprintf(fout, "\n");
02533 }
02534 fclose(fout);
02535 }
02536 }
02537
02539
02540
02541
02542
02543
02545
02546 void tetgenio::save_elements(char* filename)
02547 {
02548 FILE *fout;
02549 char outelefilename[FILENAMESIZE];
02550 int i, j;
02551
02552 sprintf(outelefilename, "%s.ele", filename);
02553 printf("Saving elements to %s\n", outelefilename);
02554 fout = fopen(outelefilename, "w");
02555 fprintf(fout, "%d %d %d\n", numberoftetrahedra, numberofcorners,
02556 numberoftetrahedronattributes);
02557 for (i = 0; i < numberoftetrahedra; i++) {
02558 fprintf(fout, "%d", i + firstnumber);
02559 for (j = 0; j < numberofcorners; j++) {
02560 fprintf(fout, " %5d", tetrahedronlist[i * numberofcorners + j]);
02561 }
02562 for (j = 0; j < numberoftetrahedronattributes; j++) {
02563 fprintf(fout, " %g",
02564 tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
02565 }
02566 fprintf(fout, "\n");
02567 }
02568
02569 fclose(fout);
02570 }
02571
02573
02574
02575
02576
02577
02579
02580 void tetgenio::save_faces(char* filename)
02581 {
02582 FILE *fout;
02583 char outfacefilename[FILENAMESIZE];
02584 int i;
02585
02586 sprintf(outfacefilename, "%s.face", filename);
02587 printf("Saving faces to %s\n", outfacefilename);
02588 fout = fopen(outfacefilename, "w");
02589 fprintf(fout, "%d %d\n", numberoftrifaces,
02590 trifacemarkerlist != NULL ? 1 : 0);
02591 for (i = 0; i < numberoftrifaces; i++) {
02592 fprintf(fout, "%d %5d %5d %5d", i + firstnumber, trifacelist[i * 3],
02593 trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
02594 if (trifacemarkerlist != NULL) {
02595 fprintf(fout, " %d", trifacemarkerlist[i]);
02596 }
02597 fprintf(fout, "\n");
02598 }
02599
02600 fclose(fout);
02601 }
02602
02604
02605
02606
02607
02608
02610
02611 void tetgenio::save_edges(char* filename)
02612 {
02613 FILE *fout;
02614 char outedgefilename[FILENAMESIZE];
02615 int i;
02616
02617 sprintf(outedgefilename, "%s.edge", filename);
02618 printf("Saving edges to %s\n", outedgefilename);
02619 fout = fopen(outedgefilename, "w");
02620 fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02621 for (i = 0; i < numberofedges; i++) {
02622 fprintf(fout, "%d %4d %4d", i + firstnumber, edgelist[i * 2],
02623 edgelist[i * 2 + 1]);
02624 if (edgemarkerlist != NULL) {
02625 fprintf(fout, " %d", edgemarkerlist[i]);
02626 }
02627 fprintf(fout, "\n");
02628 }
02629
02630 fclose(fout);
02631 }
02632
02634
02635
02636
02637
02638
02640
02641 void tetgenio::save_neighbors(char* filename)
02642 {
02643 FILE *fout;
02644 char outneighborfilename[FILENAMESIZE];
02645 int i;
02646
02647 sprintf(outneighborfilename, "%s.neigh", filename);
02648 printf("Saving neighbors to %s\n", outneighborfilename);
02649 fout = fopen(outneighborfilename, "w");
02650 fprintf(fout, "%d %d\n", numberoftetrahedra, mesh_dim + 1);
02651 for (i = 0; i < numberoftetrahedra; i++) {
02652 if (mesh_dim == 2) {
02653 fprintf(fout, "%d %5d %5d %5d", i + firstnumber, neighborlist[i * 3],
02654 neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]);
02655 } else {
02656 fprintf(fout, "%d %5d %5d %5d %5d", i + firstnumber,
02657 neighborlist[i * 4], neighborlist[i * 4 + 1],
02658 neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]);
02659 }
02660 fprintf(fout, "\n");
02661 }
02662
02663 fclose(fout);
02664 }
02665
02667
02668
02669
02670
02671
02672
02673
02675
02676 void tetgenio::save_poly(char* filename)
02677 {
02678 FILE *fout;
02679 facet *f;
02680 polygon *p;
02681 char outpolyfilename[FILENAMESIZE];
02682 int i, j, k;
02683
02684 sprintf(outpolyfilename, "%s.poly", filename);
02685 printf("Saving poly to %s\n", outpolyfilename);
02686 fout = fopen(outpolyfilename, "w");
02687
02688
02689
02690
02691 fprintf(fout, "%d %d %d %d\n", 0, mesh_dim, numberofpointattributes,
02692 pointmarkerlist != NULL ? 1 : 0);
02693
02694
02695 if (mesh_dim == 2) {
02696
02697 fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
02698 for (i = 0; i < numberofedges; i++) {
02699 fprintf(fout, "%d %4d %4d", i + firstnumber, edgelist[i * 2],
02700 edgelist[i * 2 + 1]);
02701 if (edgemarkerlist != NULL) {
02702 fprintf(fout, " %d", edgemarkerlist[i]);
02703 }
02704 fprintf(fout, "\n");
02705 }
02706 } else {
02707
02708 fprintf(fout, "%d %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0);
02709 for (i = 0; i < numberoffacets; i++) {
02710 f = &(facetlist[i]);
02711 fprintf(fout, "%d %d %d # %d\n", f->numberofpolygons,f->numberofholes,
02712 facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber);
02713
02714 for (j = 0; j < f->numberofpolygons; j++) {
02715 p = &(f->polygonlist[j]);
02716 fprintf(fout, "%d ", p->numberofvertices);
02717 for (k = 0; k < p->numberofvertices; k++) {
02718 if (((k + 1) % 10) == 0) {
02719 fprintf(fout, "\n ");
02720 }
02721 fprintf(fout, " %d", p->vertexlist[k]);
02722 }
02723 fprintf(fout, "\n");
02724 }
02725
02726 for (j = 0; j < f->numberofholes; j++) {
02727 fprintf(fout, "%d %.12g %.12g %.12g\n", j + firstnumber,
02728 f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]);
02729 }
02730 }
02731 }
02732
02733
02734 fprintf(fout, "%d\n", numberofholes);
02735 for (i = 0; i < numberofholes; i++) {
02736
02737 fprintf(fout, "%d %.12g %.12g", i + firstnumber, holelist[i * mesh_dim],
02738 holelist[i * mesh_dim + 1]);
02739 if (mesh_dim == 3) {
02740
02741 fprintf(fout, " %.12g", holelist[i * mesh_dim + 2]);
02742 }
02743 fprintf(fout, "\n");
02744 }
02745
02746
02747 fprintf(fout, "%d\n", numberofregions);
02748 for (i = 0; i < numberofregions; i++) {
02749 if (mesh_dim == 2) {
02750
02751
02752 fprintf(fout, "%d %.12g %.12g %.12g %.12g\n", i + firstnumber,
02753 regionlist[i * 4], regionlist[i * 4 + 1],
02754 regionlist[i * 4 + 2], regionlist[i * 4 + 3]);
02755 } else {
02756
02757
02758 fprintf(fout, "%d %.12g %.12g %.12g %.12g %.12g\n", i + firstnumber,
02759 regionlist[i * 5], regionlist[i * 5 + 1],
02760 regionlist[i * 5 + 2], regionlist[i * 5 + 3],
02761 regionlist[i * 5 + 4]);
02762 }
02763 }
02764
02765 fclose(fout);
02766 }
02767
02769
02770
02771
02772
02773
02774
02775
02776
02777
02779
02780 char* tetgenio::readline(char *string, FILE *infile, int *linenumber)
02781 {
02782 char *result;
02783
02784
02785 do {
02786 result = fgets(string, INPUTLINESIZE - 1, infile);
02787 if (linenumber) (*linenumber)++;
02788 if (result == (char *) NULL) {
02789 return (char *) NULL;
02790 }
02791
02792 while ((*result == ' ') || (*result == '\t')) result++;
02793
02794 } while (*result == '\0');
02795 return result;
02796 }
02797
02799
02800
02801
02802
02803
02804
02806
02807 char* tetgenio::findnextfield(char *string)
02808 {
02809 char *result;
02810
02811 result = string;
02812
02813 while ((*result != '\0') && (*result != ' ') && (*result != '\t') &&
02814 (*result != ',') && (*result != ';')) {
02815 result++;
02816 }
02817
02818
02819 while ((*result == ' ') || (*result == '\t') || (*result == ',') ||
02820 (*result == ';')) {
02821 result++;
02822 }
02823 return result;
02824 }
02825
02827
02828
02829
02830
02831
02832
02834
02835 char* tetgenio::readnumberline(char *string, FILE *infile, char *infilename)
02836 {
02837 char *result;
02838
02839
02840 do {
02841 result = fgets(string, INPUTLINESIZE, infile);
02842 if (result == (char *) NULL) {
02843 if (infilename != (char *) NULL) {
02844 printf(" Error: Unexpected end of file in %s.\n", infilename);
02845 terminatetetgen(1);
02846 }
02847 return result;
02848 }
02849
02850
02851 while ((*result != '\0') && (*result != '#')
02852 && (*result != '.') && (*result != '+') && (*result != '-')
02853 && ((*result < '0') || (*result > '9'))) {
02854 result++;
02855 }
02856
02857 } while ((*result == '#') || (*result == '\0'));
02858 return result;
02859 }
02860
02862
02863
02864
02865
02866
02867
02868
02870
02871 char* tetgenio::findnextnumber(char *string)
02872 {
02873 char *result;
02874
02875 result = string;
02876
02877 while ((*result != '\0') && (*result != '#') && (*result != ' ') &&
02878 (*result != '\t') && (*result != ',')) {
02879 result++;
02880 }
02881
02882
02883 while ((*result != '\0') && (*result != '#')
02884 && (*result != '.') && (*result != '+') && (*result != '-')
02885 && ((*result < '0') || (*result > '9'))) {
02886 result++;
02887 }
02888
02889 if (*result == '#') {
02890 *result = '\0';
02891 }
02892 return result;
02893 }
02894
02895
02896
02897
02898
02899 static REAL PI = 3.14159265358979323846264338327950288419716939937510582;
02900
02901
02902
02903
02904
02906
02907
02908
02910
02911 tetgenbehavior::tetgenbehavior()
02912 {
02913
02914 plc = 0;
02915 quality = 0;
02916 refine = 0;
02917 coarse = 0;
02918 metric = 0;
02919 minratio = 2.0;
02920 goodratio = 0.0;
02921 minangle = 20.0;
02922 goodangle = 0.0;
02923 maxdihedral = 165.0;
02924 mindihedral = 5.0;
02925 varvolume = 0;
02926 fixedvolume = 0;
02927 maxvolume = -1.0;
02928 regionattrib = 0;
02929 insertaddpoints = 0;
02930 diagnose = 0;
02931 offcenter = 0;
02932 conformdel = 0;
02933 alpha1 = sqrt(2.0);
02934 alpha2 = 1.0;
02935 alpha3 = 0.6;
02936 zeroindex = 0;
02937 facesout = 0;
02938 edgesout = 0;
02939 neighout = 0;
02940 voroout = 0;
02941 meditview = 0;
02942 gidview = 0;
02943 geomview = 0;
02944 optlevel = 3;
02945 optpasses = 3;
02946 order = 1;
02947 nojettison = 0;
02948 nobound = 0;
02949 nonodewritten = 0;
02950 noelewritten = 0;
02951 nofacewritten = 0;
02952 noiterationnum = 0;
02953 nobisect = 0;
02954 noflip = 0;
02955 steiner = -1;
02956 fliprepair = 1;
02957 nomerge = 0;
02958 docheck = 0;
02959 quiet = 0;
02960 verbose = 0;
02961 useshelles = 0;
02962 epsilon = 1.0e-8;
02963 epsilon2 = 1.0e-5;
02964 object = NONE;
02965
02966 commandline[0] = '\0';
02967 infilename[0] = '\0';
02968 outfilename[0] = '\0';
02969 addinfilename[0] = '\0';
02970 bgmeshfilename[0] = '\0';
02971 }
02972
02974
02975
02976
02978
02979 void tetgenbehavior::versioninfo()
02980 {
02981 printf("Version 1.4.2 (April 16, 2007).\n");
02982 printf("\n");
02983 printf("Copyright (C) 2002 - 2007\n");
02984 printf("Hang Si\n");
02985 printf("Mohrenstr. 39, 10117 Berlin, Germany\n");
02986 printf("si@wias-berlin.de\n");
02987 }
02988
02990
02991
02992
02994
02995 void tetgenbehavior::syntax()
02996 {
02997 printf(" tetgen [-prq_Ra_AiMYS_T_dzo_fenvgGOJBNEFICQVh] input_file\n");
02998 printf(" -p Tetrahedralizes a piecewise linear complex (PLC).\n");
02999 printf(" -r Reconstructs a previously generated mesh.\n");
03000 printf(" -q Quality mesh generation (adding new mesh points to ");
03001 printf("improve mesh quality).\n");
03002 printf(" -R Mesh coarsening (deleting redundant mesh points).\n");
03003 printf(" -a Applies a maximum tetrahedron volume constraint.\n");
03004 printf(" -A Assigns attributes to identify tetrahedra in different ");
03005 printf("regions.\n");
03006 printf(" -i Inserts a list of additional points into mesh.\n");
03007 printf(" -M Does not merge coplanar facets.\n");
03008 printf(" -Y Suppresses boundary facets/segments splitting.\n");
03009 printf(" -S Specifies maximum number of added points.\n");
03010 printf(" -T Sets a tolerance for coplanar test (default 1e-8).\n");
03011 printf(" -d Detects self-intersections of facets of the PLC.\n");
03012 printf(" -z Numbers all output items starting from zero.\n");
03013 printf(" -o2 Generates second-order subparametric elements.\n");
03014 printf(" -f Outputs all faces to .face file.");
03015 printf("file.\n");
03016 printf(" -e Outputs all edges to .edge file.\n");
03017 printf(" -n Outputs tetrahedra neighbors to .neigh file.\n");
03018 printf(" -v Outputs Voronoi diagram to files.\n");
03019 printf(" -g Outputs mesh to .mesh file for viewing by Medit.\n");
03020 printf(" -G Outputs mesh to .msh file for viewing by Gid.\n");
03021 printf(" -O Outputs mesh to .off file for viewing by Geomview.\n");
03022 printf(" -J No jettison of unused vertices from output .node file.\n");
03023 printf(" -B Suppresses output of boundary information.\n");
03024 printf(" -N Suppresses output of .node file.\n");
03025 printf(" -E Suppresses output of .ele file.\n");
03026 printf(" -F Suppresses output of .face file.\n");
03027 printf(" -I Suppresses mesh iteration numbers.\n");
03028 printf(" -C Checks the consistency of the final mesh.\n");
03029 printf(" -Q Quiet: No terminal output except errors.\n");
03030 printf(" -V Verbose: Detailed information, more terminal output.\n");
03031 printf(" -h Help: A brief instruction for using TetGen.\n");
03032 }
03033
03035
03036
03037
03039
03040 void tetgenbehavior::usage()
03041 {
03042 printf("TetGen\n");
03043 printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
03044 printf("Triangulator\n");
03045 versioninfo();
03046 printf("\n");
03047 printf("What Can TetGen Do?\n");
03048 printf("\n");
03049 printf(" TetGen generates exact Delaunay tetrahedralizations, exact\n");
03050 printf(" constrained Delaunay tetrahedralizations, and quality ");
03051 printf("tetrahedral\n meshes. The latter are nicely graded and whose ");
03052 printf("tetrahedra have\n radius-edge ratio bounded, thus are suitable ");
03053 printf("for finite element and\n finite volume analysis.\n");
03054 printf("\n");
03055 printf("Command Line Syntax:\n");
03056 printf("\n");
03057 printf(" Below is the command line syntax of TetGen with a list of ");
03058 printf("short\n");
03059 printf(" descriptions. Underscores indicate that numbers may optionally\n");
03060 printf(" follow certain switches. Do not leave any space between a ");
03061 printf("switch\n");
03062 printf(" and its numeric parameter. \'input_file\' contains input data\n");
03063 printf(" depending on the switches you supplied which may be a ");
03064 printf(" piecewise\n");
03065 printf(" linear complex or a list of nodes. File formats and detailed\n");
03066 printf(" description of command line switches are found in user's ");
03067 printf("manual.\n");
03068 printf("\n");
03069 syntax();
03070 printf("\n");
03071 printf("Examples of How to Use TetGen:\n");
03072 printf("\n");
03073 printf(" \'tetgen object\' reads vertices from object.node, and writes ");
03074 printf("their\n Delaunay tetrahedralization to object.1.node and ");
03075 printf("object.1.ele.\n");
03076 printf("\n");
03077 printf(" \'tetgen -p object\' reads a PLC from object.poly or object.");
03078 printf("smesh (and\n possibly object.node) and writes its constrained ");
03079 printf("Delaunay\n tetrahedralization to object.1.node, object.1.ele and ");
03080 printf("object.1.face.\n");
03081 printf("\n");
03082 printf(" \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
03083 printf(" object.smesh (and possibly object.node), generates a mesh ");
03084 printf("whose\n tetrahedra have radius-edge ratio smaller than 1.414 and ");
03085 printf("have volume\n of 0.1 or less, and writes the mesh to ");
03086 printf("object.1.node, object.1.ele\n and object.1.face.\n");
03087 printf("\n");
03088 printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
03089 }
03090
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110
03111
03112
03114
03115 bool tetgenbehavior::parse_commandline(int argc, char **argv)
03116 {
03117 int startindex;
03118 int increment;
03119 int meshnumber;
03120 int scount;
03121 int i, j, k;
03122 char workstring[1024];
03123
03124
03125 if (argc == 0) {
03126 startindex = 0;
03127 argc = 1;
03128 commandline[0] = '\0';
03129 } else {
03130 startindex = 1;
03131 strcpy(commandline, argv[0]);
03132 strcat(commandline, " ");
03133 }
03134
03135
03136 scount = 0;
03137
03138 for (i = startindex; i < argc; i++) {
03139
03140 strcat(commandline, argv[i]);
03141 strcat(commandline, " ");
03142 if (startindex == 1) {
03143
03144 if (argv[i][0] != '-') {
03145 strncpy(infilename, argv[i], 1024 - 1);
03146 infilename[1024 - 1] = '\0';
03147
03148 continue;
03149 }
03150 }
03151
03152 for (j = startindex; argv[i][j] != '\0'; j++) {
03153 if (argv[i][j] == 'p') {
03154 plc = 1;
03155 } else if (argv[i][j] == 'r') {
03156 refine = 1;
03157 } else if (argv[i][j] == 'R') {
03158 coarse = 1;
03159 } else if (argv[i][j] == 'q') {
03160 quality++;
03161 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03162 (argv[i][j + 1] == '.')) {
03163 k = 0;
03164 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03165 (argv[i][j + 1] == '.')) {
03166 j++;
03167 workstring[k] = argv[i][j];
03168 k++;
03169 }
03170 workstring[k] = '\0';
03171 if (quality == 1) {
03172 minratio = (REAL) strtod(workstring, (char **) NULL);
03173 } else if (quality == 2) {
03174 mindihedral = (REAL) strtod(workstring, (char **) NULL);
03175 } else if (quality == 3) {
03176 maxdihedral = (REAL) strtod(workstring, (char **) NULL);
03177 } else if (quality == 4) {
03178 alpha2 = (REAL) strtod(workstring, (char **) NULL);
03179 } else if (quality == 5) {
03180 alpha1 = (REAL) strtod(workstring, (char **) NULL);
03181 }
03182 }
03183 } else if (argv[i][j] == 'm') {
03184 metric++;
03185 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03186 (argv[i][j + 1] == '.')) {
03187 k = 0;
03188 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03189 (argv[i][j + 1] == '.')) {
03190 j++;
03191 workstring[k] = argv[i][j];
03192 k++;
03193 }
03194 workstring[k] = '\0';
03195 if (metric == 1) {
03196 alpha1 = (REAL) strtod(workstring, (char **) NULL);
03197 } else if (metric == 2) {
03198 alpha2 = (REAL) strtod(workstring, (char **) NULL);
03199 }
03200 }
03201 } else if (argv[i][j] == 'a') {
03202 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03203 (argv[i][j + 1] == '.')) {
03204 fixedvolume = 1;
03205 k = 0;
03206 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03207 (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03208 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03209 j++;
03210 workstring[k] = argv[i][j];
03211 k++;
03212 }
03213 workstring[k] = '\0';
03214 maxvolume = (REAL) strtod(workstring, (char **) NULL);
03215 } else {
03216 varvolume = 1;
03217 }
03218 } else if (argv[i][j] == 'A') {
03219 regionattrib++;
03220 } else if (argv[i][j] == 'i') {
03221 insertaddpoints = 1;
03222 } else if (argv[i][j] == 'd') {
03223 diagnose = 1;
03224 } else if (argv[i][j] == 'z') {
03225 zeroindex = 1;
03226 } else if (argv[i][j] == 'f') {
03227 facesout = 1;
03228 } else if (argv[i][j] == 'e') {
03229 edgesout++;
03230 } else if (argv[i][j] == 'n') {
03231 neighout++;
03232 } else if (argv[i][j] == 'v') {
03233 voroout = 1;
03234 } else if (argv[i][j] == 'g') {
03235 meditview = 1;
03236 } else if (argv[i][j] == 'G') {
03237 gidview = 1;
03238 } else if (argv[i][j] == 'O') {
03239 geomview = 1;
03240 } else if (argv[i][j] == 'M') {
03241 nomerge = 1;
03242 } else if (argv[i][j] == 'Y') {
03243 nobisect++;
03244 } else if (argv[i][j] == 'J') {
03245 nojettison = 1;
03246 } else if (argv[i][j] == 'B') {
03247 nobound = 1;
03248 } else if (argv[i][j] == 'N') {
03249 nonodewritten = 1;
03250 } else if (argv[i][j] == 'E') {
03251 noelewritten = 1;
03252 } else if (argv[i][j] == 'F') {
03253 nofacewritten = 1;
03254 } else if (argv[i][j] == 'I') {
03255 noiterationnum = 1;
03256 } else if (argv[i][j] == 'o') {
03257 if (argv[i][j + 1] == '2') {
03258 j++;
03259 order = 2;
03260 }
03261 } else if (argv[i][j] == 'S') {
03262 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03263 (argv[i][j + 1] == '.')) {
03264 k = 0;
03265 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03266 (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03267 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03268 j++;
03269 workstring[k] = argv[i][j];
03270 k++;
03271 }
03272 workstring[k] = '\0';
03273 steiner = (int) strtol(workstring, (char **) NULL, 0);
03274 }
03275 } else if (argv[i][j] == 's') {
03276 scount++;
03277 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03278 (argv[i][j + 1] == '.')) {
03279 k = 0;
03280 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03281 (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03282 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03283 j++;
03284 workstring[k] = argv[i][j];
03285 k++;
03286 }
03287 workstring[k] = '\0';
03288 if (scount == 1) {
03289 optlevel = (int) strtol(workstring, (char **) NULL, 0);
03290 } else if (scount == 2) {
03291 optpasses = (int) strtol(workstring, (char **) NULL, 0);
03292 }
03293 }
03294 } else if (argv[i][j] == 'D') {
03295 conformdel++;
03296 } else if (argv[i][j] == 'T') {
03297 if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03298 (argv[i][j + 1] == '.')) {
03299 k = 0;
03300 while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
03301 (argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
03302 (argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
03303 j++;
03304 workstring[k] = argv[i][j];
03305 k++;
03306 }
03307 workstring[k] = '\0';
03308 epsilon = (REAL) strtod(workstring, (char **) NULL);
03309 }
03310 } else if (argv[i][j] == 'C') {
03311 docheck++;
03312 } else if (argv[i][j] == 'X') {
03313 fliprepair = 0;
03314 } else if (argv[i][j] == 'Q') {
03315 quiet = 1;
03316 } else if (argv[i][j] == 'V') {
03317 verbose++;
03318
03319
03320
03321 } else if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
03322 (argv[i][j] == '?')) {
03323 usage();
03324 terminatetetgen(0);
03325 } else {
03326 printf("Warning: Unknown switch -%c.\n", argv[i][j]);
03327 }
03328 }
03329 }
03330
03331 if (startindex == 0) {
03332
03333 strcpy(infilename, "tetgen-tmpfile");
03334 } else {
03335 if (infilename[0] == '\0') {
03336
03337 syntax();
03338 terminatetetgen(0);
03339 }
03340
03341 if (!strcmp(&infilename[strlen(infilename) - 5], ".node")) {
03342 infilename[strlen(infilename) - 5] = '\0';
03343 object = NODES;
03344 } else if (!strcmp(&infilename[strlen(infilename) - 5], ".poly")) {
03345 infilename[strlen(infilename) - 5] = '\0';
03346 object = POLY;
03347 plc = 1;
03348 } else if (!strcmp(&infilename[strlen(infilename) - 6], ".smesh")) {
03349 infilename[strlen(infilename) - 6] = '\0';
03350 object = POLY;
03351 plc = 1;
03352 } else if (!strcmp(&infilename[strlen(infilename) - 4], ".off")) {
03353 infilename[strlen(infilename) - 4] = '\0';
03354 object = OFF;
03355 plc = 1;
03356 } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ply")) {
03357 infilename[strlen(infilename) - 4] = '\0';
03358 object = PLY;
03359 plc = 1;
03360 } else if (!strcmp(&infilename[strlen(infilename) - 4], ".stl")) {
03361 infilename[strlen(infilename) - 4] = '\0';
03362 object = STL;
03363 plc = 1;
03364 } else if (!strcmp(&infilename[strlen(infilename) - 5], ".mesh")) {
03365 infilename[strlen(infilename) - 5] = '\0';
03366 object = MEDIT;
03367 plc = 1;
03368 } else if (!strcmp(&infilename[strlen(infilename) - 4], ".ele")) {
03369 infilename[strlen(infilename) - 4] = '\0';
03370 object = MESH;
03371 refine = 1;
03372 }
03373 }
03374 plc = plc || diagnose;
03375 useshelles = plc || refine || coarse || quality;
03376 goodratio = minratio;
03377 goodratio *= goodratio;
03378
03379
03380 if (plc && refine) {
03381 printf("Error: Switch -r cannot use together with -p.\n");
03382 return false;
03383 }
03384 if (refine && (plc || noiterationnum)) {
03385 printf("Error: Switches %s cannot use together with -r.\n",
03386 "-p, -d, and -I");
03387 return false;
03388 }
03389 if (diagnose && (quality || insertaddpoints || (order == 2) || neighout
03390 || docheck)) {
03391 printf("Error: Switches %s cannot use together with -d.\n",
03392 "-q, -i, -o2, -n, and -C");
03393 return false;
03394 }
03395
03396
03397
03398 if (!refine && !plc) {
03399 varvolume = 0;
03400 }
03401
03402
03403 if (refine || !plc) {
03404 regionattrib = 0;
03405 }
03406
03407 if (fixedvolume || varvolume) {
03408 if (quality == 0) {
03409 quality = 1;
03410 }
03411 }
03412
03413 goodangle = cos(minangle * PI / 180.0);
03414 goodangle *= goodangle;
03415
03416 increment = 0;
03417 strcpy(workstring, infilename);
03418 j = 1;
03419 while (workstring[j] != '\0') {
03420 if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
03421 increment = j + 1;
03422 }
03423 j++;
03424 }
03425 meshnumber = 0;
03426 if (increment > 0) {
03427 j = increment;
03428 do {
03429 if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
03430 meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
03431 } else {
03432 increment = 0;
03433 }
03434 j++;
03435 } while (workstring[j] != '\0');
03436 }
03437 if (noiterationnum) {
03438 strcpy(outfilename, infilename);
03439 } else if (increment == 0) {
03440 strcpy(outfilename, infilename);
03441 strcat(outfilename, ".1");
03442 } else {
03443 workstring[increment] = '%';
03444 workstring[increment + 1] = 'd';
03445 workstring[increment + 2] = '\0';
03446 sprintf(outfilename, workstring, meshnumber + 1);
03447 }
03448
03449 strcpy(addinfilename, infilename);
03450 strcat(addinfilename, ".a");
03451
03452 strcpy(bgmeshfilename, infilename);
03453 strcat(bgmeshfilename, ".b");
03454
03455 return true;
03456 }
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476 int tetgenmesh::compare_2_ints(const void* x, const void* y) {
03477 if (* (int *) x < * (int *) y) {
03478 return -1;
03479 } else if (* (int *) x > * (int *) y) {
03480 return 1;
03481 } else {
03482 return 0;
03483 }
03484 }
03485
03486
03487
03488 int tetgenmesh::compare_2_longs(const void* x, const void* y) {
03489 if (* (long *) x < * (long *) y) {
03490 return -1;
03491 } else if (* (long *) x > * (long *) y) {
03492 return 1;
03493 } else {
03494 return 0;
03495 }
03496 }
03497
03498
03499 int tetgenmesh::compare_2_unsignedlongs(const void* x, const void* y) {
03500 if (* (unsigned long *) x < * (unsigned long *) y) {
03501 return -1;
03502 } else if (* (unsigned long *) x > * (unsigned long *) y) {
03503 return 1;
03504 } else {
03505 return 0;
03506 }
03507 }
03508
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03523
03524 void tetgenmesh::set_compfunc(char* str, int* itbytes, compfunc* pcomp)
03525 {
03526
03527 if (str[strlen(str) - 1] == '*') {
03528 *itbytes = sizeof(unsigned long);
03529 *pcomp = &compare_2_unsignedlongs;
03530 return;
03531 }
03532
03533 if (strcmp(str, "int") == 0) {
03534 *itbytes = sizeof(int);
03535 *pcomp = &compare_2_ints;
03536 } else if (strcmp(str, "long") == 0) {
03537 *itbytes = sizeof(long);
03538 *pcomp = &compare_2_longs;
03539 } else if (strcmp(str, "unsigned long") == 0) {
03540 *itbytes = sizeof(unsigned long);
03541 *pcomp = &compare_2_unsignedlongs;
03542 } else {
03543
03544 printf("Error in set_compfunc(): unknown type %s.\n", str);
03545 terminatetetgen(1);
03546 }
03547 }
03548
03550
03551
03552
03553
03554
03555
03556
03558
03559 void tetgenmesh::list::
03560 listinit(int itbytes, compfunc pcomp, int mitems,int exsize)
03561 {
03562 #ifdef SELF_CHECK
03563 assert(itbytes > 0 && mitems > 0 && exsize > 0);
03564 #endif
03565 itembytes = itbytes;
03566 comp = pcomp;
03567 maxitems = mitems;
03568 expandsize = exsize;
03569 base = (char *) malloc(maxitems * itembytes);
03570 if (base == (char *) NULL) {
03571 printf("Error: Out of memory.\n");
03572 terminatetetgen(1);
03573 }
03574 items = 0;
03575 }
03576
03578
03579
03580
03581
03582
03583
03584
03585
03587
03588 void* tetgenmesh::list::append(void *appitem)
03589 {
03590
03591 if (items == maxitems) {
03592 char* newbase = (char *) realloc(base, (maxitems + expandsize) *
03593 itembytes);
03594 if (newbase == (char *) NULL) {
03595 printf("Error: Out of memory.\n");
03596 terminatetetgen(1);
03597 }
03598 base = newbase;
03599 maxitems += expandsize;
03600 }
03601 if (appitem != (void *) NULL) {
03602 memcpy(base + items * itembytes, appitem, itembytes);
03603 }
03604 items++;
03605 return (void *) (base + (items - 1) * itembytes);
03606 }
03607
03609
03610
03611
03612
03613
03614
03615
03616
03618
03619 void* tetgenmesh::list::insert(int pos, void* insitem)
03620 {
03621 if (pos >= items) {
03622 return append(insitem);
03623 }
03624
03625 if (items == maxitems) {
03626 char* newbase = (char *) realloc(base, (maxitems + expandsize) *
03627 itembytes);
03628 if (newbase == (char *) NULL) {
03629 printf("Error: Out of memory.\n");
03630 terminatetetgen(1);
03631 }
03632 base = newbase;
03633 maxitems += expandsize;
03634 }
03635
03636 memmove(base + (pos + 1) * itembytes,
03637 base + pos * itembytes,
03638 (items - pos) * itembytes);
03639
03640 if (insitem != (void *) NULL) {
03641 memcpy(base + pos * itembytes, insitem, itembytes);
03642 }
03643 items++;
03644 return (void *) (base + pos * itembytes);
03645 }
03646
03648
03649
03650
03651
03652
03653
03654
03655
03657
03658 void tetgenmesh::list::del(int pos, int order)
03659 {
03660
03661 if (pos >= 0 && pos < items - 1) {
03662 if (order == 1) {
03663
03664 memmove(base + pos * itembytes,
03665 base + (pos + 1) * itembytes,
03666 (items - pos - 1) * itembytes);
03667 } else {
03668
03669 memcpy(base + pos * itembytes,
03670 base + (items - 1) * itembytes,
03671 itembytes);
03672 }
03673 }
03674 if (items > 0) {
03675 items--;
03676 }
03677 }
03678
03680
03681
03682
03683
03684
03685
03686
03688
03689 int tetgenmesh::list::hasitem(void* checkitem)
03690 {
03691 int i;
03692
03693 for (i = 0; i < items; i++) {
03694 if (comp != (compfunc) NULL) {
03695 if ((* comp)((void *)(base + i * itembytes), checkitem) == 0) {
03696 return i;
03697 }
03698 }
03699 }
03700 return -1;
03701 }
03702
03704
03705
03706
03707
03708
03710
03711 void tetgenmesh::list::sort()
03712 {
03713 qsort((void *) base, (size_t) items, (size_t) itembytes, comp);
03714 }
03715
03717
03718
03719
03721
03722 tetgenmesh::memorypool::memorypool()
03723 {
03724 firstblock = nowblock = (void **) NULL;
03725 nextitem = (void *) NULL;
03726 deaditemstack = (void *) NULL;
03727 pathblock = (void **) NULL;
03728 pathitem = (void *) NULL;
03729 itemwordtype = POINTER;
03730 alignbytes = 0;
03731 itembytes = itemwords = 0;
03732 itemsperblock = 0;
03733 items = maxitems = 0l;
03734 unallocateditems = 0;
03735 pathitemsleft = 0;
03736 }
03737
03738 tetgenmesh::memorypool::
03739 memorypool(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03740 {
03741 poolinit(bytecount, itemcount, wtype, alignment);
03742 }
03743
03745
03746
03747
03749
03750 tetgenmesh::memorypool::~memorypool()
03751 {
03752 while (firstblock != (void **) NULL) {
03753 nowblock = (void **) *(firstblock);
03754 free(firstblock);
03755 firstblock = nowblock;
03756 }
03757 }
03758
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03774
03775 void tetgenmesh::memorypool::
03776 poolinit(int bytecount, int itemcount, enum wordtype wtype, int alignment)
03777 {
03778 int wordsize;
03779
03780
03781 itemwordtype = wtype;
03782 wordsize = (itemwordtype == POINTER) ? sizeof(void *) : sizeof(REAL);
03783
03784
03785
03786
03787
03788 if (alignment > wordsize) {
03789 alignbytes = alignment;
03790 } else {
03791 alignbytes = wordsize;
03792 }
03793 if ((int) sizeof(void *) > alignbytes) {
03794 alignbytes = (int) sizeof(void *);
03795 }
03796 itemwords = ((bytecount + alignbytes - 1) / alignbytes)
03797 * (alignbytes / wordsize);
03798 itembytes = itemwords * wordsize;
03799 itemsperblock = itemcount;
03800
03801
03802
03803
03804 firstblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *)
03805 + alignbytes);
03806 if (firstblock == (void **) NULL) {
03807 printf("Error: Out of memory.\n");
03808 terminatetetgen(1);
03809 }
03810
03811 *(firstblock) = (void *) NULL;
03812 restart();
03813 }
03814
03816
03817
03818
03819
03820
03821
03822
03824
03825 void tetgenmesh::memorypool::restart()
03826 {
03827 unsigned long alignptr;
03828
03829 items = 0;
03830 maxitems = 0;
03831
03832
03833 nowblock = firstblock;
03834
03835 alignptr = (unsigned long) (nowblock + 1);
03836
03837 nextitem = (void *)
03838 (alignptr + (unsigned long) alignbytes -
03839 (alignptr % (unsigned long) alignbytes));
03840
03841 unallocateditems = itemsperblock;
03842
03843 deaditemstack = (void *) NULL;
03844 }
03845
03847
03848
03849
03851
03852 void* tetgenmesh::memorypool::alloc()
03853 {
03854 void *newitem;
03855 void **newblock;
03856 unsigned long alignptr;
03857
03858
03859
03860 if (deaditemstack != (void *) NULL) {
03861 newitem = deaditemstack;
03862 deaditemstack = * (void **) deaditemstack;
03863 } else {
03864
03865 if (unallocateditems == 0) {
03866
03867 if (*nowblock == (void *) NULL) {
03868
03869 newblock = (void **) malloc(itemsperblock * itembytes + sizeof(void *)
03870 + alignbytes);
03871 if (newblock == (void **) NULL) {
03872 printf("Error: Out of memory.\n");
03873 terminatetetgen(1);
03874 }
03875 *nowblock = (void *) newblock;
03876
03877 *newblock = (void *) NULL;
03878 }
03879
03880 nowblock = (void **) *nowblock;
03881
03882
03883 alignptr = (unsigned long) (nowblock + 1);
03884
03885 nextitem = (void *)
03886 (alignptr + (unsigned long) alignbytes -
03887 (alignptr % (unsigned long) alignbytes));
03888
03889 unallocateditems = itemsperblock;
03890 }
03891
03892 newitem = nextitem;
03893
03894 if (itemwordtype == POINTER) {
03895 nextitem = (void *) ((void **) nextitem + itemwords);
03896 } else {
03897 nextitem = (void *) ((REAL *) nextitem + itemwords);
03898 }
03899 unallocateditems--;
03900 maxitems++;
03901 }
03902 items++;
03903 return newitem;
03904 }
03905
03907
03908
03909
03910
03911
03913
03914 void tetgenmesh::memorypool::dealloc(void *dyingitem)
03915 {
03916
03917 *((void **) dyingitem) = deaditemstack;
03918 deaditemstack = dyingitem;
03919 items--;
03920 }
03921
03923
03924
03925
03926
03927
03929
03930 void tetgenmesh::memorypool::traversalinit()
03931 {
03932 unsigned long alignptr;
03933
03934
03935 pathblock = firstblock;
03936
03937 alignptr = (unsigned long) (pathblock + 1);
03938
03939 pathitem = (void *)
03940 (alignptr + (unsigned long) alignbytes -
03941 (alignptr % (unsigned long) alignbytes));
03942
03943 pathitemsleft = itemsperblock;
03944 }
03945
03947
03948
03949
03950
03951
03952
03953
03954
03955
03957
03958 void* tetgenmesh::memorypool::traverse()
03959 {
03960 void *newitem;
03961 unsigned long alignptr;
03962
03963
03964 if (pathitem == nextitem) {
03965 return (void *) NULL;
03966 }
03967
03968 if (pathitemsleft == 0) {
03969
03970 pathblock = (void **) *pathblock;
03971
03972 alignptr = (unsigned long) (pathblock + 1);
03973
03974 pathitem = (void *)
03975 (alignptr + (unsigned long) alignbytes -
03976 (alignptr % (unsigned long) alignbytes));
03977
03978 pathitemsleft = itemsperblock;
03979 }
03980 newitem = pathitem;
03981
03982 if (itemwordtype == POINTER) {
03983 pathitem = (void *) ((void **) pathitem + itemwords);
03984 } else {
03985 pathitem = (void *) ((REAL *) pathitem + itemwords);
03986 }
03987 pathitemsleft--;
03988 return newitem;
03989 }
03990
03992
03993
03994
03995
03996
03997
03999
04000 void tetgenmesh::link::linkinit(int bytecount, compfunc pcomp, int itemcount)
04001 {
04002 #ifdef SELF_CHECK
04003 assert(bytecount > 0 && itemcount > 0);
04004 #endif
04005
04006 linkitembytes = bytecount;
04007
04008 comp = pcomp;
04009
04010
04011
04012
04013
04014 poolinit(bytecount + 2 * sizeof(void **), itemcount + 2, POINTER, 0);
04015
04016
04017 head = (void **) alloc();
04018 tail = (void **) alloc();
04019 *head = (void *) tail;
04020 *(head + 1) = NULL;
04021 *tail = NULL;
04022 *(tail + 1) = (void *) head;
04023 nextlinkitem = *head;
04024 curpos = 1;
04025 linkitems = 0;
04026 }
04027
04029
04030
04031
04032
04033
04034
04035
04037
04038 void tetgenmesh::link::clear()
04039 {
04040
04041 restart();
04042
04043
04044 head = (void **) alloc();
04045 tail = (void **) alloc();
04046 *head = (void *) tail;
04047 *(head + 1) = NULL;
04048 *tail = NULL;
04049 *(tail + 1) = (void *) head;
04050 nextlinkitem = *head;
04051 curpos = 1;
04052 linkitems = 0;
04053 }
04054
04056
04057
04058
04059
04060
04061
04062
04063
04065
04066 bool tetgenmesh::link::move(int numberofnodes)
04067 {
04068 void **nownode;
04069 int i;
04070
04071 nownode = (void **) nextlinkitem;
04072 if (numberofnodes > 0) {
04073
04074 i = 0;
04075 while ((i < numberofnodes) && *nownode) {
04076 nownode = (void **) *nownode;
04077 i++;
04078 }
04079 if (*nownode == NULL) return false;
04080 nextlinkitem = (void *) nownode;
04081 curpos += numberofnodes;
04082 } else if (numberofnodes < 0) {
04083
04084 i = 0;
04085 numberofnodes = -numberofnodes;
04086 while ((i < numberofnodes) && *(nownode + 1)) {
04087 nownode = (void **) *(nownode + 1);
04088 i++;
04089 }
04090 if (*(nownode + 1) == NULL) return false;
04091 nextlinkitem = (void *) nownode;
04092 curpos -= numberofnodes;
04093 }
04094 return true;
04095 }
04096
04098
04099
04100
04101
04102
04103
04104
04105
04106
04108
04109 bool tetgenmesh::link::locate(int pos)
04110 {
04111 int headdist, taildist, curdist;
04112 int abscurdist, mindist;
04113
04114 if (pos < 1 || pos > linkitems) return false;
04115
04116 headdist = pos - 1;
04117 taildist = linkitems - pos;
04118 curdist = pos - curpos;
04119 abscurdist = curdist >= 0 ? curdist : -curdist;
04120
04121 if (headdist > taildist) {
04122 if (taildist > abscurdist) {
04123 mindist = curdist;
04124 } else {
04125
04126 mindist = -taildist;
04127 goend();
04128 }
04129 } else {
04130
04131 if (headdist > abscurdist) {
04132 mindist = curdist;
04133 } else {
04134
04135 mindist = headdist;
04136 rewind();
04137 }
04138 }
04139
04140 return move(mindist);
04141 }
04142
04144
04145
04146
04147
04148
04149
04150
04152
04153 void* tetgenmesh::link::add(void* newitem)
04154 {
04155 void **newnode = tail;
04156 if (newitem != (void *) NULL) {
04157 memcpy((void *)(newnode + 2), newitem, linkitembytes);
04158 }
04159 tail = (void **) alloc();
04160 *tail = NULL;
04161 *newnode = (void*) tail;
04162 *(tail + 1) = (void*) newnode;
04163 linkitems++;
04164 return (void *)(newnode + 2);
04165 }
04166
04168
04169
04170
04171
04172
04173
04174
04175
04176
04178
04179 void* tetgenmesh::link::insert(int pos, void* insitem)
04180 {
04181 if (!locate(pos)) {
04182 return add(insitem);
04183 }
04184
04185 void **nownode = (void **) nextlinkitem;
04186
04187
04188 void **newnode = (void **) alloc();
04189 if (insitem != (void *) NULL) {
04190 memcpy((void *)(newnode + 2), insitem, linkitembytes);
04191 }
04192
04193 *(void **)(*(nownode + 1)) = (void *) newnode;
04194 *newnode = (void *) nownode;
04195 *(newnode + 1) = *(nownode + 1);
04196 *(nownode + 1) = (void *) newnode;
04197
04198 linkitems++;
04199
04200 nextlinkitem = (void *) newnode;
04201 return (void *)(newnode + 2);
04202 }
04203
04205
04206
04207
04208
04209
04210
04212
04213 void* tetgenmesh::link::deletenode(void** deadnode)
04214 {
04215 void **nextnode = (void **) *deadnode;
04216 void **prevnode = (void **) *(deadnode + 1);
04217 *prevnode = (void *) nextnode;
04218 *(nextnode + 1) = (void *) prevnode;
04219
04220 dealloc((void *) deadnode);
04221 linkitems--;
04222
04223 nextlinkitem = (void *) nextnode;
04224 return (void *)(deadnode + 2);
04225 }
04226
04228
04229
04230
04231
04232
04233
04234
04236
04237 void* tetgenmesh::link::del(int pos)
04238 {
04239 if (!locate(pos) || (linkitems == 0)) {
04240 return (void *) NULL;
04241 }
04242 return deletenode((void **) nextlinkitem);
04243 }
04244
04246
04247
04248
04249
04250
04251
04252
04254
04255 void* tetgenmesh::link::getitem()
04256 {
04257 if (nextlinkitem == (void *) tail) return NULL;
04258 void **nownode = (void **) nextlinkitem;
04259 nextlinkitem = *nownode;
04260 curpos += 1;
04261 return (void *)(nownode + 2);
04262 }
04263
04265
04266
04267
04268
04269
04270
04272
04273 void* tetgenmesh::link::getnitem(int pos)
04274 {
04275 if (!locate(pos)) return NULL;
04276 return (void *)((void **) nextlinkitem + 2);
04277 }
04278
04280
04281
04282
04283
04284
04285
04286
04288
04289 int tetgenmesh::link::hasitem(void* checkitem)
04290 {
04291 void *pathitem;
04292 int count;
04293
04294 rewind();
04295 pathitem = getitem();
04296 count = 0;
04297 while (pathitem) {
04298 count ++;
04299 if (comp) {
04300 if ((* comp)(pathitem, checkitem) == 0) {
04301 return count;
04302 }
04303 }
04304 pathitem = getitem();
04305 }
04306 return -1;
04307 }
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323 int tetgenmesh::plus1mod3[3] = {1, 2, 0};
04324 int tetgenmesh::minus1mod3[3] = {2, 0, 1};
04325
04326
04327
04328
04329 int tetgenmesh::ve[6] = { 2, 5, 4, 1, 0, 3 };
04330
04331
04332
04333
04334 int tetgenmesh::vo[6] = { 0, 1, 1, 2, 2, 0 };
04335 int tetgenmesh::vd[6] = { 1, 0, 2, 1, 0, 2 };
04336 int tetgenmesh::va[6] = { 2, 2, 0, 0, 1, 1 };
04337
04338
04339
04340
04341
04342
04343 int tetgenmesh::locver2org[4][6] = {
04344 {0, 1, 1, 2, 2, 0},
04345 {0, 3, 3, 1, 1, 0},
04346 {1, 3, 3, 2, 2, 1},
04347 {2, 3, 3, 0, 0, 2}
04348 };
04349 int tetgenmesh::locver2dest[4][6] = {
04350 {1, 0, 2, 1, 0, 2},
04351 {3, 0, 1, 3, 0, 1},
04352 {3, 1, 2, 3, 1, 2},
04353 {3, 2, 0, 3, 2, 0}
04354 };
04355 int tetgenmesh::locver2apex[4][6] = {
04356 {2, 2, 0, 0, 1, 1},
04357 {1, 1, 0, 0, 3, 3},
04358 {2, 2, 1, 1, 3, 3},
04359 {0, 0, 2, 2, 3, 3}
04360 };
04361
04362
04363
04364 int tetgenmesh::loc2oppo[4] = { 3, 2, 0, 1 };
04365
04366
04367
04368
04369
04370 int tetgenmesh::locver2nextf[4][6][2] = {
04371 { {1, 5}, {-1, -1}, {2, 5}, {-1, -1}, {3, 5}, {-1, -1} },
04372 { {3, 3}, {-1, -1}, {2, 1}, {-1, -1}, {0, 1}, {-1, -1} },
04373 { {1, 3}, {-1, -1}, {3, 1}, {-1, -1}, {0, 3}, {-1, -1} },
04374 { {2, 3}, {-1, -1}, {1, 1}, {-1, -1}, {0, 5}, {-1, -1} }
04375 };
04376
04377
04378
04379
04380
04381 int tetgenmesh::locver2edge[4][6] = {
04382 {0, 0, 1, 1, 2, 2},
04383 {3, 3, 4, 4, 0, 0},
04384 {4, 4, 5, 5, 1, 1},
04385 {5, 5, 3, 3, 2, 2}
04386 };
04387
04388 int tetgenmesh::edge2locver[6][2] = {
04389 {0, 0},
04390 {0, 2},
04391 {0, 4},
04392 {1, 0},
04393 {1, 2},
04394 {2, 2}
04395 };
04396
04397
04398
04399
04400
04401
04402
04403 #define Div2 >> 1
04404 #define Mod2 & 01
04405
04406
04407
04408
04409
04410 #define Orient(V) ((V) Div2)
04411
04412
04413
04414 #define EdgeRing(V) ((V) Mod2)
04415
04416
04417
04418
04419
04420
04421
04422
04423
04424
04425
04426
04427
04428
04429 inline void tetgenmesh::decode(tetrahedron ptr, triface& t) {
04430 t.loc = (int) ((unsigned long) (ptr) & (unsigned long) 3l);
04431 t.tet = (tetrahedron *) ((unsigned long) (ptr) & ~(unsigned long) 7l);
04432 }
04433
04434 inline tetgenmesh::tetrahedron tetgenmesh::encode(triface& t) {
04435 return (tetrahedron) ((unsigned long) t.tet | (unsigned long) t.loc);
04436 }
04437
04438
04439
04440 inline void tetgenmesh::sym(triface& t1, triface& t2) {
04441 tetrahedron ptr = t1.tet[t1.loc];
04442 decode(ptr, t2);
04443 }
04444
04445 inline void tetgenmesh::symself(triface& t) {
04446 tetrahedron ptr = t.tet[t.loc];
04447 decode(ptr, t);
04448 }
04449
04450
04451
04452 inline void tetgenmesh::bond(triface& t1, triface& t2) {
04453 t1.tet[t1.loc] = encode(t2);
04454 t2.tet[t2.loc] = encode(t1);
04455 }
04456
04457
04458
04459
04460
04461
04462 inline void tetgenmesh::dissolve(triface& t) {
04463 t.tet[t.loc] = (tetrahedron) dummytet;
04464 }
04465
04466
04467
04468
04469 inline tetgenmesh::point tetgenmesh::org(triface& t) {
04470 return (point) t.tet[locver2org[t.loc][t.ver] + 4];
04471 }
04472
04473 inline tetgenmesh::point tetgenmesh::dest(triface& t) {
04474 return (point) t.tet[locver2dest[t.loc][t.ver] + 4];
04475 }
04476
04477 inline tetgenmesh::point tetgenmesh::apex(triface& t) {
04478 return (point) t.tet[locver2apex[t.loc][t.ver] + 4];
04479 }
04480
04481 inline tetgenmesh::point tetgenmesh::oppo(triface& t) {
04482 return (point) t.tet[loc2oppo[t.loc] + 4];
04483 }
04484
04485 inline void tetgenmesh::setorg(triface& t, point pointptr) {
04486 t.tet[locver2org[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04487 }
04488
04489 inline void tetgenmesh::setdest(triface& t, point pointptr) {
04490 t.tet[locver2dest[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04491 }
04492
04493 inline void tetgenmesh::setapex(triface& t, point pointptr) {
04494 t.tet[locver2apex[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
04495 }
04496
04497 inline void tetgenmesh::setoppo(triface& t, point pointptr) {
04498 t.tet[loc2oppo[t.loc] + 4] = (tetrahedron) pointptr;
04499 }
04500
04501
04502
04503
04504
04505
04506
04507
04508 inline void tetgenmesh::esym(triface& t1, triface& t2) {
04509 t2.tet = t1.tet;
04510 t2.loc = t1.loc;
04511 t2.ver = t1.ver + (EdgeRing(t1.ver) ? -1 : 1);
04512 }
04513
04514 inline void tetgenmesh::esymself(triface& t) {
04515 t.ver += (EdgeRing(t.ver) ? -1 : 1);
04516 }
04517
04518
04519
04520 inline void tetgenmesh::enext(triface& t1, triface& t2) {
04521 t2.tet = t1.tet;
04522 t2.loc = t1.loc;
04523 t2.ver = ve[t1.ver];
04524 }
04525
04526 inline void tetgenmesh::enextself(triface& t) {
04527 t.ver = ve[t.ver];
04528 }
04529
04530
04531
04532 inline void tetgenmesh::enext2(triface& t1, triface& t2) {
04533 t2.tet = t1.tet;
04534 t2.loc = t1.loc;
04535 t2.ver = ve[ve[t1.ver]];
04536 }
04537
04538 inline void tetgenmesh::enext2self(triface& t) {
04539 t.ver = ve[ve[t.ver]];
04540 }
04541
04542
04543
04544
04545
04546 inline bool tetgenmesh::fnext(triface& t1, triface& t2)
04547 {
04548
04549 t2.loc = locver2nextf[t1.loc][t1.ver][0];
04550
04551 if (t2.loc != -1) {
04552
04553 t2.ver = locver2nextf[t1.loc][t1.ver][1];
04554 t2.tet = t1.tet;
04555 } else {
04556
04557 sym(t1, t2);
04558 if (t2.tet != dummytet) {
04559
04560 point torg;
04561 int tloc, tver, i;
04562 t2.ver = 0;
04563 torg = org(t1);
04564 for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04565 enextself(t2);
04566 }
04567
04568 tloc = t2.loc;
04569 tver = t2.ver;
04570 t2.loc = locver2nextf[tloc][tver][0];
04571 t2.ver = locver2nextf[tloc][tver][1];
04572 }
04573 }
04574 return t2.tet != dummytet;
04575 }
04576
04577 inline bool tetgenmesh::fnextself(triface& t1)
04578 {
04579 triface t2;
04580
04581
04582 t2.loc = locver2nextf[t1.loc][t1.ver][0];
04583
04584 if (t2.loc != -1) {
04585
04586 t2.ver = locver2nextf[t1.loc][t1.ver][1];
04587 t1.loc = t2.loc;
04588 t1.ver = t2.ver;
04589 } else {
04590
04591 sym(t1, t2);
04592 if (t2.tet != dummytet) {
04593
04594 point torg;
04595 int i;
04596 t2.ver = 0;
04597 torg = org(t1);
04598 for (i = 0; (i < 3) && (org(t2) != torg); i++) {
04599 enextself(t2);
04600 }
04601 t1.loc = locver2nextf[t2.loc][t2.ver][0];
04602 t1.ver = locver2nextf[t2.loc][t2.ver][1];
04603 t1.tet = t2.tet;
04604 }
04605 }
04606 return t2.tet != dummytet;
04607 }
04608
04609
04610
04611
04612 inline void tetgenmesh::enextfnext(triface& t1, triface& t2) {
04613 enext(t1, t2);
04614 fnextself(t2);
04615 }
04616
04617 inline void tetgenmesh::enextfnextself(triface& t) {
04618 enextself(t);
04619 fnextself(t);
04620 }
04621
04622 inline void tetgenmesh::enext2fnext(triface& t1, triface& t2) {
04623 enext2(t1, t2);
04624 fnextself(t2);
04625 }
04626
04627 inline void tetgenmesh::enext2fnextself(triface& t) {
04628 enext2self(t);
04629 fnextself(t);
04630 }
04631
04632
04633
04634
04635
04636 inline void tetgenmesh::infect(triface& t) {
04637 t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] | (unsigned long) 4l);
04638 }
04639
04640 inline void tetgenmesh::uninfect(triface& t) {
04641 t.tet[0] = (tetrahedron) ((unsigned long) t.tet[0] & ~ (unsigned long) 4l);
04642 }
04643
04644
04645
04646 inline bool tetgenmesh::infected(triface& t) {
04647 return (((unsigned long) t.tet[0] & (unsigned long) 4l) != 0);
04648 }
04649
04650
04651
04652 inline REAL tetgenmesh::elemattribute(tetrahedron* ptr, int attnum) {
04653 return ((REAL *) (ptr))[elemattribindex + attnum];
04654 }
04655
04656 inline void tetgenmesh::
04657 setelemattribute(tetrahedron* ptr, int attnum, REAL value){
04658 ((REAL *) (ptr))[elemattribindex + attnum] = value;
04659 }
04660
04661
04662
04663 inline REAL tetgenmesh::volumebound(tetrahedron* ptr) {
04664 return ((REAL *) (ptr))[volumeboundindex];
04665 }
04666
04667 inline void tetgenmesh::setvolumebound(tetrahedron* ptr, REAL value) {
04668 ((REAL *) (ptr))[volumeboundindex] = value;
04669 }
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679
04680
04681
04682
04683
04684
04685
04686
04687 inline void tetgenmesh::sdecode(shellface sptr, face& s) {
04688 s.shver = (int) ((unsigned long) (sptr) & (unsigned long) 7l);
04689 s.sh = (shellface *) ((unsigned long) (sptr) & ~ (unsigned long) 7l);
04690 }
04691
04692 inline tetgenmesh::shellface tetgenmesh::sencode(face& s) {
04693 return (shellface) ((unsigned long) s.sh | (unsigned long) s.shver);
04694 }
04695
04696
04697
04698
04699 inline void tetgenmesh::spivot(face& s1, face& s2) {
04700 shellface sptr = s1.sh[Orient(s1.shver)];
04701 sdecode(sptr, s2);
04702 }
04703
04704 inline void tetgenmesh::spivotself(face& s) {
04705 shellface sptr = s.sh[Orient(s.shver)];
04706 sdecode(sptr, s);
04707 }
04708
04709
04710
04711
04712 inline void tetgenmesh::sbond(face& s1, face& s2) {
04713 s1.sh[Orient(s1.shver)] = sencode(s2);
04714 s2.sh[Orient(s2.shver)] = sencode(s1);
04715 }
04716
04717
04718
04719
04720 inline void tetgenmesh::sbond1(face& s1, face& s2) {
04721 s1.sh[Orient(s1.shver)] = sencode(s2);
04722 }
04723
04724
04725
04726
04727 inline void tetgenmesh::sdissolve(face& s) {
04728 s.sh[Orient(s.shver)] = (shellface) dummysh;
04729 }
04730
04731
04732
04733
04734 inline tetgenmesh::point tetgenmesh::sorg(face& s) {
04735 return (point) s.sh[3 + vo[s.shver]];
04736 }
04737
04738 inline tetgenmesh::point tetgenmesh::sdest(face& s) {
04739 return (point) s.sh[3 + vd[s.shver]];
04740 }
04741
04742 inline tetgenmesh::point tetgenmesh::sapex(face& s) {
04743 return (point) s.sh[3 + va[s.shver]];
04744 }
04745
04746 inline void tetgenmesh::setsorg(face& s, point pointptr) {
04747 s.sh[3 + vo[s.shver]] = (shellface) pointptr;
04748 }
04749
04750 inline void tetgenmesh::setsdest(face& s, point pointptr) {
04751 s.sh[3 + vd[s.shver]] = (shellface) pointptr;
04752 }
04753
04754 inline void tetgenmesh::setsapex(face& s, point pointptr) {
04755 s.sh[3 + va[s.shver]] = (shellface) pointptr;
04756 }
04757
04758
04759
04760
04761 inline void tetgenmesh::sesym(face& s1, face& s2) {
04762 s2.sh = s1.sh;
04763 s2.shver = s1.shver + (EdgeRing(s1.shver) ? -1 : 1);
04764 }
04765
04766 inline void tetgenmesh::sesymself(face& s) {
04767 s.shver += (EdgeRing(s.shver) ? -1 : 1);
04768 }
04769
04770 inline void tetgenmesh::senext(face& s1, face& s2) {
04771 s2.sh = s1.sh;
04772 s2.shver = ve[s1.shver];
04773 }
04774
04775 inline void tetgenmesh::senextself(face& s) {
04776 s.shver = ve[s.shver];
04777 }
04778
04779 inline void tetgenmesh::senext2(face& s1, face& s2) {
04780 s2.sh = s1.sh;
04781 s2.shver = ve[ve[s1.shver]];
04782 }
04783
04784 inline void tetgenmesh::senext2self(face& s) {
04785 s.shver = ve[ve[s.shver]];
04786 }
04787
04788
04789
04790 inline void tetgenmesh::sfnext(face& s1, face& s2) {
04791 getnextsface(&s1, &s2);
04792 }
04793
04794 inline void tetgenmesh::sfnextself(face& s) {
04795 getnextsface(&s, NULL);
04796 }
04797
04798
04799
04800
04801 inline tetgenmesh::badface* tetgenmesh::shell2badface(face& s) {
04802 return (badface*) s.sh[11];
04803 }
04804
04805 inline void tetgenmesh::setshell2badface(face& s, badface* value) {
04806 s.sh[11] = (shellface) value;
04807 }
04808
04809
04810
04811 inline REAL tetgenmesh::areabound(face& s) {
04812 return ((REAL *) (s.sh))[areaboundindex];
04813 }
04814
04815 inline void tetgenmesh::setareabound(face& s, REAL value) {
04816 ((REAL *) (s.sh))[areaboundindex] = value;
04817 }
04818
04819
04820
04821
04822 inline int tetgenmesh::shellmark(face& s) {
04823 return ((int *) (s.sh))[shmarkindex];
04824 }
04825
04826 inline void tetgenmesh::setshellmark(face& s, int value) {
04827 ((int *) (s.sh))[shmarkindex] = value;
04828 }
04829
04830
04831
04832 inline enum tetgenmesh::shestype tetgenmesh::shelltype(face& s) {
04833 return (enum shestype) ((int *) (s.sh))[shmarkindex + 1];
04834 }
04835
04836 inline void tetgenmesh::setshelltype(face& s, enum shestype value) {
04837 ((int *) (s.sh))[shmarkindex + 1] = (int) value;
04838 }
04839
04840
04841
04842 inline int tetgenmesh::shellpbcgroup(face& s) {
04843 return ((int *) (s.sh))[shmarkindex + 2];
04844 }
04845
04846 inline void tetgenmesh::setshellpbcgroup(face& s, int value) {
04847 ((int *) (s.sh))[shmarkindex + 2] = value;
04848 }
04849
04850
04851
04852
04853 inline void tetgenmesh::sinfect(face& s) {
04854 s.sh[6] = (shellface) ((unsigned long) s.sh[6] | (unsigned long) 4l);
04855 }
04856
04857 inline void tetgenmesh::suninfect(face& s) {
04858 s.sh[6] = (shellface)((unsigned long) s.sh[6] & ~(unsigned long) 4l);
04859 }
04860
04861
04862
04863 inline bool tetgenmesh::sinfected(face& s) {
04864 return (((unsigned long) s.sh[6] & (unsigned long) 4l) != 0);
04865 }
04866
04867
04868
04869
04870
04871
04872
04873
04874
04875
04876
04877 inline void tetgenmesh::tspivot(triface& t, face& s) {
04878 shellface sptr = (shellface) t.tet[8 + t.loc];
04879 sdecode(sptr, s);
04880 }
04881
04882
04883
04884 inline void tetgenmesh::stpivot(face& s, triface& t) {
04885 tetrahedron ptr = (tetrahedron) s.sh[6 + EdgeRing(s.shver)];
04886 decode(ptr, t);
04887 }
04888
04889
04890
04891 inline void tetgenmesh::tsbond(triface& t, face& s) {
04892 t.tet[8 + t.loc] = (tetrahedron) sencode(s);
04893 s.sh[6 + EdgeRing(s.shver)] = (shellface) encode(t);
04894 }
04895
04896
04897
04898 inline void tetgenmesh::tsdissolve(triface& t) {
04899 t.tet[8 + t.loc] = (tetrahedron) dummysh;
04900 }
04901
04902
04903
04904 inline void tetgenmesh::stdissolve(face& s) {
04905 s.sh[6 + EdgeRing(s.shver)] = (shellface) dummytet;
04906 }
04907
04908
04909
04910
04911
04912
04913
04914
04915
04916
04917
04918 inline void tetgenmesh::sspivot(face& s, face& edge) {
04919 shellface sptr = (shellface) s.sh[8 + Orient(s.shver)];
04920 sdecode(sptr, edge);
04921 }
04922
04923
04924
04925 inline void tetgenmesh::ssbond(face& s, face& edge) {
04926 s.sh[8 + Orient(s.shver)] = sencode(edge);
04927 edge.sh[0] = sencode(s);
04928 }
04929
04930
04931
04932 inline void tetgenmesh::ssdissolve(face& s) {
04933 s.sh[8 + Orient(s.shver)] = (shellface) dummysh;
04934 }
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944 inline void tetgenmesh::tsspivot1(triface& t, face& seg)
04945 {
04946 shellface sptr = (shellface) t.tet[8 + locver2edge[t.loc][t.ver]];
04947 sdecode(sptr, seg);
04948 }
04949
04950
04951
04952 inline void tetgenmesh::tssbond1(triface& t, face& seg)
04953 {
04954 t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) sencode(seg);
04955 }
04956
04957 inline void tetgenmesh::tssdissolve1(triface& t)
04958 {
04959 t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) dummysh;
04960 }
04961
04962
04963
04964
04965
04966
04967
04968
04969
04970 inline int tetgenmesh::pointmark(point pt) {
04971 return ((int *) (pt))[pointmarkindex];
04972 }
04973
04974 inline void tetgenmesh::setpointmark(point pt, int value) {
04975 ((int *) (pt))[pointmarkindex] = value;
04976 }
04977
04978
04979
04980 inline enum tetgenmesh::verttype tetgenmesh::pointtype(point pt) {
04981 return (enum verttype) ((int *) (pt))[pointmarkindex + 1];
04982 }
04983
04984 inline void tetgenmesh::setpointtype(point pt, enum verttype value) {
04985 ((int *) (pt))[pointmarkindex + 1] = (int) value;
04986 }
04987
04988
04989
04990
04991 inline tetgenmesh::tetrahedron tetgenmesh::point2tet(point pt) {
04992 return ((tetrahedron *) (pt))[point2simindex];
04993 }
04994
04995 inline void tetgenmesh::setpoint2tet(point pt, tetrahedron value) {
04996 ((tetrahedron *) (pt))[point2simindex] = value;
04997 }
04998
04999 inline tetgenmesh::shellface tetgenmesh::point2sh(point pt) {
05000 return (shellface) ((tetrahedron *) (pt))[point2simindex + 1];
05001 }
05002
05003 inline void tetgenmesh::setpoint2sh(point pt, shellface value) {
05004 ((tetrahedron *) (pt))[point2simindex + 1] = (tetrahedron) value;
05005 }
05006
05007 inline tetgenmesh::point tetgenmesh::point2ppt(point pt) {
05008 return (point) ((tetrahedron *) (pt))[point2simindex + 2];
05009 }
05010
05011 inline void tetgenmesh::setpoint2ppt(point pt, point value) {
05012 ((tetrahedron *) (pt))[point2simindex + 2] = (tetrahedron) value;
05013 }
05014
05015 inline tetgenmesh::tetrahedron tetgenmesh::point2bgmtet(point pt) {
05016 return ((tetrahedron *) (pt))[point2simindex + 3];
05017 }
05018
05019 inline void tetgenmesh::setpoint2bgmtet(point pt, tetrahedron value) {
05020 ((tetrahedron *) (pt))[point2simindex + 3] = value;
05021 }
05022
05023
05024
05025 inline tetgenmesh::point tetgenmesh::point2pbcpt(point pt) {
05026 return (point) ((tetrahedron *) (pt))[point2pbcptindex];
05027 }
05028
05029 inline void tetgenmesh::setpoint2pbcpt(point pt, point value) {
05030 ((tetrahedron *) (pt))[point2pbcptindex] = (tetrahedron) value;
05031 }
05032
05033
05034
05035
05036
05037
05038
05039
05040
05041
05042
05043
05044
05045 inline void tetgenmesh::adjustedgering(triface& t, int direction) {
05046 if (EdgeRing(t.ver) != direction) {
05047 esymself(t);
05048 }
05049 }
05050
05051 inline void tetgenmesh::adjustedgering(face& s, int direction) {
05052 if (EdgeRing(s.shver) != direction) {
05053 sesymself(s);
05054 }
05055 }
05056
05057
05058
05059 inline bool tetgenmesh::isdead(triface* t) {
05060 if (t->tet == (tetrahedron *) NULL) return true;
05061 else return t->tet[4] == (tetrahedron) NULL;
05062 }
05063
05064 inline bool tetgenmesh::isdead(face* s) {
05065 if (s->sh == (shellface *) NULL) return true;
05066 else return s->sh[3] == (shellface) NULL;
05067 }
05068
05069
05070
05071
05072 inline bool tetgenmesh::isfacehaspoint(triface* t, point testpoint) {
05073 return ((org(*t) == testpoint) || (dest(*t) == testpoint) ||
05074 (apex(*t) == testpoint));
05075 }
05076
05077 inline bool tetgenmesh::isfacehaspoint(face* s, point testpoint) {
05078 return (s->sh[3] == (shellface) testpoint) ||
05079 (s->sh[4] == (shellface) testpoint) ||
05080 (s->sh[5] == (shellface) testpoint);
05081 }
05082
05083
05084
05085
05086 inline bool tetgenmesh::isfacehasedge(face* s, point tend1, point tend2) {
05087 return (isfacehaspoint(s, tend1) && isfacehaspoint(s, tend2));
05088 }
05089
05090
05091
05092 inline bool tetgenmesh::issymexist(triface* t) {
05093 tetrahedron *ptr = (tetrahedron *)
05094 ((unsigned long)(t->tet[t->loc]) & ~(unsigned long)7l);
05095 return ptr != dummytet;
05096 }
05097
05099
05100
05101
05102
05103
05104
05105
05107
05108 void tetgenmesh::getnextsface(face* s1, face* s2)
05109 {
05110 face neighsh, spinsh;
05111 face testseg;
05112
05113 sspivot(*s1, testseg);
05114 if (testseg.sh != dummysh) {
05115 testseg.shver = 0;
05116 if (sorg(testseg) == sorg(*s1)) {
05117 spivot(*s1, neighsh);
05118 } else {
05119 spinsh = *s1;
05120 do {
05121 neighsh = spinsh;
05122 spivotself(spinsh);
05123 } while (spinsh.sh != s1->sh);
05124 }
05125 } else {
05126 spivot(*s1, neighsh);
05127 }
05128 if (sorg(neighsh) != sorg(*s1)) {
05129 sesymself(neighsh);
05130 }
05131 if (s2 != (face *) NULL) {
05132 *s2 = neighsh;
05133 } else {
05134 *s1 = neighsh;
05135 }
05136 }
05137
05139
05140
05141
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151
05153
05154 void tetgenmesh::tsspivot(triface* checkedge, face* checkseg)
05155 {
05156 triface spintet;
05157 face parentsh;
05158 point tapex;
05159 int hitbdry;
05160
05161 spintet = *checkedge;
05162 tapex = apex(*checkedge);
05163 hitbdry = 0;
05164 do {
05165 tspivot(spintet, parentsh);
05166
05167 if ((parentsh.sh != dummysh) && (sapex(parentsh) != NULL)) {
05168
05169 findedge(&parentsh, org(*checkedge), dest(*checkedge));
05170 sspivot(parentsh, *checkseg);
05171 if (checkseg->sh != dummysh) {
05172
05173 if (sorg(*checkseg) != org(*checkedge)) {
05174 sesymself(*checkseg);
05175 }
05176 }
05177 return;
05178 }
05179 if (!fnextself(spintet)) {
05180 hitbdry++;
05181 if (hitbdry < 2) {
05182 esym(*checkedge, spintet);
05183 if (!fnextself(spintet)) {
05184 hitbdry++;
05185 }
05186 }
05187 }
05188 } while ((apex(spintet) != tapex) && (hitbdry < 2));
05189
05190 checkseg->sh = dummysh;
05191 }
05192
05194
05195
05196
05197
05198
05199
05200
05201
05203
05204 void tetgenmesh::sstpivot(face* checkseg, triface* retedge)
05205 {
05206 face parentsh;
05207
05208
05209 sdecode(checkseg->sh[0], parentsh);
05210 #ifdef SELF_CHECK
05211 assert(parentsh.sh != dummysh);
05212 #endif
05213
05214 stpivot(parentsh, *retedge);
05215 if (retedge->tet == dummytet) {
05216 sesymself(parentsh);
05217 stpivot(parentsh, *retedge);
05218 #ifdef SELF_CHECK
05219 assert(retedge->tet != dummytet);
05220 #endif
05221 }
05222
05223 findedge(retedge, sorg(*checkseg), sdest(*checkseg));
05224 }
05225
05227
05228
05229
05230
05231
05232
05233
05235
05236 bool tetgenmesh::findorg(triface* tface, point dorg)
05237 {
05238 if (org(*tface) == dorg) {
05239 return true;
05240 } else {
05241 if (dest(*tface) == dorg) {
05242 enextself(*tface);
05243 return true;
05244 } else {
05245 if (apex(*tface) == dorg) {
05246 enext2self(*tface);
05247 return true;
05248 } else {
05249 if (oppo(*tface) == dorg) {
05250
05251 adjustedgering(*tface, CCW);
05252 fnextself(*tface);
05253 enext2self(*tface);
05254 return true;
05255 }
05256 }
05257 }
05258 }
05259 return false;
05260 }
05261
05262 bool tetgenmesh::findorg(face* sface, point dorg)
05263 {
05264 if (sorg(*sface) == dorg) {
05265 return true;
05266 } else {
05267 if (sdest(*sface) == dorg) {
05268 senextself(*sface);
05269 return true;
05270 } else {
05271 if (sapex(*sface) == dorg) {
05272 senext2self(*sface);
05273 return true;
05274 }
05275 }
05276 }
05277 return false;
05278 }
05279
05281
05282
05283
05284
05285
05286
05287
05289
05290 void tetgenmesh::findedge(triface* tface, point eorg, point edest)
05291 {
05292 int i;
05293
05294 for (i = 0; i < 3; i++) {
05295 if (org(*tface) == eorg) {
05296 if (dest(*tface) == edest) {
05297
05298 return;
05299 }
05300 } else {
05301 if (org(*tface) == edest) {
05302 if (dest(*tface) == eorg) {
05303
05304 esymself(*tface);
05305 return;
05306 }
05307 }
05308 }
05309 enextself(*tface);
05310 }
05311
05312 printf("Internalerror in findedge(): Unable to find an edge in tet.\n");
05313 internalerror();
05314 }
05315
05316 void tetgenmesh::findedge(face* sface, point eorg, point edest)
05317 {
05318 int i;
05319
05320 for (i = 0; i < 3; i++) {
05321 if (sorg(*sface) == eorg) {
05322 if (sdest(*sface) == edest) {
05323
05324 return;
05325 }
05326 } else {
05327 if (sorg(*sface) == edest) {
05328 if (sdest(*sface) == eorg) {
05329
05330 sesymself(*sface);
05331 return;
05332 }
05333 }
05334 }
05335 senextself(*sface);
05336 }
05337 printf("Internalerror in findedge(): Unable to find an edge in subface.\n");
05338 internalerror();
05339 }
05340
05342
05343
05344
05345
05346
05347
05348
05350
05351 void tetgenmesh::findface(triface *fface, point forg, point fdest, point fapex)
05352 {
05353 triface spintet;
05354 enum finddirectionresult collinear;
05355 int hitbdry;
05356
05357 if (!isdead(fface)) {
05358
05359 if (org(*fface) == forg && dest(*fface) == fdest &&
05360 apex(*fface) == fapex) return;
05361 } else {
05362
05363 if (!isdead(&recenttet)) *fface = recenttet;
05364 }
05365
05366 if (!isdead(fface)) {
05367 if (!findorg(fface, forg)) {
05368
05369 preciselocate(forg, fface, tetrahedrons->items);
05370 }
05371
05372 if (org(*fface) == forg) {
05373 collinear = finddirection(fface, fdest, tetrahedrons->items);
05374 if (collinear == RIGHTCOLLINEAR) {
05375
05376 } else if (collinear == LEFTCOLLINEAR) {
05377 enext2self(*fface);
05378 esymself(*fface);
05379 } else if (collinear == TOPCOLLINEAR) {
05380 fnextself(*fface);
05381 enext2self(*fface);
05382 esymself(*fface);
05383 }
05384 }
05385
05386 if ((org(*fface) == forg) && (dest(*fface) == fdest)) {
05387
05388 spintet = *fface;
05389 hitbdry = 0;
05390 do {
05391 if (apex(spintet) == fapex) {
05392
05393
05394 if (org(spintet) != org(*fface)) {
05395 esymself(spintet);
05396 }
05397 *fface = spintet;
05398 return;
05399 }
05400 if (!fnextself(spintet)) {
05401 hitbdry ++;
05402 if (hitbdry < 2) {
05403 esym(*fface, spintet);
05404 if (!fnextself(spintet)) {
05405 hitbdry ++;
05406 }
05407 }
05408 }
05409 } while (hitbdry < 2 && apex(spintet) != apex(*fface));
05410
05411 }
05412 }
05413
05414 if (isdead(fface) || (org(*fface) != forg) || (dest(*fface) != fdest) ||
05415 (apex(*fface) != fapex)) {
05416
05417
05418
05419 if (b->verbose > 1) {
05420 printf("Warning in findface(): Perform a brute-force searching.\n");
05421 }
05422 enum verttype forgty, fdestty, fapexty;
05423 int share, i;
05424 forgty = pointtype(forg);
05425 fdestty = pointtype(fdest);
05426 fapexty = pointtype(fapex);
05427 setpointtype(forg, DEADVERTEX);
05428 setpointtype(fdest, DEADVERTEX);
05429 setpointtype(fapex, DEADVERTEX);
05430 tetrahedrons->traversalinit();
05431 fface->tet = tetrahedrontraverse();
05432 while (fface->tet != (tetrahedron *) NULL) {
05433 share = 0;
05434 for (i = 0; i < 4; i++) {
05435 if (pointtype((point) fface->tet[4 + i]) == DEADVERTEX) share ++;
05436 }
05437 if (share == 3) {
05438
05439 if (pointtype((point) fface->tet[4]) != DEADVERTEX) {
05440 fface->loc = 2;
05441 } else if (pointtype((point) fface->tet[5]) != DEADVERTEX) {
05442 fface->loc = 3;
05443 } else if (pointtype((point) fface->tet[6]) != DEADVERTEX) {
05444 fface->loc = 1;
05445 } else {
05446 fface->loc = 0;
05447 }
05448 findedge(fface, forg, fdest);
05449 break;
05450 }
05451 fface->tet = tetrahedrontraverse();
05452 }
05453 setpointtype(forg, forgty);
05454 setpointtype(fdest, fdestty);
05455 setpointtype(fapex, fapexty);
05456 if (fface->tet == (tetrahedron *) NULL) {
05457
05458 printf("Internal error: Fail to find the indicated face.\n");
05459 internalerror();
05460 }
05461 }
05462 }
05463
05465
05466
05467
05468
05469
05470
05472
05473 void tetgenmesh::getonextseg(face* s, face* lseg)
05474 {
05475 face checksh, checkseg;
05476 point forg;
05477
05478 forg = sorg(*s);
05479 checksh = *s;
05480 do {
05481
05482 senext2self(checksh);
05483
05484 sspivot(checksh, checkseg);
05485 if (checkseg.sh != dummysh) break;
05486
05487 spivotself(checksh);
05488 #ifdef SELF_CHECK
05489
05490 assert(checksh.sh != s->sh);
05491 #endif
05492 if (sorg(checksh) != forg) {
05493 sesymself(checksh);
05494 #ifdef SELF_CHECK
05495 assert(sorg(checksh) == forg);
05496 #endif
05497 }
05498 } while (true);
05499 if (sorg(checkseg) != forg) sesymself(checkseg);
05500 *lseg = checkseg;
05501 }
05502
05504
05505
05506
05507
05508
05509
05510
05512
05513 void tetgenmesh::getseghasorg(face* sseg, point dorg)
05514 {
05515 face nextseg;
05516 point checkpt;
05517
05518 nextseg = *sseg;
05519 checkpt = sorg(nextseg);
05520 while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05521
05522 senext2self(nextseg);
05523 spivotself(nextseg);
05524 nextseg.shver = 0;
05525 if (sdest(nextseg) != checkpt) sesymself(nextseg);
05526 checkpt = sorg(nextseg);
05527 }
05528 if (checkpt == dorg) {
05529 *sseg = nextseg;
05530 return;
05531 }
05532 nextseg = *sseg;
05533 checkpt = sdest(nextseg);
05534 while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
05535
05536 senextself(nextseg);
05537 spivotself(nextseg);
05538 nextseg.shver = 0;
05539 if (sorg(nextseg) != checkpt) sesymself(nextseg);
05540 checkpt = sdest(nextseg);
05541 }
05542 if (checkpt == dorg) {
05543 sesym(nextseg, *sseg);
05544 return;
05545 }
05546
05547 printf("Internalerror in getseghasorg(): Unable to find the subseg.\n");
05548 internalerror();
05549 }
05550
05552
05553
05554
05556
05557 tetgenmesh::point tetgenmesh::getsubsegfarorg(face* sseg)
05558 {
05559 face prevseg;
05560 point checkpt;
05561
05562 checkpt = sorg(*sseg);
05563 senext2(*sseg, prevseg);
05564 spivotself(prevseg);
05565
05566 while (prevseg.sh != dummysh) {
05567 prevseg.shver = 0;
05568 if (sdest(prevseg) != checkpt) sesymself(prevseg);
05569 checkpt = sorg(prevseg);
05570 senext2self(prevseg);
05571 spivotself(prevseg);
05572 }
05573 return checkpt;
05574 }
05575
05577
05578
05579
05581
05582 tetgenmesh::point tetgenmesh::getsubsegfardest(face* sseg)
05583 {
05584 face nextseg;
05585 point checkpt;
05586
05587 checkpt = sdest(*sseg);
05588 senext(*sseg, nextseg);
05589 spivotself(nextseg);
05590
05591 while (nextseg.sh != dummysh) {
05592 nextseg.shver = 0;
05593 if (sorg(nextseg) != checkpt) sesymself(nextseg);
05594 checkpt = sdest(nextseg);
05595 senextself(nextseg);
05596 spivotself(nextseg);
05597 }
05598 return checkpt;
05599 }
05600
05602
05603
05604
05605
05606
05608
05609 void tetgenmesh::printtet(triface* tface)
05610 {
05611 triface tmpface, prtface;
05612 point tmppt;
05613 face tmpsh;
05614 int facecount;
05615
05616 printf("Tetra x%lx with loc(%i) and ver(%i):",
05617 (unsigned long)(tface->tet), tface->loc, tface->ver);
05618 if (infected(*tface)) {
05619 printf(" (infected)");
05620 }
05621 printf("\n");
05622
05623 tmpface = *tface;
05624 facecount = 0;
05625 while(facecount < 4) {
05626 tmpface.loc = facecount;
05627 sym(tmpface, prtface);
05628 if(prtface.tet == dummytet) {
05629 printf(" [%i] Outer space.\n", facecount);
05630 } else {
05631 printf(" [%i] x%lx loc(%i).", facecount,
05632 (unsigned long)(prtface.tet), prtface.loc);
05633 if (infected(prtface)) {
05634 printf(" (infected)");
05635 }
05636 printf("\n");
05637 }
05638 facecount ++;
05639 }
05640
05641 tmppt = org(*tface);
05642 if(tmppt == (point) NULL) {
05643 printf(" Org [%i] NULL\n", locver2org[tface->loc][tface->ver]);
05644 } else {
05645 printf(" Org [%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05646 locver2org[tface->loc][tface->ver], (unsigned long)(tmppt),
05647 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05648 }
05649 tmppt = dest(*tface);
05650 if(tmppt == (point) NULL) {
05651 printf(" Dest[%i] NULL\n", locver2dest[tface->loc][tface->ver]);
05652 } else {
05653 printf(" Dest[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05654 locver2dest[tface->loc][tface->ver], (unsigned long)(tmppt),
05655 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05656 }
05657 tmppt = apex(*tface);
05658 if(tmppt == (point) NULL) {
05659 printf(" Apex[%i] NULL\n", locver2apex[tface->loc][tface->ver]);
05660 } else {
05661 printf(" Apex[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05662 locver2apex[tface->loc][tface->ver], (unsigned long)(tmppt),
05663 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05664 }
05665 tmppt = oppo(*tface);
05666 if(tmppt == (point) NULL) {
05667 printf(" Oppo[%i] NULL\n", loc2oppo[tface->loc]);
05668 } else {
05669 printf(" Oppo[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
05670 loc2oppo[tface->loc], (unsigned long)(tmppt),
05671 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
05672 }
05673
05674 if (b->useshelles) {
05675 tmpface = *tface;
05676 facecount = 0;
05677 while(facecount < 6) {
05678 tmpface.loc = facecount;
05679 tspivot(tmpface, tmpsh);
05680 if(tmpsh.sh != dummysh) {
05681 printf(" [%i] x%lx ID(%i) ", facecount,
05682 (unsigned long)(tmpsh.sh), shellmark(tmpsh));
05683 if (sorg(tmpsh) == (point) NULL) {
05684 printf("(fake)");
05685 }
05686 printf("\n");
05687 }
05688 facecount ++;
05689 }
05690 }
05691 }
05692
05694
05695
05696
05697
05698
05700
05701 void tetgenmesh::printsh(face* sface)
05702 {
05703 face prtsh;
05704 triface prttet;
05705 point printpoint;
05706
05707 if (sapex(*sface) != NULL) {
05708 printf("subface x%lx, ver %d, mark %d:",
05709 (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05710 } else {
05711 printf("Subsegment x%lx, ver %d, mark %d:",
05712 (unsigned long)(sface->sh), sface->shver, shellmark(*sface));
05713 }
05714 if (sinfected(*sface)) {
05715 printf(" (infected)");
05716 }
05717 if (shell2badface(*sface)) {
05718 printf(" (queued)");
05719 }
05720 if (sapex(*sface) != NULL) {
05721 if (shelltype(*sface) == SHARP) {
05722 printf(" (sharp)");
05723 }
05724 } else {
05725 if (shelltype(*sface) == SHARP) {
05726 printf(" (sharp)");
05727 }
05728 }
05729 if (checkpbcs) {
05730 if (shellpbcgroup(*sface) >= 0) {
05731 printf(" (pbc %d)", shellpbcgroup(*sface));
05732 }
05733 }
05734 printf("\n");
05735
05736 sdecode(sface->sh[0], prtsh);
05737 if (prtsh.sh == dummysh) {
05738 printf(" [0] = No shell\n");
05739 } else {
05740 printf(" [0] = x%lx %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05741 }
05742 sdecode(sface->sh[1], prtsh);
05743 if (prtsh.sh == dummysh) {
05744 printf(" [1] = No shell\n");
05745 } else {
05746 printf(" [1] = x%lx %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05747 }
05748 sdecode(sface->sh[2], prtsh);
05749 if (prtsh.sh == dummysh) {
05750 printf(" [2] = No shell\n");
05751 } else {
05752 printf(" [2] = x%lx %d\n", (unsigned long)(prtsh.sh), prtsh.shver);
05753 }
05754
05755 printpoint = sorg(*sface);
05756 if (printpoint == (point) NULL)
05757 printf(" Org [%d] = NULL\n", vo[sface->shver]);
05758 else
05759 printf(" Org [%d] = x%lx (%.12g,%.12g,%.12g) %d\n",
05760 vo[sface->shver], (unsigned long)(printpoint), printpoint[0],
05761 printpoint[1], printpoint[2], pointmark(printpoint));
05762 printpoint = sdest(*sface);
05763 if (printpoint == (point) NULL)
05764 printf(" Dest[%d] = NULL\n", vd[sface->shver]);
05765 else
05766 printf(" Dest[%d] = x%lx (%.12g,%.12g,%.12g) %d\n",
05767 vd[sface->shver], (unsigned long)(printpoint), printpoint[0],
05768 printpoint[1], printpoint[2], pointmark(printpoint));
05769
05770 if (sapex(*sface) != NULL) {
05771 printpoint = sapex(*sface);
05772 if (printpoint == (point) NULL)
05773 printf(" Apex[%d] = NULL\n", va[sface->shver]);
05774 else
05775 printf(" Apex[%d] = x%lx (%.12g,%.12g,%.12g) %d\n",
05776 va[sface->shver], (unsigned long)(printpoint), printpoint[0],
05777 printpoint[1], printpoint[2], pointmark(printpoint));
05778
05779 decode(sface->sh[6], prttet);
05780 if (prttet.tet == dummytet) {
05781 printf(" [6] = Outer space\n");
05782 } else {
05783 printf(" [6] = x%lx %d\n",
05784 (unsigned long)(prttet.tet), prttet.loc);
05785 }
05786 decode(sface->sh[7], prttet);
05787 if (prttet.tet == dummytet) {
05788 printf(" [7] = Outer space\n");
05789 } else {
05790 printf(" [7] = x%lx %d\n",
05791 (unsigned long)(prttet.tet), prttet.loc);
05792 }
05793
05794 sdecode(sface->sh[8], prtsh);
05795 if (prtsh.sh == dummysh) {
05796 printf(" [8] = No subsegment\n");
05797 } else {
05798 printf(" [8] = x%lx %d\n",
05799 (unsigned long)(prtsh.sh), prtsh.shver);
05800 }
05801 sdecode(sface->sh[9], prtsh);
05802 if (prtsh.sh == dummysh) {
05803 printf(" [9] = No subsegment\n");
05804 } else {
05805 printf(" [9] = x%lx %d\n",
05806 (unsigned long)(prtsh.sh), prtsh.shver);
05807 }
05808 sdecode(sface->sh[10], prtsh);
05809 if (prtsh.sh == dummysh) {
05810 printf(" [10]= No subsegment\n");
05811 } else {
05812 printf(" [10]= x%lx %d\n",
05813 (unsigned long)(prtsh.sh), prtsh.shver);
05814 }
05815 }
05816 }
05817
05818
05819
05820
05821
05822
05823
05824
05825
05826
05827
05828
05829
05831
05832
05833
05834
05835
05836
05837
05838
05840
05841 void tetgenmesh::makepoint2tetmap()
05842 {
05843 triface tetloop;
05844 point pointptr;
05845
05846 if (b->verbose > 0) {
05847 printf(" Constructing mapping from points to tetrahedra.\n");
05848 }
05849
05850
05851 points->traversalinit();
05852 pointptr = pointtraverse();
05853 while (pointptr != (point) NULL) {
05854 setpoint2tet(pointptr, (tetrahedron) NULL);
05855 pointptr = pointtraverse();
05856 }
05857
05858 tetrahedrons->traversalinit();
05859 tetloop.tet = tetrahedrontraverse();
05860 while (tetloop.tet != (tetrahedron *) NULL) {
05861
05862 tetloop.loc = 0;
05863 pointptr = org(tetloop);
05864 setpoint2tet(pointptr, encode(tetloop));
05865 pointptr = dest(tetloop);
05866 setpoint2tet(pointptr, encode(tetloop));
05867 pointptr = apex(tetloop);
05868 setpoint2tet(pointptr, encode(tetloop));
05869 pointptr = oppo(tetloop);
05870 setpoint2tet(pointptr, encode(tetloop));
05871
05872 tetloop.tet = tetrahedrontraverse();
05873 }
05874 }
05875
05877
05878
05879
05880
05881
05882
05883
05884
05886
05887 void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
05888 {
05889 point pointloop;
05890 int idx;
05891
05892 if (b->verbose > 0) {
05893 printf(" Constructing mapping from indices to points.\n");
05894 }
05895
05896 idx2verlist = new point[points->items];
05897
05898 points->traversalinit();
05899 pointloop = pointtraverse();
05900 idx = 0;
05901 while (pointloop != (point) NULL) {
05902 idx2verlist[idx] = pointloop;
05903 idx++;
05904 pointloop = pointtraverse();
05905 }
05906 }
05907
05909
05910
05911
05912
05913
05914
05915
05916
05917
05918
05919
05920
05921
05922
05923
05925
05926 void tetgenmesh::makesegmentmap(int*& idx2seglist, shellface**& segsperverlist)
05927 {
05928 shellface *shloop;
05929 int i, j, k;
05930
05931 if (b->verbose > 0) {
05932 printf(" Constructing mapping from points to segments.\n");
05933 }
05934
05935
05936 idx2seglist = new int[points->items + 1];
05937 for (i = 0; i < points->items + 1; i++) idx2seglist[i] = 0;
05938
05939
05940
05941 subsegs->traversalinit();
05942 shloop = shellfacetraverse(subsegs);
05943 while (shloop != (shellface *) NULL) {
05944
05945 for (i = 0; i < 2; i++) {
05946 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05947 idx2seglist[j]++;
05948 }
05949 shloop = shellfacetraverse(subsegs);
05950 }
05951
05952
05953 j = idx2seglist[0];
05954 idx2seglist[0] = 0;
05955 for (i = 0; i < points->items; i++) {
05956 k = idx2seglist[i + 1];
05957 idx2seglist[i + 1] = idx2seglist[i] + j;
05958 j = k;
05959 }
05960
05961 segsperverlist = new shellface*[idx2seglist[i]];
05962
05963 subsegs->traversalinit();
05964 shloop = shellfacetraverse(subsegs);
05965 while (shloop != (shellface *) NULL) {
05966 for (i = 0; i < 2; i++) {
05967 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
05968 segsperverlist[idx2seglist[j]] = shloop;
05969 idx2seglist[j]++;
05970 }
05971 shloop = shellfacetraverse(subsegs);
05972 }
05973
05974 for (i = points->items - 1; i >= 0; i--) {
05975 idx2seglist[i + 1] = idx2seglist[i];
05976 }
05977 idx2seglist[0] = 0;
05978 }
05979
05981
05982
05983
05984
05985
05986
05987
05988
05989
05990
05991
05992
05993
05994
05995
05997
05998 void tetgenmesh::
05999 makesubfacemap(int*& idx2facelist, shellface**& facesperverlist)
06000 {
06001 shellface *shloop;
06002 int i, j, k;
06003
06004 if (b->verbose > 0) {
06005 printf(" Constructing mapping from points to subfaces.\n");
06006 }
06007
06008
06009 idx2facelist = new int[points->items + 1];
06010 for (i = 0; i < points->items + 1; i++) idx2facelist[i] = 0;
06011
06012
06013
06014 subfaces->traversalinit();
06015 shloop = shellfacetraverse(subfaces);
06016 while (shloop != (shellface *) NULL) {
06017
06018 for (i = 0; i < 3; i++) {
06019 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06020 idx2facelist[j]++;
06021 }
06022 shloop = shellfacetraverse(subfaces);
06023 }
06024
06025
06026 j = idx2facelist[0];
06027 idx2facelist[0] = 0;
06028 for (i = 0; i < points->items; i++) {
06029 k = idx2facelist[i + 1];
06030 idx2facelist[i + 1] = idx2facelist[i] + j;
06031 j = k;
06032 }
06033
06034 facesperverlist = new shellface*[idx2facelist[i]];
06035
06036 subfaces->traversalinit();
06037 shloop = shellfacetraverse(subfaces);
06038 while (shloop != (shellface *) NULL) {
06039 for (i = 0; i < 3; i++) {
06040 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
06041 facesperverlist[idx2facelist[j]] = shloop;
06042 idx2facelist[j]++;
06043 }
06044 shloop = shellfacetraverse(subfaces);
06045 }
06046
06047 for (i = points->items - 1; i >= 0; i--) {
06048 idx2facelist[i + 1] = idx2facelist[i];
06049 }
06050 idx2facelist[0] = 0;
06051 }
06052
06054
06055
06056
06057
06058
06059
06060
06061
06062
06063
06064
06065
06066
06067
06068
06070
06071 void tetgenmesh::
06072 maketetrahedronmap(int*& idx2tetlist, tetrahedron**& tetsperverlist)
06073 {
06074 tetrahedron *tetloop;
06075 int i, j, k;
06076
06077 if (b->verbose > 0) {
06078 printf(" Constructing mapping from points to tetrahedra.\n");
06079 }
06080
06081
06082 idx2tetlist = new int[points->items + 1];
06083 for (i = 0; i < points->items + 1; i++) idx2tetlist[i] = 0;
06084
06085
06086
06087 tetrahedrons->traversalinit();
06088 tetloop = tetrahedrontraverse();
06089 while (tetloop != (tetrahedron *) NULL) {
06090
06091 for (i = 0; i < 4; i++) {
06092 j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06093 idx2tetlist[j]++;
06094 }
06095 tetloop = tetrahedrontraverse();
06096 }
06097
06098
06099 j = idx2tetlist[0];
06100 idx2tetlist[0] = 0;
06101 for (i = 0; i < points->items; i++) {
06102 k = idx2tetlist[i + 1];
06103 idx2tetlist[i + 1] = idx2tetlist[i] + j;
06104 j = k;
06105 }
06106
06107 tetsperverlist = new tetrahedron*[idx2tetlist[i]];
06108
06109 tetrahedrons->traversalinit();
06110 tetloop = tetrahedrontraverse();
06111 while (tetloop != (tetrahedron *) NULL) {
06112 for (i = 0; i < 4; i++) {
06113 j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
06114 tetsperverlist[idx2tetlist[j]] = tetloop;
06115 idx2tetlist[j]++;
06116 }
06117 tetloop = tetrahedrontraverse();
06118 }
06119
06120 for (i = points->items - 1; i >= 0; i--) {
06121 idx2tetlist[i + 1] = idx2tetlist[i];
06122 }
06123 idx2tetlist[0] = 0;
06124 }
06125
06126
06127
06128
06129
06130
06131
06132
06133
06134
06135
06136 inline REAL tetgenmesh::dot(REAL* v1, REAL* v2)
06137 {
06138 return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
06139 }
06140
06141
06142
06143 inline void tetgenmesh::cross(REAL* v1, REAL* v2, REAL* n)
06144 {
06145 n[0] = v1[1] * v2[2] - v2[1] * v1[2];
06146 n[1] = -(v1[0] * v2[2] - v2[0] * v1[2]);
06147 n[2] = v1[0] * v2[1] - v2[0] * v1[1];
06148 }
06149
06150
06151 static void initm44(REAL a00, REAL a01, REAL a02, REAL a03,
06152 REAL a10, REAL a11, REAL a12, REAL a13,
06153 REAL a20, REAL a21, REAL a22, REAL a23,
06154 REAL a30, REAL a31, REAL a32, REAL a33,
06155 REAL M[4][4])
06156 {
06157 M[0][0] = a00; M[0][1] = a01; M[0][2] = a02; M[0][3] = a03;
06158 M[1][0] = a10; M[1][1] = a11; M[1][2] = a12; M[1][3] = a13;
06159 M[2][0] = a20; M[2][1] = a21; M[2][2] = a22; M[2][3] = a23;
06160 M[3][0] = a30; M[3][1] = a31; M[3][2] = a32; M[3][3] = a33;
06161 }
06162
06163
06164 static void m4xm4(REAL m1[4][4], REAL m2[4][4])
06165 {
06166 REAL tmp[4];
06167 int i, j;
06168
06169 for (i = 0; i < 4; i++) {
06170 for (j = 0; j < 4; j++) {
06171 tmp[j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j]
06172 + m1[i][2] * m2[2][j] + m1[i][3] * m2[3][j];
06173 }
06174 for (j = 0; j < 4; j++)
06175 m1[i][j] = tmp[j];
06176 }
06177 }
06178
06179
06180 static void m4xv4(REAL v2[4], REAL m[4][4], REAL v1[4])
06181 {
06182 v2[0] = m[0][0]*v1[0] + m[0][1]*v1[1] + m[0][2]*v1[2] + m[0][3]*v1[3];
06183 v2[1] = m[1][0]*v1[0] + m[1][1]*v1[1] + m[1][2]*v1[2] + m[1][3]*v1[3];
06184 v2[2] = m[2][0]*v1[0] + m[2][1]*v1[1] + m[2][2]*v1[2] + m[2][3]*v1[3];
06185 v2[3] = m[3][0]*v1[0] + m[3][1]*v1[1] + m[3][2]*v1[2] + m[3][3]*v1[3];
06186 }
06187
06189
06190
06191
06192
06193
06194
06195
06196
06197
06198
06199
06200
06201
06202
06203
06204
06205
06206
06207
06208
06209
06211
06212 bool tetgenmesh::lu_decmp(REAL lu[4][4], int n, int* ps, REAL* d, int N)
06213 {
06214 REAL scales[4];
06215 REAL pivot, biggest, mult, tempf;
06216 int pivotindex = 0;
06217 int i, j, k;
06218
06219 *d = 1.0;
06220
06221 for (i = N; i < n + N; i++) {
06222
06223 biggest = 0.0;
06224 for (j = N; j < n + N; j++)
06225 if (biggest < (tempf = fabs(lu[i][j])))
06226 biggest = tempf;
06227 if (biggest != 0.0)
06228 scales[i] = 1.0 / biggest;
06229 else {
06230 scales[i] = 0.0;
06231 return false;
06232 }
06233 ps[i] = i;
06234 }
06235
06236 for (k = N; k < n + N - 1; k++) {
06237
06238 biggest = 0.0;
06239 for (i = k; i < n + N; i++) {
06240 if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
06241 biggest = tempf;
06242 pivotindex = i;
06243 }
06244 }
06245 if (biggest == 0.0) {
06246 return false;
06247 }
06248 if (pivotindex != k) {
06249 j = ps[k];
06250 ps[k] = ps[pivotindex];
06251 ps[pivotindex] = j;
06252 *d = -(*d);
06253 }
06254
06255
06256 pivot = lu[ps[k]][k];
06257 for (i = k + 1; i < n + N; i++) {
06258 lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
06259 if (mult != 0.0) {
06260 for (j = k + 1; j < n + N; j++)
06261 lu[ps[i]][j] -= mult * lu[ps[k]][j];
06262 }
06263 }
06264 }
06265
06266
06267 return lu[ps[n + N - 1]][n + N - 1] != 0.0;
06268 }
06269
06271
06272
06273
06274
06275
06276
06277
06278
06279
06280
06281
06282
06284
06285 void tetgenmesh::lu_solve(REAL lu[4][4], int n, int* ps, REAL* b, int N)
06286 {
06287 int i, j;
06288 REAL X[4], dot;
06289
06290 for (i = N; i < n + N; i++) X[i] = 0.0;
06291
06292
06293 for (i = N; i < n + N; i++) {
06294 dot = 0.0;
06295 for (j = N; j < i + N; j++)
06296 dot += lu[ps[i]][j] * X[j];
06297 X[i] = b[ps[i]] - dot;
06298 }
06299
06300
06301 for (i = n + N - 1; i >= N; i--) {
06302 dot = 0.0;
06303 for (j = i + 1; j < n + N; j++)
06304 dot += lu[ps[i]][j] * X[j];
06305 X[i] = (X[i] - dot) / lu[ps[i]][i];
06306 }
06307
06308 for (i = N; i < n + N; i++) b[i] = X[i];
06309 }
06310
06311
06312
06313
06314
06315
06316
06317
06318
06319
06320
06321
06322
06323
06325
06326
06327
06328
06329
06330
06331
06332
06333
06334
06335
06336
06338
06339 enum tetgenmesh::interresult tetgenmesh::edge_vert_col_inter(REAL* A, REAL* B,
06340 REAL* P)
06341 {
06342 int i = 0;
06343 do {
06344 if (A[i] < B[i]) {
06345 if (P[i] < A[i]) {
06346 return DISJOINT;
06347 } else if (P[i] > A[i]) {
06348 if (P[i] < B[i]) {
06349 return INTERSECT;
06350 } else if (P[i] > B[i]) {
06351 return DISJOINT;
06352 } else {
06353
06354 return SHAREVERTEX;
06355 }
06356 } else {
06357
06358 return SHAREVERTEX;
06359 }
06360 } else if (A[i] > B[i]) {
06361 if (P[i] < B[i]) {
06362 return DISJOINT;
06363 } else if (P[i] > B[i]) {
06364 if (P[i] < A[i]) {
06365 return INTERSECT;
06366 } else if (P[i] > A[i]) {
06367 return DISJOINT;
06368 } else {
06369
06370 return SHAREVERTEX;
06371 }
06372 } else {
06373
06374 return SHAREVERTEX;
06375 }
06376 }
06377
06378 i++;
06379 } while (i < 3);
06380
06381 return DISJOINT;
06382 }
06383
06385
06386
06387
06388
06389
06390
06391
06392
06393
06394
06395
06396
06397
06398
06399
06401
06402 enum tetgenmesh::interresult tetgenmesh:: edge_edge_cop_inter(REAL* A, REAL* B,
06403 REAL* P, REAL* Q, REAL* R)
06404 {
06405 REAL s1, s2, s3, s4;
06406
06407 #ifdef SELF_CHECK
06408 assert(R != NULL);
06409 #endif
06410 s1 = orient3d(A, B, R, P);
06411 s2 = orient3d(A, B, R, Q);
06412 if (s1 * s2 > 0.0) {
06413
06414 return DISJOINT;
06415 }
06416 s3 = orient3d(P, Q, R, A);
06417 s4 = orient3d(P, Q, R, B);
06418 if (s3 * s4 > 0.0) {
06419
06420 return DISJOINT;
06421 }
06422
06423
06424
06425
06426
06427 enum interresult abp, abq;
06428 enum interresult pqa, pqb;
06429
06430 if (s1 == 0.0) {
06431
06432 abp = edge_vert_col_inter(A, B, P);
06433 if (abp == INTERSECT) {
06434
06435 return INTERSECT;
06436 }
06437 if (s2 == 0.0) {
06438
06439 abq = edge_vert_col_inter(A, B, Q);
06440 if (abq == INTERSECT) {
06441
06442 return INTERSECT;
06443 }
06444 if (abp == SHAREVERTEX && abq == SHAREVERTEX) {
06445
06446 return SHAREEDGE;
06447 }
06448 pqa = edge_vert_col_inter(P, Q, A);
06449 if (pqa == INTERSECT) {
06450
06451 return INTERSECT;
06452 }
06453 pqb = edge_vert_col_inter(P, Q, B);
06454 if (pqb == INTERSECT) {
06455
06456 return INTERSECT;
06457 }
06458 if (abp == SHAREVERTEX || abq == SHAREVERTEX) {
06459
06460 #ifdef SELF_CHECK
06461
06462 assert(abp ^ abq);
06463 #endif
06464 return SHAREVERTEX;
06465 }
06466
06467 #ifdef SELF_CHECK
06468 assert((abp == DISJOINT) && (abp == abq && abq == pqa && pqa == pqb));
06469 #endif
06470 return DISJOINT;
06471 } else {
06472
06473 #ifdef SELF_CHECK
06474 assert(abp == SHAREVERTEX || abp == DISJOINT);
06475 #endif
06476 return abp;
06477 }
06478 }
06479
06480 if (s2 == 0.0) {
06481
06482 abq = edge_vert_col_inter(A, B, Q);
06483 #ifdef SELF_CHECK
06484 assert(abq == SHAREVERTEX || abq == DISJOINT || abq == INTERSECT);
06485 #endif
06486 return abq;
06487 }
06488
06489
06490
06491 if (s3 == 0.0) {
06492
06493 #ifdef SELF_CHECK
06494 assert(s4 != 0.0);
06495 #endif
06496 pqa = edge_vert_col_inter(P, Q, A);
06497 #ifdef SELF_CHECK
06498
06499 assert(pqa != SHAREVERTEX);
06500 assert(pqa == INTERSECT || pqa == DISJOINT);
06501 #endif
06502 return pqa;
06503 }
06504 if (s4 == 0.0) {
06505
06506 #ifdef SELF_CHECK
06507 assert(s3 != 0.0);
06508 #endif
06509 pqb = edge_vert_col_inter(P, Q, B);
06510 #ifdef SELF_CHECK
06511
06512 assert(pqb != SHAREVERTEX);
06513 assert(pqb == INTERSECT || pqb == DISJOINT);
06514 #endif
06515 return pqb;
06516 }
06517
06518
06519 return INTERSECT;
06520 }
06521
06523
06524
06525
06526
06527
06528
06529
06530
06531
06533
06535
06536
06537
06538
06539
06540
06541
06542
06543
06544
06545
06546
06547
06548
06550
06551 enum tetgenmesh::interresult tetgenmesh::tri_vert_cop_inter(REAL* A, REAL* B,
06552 REAL* C, REAL* P, REAL* R)
06553 {
06554 REAL s1, s2, s3;
06555 int sign;
06556
06557 #ifdef SELF_CHECK
06558 assert(R != (REAL *) NULL);
06559 #endif
06560
06561
06562 s1 = orient3d(A, B, C, R);
06563 #ifdef SELF_CHECK
06564 assert(s1 != 0.0);
06565 #endif
06566 sign = s1 < 0.0 ? 1 : -1;
06567
06568
06569 s1 = orient3d(A, B, R, P) * sign;
06570 if (s1 < 0.0) {
06571
06572 return DISJOINT;
06573 }
06574 s2 = orient3d(B, C, R, P) * sign;
06575 if (s2 < 0.0) {
06576
06577 return DISJOINT;
06578 }
06579 s3 = orient3d(C, A, R, P) * sign;
06580 if (s3 < 0.0) {
06581
06582 return DISJOINT;
06583 }
06584 if (s1 == 0.0) {
06585
06586 if (s2 == 0.0) {
06587
06588 #ifdef SELF_CHECK
06589 assert(s3 > 0.0);
06590 #endif
06591
06592 return SHAREVERTEX;
06593 }
06594 if (s3 == 0.0) {
06595
06596
06597 return SHAREVERTEX;
06598 }
06599
06600 return INTERSECT;
06601 }
06602
06603 if (s2 == 0.0) {
06604
06605 if (s3 == 0.0) {
06606
06607
06608 return SHAREVERTEX;
06609 }
06610
06611 return INTERSECT;
06612 }
06613 if (s3 == 0.0) {
06614
06615
06616 return INTERSECT;
06617 }
06618
06619
06620 return INTERSECT;
06621 }
06622
06624
06625
06626
06627
06628
06629
06630
06631
06632
06633
06634
06636
06637 enum tetgenmesh::interresult tetgenmesh::tri_edge_cop_inter(REAL* A, REAL* B,
06638 REAL* C, REAL* P, REAL* Q, REAL* R)
06639 {
06640 enum interresult abpq, bcpq, capq;
06641 enum interresult abcp, abcq;
06642
06643
06644 abpq = edge_edge_cop_inter(A, B, P, Q, R);
06645 if (abpq == INTERSECT || abpq == SHAREEDGE) {
06646 return abpq;
06647 }
06648 bcpq = edge_edge_cop_inter(B, C, P, Q, R);
06649 if (bcpq == INTERSECT || bcpq == SHAREEDGE) {
06650 return bcpq;
06651 }
06652 capq = edge_edge_cop_inter(C, A, P, Q, R);
06653 if (capq == INTERSECT || capq == SHAREEDGE) {
06654 return capq;
06655 }
06656
06657
06658 abcp = tri_vert_cop_inter(A, B, C, P, R);
06659 if (abcp == INTERSECT) {
06660 return INTERSECT;
06661 }
06662 abcq = tri_vert_cop_inter(A, B, C, Q, R);
06663 if (abcq == INTERSECT) {
06664 return INTERSECT;
06665 }
06666
06667
06668
06669 if (abpq == SHAREVERTEX) {
06670
06671 #ifdef SELF_CHECK
06672 assert(abcp ^ abcq);
06673 #endif
06674 return SHAREVERTEX;
06675 }
06676 if (bcpq == SHAREVERTEX) {
06677
06678 #ifdef SELF_CHECK
06679 assert(abcp ^ abcq);
06680 #endif
06681 return SHAREVERTEX;
06682 }
06683 if (capq == SHAREVERTEX) {
06684
06685 #ifdef SELF_CHECK
06686 assert(abcp ^ abcq);
06687 #endif
06688 return SHAREVERTEX;
06689 }
06690
06691
06692 return DISJOINT;
06693 }
06694
06696
06697
06698
06699
06700
06701
06702
06703
06704
06705
06706
06708
06709 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter_tail(REAL* A, REAL* B,
06710 REAL* C, REAL* P, REAL* Q, REAL s1, REAL s2)
06711 {
06712 REAL s3, s4, s5;
06713 int sign;
06714
06715 if (s1 * s2 > 0.0) {
06716
06717 return DISJOINT;
06718 }
06719
06720 if (s1 * s2 < 0.0) {
06721
06722
06723
06724 sign = s1 < 0.0 ? 1 : -1;
06725 s3 = orient3d(A, B, P, Q) * sign;
06726 if (s3 < 0.0) {
06727
06728 return DISJOINT;
06729 }
06730 s4 = orient3d(B, C, P, Q) * sign;
06731 if (s4 < 0.0) {
06732
06733 return DISJOINT;
06734 }
06735 s5 = orient3d(C, A, P, Q) * sign;
06736 if (s5 < 0.0) {
06737
06738 return DISJOINT;
06739 }
06740 if (s3 == 0.0) {
06741
06742 if (s4 == 0.0) {
06743
06744 #ifdef SELF_CHECK
06745 assert(s5 > 0.0);
06746 #endif
06747
06748 return SHAREVERTEX;
06749 }
06750 if (s5 == 0.0) {
06751
06752
06753 return SHAREVERTEX;
06754 }
06755
06756
06757 return INTERSECT;
06758 }
06759
06760 if (s4 == 0.0) {
06761
06762 if (s5 == 0.0) {
06763
06764
06765 return SHAREVERTEX;
06766 }
06767
06768 return INTERSECT;
06769 }
06770
06771 if (s5 == 0.0) {
06772
06773
06774 return INTERSECT;
06775 }
06776
06777
06778 return INTERSECT;
06779 }
06780
06781 if (s1 != 0.0 || s2 != 0.0) {
06782
06783 if (s1 == 0.0) {
06784
06785 #ifdef SELF_CHECK
06786 assert(s2 != 0.0);
06787 #endif
06788 return tri_vert_cop_inter(A, B, C, P, Q);
06789 } else {
06790
06791 #ifdef SELF_CHECK
06792 assert(s2 == 0.0);
06793 #endif
06794 return tri_vert_cop_inter(A, B, C, Q, P);
06795 }
06796 }
06797
06798
06799
06800 REAL R[3], N[3];
06801 REAL ax, ay, az, bx, by, bz;
06802
06803 ax = A[0] - B[0];
06804 ay = A[1] - B[1];
06805 az = A[2] - B[2];
06806 bx = A[0] - C[0];
06807 by = A[1] - C[1];
06808 bz = A[2] - C[2];
06809 N[0] = ay * bz - by * az;
06810 N[1] = az * bx - bz * ax;
06811 N[2] = ax * by - bx * ay;
06812
06813 #ifdef SELF_CHECK
06814 assert((fabs(N[0]) + fabs(N[1]) + fabs(N[2])) > 0.0);
06815 #endif
06816
06817
06818 R[0] = N[0] + A[0];
06819 R[1] = N[1] + A[1];
06820 R[2] = N[2] + A[2];
06821
06822
06823
06824 if (R[0] == A[0] && R[1] == A[1] && R[2] == A[2]) {
06825 int i, j;
06826 for (i = 0; i < 3; i++) {
06827 #ifdef SELF_CHECK
06828 assert (R[i] == A[i]);
06829 #endif
06830 j = 2;
06831 do {
06832 if (N[i] > 0.0) {
06833 N[i] += (j * macheps);
06834 } else {
06835 N[i] -= (j * macheps);
06836 }
06837 R[i] = N[i] + A[i];
06838 j *= 2;
06839 } while (R[i] == A[i]);
06840 }
06841 }
06842
06843 return tri_edge_cop_inter(A, B, C, P, Q, R);
06844 }
06845
06847
06848
06849
06850
06851
06852
06853
06855
06856 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter(REAL* A, REAL* B,
06857 REAL* C, REAL* P, REAL* Q)
06858 {
06859 REAL s1, s2;
06860
06861
06862 s1 = orient3d(A, B, C, P);
06863 s2 = orient3d(A, B, C, Q);
06864
06865 return tri_edge_inter_tail(A, B, C, P, Q, s1, s2);
06866 }
06867
06869
06870
06871
06872
06873
06874
06875
06877
06878 enum tetgenmesh::interresult tetgenmesh::tri_tri_inter(REAL* A, REAL* B,
06879 REAL* C, REAL* O, REAL* P, REAL* Q)
06880 {
06881 REAL s_o, s_p, s_q;
06882 REAL s_a, s_b, s_c;
06883
06884 s_o = orient3d(A, B, C, O);
06885 s_p = orient3d(A, B, C, P);
06886 s_q = orient3d(A, B, C, Q);
06887 if ((s_o * s_p > 0.0) && (s_o * s_q > 0.0)) {
06888
06889 return DISJOINT;
06890 }
06891
06892 s_a = orient3d(O, P, Q, A);
06893 s_b = orient3d(O, P, Q, B);
06894 s_c = orient3d(O, P, Q, C);
06895 if ((s_a * s_b > 0.0) && (s_a * s_c > 0.0)) {
06896
06897 return DISJOINT;
06898 }
06899
06900 enum interresult abcop, abcpq, abcqo;
06901 int shareedge = 0;
06902
06903 abcop = tri_edge_inter_tail(A, B, C, O, P, s_o, s_p);
06904 if (abcop == INTERSECT) {
06905 return INTERSECT;
06906 } else if (abcop == SHAREEDGE) {
06907 shareedge++;
06908 }
06909 abcpq = tri_edge_inter_tail(A, B, C, P, Q, s_p, s_q);
06910 if (abcpq == INTERSECT) {
06911 return INTERSECT;
06912 } else if (abcpq == SHAREEDGE) {
06913 shareedge++;
06914 }
06915 abcqo = tri_edge_inter_tail(A, B, C, Q, O, s_q, s_o);
06916 if (abcqo == INTERSECT) {
06917 return INTERSECT;
06918 } else if (abcqo == SHAREEDGE) {
06919 shareedge++;
06920 }
06921 if (shareedge == 3) {
06922
06923 return SHAREFACE;
06924 }
06925 #ifdef SELF_CHECK
06926
06927 assert(shareedge == 0 || shareedge == 1);
06928 #endif
06929
06930
06931 enum interresult opqab, opqbc, opqca;
06932
06933 opqab = tri_edge_inter_tail(O, P, Q, A, B, s_a, s_b);
06934 if (opqab == INTERSECT) {
06935 return INTERSECT;
06936 }
06937 opqbc = tri_edge_inter_tail(O, P, Q, B, C, s_b, s_c);
06938 if (opqbc == INTERSECT) {
06939 return INTERSECT;
06940 }
06941 opqca = tri_edge_inter_tail(O, P, Q, C, A, s_c, s_a);
06942 if (opqca == INTERSECT) {
06943 return INTERSECT;
06944 }
06945
06946
06947
06948 if (abcop == SHAREEDGE) {
06949 #ifdef SELF_CHECK
06950 assert(abcpq == SHAREVERTEX && abcqo == SHAREVERTEX);
06951 #endif
06952
06953 return SHAREEDGE;
06954 }
06955 if (abcpq == SHAREEDGE) {
06956 #ifdef SELF_CHECK
06957 assert(abcop == SHAREVERTEX && abcqo == SHAREVERTEX);
06958 #endif
06959
06960 return SHAREEDGE;
06961 }
06962 if (abcqo == SHAREEDGE) {
06963 #ifdef SELF_CHECK
06964 assert(abcop == SHAREVERTEX && abcpq == SHAREVERTEX);
06965 #endif
06966
06967 return SHAREEDGE;
06968 }
06969
06970
06971 if (abcop == SHAREVERTEX) {
06972
06973 if (abcpq == SHAREVERTEX) {
06974
06975 #ifdef SELF_CHECK
06976 assert(abcqo != SHAREVERTEX);
06977 #endif
06978 } else {
06979
06980 #ifdef SELF_CHECK
06981 assert(abcqo == SHAREVERTEX);
06982 #endif
06983 }
06984 return SHAREVERTEX;
06985 }
06986 if (abcpq == SHAREVERTEX) {
06987
06988 #ifdef SELF_CHECK
06989 assert(abcqo == SHAREVERTEX);
06990 #endif
06991 return SHAREVERTEX;
06992 }
06993
06994
06995 return DISJOINT;
06996 }
06997
06999
07000
07001
07002
07003
07004
07005
07006
07007
07008
07010
07011 REAL tetgenmesh::insphere_sos(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
07012 int ia, int ib, int ic, int id, int ie)
07013 {
07014 REAL det;
07015
07016 det = insphere(pa, pb, pc, pd, pe);
07017 if (det != 0.0) {
07018 return det;
07019 }
07020
07021
07022 REAL *p[5], *tmpp;
07023 REAL sign, det_c, det_d;
07024 int idx[5], perm, tmp;
07025 int n, i, j;
07026
07027 p[0] = pa; idx[0] = ia;
07028 p[1] = pb; idx[1] = ib;
07029 p[2] = pc; idx[2] = ic;
07030 p[3] = pd; idx[3] = id;
07031 p[4] = pe; idx[4] = ie;
07032
07033
07034 n = 5;
07035 perm = 0;
07036 for (i = 0; i < n - 1; i++) {
07037 for (j = 0; j < n - 1 - i; j++) {
07038 if (idx[j + 1] < idx[j]) {
07039 tmp = idx[j];
07040 idx[j] = idx[j + 1];
07041 idx[j + 1] = tmp;
07042 tmpp = p[j];
07043 p[j] = p[j + 1];
07044 p[j + 1] = tmpp;
07045 perm++;
07046 }
07047 }
07048 }
07049
07050 sign = (perm % 2 == 0) ? 1.0 : -1.0;
07051 det_c = orient3d(p[1], p[2], p[3], p[4]);
07052 if (det_c != 0.0) {
07053 return sign * det_c;
07054 }
07055 det_d = orient3d(p[0], p[2], p[3], p[4]);
07056 return -sign * det_d;
07057 }
07058
07060
07061
07062
07063
07064
07065
07066
07068
07069 bool tetgenmesh::iscollinear(REAL* A, REAL* B, REAL* C, REAL eps)
07070 {
07071 REAL abx, aby, abz;
07072 REAL acx, acy, acz;
07073 REAL Lv, Lw, dd;
07074 REAL d, q;
07075
07076
07077 q = longest * eps;
07078 q *= q;
07079
07080 abx = A[0] - B[0];
07081 aby = A[1] - B[1];
07082 abz = A[2] - B[2];
07083 acx = A[0] - C[0];
07084 acy = A[1] - C[1];
07085 acz = A[2] - C[2];
07086 Lv = abx * abx + aby * aby + abz * abz;
07087
07088 if (Lv < q) return true;
07089 Lw = acx * acx + acy * acy + acz * acz;
07090
07091 if (Lw < q) return true;
07092 dd = abx * acx + aby * acy + abz * acz;
07093
07094 d = (dd * dd) / (Lv * Lw);
07095 if (d > 1.0) d = 1.0;
07096 q = 1.0 - sqrt(d);
07097
07098 return q <= eps;
07099 }
07100
07102
07103
07104
07105
07106
07107
07108
07109
07111
07112 bool tetgenmesh::
07113 iscoplanar(REAL* k, REAL* l, REAL* m, REAL* n, REAL vol6, REAL eps)
07114 {
07115 REAL L, q;
07116 REAL x, y, z;
07117
07118 if (vol6 == 0.0) return true;
07119
07120 x = k[0] - l[0];
07121 y = k[1] - l[1];
07122 z = k[2] - l[2];
07123 L = sqrt(x * x + y * y + z * z);
07124 x = l[0] - m[0];
07125 y = l[1] - m[1];
07126 z = l[2] - m[2];
07127 L += sqrt(x * x + y * y + z * z);
07128 x = m[0] - k[0];
07129 y = m[1] - k[1];
07130 z = m[2] - k[2];
07131 L += sqrt(x * x + y * y + z * z);
07132 x = k[0] - n[0];
07133 y = k[1] - n[1];
07134 z = k[2] - n[2];
07135 L += sqrt(x * x + y * y + z * z);
07136 x = l[0] - n[0];
07137 y = l[1] - n[1];
07138 z = l[2] - n[2];
07139 L += sqrt(x * x + y * y + z * z);
07140 x = m[0] - n[0];
07141 y = m[1] - n[1];
07142 z = m[2] - n[2];
07143 L += sqrt(x * x + y * y + z * z);
07144 #ifdef SELF_CHECK
07145 assert(L > 0.0);
07146 #endif
07147 L /= 6.0;
07148 q = fabs(vol6) / (L * L * L);
07149
07150 return q <= eps;
07151 }
07152
07154
07155
07156
07157
07158
07159
07160
07161
07163
07164 bool tetgenmesh::
07165 iscospheric(REAL* k, REAL* l, REAL* m, REAL* n, REAL* o, REAL vol24, REAL eps)
07166 {
07167 REAL L, q;
07168
07169
07170 L = distance(k, l);
07171 L += distance(l, m);
07172 L += distance(m, k);
07173 L += distance(k, n);
07174 L += distance(l, n);
07175 L += distance(m, n);
07176 L += distance(k, o);
07177 L += distance(l, o);
07178 L += distance(m, o);
07179 L += distance(n, o);
07180 #ifdef SELF_CHECK
07181 assert(L > 0.0);
07182 #endif
07183 L /= 10.0;
07184 q = fabs(vol24) / (L * L * L * L);
07185
07186 return q < eps;
07187 }
07188
07189
07190
07191
07192
07193
07194
07195
07196
07197
07198 inline REAL tetgenmesh::distance(REAL* p1, REAL* p2)
07199 {
07200 return sqrt((p2[0] - p1[0]) * (p2[0] - p1[0]) +
07201 (p2[1] - p1[1]) * (p2[1] - p1[1]) +
07202 (p2[2] - p1[2]) * (p2[2] - p1[2]));
07203 }
07204
07206
07207
07208
07209
07210
07211
07212
07213
07214
07215
07216
07218
07219 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2)
07220 {
07221 REAL v1[3], v2[3];
07222 REAL len, l_p;
07223
07224 v1[0] = e2[0] - e1[0];
07225 v1[1] = e2[1] - e1[1];
07226 v1[2] = e2[2] - e1[2];
07227 v2[0] = p[0] - e1[0];
07228 v2[1] = p[1] - e1[1];
07229 v2[2] = p[2] - e1[2];
07230
07231 len = sqrt(dot(v1, v1));
07232 #ifdef SELF_CHECK
07233 assert(len != 0.0);
07234 #endif
07235 v1[0] /= len;
07236 v1[1] /= len;
07237 v1[2] /= len;
07238 l_p = dot(v1, v2);
07239
07240 return sqrt(dot(v2, v2) - l_p * l_p);
07241 }
07242
07244
07245
07246
07248
07249 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2, REAL* e3)
07250 {
07251 REAL prj[3];
07252
07253 projpt2face(p, e1, e2, e3, prj);
07254 return distance(p, prj);
07255 }
07256
07258
07259
07260
07261
07262
07263
07264
07265
07266
07267
07269
07270 REAL tetgenmesh::interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n)
07271 {
07272 REAL v1[3], v2[3], np[3];
07273 REAL theta, costheta, lenlen;
07274 REAL ori, len1, len2;
07275
07276
07277 v1[0] = p1[0] - o[0];
07278 v1[1] = p1[1] - o[1];
07279 v1[2] = p1[2] - o[2];
07280 v2[0] = p2[0] - o[0];
07281 v2[1] = p2[1] - o[1];
07282 v2[2] = p2[2] - o[2];
07283 len1 = sqrt(dot(v1, v1));
07284 len2 = sqrt(dot(v2, v2));
07285 lenlen = len1 * len2;
07286 #ifdef SELF_CHECK
07287 assert(lenlen != 0.0);
07288 #endif
07289 costheta = dot(v1, v2) / lenlen;
07290 if (costheta > 1.0) {
07291 costheta = 1.0;
07292 } else if (costheta < -1.0) {
07293 costheta = -1.0;
07294 }
07295 theta = acos(costheta);
07296 if (n != NULL) {
07297
07298 np[0] = o[0] + n[0];
07299 np[1] = o[1] + n[1];
07300 np[2] = o[2] + n[2];
07301
07302 ori = orient3d(p1, o, np, p2);
07303 if (ori > 0.0) {
07304 theta = 2 * PI - theta;
07305 }
07306 }
07307
07308 return theta;
07309 }
07310
07312
07313
07314
07316
07317 void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj)
07318 {
07319 REAL v1[3], v2[3];
07320 REAL len, l_p;
07321
07322 v1[0] = e2[0] - e1[0];
07323 v1[1] = e2[1] - e1[1];
07324 v1[2] = e2[2] - e1[2];
07325 v2[0] = p[0] - e1[0];
07326 v2[1] = p[1] - e1[1];
07327 v2[2] = p[2] - e1[2];
07328
07329 len = sqrt(dot(v1, v1));
07330 #ifdef SELF_CHECK
07331 assert(len != 0.0);
07332 #endif
07333 v1[0] /= len;
07334 v1[1] /= len;
07335 v1[2] /= len;
07336 l_p = dot(v1, v2);
07337
07338 prj[0] = e1[0] + l_p * v1[0];
07339 prj[1] = e1[1] + l_p * v1[1];
07340 prj[2] = e1[2] + l_p * v1[2];
07341 }
07342
07344
07345
07346
07348
07349 void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj)
07350 {
07351 REAL fnormal[3], v1[3];
07352 REAL len, dist;
07353
07354
07355 facenormal(f1, f2, f3, fnormal, &len);
07356 #ifdef SELF_CHECK
07357 assert(len > 0.0);
07358 #endif
07359 fnormal[0] /= len;
07360 fnormal[1] /= len;
07361 fnormal[2] /= len;
07362
07363 v1[0] = p[0] - f1[0];
07364 v1[1] = p[1] - f1[1];
07365 v1[2] = p[2] - f1[2];
07366
07367 dist = dot(fnormal, v1);
07368
07369
07370 prj[0] = p[0] - dist * fnormal[0];
07371 prj[1] = p[1] - dist * fnormal[1];
07372 prj[2] = p[2] - dist * fnormal[2];
07373 }
07374
07376
07377
07378
07379
07380
07381
07382
07383
07385
07386 void tetgenmesh::facenormal(REAL* pa, REAL* pb, REAL* pc, REAL* n, REAL* nlen)
07387 {
07388 REAL v1[3], v2[3];
07389
07390 v1[0] = pb[0] - pa[0];
07391 v1[1] = pb[1] - pa[1];
07392 v1[2] = pb[2] - pa[2];
07393 v2[0] = pc[0] - pa[0];
07394 v2[1] = pc[1] - pa[1];
07395 v2[2] = pc[2] - pa[2];
07396
07397 cross(v1, v2, n);
07398 if (nlen != (REAL *) NULL) {
07399 *nlen = sqrt(dot(n, n));
07400 }
07401 }
07402
07404
07405
07406
07407
07408
07409
07410
07411
07412
07413
07414
07415
07416
07418
07419 void tetgenmesh::edgeorthonormal(REAL* e1, REAL* e2, REAL* op, REAL* n)
07420 {
07421 REAL v1[3], v2[3], fn[3];
07422 REAL len;
07423
07424
07425 v1[0] = e2[0] - e1[0];
07426 v1[1] = e2[1] - e1[1];
07427 v1[2] = e2[2] - e1[2];
07428
07429 v2[0] = op[0] - e1[0];
07430 v2[1] = op[1] - e1[1];
07431 v2[2] = op[2] - e1[2];
07432
07433 cross(v1, v2, fn);
07434
07435 cross(fn, v1, n);
07436
07437 len = sqrt(dot(n, n));
07438 n[0] /= len;
07439 n[1] /= len;
07440 n[2] /= len;
07441 }
07442
07444
07445
07446
07447
07448
07449
07450
07451
07453
07454 REAL tetgenmesh::facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2)
07455 {
07456 REAL n1[3], n2[3];
07457 REAL n1len, n2len;
07458 REAL costheta, ori;
07459 REAL theta;
07460
07461 facenormal(pa, pb, pc1, n1, &n1len);
07462 facenormal(pa, pb, pc2, n2, &n2len);
07463 costheta = dot(n1, n2) / (n1len * n2len);
07464
07465 if (costheta > 1.0) {
07466 costheta = 1.0;
07467 } else if (costheta < -1.0) {
07468 costheta = -1.0;
07469 }
07470 theta = acos(costheta);
07471 ori = orient3d(pa, pb, pc1, pc2);
07472 if (ori > 0.0) {
07473 theta = 2 * PI - theta;
07474 }
07475
07476 return theta;
07477 }
07478
07480
07481
07482
07483
07484
07485
07486
07487
07489
07490 void tetgenmesh::tetalldihedral(point pa, point pb, point pc, point pd,
07491 REAL* cosdd, REAL* cosmaxd, REAL* cosmind)
07492 {
07493 REAL N[4][3], cosd, len;
07494 int f1, f2, i, j;
07495
07496 f1=0;
07497 f2=0;
07498
07499
07500 tetallnormal(pa, pb, pc, pd, N, NULL);
07501
07502 for (i = 0; i < 4; i++) {
07503 len = sqrt(dot(N[i], N[i]));
07504 if (len != 0.0) {
07505 for (j = 0; j < 3; j++) N[i][j] /= len;
07506 }
07507 }
07508
07509 for (i = 0; i < 6; i++) {
07510 switch (i) {
07511 case 0: f1 = 2; f2 = 3; break;
07512 case 1: f1 = 0; f2 = 3; break;
07513 case 2: f1 = 1; f2 = 3; break;
07514 case 3: f1 = 1; f2 = 2; break;
07515 case 4: f1 = 2; f2 = 0; break;
07516 case 5: f1 = 0; f2 = 1; break;
07517 }
07518 cosd = -dot(N[f1], N[f2]);
07519 if (cosdd) cosdd[i] = cosd;
07520 if (i == 0) {
07521 if (cosmaxd) *cosmaxd = cosd;
07522 if (cosmind) *cosmind = cosd;
07523 } else {
07524 if (cosmaxd) *cosmaxd = cosd < *cosmaxd ? cosd : *cosmaxd;
07525 if (cosmind) *cosmind = cosd > *cosmind ? cosd : *cosmind;
07526 }
07527 }
07528 }
07529
07531
07532
07533
07534
07535
07536
07538
07539 void tetgenmesh::tetallnormal(point pa, point pb, point pc, point pd,
07540 REAL N[4][3], REAL* volume)
07541 {
07542 REAL A[4][4], rhs[4], D;
07543 int indx[4];
07544 int i, j;
07545
07546
07547 for (i = 0; i < 3; i++) A[0][i] = pa[i] - pd[i];
07548 for (i = 0; i < 3; i++) A[1][i] = pb[i] - pd[i];
07549 for (i = 0; i < 3; i++) A[2][i] = pc[i] - pd[i];
07550
07551 lu_decmp(A, 3, indx, &D, 0);
07552 if (volume != NULL) {
07553
07554 *volume = fabs((A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2])) / 6.0;
07555 }
07556 for (j = 0; j < 3; j++) {
07557 for (i = 0; i < 3; i++) rhs[i] = 0.0;
07558 rhs[j] = 1.0;
07559 lu_solve(A, 3, indx, rhs, 0);
07560 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07561 }
07562
07563 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07564 }
07565
07567
07568
07569
07570
07571
07572
07574
07575 REAL tetgenmesh::tetaspectratio(point pa, point pb, point pc, point pd)
07576 {
07577 REAL vda[3], vdb[3], vdc[3];
07578 REAL N[4][3], A[4][4], rhs[4], D;
07579 REAL H[4], volume, radius2, minheightinv;
07580 int indx[4];
07581 int i, j;
07582
07583
07584 for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
07585 for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
07586 for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
07587
07588 lu_decmp(A, 3, indx, &D, 0);
07589
07590 volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
07591
07592 if (volume == 0.0) return 1.0e+200;
07593
07594
07595 rhs[0] = 0.5 * dot(vda, vda);
07596 rhs[1] = 0.5 * dot(vdb, vdb);
07597 rhs[2] = 0.5 * dot(vdc, vdc);
07598 lu_solve(A, 3, indx, rhs, 0);
07599
07600
07601
07602 radius2 = dot(rhs, rhs);
07603
07604
07605 for (j = 0; j < 3; j++) {
07606 for (i = 0; i < 3; i++) rhs[i] = 0.0;
07607 rhs[j] = 1.0;
07608 lu_solve(A, 3, indx, rhs, 0);
07609 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
07610 }
07611
07612 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
07613
07614 for (i = 0; i < 4; i++) {
07615
07616 H[i] = sqrt(dot(N[i], N[i]));
07617
07618
07619
07620 }
07621
07622
07623
07624 minheightinv = H[0];
07625 for (i = 1; i < 3; i++) {
07626 if (H[i] > minheightinv) minheightinv = H[i];
07627 }
07628
07629 return sqrt(radius2) * minheightinv;
07630 }
07631
07633
07634
07635
07636
07637
07638
07639
07640
07641
07642
07643
07644
07646
07647 bool tetgenmesh::
07648 circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* cent, REAL* radius)
07649 {
07650 REAL A[4][4], rhs[4], D;
07651 int indx[4];
07652
07653
07654 A[0][0] = pb[0] - pa[0];
07655 A[0][1] = pb[1] - pa[1];
07656 A[0][2] = pb[2] - pa[2];
07657 A[1][0] = pc[0] - pa[0];
07658 A[1][1] = pc[1] - pa[1];
07659 A[1][2] = pc[2] - pa[2];
07660 if (pd != NULL) {
07661 A[2][0] = pd[0] - pa[0];
07662 A[2][1] = pd[1] - pa[1];
07663 A[2][2] = pd[2] - pa[2];
07664 } else {
07665 cross(A[0], A[1], A[2]);
07666 }
07667
07668
07669 rhs[0] = 0.5 * dot(A[0], A[0]);
07670 rhs[1] = 0.5 * dot(A[1], A[1]);
07671 if (pd != NULL) {
07672 rhs[2] = 0.5 * dot(A[2], A[2]);
07673 } else {
07674 rhs[2] = 0.0;
07675 }
07676
07677
07678
07679 if (!lu_decmp(A, 3, indx, &D, 0)) {
07680 if (radius != (REAL *) NULL) *radius = 0.0;
07681 return false;
07682 }
07683 lu_solve(A, 3, indx, rhs, 0);
07684 if (cent != (REAL *) NULL) {
07685 cent[0] = pa[0] + rhs[0];
07686 cent[1] = pa[1] + rhs[1];
07687 cent[2] = pa[2] + rhs[2];
07688 }
07689 if (radius != (REAL *) NULL) {
07690 *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
07691 }
07692 return true;
07693 }
07694
07696
07697
07698
07699
07700
07701
07702
07703
07704
07705
07706
07707
07708
07709
07710
07711
07712
07713
07714
07715
07717
07718 void tetgenmesh::inscribedsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
07719 REAL* cent, REAL* radius)
07720 {
07721 REAL N[4][3], H[4];
07722 REAL rd;
07723 int i;
07724
07725
07726 tetallnormal(pa, pb, pc, pd, N, NULL);
07727 for (i = 0; i < 4; i++) {
07728
07729 H[i] = sqrt(dot(N[i], N[i]));
07730 }
07731
07732 rd = 1.0 / (H[0] + H[1] + H[2] + H[3]);
07733 if (radius != (REAL*) NULL) *radius = rd;
07734 if (cent != (REAL*) NULL) {
07735
07736 cent[0] = rd * (H[0] * pa[0] + H[1] * pb[0] + H[2] * pc[0] + H[3] * pd[0]);
07737 cent[1] = rd * (H[0] * pa[1] + H[1] * pb[1] + H[2] * pc[1] + H[3] * pd[1]);
07738 cent[2] = rd * (H[0] * pa[2] + H[1] * pb[2] + H[2] * pc[2] + H[3] * pd[2]);
07739 }
07740 }
07741
07743
07744
07745
07746
07747
07748
07749
07750
07751
07752
07753
07754
07755
07756
07757
07758
07759
07760
07761
07762
07764
07765 void tetgenmesh::rotatepoint(REAL* p, REAL rotangle, REAL* p1, REAL* p2)
07766 {
07767 REAL T[4][4], pp0[4], p0t[4], p2t[4];
07768 REAL roty, rotx, alphaR, projlen;
07769 REAL dx, dy, dz;
07770
07771 initm44(1, 0, 0, -p1[0],
07772 0, 1, 0, -p1[1],
07773 0, 0, 1, -p1[2],
07774 0, 0, 0, 1, T);
07775 pp0[0] = p[0]; pp0[1] = p[1]; pp0[2] = p[2]; pp0[3] = 1.0;
07776 m4xv4(p0t, T, pp0);
07777 pp0[0] = p2[0]; pp0[1] = p2[1]; pp0[2] = p2[2]; pp0[3] = 1.0;
07778 m4xv4(p2t, T, pp0);
07779
07780
07781 dx = p2t[0];
07782 dz = p2t[2];
07783 projlen = sqrt(dx * dx + dz * dz);
07784 if (projlen <= (b->epsilon * 1e-2) * longest) {
07785 roty = 0;
07786 } else {
07787 roty = acos(dz / projlen);
07788 if (dx < 0) {
07789 roty = -roty;
07790 }
07791 }
07792
07793 initm44(cos(-roty), 0, sin(-roty), 0,
07794 0, 1, 0, 0,
07795 -sin(-roty), 0, cos(-roty), 0,
07796 0, 0, 0, 1, T);
07797 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07798 m4xv4(p0t, T, pp0);
07799 pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
07800 m4xv4(p2t, T, pp0);
07801
07802
07803 dy = p2t[1];
07804 dz = p2t[2];
07805 projlen = sqrt(dy * dy + dz * dz);
07806 if (projlen <= (b->epsilon * 1e-2) * longest) {
07807 rotx = 0;
07808 } else {
07809 rotx = acos(dz / projlen);
07810 if (dy < 0) {
07811 rotx = -rotx;
07812 }
07813 }
07814
07815 initm44(1, 0, 0, 0,
07816 0, cos(rotx), -sin(rotx), 0,
07817 0, sin(rotx), cos(rotx), 0,
07818 0, 0, 0, 1, T);
07819 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07820 m4xv4(p0t, T, pp0);
07821
07822
07823
07824 alphaR = rotangle;
07825 initm44(cos(alphaR), -sin(alphaR), 0, 0,
07826 sin(alphaR), cos(alphaR), 0, 0,
07827 0, 0, 1, 0,
07828 0, 0, 0, 1, T);
07829 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07830 m4xv4(p0t, T, pp0);
07831
07832 initm44(1, 0, 0, 0,
07833 0, cos(-rotx), -sin(-rotx), 0,
07834 0, sin(-rotx), cos(-rotx), 0,
07835 0, 0, 0, 1, T);
07836 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07837 m4xv4(p0t, T, pp0);
07838
07839 initm44(cos(roty), 0, sin(roty), 0,
07840 0, 1, 0, 0,
07841 -sin(roty), 0, cos(roty), 0,
07842 0, 0, 0, 1, T);
07843 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07844 m4xv4(p0t, T, pp0);
07845
07846 initm44(1, 0, 0, p1[0],
07847 0, 1, 0, p1[1],
07848 0, 0, 1, p1[2],
07849 0, 0, 0, 1, T);
07850 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
07851 m4xv4(p0t, T, pp0);
07852
07853 p[0] = p0t[0];
07854 p[1] = p0t[1];
07855 p[2] = p0t[2];
07856 }
07857
07859
07860
07861
07862
07863
07864
07865
07866
07867
07868
07870
07871 void tetgenmesh::spherelineint(REAL* p1, REAL* p2, REAL* C, REAL R, REAL p[7])
07872 {
07873 REAL x1, y1, z1;
07874 REAL x2, y2, z2;
07875 REAL x3, y3, z3, r;
07876 REAL a, b, c, mu, i ;
07877
07878 x1 = p1[0]; y1 = p1[1]; z1 = p1[2];
07879 x2 = p2[0]; y2 = p2[1]; z2 = p2[2];
07880 x3 = C[0]; y3 = C[1]; z3 = C[2];
07881 r = R;
07882
07883 a = (x2 - x1) * (x2 - x1)
07884 + (y2 - y1) * (y2 - y1)
07885 + (z2 - z1) * (z2 - z1);
07886 b = 2 * ( (x2 - x1) * (x1 - x3)
07887 + (y2 - y1) * (y1 - y3)
07888 + (z2 - z1) * (z1 - z3) ) ;
07889 c = (x3 * x3) + (y3 * y3) + (z3 * z3)
07890 + (x1 * x1) + (y1 * y1) + (z1 * z1)
07891 - 2 * (x3 * x1 + y3 * y1 + z3 * z1) - (r * r) ;
07892 i = b * b - 4 * a * c ;
07893
07894 if (i < 0.0) {
07895
07896 p[0] = 0.0;
07897 } else if (i == 0.0) {
07898
07899 p[0] = 1.0;
07900 mu = -b / (2 * a) ;
07901 p[1] = x1 + mu * (x2 - x1);
07902 p[2] = y1 + mu * (y2 - y1);
07903 p[3] = z1 + mu * (z2 - z1);
07904 } else {
07905
07906 p[0] = 2.0;
07907
07908 mu = (-b + sqrt((b * b) - 4 * a * c)) / (2 * a);
07909 p[1] = x1 + mu * (x2 - x1);
07910 p[2] = y1 + mu * (y2 - y1);
07911 p[3] = z1 + mu * (z2 - z1);
07912
07913 mu = (-b - sqrt((b * b) - 4 * a * c)) / (2 * a);
07914 p[4] = x1 + mu * (x2 - x1);
07915 p[5] = y1 + mu * (y2 - y1);
07916 p[6] = z1 + mu * (z2 - z1);
07917 }
07918 }
07919
07921
07922
07923
07924
07925
07926
07927
07928
07929
07930
07931
07932
07933
07934
07935
07936
07937
07939
07940 void tetgenmesh::linelineint(REAL *p1,REAL *p2, REAL *p3, REAL *p4, REAL p[7])
07941 {
07942 REAL p13[3], p43[3], p21[3];
07943 REAL d1343, d4321, d1321, d4343, d2121;
07944 REAL numer, denom;
07945 REAL mua, mub;
07946
07947 p13[0] = p1[0] - p3[0];
07948 p13[1] = p1[1] - p3[1];
07949 p13[2] = p1[2] - p3[2];
07950 p43[0] = p4[0] - p3[0];
07951 p43[1] = p4[1] - p3[1];
07952 p43[2] = p4[2] - p3[2];
07953 if (p43[0] == 0.0 && p43[1] == 0.0 && p43[2] == 0.0) {
07954 p[0] = 0.0;
07955 return;
07956 }
07957
07958 p21[0] = p2[0] - p1[0];
07959 p21[1] = p2[1] - p1[1];
07960 p21[2] = p2[2] - p1[2];
07961 if (p21[0] == 0.0 && p21[1] == 0.0 && p21[2] == 0.0) {
07962 p[0] = 0.0;
07963 return;
07964 }
07965
07966 d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
07967 d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
07968 d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
07969 d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
07970 d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
07971
07972 denom = d2121 * d4343 - d4321 * d4321;
07973 if (denom == 0.0) {
07974 p[0] = 0.0;
07975 return;
07976 }
07977 numer = d1343 * d4321 - d1321 * d4343;
07978 mua = numer / denom;
07979 mub = (d1343 + d4321 * mua) / d4343;
07980
07981 p[0] = 1.0;
07982 p[1] = p1[0] + mua * p21[0];
07983 p[2] = p1[1] + mua * p21[1];
07984 p[3] = p1[2] + mua * p21[2];
07985 p[4] = p3[0] + mub * p43[0];
07986 p[5] = p3[1] + mub * p43[1];
07987 p[6] = p3[2] + mub * p43[2];
07988 }
07989
07991
07992
07993
07994
07995
07996
07997
07998
07999
08000
08001
08002
08003
08004
08005
08006
08007
08008
08009
08010
08012
08013 void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
08014 REAL* ip, REAL* u)
08015 {
08016 REAL n[3], det, det1;
08017
08018
08019 facenormal(pa, pb, pc, n, NULL);
08020
08021 det = n[0] * (e2[0] - e1[0]) + n[1] * (e2[1] - e1[1])
08022 + n[2] * (e2[2] - e1[2]);
08023 if (det != 0.0) {
08024
08025 det1 = n[0] * (pa[0] - e1[0]) + n[1] * (pa[1] - e1[1])
08026 + n[2] * (pa[2] - e1[2]);
08027 *u = det1 / det;
08028 ip[0] = e1[0] + *u * (e2[0] - e1[0]);
08029 ip[1] = e1[1] + *u * (e2[1] - e1[1]);
08030 ip[2] = e1[2] + *u * (e2[2] - e1[2]);
08031 } else {
08032 *u = 0.0;
08033 }
08034 }
08035
08036
08037
08038
08039
08040
08041
08042
08043
08045
08046
08047
08048
08049
08050
08051
08052
08053
08054
08055
08056
08057
08059
08060 void tetgenmesh::dummyinit(int tetwords, int shwords)
08061 {
08062 unsigned long alignptr;
08063
08064
08065 dummytetbase = (tetrahedron *) new char[tetwords * sizeof(tetrahedron)
08066 + tetrahedrons->alignbytes];
08067
08068 alignptr = (unsigned long) dummytetbase;
08069 dummytet = (tetrahedron *)
08070 (alignptr + (unsigned long) tetrahedrons->alignbytes
08071 - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08072
08073
08074
08075
08076 dummytet[0] = (tetrahedron) dummytet;
08077 dummytet[1] = (tetrahedron) dummytet;
08078 dummytet[2] = (tetrahedron) dummytet;
08079 dummytet[3] = (tetrahedron) dummytet;
08080
08081 dummytet[4] = (tetrahedron) NULL;
08082 dummytet[5] = (tetrahedron) NULL;
08083 dummytet[6] = (tetrahedron) NULL;
08084 dummytet[7] = (tetrahedron) NULL;
08085
08086 if (b->useshelles) {
08087
08088
08089
08090 dummyshbase = (shellface *) new char[shwords * sizeof(shellface)
08091 + subfaces->alignbytes];
08092
08093 alignptr = (unsigned long) dummyshbase;
08094 dummysh = (shellface *)
08095 (alignptr + (unsigned long) subfaces->alignbytes
08096 - (alignptr % (unsigned long) subfaces->alignbytes));
08097
08098
08099
08100
08101 dummysh[0] = (shellface) dummysh;
08102 dummysh[1] = (shellface) dummysh;
08103 dummysh[2] = (shellface) dummysh;
08104
08105 dummysh[3] = (shellface) NULL;
08106 dummysh[4] = (shellface) NULL;
08107 dummysh[5] = (shellface) NULL;
08108
08109 dummysh[6] = (shellface) dummytet;
08110 dummysh[7] = (shellface) dummytet;
08111
08112 dummysh[8] = (shellface) dummysh;
08113 dummysh[9] = (shellface) dummysh;
08114 dummysh[10] = (shellface) dummysh;
08115
08116 dummysh[11] = (shellface) NULL;
08117
08118
08119 dummytet[8 ] = (tetrahedron) dummysh;
08120 dummytet[9 ] = (tetrahedron) dummysh;
08121 dummytet[10] = (tetrahedron) dummysh;
08122 dummytet[11] = (tetrahedron) dummysh;
08123 }
08124 }
08125
08127
08128
08129
08130
08131
08132
08133
08134
08135
08136
08137
08138
08139
08140
08141
08143
08144 void tetgenmesh::initializepools()
08145 {
08146 enum wordtype wtype;
08147 int pointsize, elesize, shsize;
08148
08149
08150 if ((b->plc || b->refine) && (in->pbcgrouplist != NULL)) {
08151 checkpbcs = 1;
08152 }
08153
08154 if (in->segmentconstraintlist || in->facetconstraintlist) {
08155 varconstraint = 1;
08156 }
08157
08158
08159
08160 pointmtrindex = 3 + in->numberofpointattributes;
08161
08162 if (b->metric) {
08163
08164 if (bgm != (tetgenmesh *) NULL) {
08165
08166 sizeoftensor = (bgm->in != (tetgenio *) NULL) ?
08167 bgm->in->numberofpointmtrs : in->numberofpointmtrs;
08168 } else {
08169
08170 sizeoftensor = in->numberofpointmtrs;
08171 }
08172
08173 sizeoftensor = (sizeoftensor > 0) ? sizeoftensor : 1;
08174 } else {
08175
08176 sizeoftensor = b->quality ? 1 : 0;
08177 }
08178
08179
08180
08181 point2simindex = ((pointmtrindex + sizeoftensor) * sizeof(REAL)
08182 + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08183 if (b->plc || b->refine) {
08184
08185
08186
08187
08188 if (b->metric) {
08189
08190 pointsize = (point2simindex + 4) * sizeof(tetrahedron);
08191 } else {
08192 pointsize = (point2simindex + 3) * sizeof(tetrahedron);
08193 }
08194
08195 point2pbcptindex = (pointsize + sizeof(tetrahedron) - 1)
08196 / sizeof(tetrahedron);
08197 if (checkpbcs) {
08198
08199
08200 pointsize = (point2pbcptindex + 1) * sizeof(tetrahedron);
08201 }
08202 } else {
08203 pointsize = point2simindex * sizeof(tetrahedron);
08204 }
08205
08206
08207 pointmarkindex = (pointsize + sizeof(int) - 1) / sizeof(int);
08208
08209
08210
08211 pointsize = (pointmarkindex + 2) * sizeof(int);
08212
08213 wtype = (sizeof(REAL) >= sizeof(tetrahedron)) ? FLOATINGPOINT : POINTER;
08214
08215 points = new memorypool(pointsize, VERPERBLOCK, wtype, 0);
08216
08217
08218
08219
08220 elesize = (8 + b->useshelles * 6) * sizeof(tetrahedron);
08221
08222 if (b->voroout && (b->useshelles == 0)) {
08223 elesize = (8 + 4) * sizeof(tetrahedron);
08224 }
08225
08226
08227 elemattribindex = (elesize + sizeof(REAL) - 1) / sizeof(REAL);
08228
08229
08230
08231 volumeboundindex = elemattribindex + in->numberoftetrahedronattributes
08232 + (b->regionattrib > 0);
08233
08234
08235 if (b->varvolume) {
08236 elesize = (volumeboundindex + 1) * sizeof(REAL);
08237 } else if (in->numberoftetrahedronattributes + b->regionattrib > 0) {
08238 elesize = volumeboundindex * sizeof(REAL);
08239 }
08240
08241
08242 elemmarkerindex = (elesize + sizeof(int) - 1) / sizeof(int);
08243 if (b->neighout || b->voroout) {
08244 elesize = (elemmarkerindex + 1) * sizeof(int);
08245 }
08246
08247
08248 highorderindex = (elesize + sizeof(tetrahedron) - 1) / sizeof(tetrahedron);
08249 if (b->order == 2) {
08250 elesize = (highorderindex + 1) * sizeof(tetrahedron);
08251 }
08252
08253 tetrahedrons = new memorypool(elesize, ELEPERBLOCK, POINTER, 8);
08254
08255 if (b->useshelles) {
08256
08257
08258
08259 shsize = 12 * sizeof(shellface);
08260
08261
08262 areaboundindex = (shsize + sizeof(REAL) - 1) / sizeof(REAL);
08263
08264
08265 if (b->quality && varconstraint) {
08266 shsize = (areaboundindex + 1) * sizeof(REAL);
08267 } else {
08268 shsize = areaboundindex * sizeof(REAL);
08269 }
08270
08271
08272 shmarkindex = (shsize + sizeof(int) - 1) / sizeof(int);
08273
08274
08275 shsize = (shmarkindex + 2 + checkpbcs) * sizeof(int);
08276
08277
08278
08279 subfaces = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08280
08281
08282 subsegs = new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
08283
08284 dummyinit(tetrahedrons->itemwords, subfaces->itemwords);
08285 } else {
08286
08287 dummyinit(tetrahedrons->itemwords, 0);
08288 }
08289 }
08290
08292
08293
08294
08296
08297 void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
08298 {
08299
08300
08301 dyingtetrahedron[4] = (tetrahedron) NULL;
08302 dyingtetrahedron[5] = (tetrahedron) NULL;
08303 dyingtetrahedron[6] = (tetrahedron) NULL;
08304 dyingtetrahedron[7] = (tetrahedron) NULL;
08305 tetrahedrons->dealloc((void *) dyingtetrahedron);
08306 }
08307
08309
08310
08311
08313
08314 tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse()
08315 {
08316 tetrahedron *newtetrahedron;
08317
08318 do {
08319 newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
08320 if (newtetrahedron == (tetrahedron *) NULL) {
08321 return (tetrahedron *) NULL;
08322 }
08323 } while (newtetrahedron[7] == (tetrahedron) NULL);
08324 return newtetrahedron;
08325 }
08326
08328
08329
08330
08331
08333
08334 void tetgenmesh::shellfacedealloc(memorypool *pool, shellface *dyingsh)
08335 {
08336
08337
08338 dyingsh[3] = (shellface) NULL;
08339 dyingsh[4] = (shellface) NULL;
08340 dyingsh[5] = (shellface) NULL;
08341 pool->dealloc((void *) dyingsh);
08342 }
08343
08345
08346
08347
08348
08350
08351 tetgenmesh::shellface* tetgenmesh::shellfacetraverse(memorypool *pool)
08352 {
08353 shellface *newshellface;
08354
08355 do {
08356 newshellface = (shellface *) pool->traverse();
08357 if (newshellface == (shellface *) NULL) {
08358 return (shellface *) NULL;
08359 }
08360 } while (newshellface[3] == (shellface) NULL);
08361 return newshellface;
08362 }
08363
08365
08366
08367
08369
08370 void tetgenmesh::badfacedealloc(memorypool *pool, badface *dying)
08371 {
08372
08373
08374 dying->forg = (point) NULL;
08375 pool->dealloc((void *) dying);
08376 }
08377
08379
08380
08381
08383
08384 tetgenmesh::badface* tetgenmesh::badfacetraverse(memorypool *pool)
08385 {
08386 badface *newsh;
08387
08388 do {
08389 newsh = (badface *) pool->traverse();
08390 if (newsh == (badface *) NULL) {
08391 return (badface *) NULL;
08392 }
08393 } while (newsh->forg == (point) NULL);
08394 return newsh;
08395 }
08396
08398
08399
08400
08402
08403 void tetgenmesh::pointdealloc(point dyingpoint)
08404 {
08405
08406
08407 setpointtype(dyingpoint, DEADVERTEX);
08408 points->dealloc((void *) dyingpoint);
08409 }
08410
08412
08413
08414
08416
08417 tetgenmesh::point tetgenmesh::pointtraverse()
08418 {
08419 point newpoint;
08420
08421 do {
08422 newpoint = (point) points->traverse();
08423 if (newpoint == (point) NULL) {
08424 return (point) NULL;
08425 }
08426 } while (pointtype(newpoint) == DEADVERTEX);
08427 return newpoint;
08428 }
08429
08431
08432
08433
08435
08436 void tetgenmesh::maketetrahedron(triface *newtet)
08437 {
08438 newtet->tet = (tetrahedron *) tetrahedrons->alloc();
08439
08440 newtet->tet[0] = (tetrahedron) dummytet;
08441 newtet->tet[1] = (tetrahedron) dummytet;
08442 newtet->tet[2] = (tetrahedron) dummytet;
08443 newtet->tet[3] = (tetrahedron) dummytet;
08444
08445 newtet->tet[4] = (tetrahedron) NULL;
08446 newtet->tet[5] = (tetrahedron) NULL;
08447 newtet->tet[6] = (tetrahedron) NULL;
08448 newtet->tet[7] = (tetrahedron) NULL;
08449
08450 if (b->useshelles) {
08451 newtet->tet[8 ] = (tetrahedron) dummysh;
08452 newtet->tet[9 ] = (tetrahedron) dummysh;
08453 newtet->tet[10] = (tetrahedron) dummysh;
08454 newtet->tet[11] = (tetrahedron) dummysh;
08455 newtet->tet[12] = (tetrahedron) dummysh;
08456 newtet->tet[13] = (tetrahedron) dummysh;
08457 }
08458 for (int i = 0; i < in->numberoftetrahedronattributes; i++) {
08459 setelemattribute(newtet->tet, i, 0.0);
08460 }
08461 if (b->varvolume) {
08462 setvolumebound(newtet->tet, -1.0);
08463 }
08464
08465 newtet->loc = 0;
08466 newtet->ver = 0;
08467 }
08468
08470
08471
08472
08473
08475
08476 void tetgenmesh::makeshellface(memorypool *pool, face *newface)
08477 {
08478 newface->sh = (shellface *) pool->alloc();
08479
08480 newface->sh[0] = (shellface) dummysh;
08481 newface->sh[1] = (shellface) dummysh;
08482 newface->sh[2] = (shellface) dummysh;
08483
08484 newface->sh[3] = (shellface) NULL;
08485 newface->sh[4] = (shellface) NULL;
08486 newface->sh[5] = (shellface) NULL;
08487
08488 newface->sh[6] = (shellface) dummytet;
08489 newface->sh[7] = (shellface) dummytet;
08490
08491
08492 newface->sh [8] = (shellface) dummysh;
08493 newface->sh [9] = (shellface) dummysh;
08494 newface->sh[10] = (shellface) dummysh;
08495
08496 newface->sh[11] = (shellface) NULL;
08497 if (b->quality && varconstraint) {
08498
08499 setareabound(*newface, 0.0);
08500 }
08501
08502 setshellmark(*newface, 0);
08503
08504 setshelltype(*newface, NSHARP);
08505 if (checkpbcs) {
08506
08507 setshellpbcgroup(*newface, -1);
08508 }
08509
08510 newface->shver = 0;
08511 }
08512
08514
08515
08516
08518
08519 void tetgenmesh::makepoint(point* pnewpoint)
08520 {
08521 int ptmark, i;
08522
08523 *pnewpoint = (point) points->alloc();
08524
08525 (*pnewpoint)[0] = 0.0;
08526 (*pnewpoint)[1] = 0.0;
08527 (*pnewpoint)[2] = 0.0;
08528
08529 for (i = 0; i < in->numberofpointattributes; i++) {
08530 (*pnewpoint)[3 + i] = 0.0;
08531 }
08532
08533 for (i = 0; i < sizeoftensor; i++) {
08534 (*pnewpoint)[pointmtrindex + i] = 0.0;
08535 }
08536 if (b->plc || b->refine) {
08537
08538 setpoint2tet(*pnewpoint, NULL);
08539 setpoint2sh(*pnewpoint, NULL);
08540 setpoint2ppt(*pnewpoint, NULL);
08541 if (b->metric) {
08542 setpoint2bgmtet(*pnewpoint, NULL);
08543 }
08544 if (checkpbcs) {
08545
08546 setpoint2pbcpt(*pnewpoint, NULL);
08547 }
08548 }
08549
08550 ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
08551 setpointmark(*pnewpoint, ptmark);
08552
08553 setpointtype(*pnewpoint, UNUSEDVERTEX);
08554 }
08555
08556
08557
08558
08559
08560
08561
08562
08563
08565
08566
08567
08569
08570 unsigned long tetgenmesh::randomnation(unsigned int choices)
08571 {
08572 unsigned long newrandom;
08573
08574 if (choices >= 714025l) {
08575 newrandom = (randomseed * 1366l + 150889l) % 714025l;
08576 randomseed = (newrandom * 1366l + 150889l) % 714025l;
08577 newrandom = newrandom * (choices / 714025l) + randomseed;
08578 if (newrandom >= choices) {
08579 return newrandom - choices;
08580 } else {
08581 return newrandom;
08582 }
08583 } else {
08584 randomseed = (randomseed * 1366l + 150889l) % 714025l;
08585 return randomseed % choices;
08586 }
08587
08588
08589
08590 }
08591
08593
08594
08595
08597
08598 REAL tetgenmesh::distance2(tetrahedron* tetptr, point p)
08599 {
08600 point p1, p2, p3, p4;
08601 REAL dx, dy, dz;
08602
08603 p1 = (point) tetptr[4];
08604 p2 = (point) tetptr[5];
08605 p3 = (point) tetptr[6];
08606 p4 = (point) tetptr[7];
08607
08608 dx = p[0] - 0.25 * (p1[0] + p2[0] + p3[0] + p4[0]);
08609 dy = p[1] - 0.25 * (p1[1] + p2[1] + p3[1] + p4[1]);
08610 dz = p[2] - 0.25 * (p1[2] + p2[2] + p3[2] + p4[2]);
08611
08612 return dx * dx + dy * dy + dz * dz;
08613 }
08614
08616
08617
08618
08619
08620
08621
08622
08623
08624
08625
08626
08627
08628
08629
08630
08631
08632
08633
08634
08635
08636
08637
08638
08639
08640
08641
08642
08644
08645 enum tetgenmesh::locateresult tetgenmesh::preciselocate(point searchpt,
08646 triface* searchtet, long maxtetnumber)
08647 {
08648 triface backtracetet;
08649 triface walkthroface;
08650 point forg, fdest, fapex, toppo;
08651 REAL ori1, ori2, ori3, ori4;
08652 long tetnumber;
08653 int side;
08654
08655 if (isdead(searchtet)) searchtet->tet = dummytet;
08656 if (searchtet->tet == dummytet) {
08657 searchtet->loc = 0;
08658 symself(*searchtet);
08659 }
08660
08661 #ifdef SELF_CHECK
08662
08663 #endif
08664 if (isdead(searchtet)) {
08665 printf("Warning: Point location failed.\n");
08666 return OUTSIDE;
08667 }
08668
08669 searchtet->ver = 0;
08670
08671
08672 for (searchtet->loc = 0; searchtet->loc < 4; searchtet->loc++) {
08673 forg = org(*searchtet);
08674 fdest = dest(*searchtet);
08675 fapex = apex(*searchtet);
08676 ori1 = orient3d(forg, fdest, fapex, searchpt);
08677 if (ori1 < 0.0) break;
08678 }
08679 #ifdef SELF_CHECK
08680 assert(searchtet->loc < 4);
08681 #endif
08682
08683
08684 tetnumber = 0l;
08685 while ((maxtetnumber > 0l) && (tetnumber <= maxtetnumber)) {
08686
08687 if (searchtet->tet == dummytet) {
08688 *searchtet = backtracetet;
08689 return OUTSIDE;
08690 }
08691
08692 walkthroface.tet = (tetrahedron *) NULL;
08693
08694 searchtet->ver = 0;
08695
08696 toppo = oppo(*searchtet);
08697
08698
08699 for (side = 0; side < 3; side++) {
08700 forg = org(*searchtet);
08701 fdest = dest(*searchtet);
08702 ori2 = orient3d(forg, fdest, toppo, searchpt);
08703 if (ori2 == 0.0) {
08704
08705
08706 fapex = apex(*searchtet);
08707 ori3 = orient3d(fdest, fapex, toppo, searchpt);
08708 if (ori3 < 0.0) {
08709
08710 enextself(*searchtet);
08711 fnext(*searchtet, walkthroface);
08712 break;
08713 }
08714 ori4 = orient3d(fapex, forg, toppo, searchpt);
08715 if (ori4 < 0.0) {
08716
08717 enext2self(*searchtet);
08718 fnext(*searchtet, walkthroface);
08719 break;
08720 }
08721
08722
08723 #ifdef SELF_CHECK
08724 assert(ori1 < 0.0);
08725 #endif
08726
08727
08728
08729
08730
08731 fnextself(*searchtet);
08732 if (ori3 == 0.0) {
08733 if (ori4 == 0.0) {
08734
08735 enext2self(*searchtet);
08736 return ONVERTEX;
08737 } else {
08738
08739 enextself(*searchtet);
08740 return ONEDGE;
08741 }
08742 }
08743 if (ori4 == 0.0) {
08744
08745 enext2self(*searchtet);
08746 return ONEDGE;
08747 }
08748
08749 return ONFACE;
08750 } else if (ori2 < 0.0) {
08751
08752 fnext(*searchtet, walkthroface);
08753 break;
08754 }
08755
08756 enextself(*searchtet);
08757 }
08758 if (side >= 3) {
08759
08760 return INTETRAHEDRON;
08761 }
08762
08763 #ifdef SELF_CHECK
08764 assert(walkthroface.tet != (tetrahedron *) NULL);
08765 #endif
08766
08767
08768
08769 backtracetet = walkthroface;
08770 sym(walkthroface, *searchtet);
08771 tetnumber++;
08772 }
08773
08774
08775
08776
08777 return OUTSIDE;
08778 }
08779
08781
08782
08783
08784
08785
08786
08787
08788
08789
08790
08791
08792
08793
08794
08795
08796
08797
08798
08799
08801
08802 enum tetgenmesh::locateresult tetgenmesh::locate(point searchpt,
08803 triface *searchtet)
08804 {
08805 tetrahedron *firsttet, *tetptr;
08806 void **sampleblock;
08807 long sampleblocks, samplesperblock, samplenum;
08808 long tetblocks, i, j;
08809 unsigned long alignptr;
08810 REAL searchdist, dist;
08811
08812
08813 if (isdead(searchtet)) {
08814 searchtet->tet = dummytet;
08815 }
08816 if (searchtet->tet == dummytet) {
08817
08818 searchtet->loc = 0;
08819 symself(*searchtet);
08820 }
08821 #ifdef SELF_CHECK
08822
08823 #endif
08824 if (isdead(searchtet)) {
08825 printf("Warning: Point location failed.\n");
08826 return OUTSIDE;
08827 }
08828
08829
08830 searchdist = distance2(searchtet->tet, searchpt);
08831
08832
08833
08834 if (!isdead(&recenttet) && (recenttet.tet != searchtet->tet)) {
08835 dist = distance2(recenttet.tet, searchpt);
08836 if (dist < searchdist) {
08837 *searchtet = recenttet;
08838 searchdist = dist;
08839 }
08840 }
08841
08842
08843
08844
08845
08846 while (SAMPLEFACTOR * samples * samples * samples * samples <
08847 tetrahedrons->items) {
08848 samples++;
08849 }
08850
08851 tetblocks = (tetrahedrons->maxitems + ELEPERBLOCK - 1) / ELEPERBLOCK;
08852
08853 samplesperblock = 1 + (samples / tetblocks);
08854 sampleblocks = samples / samplesperblock;
08855 sampleblock = tetrahedrons->firstblock;
08856 for (i = 0; i < sampleblocks; i++) {
08857 alignptr = (unsigned long) (sampleblock + 1);
08858 firsttet = (tetrahedron *)
08859 (alignptr + (unsigned long) tetrahedrons->alignbytes
08860 - (alignptr % (unsigned long) tetrahedrons->alignbytes));
08861 for (j = 0; j < samplesperblock; j++) {
08862 if (i == tetblocks - 1) {
08863
08864 samplenum = randomnation((int)
08865 (tetrahedrons->maxitems - (i * ELEPERBLOCK)));
08866 } else {
08867 samplenum = randomnation(ELEPERBLOCK);
08868 }
08869 tetptr = (tetrahedron *)
08870 (firsttet + (samplenum * tetrahedrons->itemwords));
08871 if (tetptr[4] != (tetrahedron) NULL) {
08872 dist = distance2(tetptr, searchpt);
08873 if (dist < searchdist) {
08874 searchtet->tet = tetptr;
08875 searchdist = dist;
08876 }
08877 }
08878 }
08879 sampleblock = (void **) *sampleblock;
08880 }
08881
08882
08883 return preciselocate(searchpt, searchtet, tetrahedrons->items);
08884 }
08885
08887
08888
08889
08890
08891
08892
08893
08894
08895
08896
08897
08898
08899
08900
08901
08902
08903
08904
08905
08906
08908
08909 enum tetgenmesh::locateresult tetgenmesh::adjustlocate(point searchpt,
08910 triface* searchtet, enum locateresult precise, REAL epspp)
08911 {
08912 point torg, tdest, tapex, toppo;
08913 REAL s1, s2, s3, s4;
08914
08915
08916
08917
08918
08919
08920 adjustedgering(*searchtet, CCW);
08921 torg = org(*searchtet);
08922 tdest = dest(*searchtet);
08923 tapex = apex(*searchtet);
08924 toppo = oppo(*searchtet);
08925
08926 switch (precise) {
08927 case ONVERTEX:
08928
08929 return ONVERTEX;
08930 case ONEDGE:
08931
08932 s1 = 0.0;
08933 s2 = 0.0;
08934 break;
08935 case ONFACE:
08936
08937 s1 = 0.0;
08938 s2 = orient3d(torg, tdest, toppo, searchpt);
08939 break;
08940 default:
08941 s1 = orient3d(tdest, torg, tapex, searchpt);
08942 s2 = orient3d(torg, tdest, toppo, searchpt);
08943 }
08944
08945 if (s1 != 0.0) {
08946 if (iscoplanar(tdest, torg, tapex, searchpt, s1, epspp)) {
08947 s1 = 0.0;
08948 }
08949 }
08950 if (s1 < 0.0) {
08951 return OUTSIDE;
08952 }
08953
08954 if (s2 != 0.0) {
08955 if (iscoplanar(torg, tdest, toppo, searchpt, s2, epspp)) {
08956 s2 = 0.0;
08957 }
08958 }
08959 if (s2 < 0.0) {
08960 fnextself(*searchtet);
08961 return OUTSIDE;
08962 }
08963
08964 s3 = orient3d(tdest, tapex, toppo, searchpt);
08965 if (s3 != 0.0) {
08966 if (iscoplanar(tdest, tapex, toppo, searchpt, s3, epspp)) {
08967 s3 = 0.0;
08968 }
08969 }
08970 if (s3 < 0.0) {
08971 enextfnextself(*searchtet);
08972 return OUTSIDE;
08973 }
08974
08975 s4 = orient3d(tapex, torg, toppo, searchpt);
08976 if (s4 != 0.0) {
08977 if (iscoplanar(tapex, torg, toppo, searchpt, s4, epspp)) {
08978 s4 = 0.0;
08979 }
08980 }
08981 if (s4 < 0.0) {
08982 enext2fnextself(*searchtet);
08983 return OUTSIDE;
08984 }
08985
08986
08987 if (s1 == 0.0) {
08988 if (s2 == 0.0) {
08989 if (s3 == 0.0) {
08990
08991 enextself(*searchtet);
08992 return ONVERTEX;
08993 }
08994 if (s4 == 0.0) {
08995
08996 return ONVERTEX;
08997 }
08998
08999 return ONEDGE;
09000 }
09001 if (s3 == 0.0) {
09002 if (s4 == 0.0) {
09003
09004 enext2self(*searchtet);
09005 return ONVERTEX;
09006 }
09007
09008 enextself(*searchtet);
09009 return ONEDGE;
09010 }
09011 if (s4 == 0.0) {
09012
09013 enext2self(*searchtet);
09014 return ONEDGE;
09015 }
09016
09017 return ONFACE;
09018 }
09019 if (s2 == 0.0) {
09020 fnextself(*searchtet);
09021 if (s3 == 0.0) {
09022 if (s4 == 0.0) {
09023
09024 enext2self(*searchtet);
09025 return ONVERTEX;
09026 }
09027
09028 enextself(*searchtet);
09029 return ONEDGE;
09030 }
09031 if (s4 == 0.0) {
09032
09033 enext2self(*searchtet);
09034 return ONEDGE;
09035 }
09036
09037 return ONFACE;
09038 }
09039 if (s3 == 0.0) {
09040 enextfnextself(*searchtet);
09041 if (s4 == 0.0) {
09042
09043 enextself(*searchtet);
09044 return ONEDGE;
09045 }
09046
09047 return ONFACE;
09048 }
09049 if (s4 == 0.0) {
09050 enext2fnextself(*searchtet);
09051
09052 return ONFACE;
09053 }
09054
09055
09056 return INTETRAHEDRON;
09057 }
09058
09060
09061
09062
09064
09065 enum tetgenmesh::locateresult tetgenmesh::hullwalk(point searchpt,
09066 triface *hulltet)
09067 {
09068 list* travtetlist;
09069 triface travtet, neightet;
09070 point pa, pb, pc;
09071 enum locateresult loc;
09072 REAL ori;
09073 int i;
09074
09075 travtetlist = new list(sizeof(triface), NULL, 256);
09076 travtet = *hulltet;
09077 infect(travtet);
09078 travtetlist->append(&travtet);
09079
09080 loc = OUTSIDE;
09081 for (i = 0; i < travtetlist->len(); i++) {
09082 travtet = * (triface *)(* travtetlist)[i];
09083
09084 travtet.ver = 0;
09085
09086 for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09087 pa = org(travtet);
09088 pb = dest(travtet);
09089 pc = apex(travtet);
09090 ori = orient3d(pa, pb, pc, searchpt);
09091 if (ori > 0.0) break;
09092 }
09093
09094 if (travtet.loc == 4) {
09095 hulltet->tet = travtet.tet;
09096 loc = adjustlocate(searchpt, hulltet, INTETRAHEDRON, b->epsilon);
09097 assert(loc != OUTSIDE);
09098 } else {
09099
09100 sym(travtet, neightet);
09101 if (neightet.tet == dummytet) {
09102
09103 loc = adjustlocate(searchpt, &travtet, OUTSIDE, b->epsilon);
09104 }
09105 if (loc == OUTSIDE) {
09106
09107 for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
09108 sym(travtet, neightet);
09109 if ((neightet.tet != dummytet) && !infected(neightet)) {
09110
09111 infect(neightet);
09112 travtetlist->append(&neightet);
09113 }
09114 }
09115 }
09116 }
09117 if (loc != OUTSIDE) break;
09118 }
09119
09120
09121 for (i = 0; i < travtetlist->len(); i++) {
09122 travtet = * (triface *)(* travtetlist)[i];
09123 uninfect(travtet);
09124 }
09125
09126 delete travtetlist;
09127 return loc;
09128 }
09129
09131
09132
09133
09134
09135
09136
09137
09138
09139
09140
09141
09142
09143
09144
09145
09146
09147
09148
09149
09150
09151
09153
09154 enum tetgenmesh::locateresult tetgenmesh::locatesub(point searchpt,
09155 face* searchsh, int stopatseg, REAL epspp)
09156 {
09157 face backtracksh, spinsh, checkedge;
09158 point forg, fdest, fapex;
09159 REAL orgori, destori;
09160 REAL ori, sign;
09161 int moveleft, i;
09162
09163 if (searchsh->sh == dummysh) {
09164 searchsh->shver = 0;
09165 spivotself(*searchsh);
09166 #ifdef SELF_CHECK
09167 assert(searchsh->sh != dummysh);
09168 #endif
09169 }
09170
09171 adjustedgering(*searchsh, CCW);
09172 forg = sorg(*searchsh);
09173 fdest = sdest(*searchsh);
09174 fapex = sapex(*searchsh);
09175 ori = orient3d(forg, fdest, fapex, abovepoint);
09176 sign = ori > 0.0 ? -1 : 1;
09177
09178
09179
09180
09181 for (i = 0; i < 3; i++) {
09182 forg = sorg(*searchsh);
09183 fdest = sdest(*searchsh);
09184 ori = orient3d(forg, fdest, abovepoint, searchpt) * sign;
09185 if (ori > 0.0) break;
09186 senextself(*searchsh);
09187 }
09188 #ifdef SELF_CHECK
09189 assert(i < 3);
09190 #endif
09191
09192 while (1) {
09193 fapex = sapex(*searchsh);
09194
09195 if (fapex[0] == searchpt[0] && fapex[1] == searchpt[1] &&
09196 fapex[2] == searchpt[2]) {
09197 senext2self(*searchsh);
09198 return ONVERTEX;
09199 }
09200
09201
09202 destori = orient3d(forg, fapex, abovepoint, searchpt) * sign;
09203 if (epspp > 0.0) {
09204 if (iscoplanar(forg, fapex, abovepoint, searchpt, destori, epspp)) {
09205 destori = 0.0;
09206 }
09207 }
09208
09209
09210 orgori = orient3d(fapex, fdest, abovepoint, searchpt) * sign;
09211 if (epspp > 0.0) {
09212 if (iscoplanar(fapex, fdest, abovepoint, searchpt, orgori, epspp)) {
09213 orgori = 0.0;
09214 }
09215 }
09216 if (destori > 0.0) {
09217 moveleft = 1;
09218 } else {
09219 if (orgori > 0.0) {
09220 moveleft = 0;
09221 } else {
09222
09223 if (destori == 0.0) {
09224 senext2self(*searchsh);
09225 return ONEDGE;
09226 }
09227 if (orgori == 0.0) {
09228 senextself(*searchsh);
09229 return ONEDGE;
09230 }
09231 return ONFACE;
09232 }
09233 }
09234
09235
09236 if (moveleft) {
09237 senext2(*searchsh, backtracksh);
09238 fdest = fapex;
09239 } else {
09240 senext(*searchsh, backtracksh);
09241 forg = fapex;
09242 }
09243
09244 sspivot(backtracksh, checkedge);
09245 if (checkedge.sh != dummysh) {
09246 if (stopatseg) {
09247
09248 *searchsh = backtracksh;
09249 return OUTSIDE;
09250 }
09251
09252
09253 spinsh = backtracksh;
09254 do {
09255 spivotself(spinsh);
09256 if (spinsh.sh == backtracksh.sh) {
09257
09258 break;
09259 }
09260
09261 if (shellmark(spinsh) == shellmark(backtracksh)) {
09262
09263 *searchsh = spinsh;
09264 break;
09265 }
09266
09267 ori = orient3d(forg, fdest, sapex(backtracksh), sapex(spinsh));
09268 if (iscoplanar(forg, fdest, sapex(backtracksh), sapex(spinsh), ori,
09269 b->epsilon)) {
09270
09271 *searchsh = spinsh;
09272 break;
09273 }
09274 } while (spinsh.sh != backtracksh.sh);
09275 } else {
09276 spivot(backtracksh, *searchsh);
09277 }
09278
09279 if ((searchsh->sh == dummysh) || (searchsh->sh == backtracksh.sh)) {
09280
09281 *searchsh = backtracksh;
09282 return OUTSIDE;
09283 }
09284
09285 if (sorg(*searchsh) != forg) sesymself(*searchsh);
09286 #ifdef SELF_CHECK
09287 assert((sorg(*searchsh) == forg) && (sdest(*searchsh) == fdest));
09288 #endif
09289 }
09290 }
09291
09293
09294
09295
09296
09297
09298
09299
09300
09301
09302
09303
09304
09305
09306
09307
09308
09309
09310
09311
09312
09313
09315
09316 enum tetgenmesh::locateresult tetgenmesh::
09317 adjustlocatesub(point searchpt, face* searchsh, enum locateresult precise,
09318 REAL epspp)
09319 {
09320 point pa, pb, pc;
09321 bool s1, s2, s3;
09322
09323 pa = sorg(*searchsh);
09324 pb = sdest(*searchsh);
09325 pc = sapex(*searchsh);
09326
09327 if (precise == ONEDGE) {
09328 s1 = true;
09329 } else {
09330 s1 = iscollinear(pa, pb, searchpt, epspp);
09331 }
09332 s2 = iscollinear(pb, pc, searchpt, epspp);
09333 s3 = iscollinear(pc, pa, searchpt, epspp);
09334 if (s1) {
09335 if (s2) {
09336
09337 #ifdef SELF_CHECK
09338 assert(!s3);
09339 #endif
09340 senextself(*searchsh);
09341 return ONVERTEX;
09342 } else if (s3) {
09343
09344 return ONVERTEX;
09345 } else {
09346
09347 return ONEDGE;
09348 }
09349 } else if (s2) {
09350 if (s3) {
09351
09352 senext2self(*searchsh);
09353 return ONVERTEX;
09354 } else {
09355
09356 senextself(*searchsh);
09357 return ONEDGE;
09358 }
09359 } else if (s3) {
09360
09361 senext2self(*searchsh);
09362 return ONEDGE;
09363 } else {
09364 return precise;
09365 }
09366 }
09367
09369
09370
09371
09372
09373
09374
09375
09376
09377
09378
09379
09380
09382
09383 enum tetgenmesh::locateresult tetgenmesh::
09384 locateseg(point searchpt, face* searchseg)
09385 {
09386 face backtraceseg;
09387 point pa, pb;
09388 REAL dx, dy, dz;
09389 int moveleft;
09390 int i;
09391
09392 moveleft = 0;
09393 while (1) {
09394 searchseg->shver = 0;
09395 pa = sorg(*searchseg);
09396 pb = sdest(*searchseg);
09397
09398 dx = fabs(pb[0] - pa[0]);
09399 dy = fabs(pb[1] - pa[1]);
09400 dz = fabs(pb[2] - pa[2]);
09401 if (dx > dy) {
09402 if (dx > dz) {
09403 i = 0;
09404 } else {
09405 i = 2;
09406 }
09407 } else {
09408 if (dy > dz) {
09409 i = 1;
09410 } else {
09411 i = 2;
09412 }
09413 }
09414 if (pa[i] < pb[i]) {
09415 if (searchpt[i] < pa[i]) {
09416 moveleft = 1;
09417 } else if (searchpt[i] > pa[i]) {
09418 if (searchpt[i] < pb[i]) {
09419 return ONEDGE;
09420 } else if (searchpt[i] > pb[i]) {
09421 moveleft = 0;
09422 } else {
09423 #ifdef SELF_CHECK
09424 assert(searchpt[i] == pb[i]);
09425 #endif
09426 sesymself(*searchseg);
09427 return ONVERTEX;
09428 }
09429 } else {
09430 #ifdef SELF_CHECK
09431 assert(searchpt[i] == pa[i]);
09432 #endif
09433 return ONVERTEX;
09434 }
09435 } else if (pa[i] > pb[i]) {
09436 if (searchpt[i] < pb[i]) {
09437 moveleft = 0;
09438 } else if (searchpt[i] > pb[i]) {
09439 if (searchpt[i] < pa[i]) {
09440 return ONEDGE;
09441 } else if (searchpt[i] > pa[i]) {
09442 moveleft = 1;
09443 } else {
09444 #ifdef SELF_CHECK
09445 assert(searchpt[i] == pa[i]);
09446 #endif
09447 return ONVERTEX;
09448 }
09449 } else {
09450 #ifdef SELF_CHECK
09451 assert(searchpt[i] == pb[i]);
09452 #endif
09453 sesymself(*searchseg);
09454 return ONVERTEX;
09455 }
09456 }
09457 backtraceseg = *searchseg;
09458 if (moveleft) {
09459 senext2self(*searchseg);
09460 } else {
09461 senextself(*searchseg);
09462 }
09463 spivotself(*searchseg);
09464 if (searchseg->sh == dummysh) {
09465 *searchseg = backtraceseg;
09466 break;
09467 }
09468 }
09469
09470 return OUTSIDE;
09471 }
09472
09474
09475
09476
09477
09478
09479
09480
09482
09483 enum tetgenmesh::locateresult tetgenmesh::
09484 adjustlocateseg(point searchpt, face* searchseg, enum locateresult precise,
09485 REAL epspp)
09486 {
09487 point pa, pb;
09488 REAL L, d, r;
09489
09490 pa = sorg(*searchseg);
09491 pb = sdest(*searchseg);
09492 L = distance(pa, pb);
09493
09494
09495 d = distance(pa, searchpt);
09496 r = d / L;
09497 if (r <= epspp) {
09498 return ONVERTEX;
09499 }
09500
09501 d = distance(pb, searchpt);
09502 r = d / L;
09503 if (r <= epspp) {
09504 sesymself(*searchseg);
09505 return ONVERTEX;
09506 }
09507
09508 return precise;
09509 }
09510
09511
09512
09513
09514
09515
09516
09517
09518
09520
09521
09522
09523
09524
09525
09526
09527
09528
09529
09530
09531
09532
09533
09534
09535
09536
09537
09538
09539
09540
09541
09542
09543
09544
09545
09546
09547
09548
09549
09551
09553
09554
09555
09556
09557
09558
09559
09560
09561
09562
09563
09564
09565
09566
09567
09568
09569
09570
09571
09572
09573
09574
09575
09576
09577
09578
09579
09580
09582
09583 enum tetgenmesh::fliptype tetgenmesh::categorizeface(triface& horiz)
09584 {
09585 triface symhoriz, casing;
09586 face checksh, checkseg;
09587 face cassh1, cassh2;
09588 point pa, pb, pc, pd, pe, pf, pg;
09589 point abdoppo, bcdoppo, cadoppo;
09590 REAL ori1, ori2, ori3;
09591 int adjtet;
09592
09593 sym(horiz, symhoriz);
09594 if (symhoriz.tet == dummytet) {
09595
09596 return N40;
09597 }
09598
09599 adjustedgering(horiz, CCW);
09600 findedge(&symhoriz, dest(horiz), org(horiz));
09601 pa = org(horiz);
09602 pb = dest(horiz);
09603 pc = apex(horiz);
09604 pd = oppo(horiz);
09605 pe = oppo(symhoriz);
09606
09607
09608
09609 abdoppo = bcdoppo = cadoppo = (point) NULL;
09610 adjtet = 0;
09611 fnext(horiz, casing);
09612 symself(casing);
09613 if (casing.tet != dummytet) {
09614 abdoppo = oppo(casing);
09615 if (abdoppo == pe) adjtet++;
09616 }
09617 enextfnext(horiz, casing);
09618 symself(casing);
09619 if (casing.tet != dummytet) {
09620 bcdoppo = oppo(casing);
09621 if (bcdoppo == pe) adjtet++;
09622 }
09623 enext2fnext(horiz, casing);
09624 symself(casing);
09625 if (casing.tet != dummytet) {
09626 cadoppo = oppo(casing);
09627 if (cadoppo == pe) adjtet++;
09628 }
09629
09630 if (adjtet == 0) {
09631
09632 ori1 = orient3d(pa, pb, pd, pe);
09633 if (checksubfaces && ori1 != 0.0) {
09634
09635 fnext(horiz, casing);
09636 tspivot(casing, cassh1);
09637 fnext(symhoriz, casing);
09638 tspivot(casing, cassh2);
09639 if ((cassh1.sh != dummysh) && (cassh2.sh != dummysh)) {
09640
09641 findedge(&cassh1, pa, pb);
09642 sspivot(cassh1, checkseg);
09643 if (checkseg.sh == dummysh) {
09644
09645
09646 ori1 = 0.0;
09647 } else {
09648
09649
09650
09651
09652
09653 if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09654 }
09655 } else {
09656
09657
09658 if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon)) ori1 = 0.0;
09659 }
09660 }
09661 if (ori1 < 0.0) {
09662
09663 #ifdef SELF_CHECK
09664 if (!nonconvex) {
09665
09666 fnext(horiz, casing);
09667 symself(casing);
09668 assert(casing.tet != dummytet);
09669 fnext(symhoriz, casing);
09670 symself(casing);
09671 assert(casing.tet != dummytet);
09672 }
09673 #endif
09674 if (checksubfaces) {
09675
09676 tsspivot(&horiz, &checkseg);
09677 if (checkseg.sh != dummysh) {
09678 return FORBIDDENEDGE;
09679 }
09680 }
09681 return N32;
09682 }
09683 ori2 = orient3d(pb, pc, pd, pe);
09684 if (checksubfaces && ori2 != 0.0) {
09685
09686 enextfnext(horiz, casing);
09687 tspivot(casing, cassh1);
09688 enext2fnext(symhoriz, casing);
09689 tspivot(casing, cassh2);
09690 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09691
09692 findedge(&cassh1, pb, pc);
09693 sspivot(cassh1, checkseg);
09694 if (checkseg.sh == dummysh) {
09695
09696
09697 ori2 = 0.0;
09698 } else {
09699 if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09700 }
09701 } else {
09702
09703
09704 if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon)) ori2 = 0.0;
09705 }
09706 }
09707 if (ori2 < 0.0) {
09708
09709 #ifdef SELF_CHECK
09710 if (!nonconvex) {
09711
09712 enextfnext(horiz, casing);
09713 symself(casing);
09714 assert(casing.tet != dummytet);
09715 enext2fnext(symhoriz, casing);
09716 symself(casing);
09717 assert(casing.tet != dummytet);
09718 }
09719 #endif
09720 enextself(horiz);
09721 if (checksubfaces) {
09722
09723 tsspivot(&horiz, &checkseg);
09724 if (checkseg.sh != dummysh) {
09725 return FORBIDDENEDGE;
09726 }
09727 }
09728 return N32;
09729 }
09730 ori3 = orient3d(pc, pa, pd, pe);
09731 if (checksubfaces && ori3 != 0.0) {
09732
09733 enext2fnext(horiz, casing);
09734 tspivot(casing, cassh1);
09735 enextfnext(symhoriz, casing);
09736 tspivot(casing, cassh2);
09737 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09738
09739 findedge(&cassh1, pc, pa);
09740 sspivot(cassh1, checkseg);
09741 if (checkseg.sh == dummysh) {
09742
09743
09744 ori3 = 0.0;
09745 } else {
09746
09747
09748
09749 if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon * 1e+2)) ori3 = 0.0;
09750 }
09751 } else {
09752
09753
09754 if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon)) ori3 = 0.0;
09755 }
09756 }
09757 if (ori3 < 0.0) {
09758
09759 #ifdef SELF_CHECK
09760 if (!nonconvex) {
09761
09762 enext2fnext(horiz, casing);
09763 symself(casing);
09764 assert(casing.tet != dummytet);
09765 enextfnext(symhoriz, casing);
09766 symself(casing);
09767 assert(casing.tet != dummytet);
09768 }
09769 #endif
09770 enext2self(horiz);
09771 if (checksubfaces) {
09772
09773 tsspivot(&horiz, &checkseg);
09774 if (checkseg.sh != dummysh) {
09775 return FORBIDDENEDGE;
09776 }
09777 }
09778 return N32;
09779 }
09780 if (ori1 == 0.0) {
09781
09782 if (ori2 * ori3 == 0.0) {
09783
09784
09785
09786
09787 return N40;
09788 }
09789 } else if (ori2 == 0.0) {
09790
09791 if (ori1 * ori3 == 0.0) {
09792
09793
09794
09795
09796 return N40;
09797 }
09798
09799 enextself(horiz);
09800 enext2self(symhoriz);
09801 } else if (ori3 == 0.0) {
09802
09803 if (ori1 * ori2 == 0.0) {
09804
09805
09806
09807
09808 return N40;
09809 }
09810
09811 enext2self(horiz);
09812 enextself(symhoriz);
09813 } else {
09814
09815 if (checksubfaces) {
09816 tspivot(horiz, checksh);
09817 if (checksh.sh != dummysh) {
09818
09819 return FORBIDDENFACE;
09820 }
09821 }
09822 return T23;
09823 }
09824
09825 if (checksubfaces) {
09826 tsspivot(&horiz, &checkseg);
09827 if (checkseg.sh != dummysh) {
09828
09829 return FORBIDDENEDGE;
09830 }
09831 tspivot(horiz, checksh);
09832 if (checksh.sh != dummysh) {
09833
09834 return FORBIDDENFACE;
09835 }
09836 }
09837
09838
09839
09840
09841 pf = pg = (point) NULL;
09842 fnext(horiz, casing);
09843 symself(casing);
09844 if (casing.tet != dummytet) {
09845 pf = oppo(casing);
09846 }
09847 fnext(symhoriz, casing);
09848 symself(casing);
09849 if (casing.tet != dummytet) {
09850 pg = oppo(casing);
09851 }
09852 if (pf == pg) {
09853
09854 if (checksubfaces) {
09855
09856 pa = org(horiz);
09857 pb = dest(horiz);
09858 pc = apex(horiz);
09859
09860 ori1 = orient3d(pc, pd, pe, pa);
09861 if (ori1 <= 0) return N40;
09862 ori1 = orient3d(pd, pc, pe, pb);
09863 if (ori1 <= 0) return N40;
09864 if (pf != (point) NULL) {
09865 ori1 = orient3d(pd, pf, pe, pa);
09866 if (ori1 <= 0) return N40;
09867 ori1 = orient3d(pf, pd, pe, pb);
09868 if (ori1 <= 0) return N40;
09869 }
09870 }
09871 if (pf == (point) NULL) {
09872
09873 return T22;
09874 } else {
09875
09876 #ifdef SELF_CHECK
09877 assert(pf != (point) NULL);
09878 #endif
09879 return T44;
09880 }
09881 } else {
09882
09883 return N32;
09884 }
09885 } else if (adjtet == 1) {
09886
09887
09888 if (bcdoppo == pe) {
09889
09890 enextself(horiz);
09891 enext2self(symhoriz);
09892 pa = org(horiz);
09893 pb = dest(horiz);
09894 pc = apex(horiz);
09895 } else if (cadoppo == pe) {
09896
09897 enext2self(horiz);
09898 enextself(symhoriz);
09899 pa = org(horiz);
09900 pb = dest(horiz);
09901 pc = apex(horiz);
09902 } else {
09903
09904 #ifdef SELF_CHECK
09905 assert(abdoppo == pe);
09906 #endif
09907 }
09908
09909 ori1 = orient3d(pc, pd, pe, pa);
09910 if (checksubfaces && ori1 != 0.0) {
09911
09912 enext2fnext(horiz, casing);
09913 tspivot(casing, cassh1);
09914 enextfnext(symhoriz, casing);
09915 tspivot(casing, cassh2);
09916 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09917
09918 findedge(&cassh1, pc, pa);
09919 sspivot(cassh1, checkseg);
09920 if (checkseg.sh == dummysh) {
09921
09922
09923 ori1 = 0.0;
09924 } else {
09925
09926
09927
09928
09929 if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
09930 }
09931 } else {
09932
09933 if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon)) ori1 = 0.0;
09934 }
09935 }
09936 if (ori1 <= 0.0) {
09937
09938 return N40;
09939 }
09940 ori2 = orient3d(pd, pc, pe, pb);
09941 if (checksubfaces && ori2 != 0.0) {
09942
09943 enextfnext(horiz, casing);
09944 tspivot(casing, cassh1);
09945 enext2fnext(symhoriz, casing);
09946 tspivot(casing, cassh2);
09947 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
09948
09949 findedge(&cassh1, pb, pc);
09950 sspivot(cassh1, checkseg);
09951 if (checkseg.sh == dummysh) {
09952
09953
09954 ori2 = 0.0;
09955 } else {
09956
09957
09958
09959
09960 if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
09961 }
09962 } else {
09963
09964 if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon)) ori2 = 0.0;
09965 }
09966 }
09967 if (ori2 <= 0.0) {
09968
09969 return N40;
09970 }
09971
09972 if (checksubfaces) {
09973
09974
09975 tsspivot(&horiz, &checkseg);
09976 if (checkseg.sh != dummysh) {
09977
09978 return FORBIDDENEDGE;
09979 }
09980
09981
09982
09983
09984 fnext(horiz, casing);
09985 tspivot(casing, cassh1);
09986 fnext(symhoriz, casing);
09987 tspivot(casing, cassh2);
09988 if (cassh1.sh != dummysh || cassh2.sh != dummysh) {
09989 if (!b->quiet) {
09990
09991 printf("Warning: A tetrahedron spans two subfaces of a facet.\n");
09992 }
09993
09994 return N32;
09995 }
09996 }
09997 return T32;
09998 } else {
09999
10000
10001 return N40;
10002 }
10003 }
10004
10006
10007
10008
10009
10010
10011
10012
10013
10015
10016 void tetgenmesh::enqueueflipface(triface& checkface, queue* flipqueue)
10017 {
10018 badface *queface;
10019 triface symface;
10020
10021 sym(checkface, symface);
10022 if (symface.tet != dummytet) {
10023 queface = (badface *) flipqueue->push((void *) NULL);
10024 queface->tt = checkface;
10025 queface->foppo = oppo(symface);
10026 }
10027 }
10028
10029 void tetgenmesh::enqueueflipedge(face& checkedge, queue* flipqueue)
10030 {
10031 badface *queface;
10032
10033 queface = (badface *) flipqueue->push((void *) NULL);
10034 queface->ss = checkedge;
10035 queface->forg = sorg(checkedge);
10036 queface->fdest = sdest(checkedge);
10037 }
10038
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049
10050
10051
10052
10054
10055 void tetgenmesh::flip23(triface* flipface, queue* flipqueue)
10056 {
10057 triface abcd, bace;
10058 triface oldabd, oldbcd, oldcad;
10059 triface abdcasing, bcdcasing, cadcasing;
10060 triface oldbae, oldcbe, oldace;
10061 triface baecasing, cbecasing, acecasing;
10062 triface worktet;
10063 face abdsh, bcdsh, cadsh;
10064 face baesh, cbesh, acesh;
10065 face abseg, bcseg, caseg;
10066 face adseg, bdseg, cdseg;
10067 face aeseg, beseg, ceseg;
10068 triface edab, edbc, edca;
10069 point pa, pb, pc, pd, pe;
10070 REAL attrib, volume;
10071 int i;
10072
10073 abcd = *flipface;
10074 adjustedgering(abcd, CCW);
10075 pa = org(abcd);
10076 pb = dest(abcd);
10077 pc = apex(abcd);
10078 pd = oppo(abcd);
10079
10080
10081 sym(abcd, bace);
10082 bace.ver = 0;
10083 for (i = 0; (i < 3) && (org(bace) != pb); i++) {
10084 enextself(bace);
10085 }
10086 pe = oppo(bace);
10087
10088 if (b->verbose > 2) {
10089 printf(" Do T23 on face (%d, %d, %d) %d, %d.\n", pointmark(pa),
10090 pointmark(pb), pointmark(pc), pointmark(pd), pointmark(pe));
10091 }
10092 flip23s++;
10093
10094
10095 fnext(abcd, oldabd);
10096 enextfnext(abcd, oldbcd);
10097 enext2fnext(abcd, oldcad);
10098 fnext(bace, oldbae);
10099 enext2fnext(bace, oldcbe);
10100 enextfnext(bace, oldace);
10101 sym(oldabd, abdcasing);
10102 sym(oldbcd, bcdcasing);
10103 sym(oldcad, cadcasing);
10104 sym(oldbae, baecasing);
10105 sym(oldcbe, cbecasing);
10106 sym(oldace, acecasing);
10107 if (checksubfaces) {
10108 tspivot(oldabd, abdsh);
10109 tspivot(oldbcd, bcdsh);
10110 tspivot(oldcad, cadsh);
10111 tspivot(oldbae, baesh);
10112 tspivot(oldcbe, cbesh);
10113 tspivot(oldace, acesh);
10114 } else if (checksubsegs) {
10115 tsspivot1(abcd, abseg);
10116 enext(abcd, worktet);
10117 tsspivot1(worktet, bcseg);
10118 enext2(abcd, worktet);
10119 tsspivot1(worktet, caseg);
10120 enext2(oldabd, worktet);
10121 tsspivot1(worktet, adseg);
10122 enext2(oldbcd, worktet);
10123 tsspivot1(worktet, bdseg);
10124 enext2(oldcad, worktet);
10125 tsspivot1(worktet, cdseg);
10126 enext(oldbae, worktet);
10127 tsspivot1(worktet, aeseg);
10128 enext(oldcbe, worktet);
10129 tsspivot1(worktet, beseg);
10130 enext(oldace, worktet);
10131 tsspivot1(worktet, ceseg);
10132 }
10133
10134
10135 edab.tet = abcd.tet;
10136 setorg (edab, pe);
10137 setdest(edab, pd);
10138 setapex(edab, pa);
10139 setoppo(edab, pb);
10140 edbc.tet = bace.tet;
10141 setorg (edbc, pe);
10142 setdest(edbc, pd);
10143 setapex(edbc, pb);
10144 setoppo(edbc, pc);
10145 maketetrahedron(&edca);
10146 setorg (edca, pe);
10147 setdest(edca, pd);
10148 setapex(edca, pc);
10149 setoppo(edca, pa);
10150
10151 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
10152 attrib = elemattribute(abcd.tet, i);
10153 setelemattribute(edca.tet, i, attrib);
10154 }
10155
10156
10157
10158 if (b->varvolume && !b->refine) {
10159 volume = volumebound(abcd.tet);
10160 setvolumebound(edca.tet, volume);
10161 }
10162
10163
10164 for (i = 0; i < 4; i ++) {
10165 edab.tet[i] = (tetrahedron) dummytet;
10166 }
10167 for (i = 0; i < 4; i ++) {
10168 edbc.tet[i] = (tetrahedron) dummytet;
10169 }
10170
10171 edab.loc = 0;
10172 edca.loc = 1;
10173 bond(edab, edca);
10174 edab.loc = 1;
10175 edbc.loc = 0;
10176 bond(edab, edbc);
10177 edbc.loc = 1;
10178 edca.loc = 0;
10179 bond(edbc, edca);
10180
10181 edab.loc = 2;
10182 bond(edab, abdcasing);
10183 edab.loc = 3;
10184 bond(edab, baecasing);
10185 edbc.loc = 2;
10186 bond(edbc, bcdcasing);
10187 edbc.loc = 3;
10188 bond(edbc, cbecasing);
10189 edca.loc = 2;
10190 bond(edca, cadcasing);
10191 edca.loc = 3;
10192 bond(edca, acecasing);
10193
10194 if (checksubfaces) {
10195
10196 for (i = 0; i < 4; i ++) {
10197 edab.loc = i;
10198 tsdissolve(edab);
10199 edbc.loc = i;
10200 tsdissolve(edbc);
10201 }
10202 if (abdsh.sh != dummysh) {
10203 edab.loc = 2;
10204 tsbond(edab, abdsh);
10205 }
10206 if (baesh.sh != dummysh) {
10207 edab.loc = 3;
10208 tsbond(edab, baesh);
10209 }
10210 if (bcdsh.sh != dummysh) {
10211 edbc.loc = 2;
10212 tsbond(edbc, bcdsh);
10213 }
10214 if (cbesh.sh != dummysh) {
10215 edbc.loc = 3;
10216 tsbond(edbc, cbesh);
10217 }
10218 if (cadsh.sh != dummysh) {
10219 edca.loc = 2;
10220 tsbond(edca, cadsh);
10221 }
10222 if (acesh.sh != dummysh) {
10223 edca.loc = 3;
10224 tsbond(edca, acesh);
10225 }
10226 } else if (checksubsegs) {
10227 for (i = 0; i < 6; i++) {
10228 edab.tet[8 + i] = (tetrahedron) dummysh;
10229 }
10230 for (i = 0; i < 6; i++) {
10231 edbc.tet[8 + i] = (tetrahedron) dummysh;
10232 }
10233 edab.loc = edab.ver = 0;
10234 edbc.loc = edab.ver = 0;
10235 edca.loc = edab.ver = 0;
10236
10237 enext(edab, worktet);
10238 tssbond1(worktet, adseg);
10239 enext2(edab, worktet);
10240 tssbond1(worktet, aeseg);
10241 fnext(edab, worktet);
10242 enextself(worktet);
10243 tssbond1(worktet, bdseg);
10244 enextself(worktet);
10245 tssbond1(worktet, beseg);
10246 enextfnext(edab, worktet);
10247 enextself(worktet);
10248 tssbond1(worktet, abseg);
10249
10250 enext(edbc, worktet);
10251 tssbond1(worktet, bdseg);
10252 enext2(edbc, worktet);
10253 tssbond1(worktet, beseg);
10254 fnext(edbc, worktet);
10255 enextself(worktet);
10256 tssbond1(worktet, cdseg);
10257 enextself(worktet);
10258 tssbond1(worktet, ceseg);
10259 enextfnext(edbc, worktet);
10260 enextself(worktet);
10261 tssbond1(worktet, bcseg);
10262
10263 enext(edca, worktet);
10264 tssbond1(worktet, cdseg);
10265 enext2(edca, worktet);
10266 tssbond1(worktet, ceseg);
10267 fnext(edca, worktet);
10268 enextself(worktet);
10269 tssbond1(worktet, adseg);
10270 enextself(worktet);
10271 tssbond1(worktet, aeseg);
10272 enextfnext(edca, worktet);
10273 enextself(worktet);
10274 tssbond1(worktet, caseg);
10275 }
10276
10277 edab.loc = 0;
10278 edbc.loc = 0;
10279 edca.loc = 0;
10280 if (b->verbose > 3) {
10281 printf(" Updating edab ");
10282 printtet(&edab);
10283 printf(" Updating edbc ");
10284 printtet(&edbc);
10285 printf(" Creating edca ");
10286 printtet(&edca);
10287 }
10288
10289 if (flipqueue != (queue *) NULL) {
10290 enextfnext(edab, abdcasing);
10291 enqueueflipface(abdcasing, flipqueue);
10292 enext2fnext(edab, baecasing);
10293 enqueueflipface(baecasing, flipqueue);
10294 enextfnext(edbc, bcdcasing);
10295 enqueueflipface(bcdcasing, flipqueue);
10296 enext2fnext(edbc, cbecasing);
10297 enqueueflipface(cbecasing, flipqueue);
10298 enextfnext(edca, cadcasing);
10299 enqueueflipface(cadcasing, flipqueue);
10300 enext2fnext(edca, acecasing);
10301 enqueueflipface(acecasing, flipqueue);
10302 }
10303
10304
10305 recenttet = edbc;
10306
10307 *flipface = edab;
10308 }
10309
10311
10312
10313
10314
10315
10316
10317
10318
10319
10320
10321
10322
10323
10324
10326
10327 void tetgenmesh::flip32(triface* flipface, queue* flipqueue)
10328 {
10329 triface edab, edbc, edca;
10330 triface oldabd, oldbcd, oldcad;
10331 triface abdcasing, bcdcasing, cadcasing;
10332 triface oldbae, oldcbe, oldace;
10333 triface baecasing, cbecasing, acecasing;
10334 triface worktet;
10335 face abdsh, bcdsh, cadsh;
10336 face baesh, cbesh, acesh;
10337 face abseg, bcseg, caseg;
10338 face adseg, bdseg, cdseg;
10339 face aeseg, beseg, ceseg;
10340 triface abcd, bace;
10341 point pa, pb, pc, pd, pe;
10342 int i;
10343
10344 edab = *flipface;
10345 adjustedgering(edab, CCW);
10346 pa = apex(edab);
10347 pb = oppo(edab);
10348 pd = dest(edab);
10349 pe = org(edab);
10350 fnext(edab, edbc);
10351 symself(edbc);
10352 edbc.ver = 0;
10353 for (i = 0; (i < 3) && (org(edbc) != pe); i++) {
10354 enextself(edbc);
10355 }
10356 pc = oppo(edbc);
10357 fnext(edbc, edca);
10358 symself(edca);
10359 edca.ver = 0;
10360 for (i = 0; (i < 3) && (org(edca) != pe); i++) {
10361 enextself(edca);
10362 }
10363
10364 if (b->verbose > 2) {
10365 printf(" Do T32 on edge (%d, %d) %d, %d, %d.\n", pointmark(pe),
10366 pointmark(pd), pointmark(pa), pointmark(pb), pointmark(pc));
10367 }
10368 flip32s++;
10369
10370
10371 enextfnext(edab, oldabd);
10372 enext2fnext(edab, oldbae);
10373 enextfnext(edbc, oldbcd);
10374 enext2fnext(edbc, oldcbe);
10375 enextfnext(edca, oldcad);
10376 enext2fnext(edca, oldace);
10377 sym(oldabd, abdcasing);
10378 sym(oldbcd, bcdcasing);
10379 sym(oldcad, cadcasing);
10380 sym(oldbae, baecasing);
10381 sym(oldcbe, cbecasing);
10382 sym(oldace, acecasing);
10383 if (checksubfaces) {
10384 tspivot(oldabd, abdsh);
10385 tspivot(oldbcd, bcdsh);
10386 tspivot(oldcad, cadsh);
10387 tspivot(oldbae, baesh);
10388 tspivot(oldcbe, cbesh);
10389 tspivot(oldace, acesh);
10390 } else if (checksubsegs) {
10391 enext(edab, worktet);
10392 tsspivot1(worktet, adseg);
10393 enext2(edab, worktet);
10394 tsspivot1(worktet, aeseg);
10395 enext(edbc, worktet);
10396 tsspivot1(worktet, bdseg);
10397 enext2(edbc, worktet);
10398 tsspivot1(worktet, beseg);
10399 enext(edca, worktet);
10400 tsspivot1(worktet, cdseg);
10401 enext2(edca, worktet);
10402 tsspivot1(worktet, ceseg);
10403 enextfnext(edab, worktet);
10404 enextself(worktet);
10405 tsspivot1(worktet, abseg);
10406 enextfnext(edbc, worktet);
10407 enextself(worktet);
10408 tsspivot1(worktet, bcseg);
10409 enextfnext(edca, worktet);
10410 enextself(worktet);
10411 tsspivot1(worktet, caseg);
10412 }
10413
10414
10415 abcd.tet = edab.tet;
10416 setorg (abcd, pa);
10417 setdest(abcd, pb);
10418 setapex(abcd, pc);
10419 setoppo(abcd, pd);
10420 bace.tet = edbc.tet;
10421 setorg (bace, pb);
10422 setdest(bace, pa);
10423 setapex(bace, pc);
10424 setoppo(bace, pe);
10425
10426 tetrahedrondealloc(edca.tet);
10427
10428
10429 for (i = 0; i < 4; i ++) {
10430 abcd.tet[i] = (tetrahedron) dummytet;
10431 }
10432 for (i = 0; i < 4; i ++) {
10433 bace.tet[i] = (tetrahedron) dummytet;
10434 }
10435
10436 abcd.loc = 0;
10437 bace.loc = 0;
10438 bond(abcd, bace);
10439
10440 abcd.loc = 1;
10441 bond(abcd, abdcasing);
10442 abcd.loc = 2;
10443 bond(abcd, bcdcasing);
10444 abcd.loc = 3;
10445 bond(abcd, cadcasing);
10446 bace.loc = 1;
10447 bond(bace, baecasing);
10448 bace.loc = 3;
10449 bond(bace, cbecasing);
10450 bace.loc = 2;
10451 bond(bace, acecasing);
10452 if (checksubfaces) {
10453
10454 for (i = 0; i < 4; i ++) {
10455 abcd.tet[8 + i] = (tetrahedron) dummysh;
10456 }
10457 for (i = 0; i < 4; i ++) {
10458 bace.tet[8 + i] = (tetrahedron) dummysh;
10459 }
10460 if (abdsh.sh != dummysh) {
10461 abcd.loc = 1;
10462 tsbond(abcd, abdsh);
10463 }
10464 if (bcdsh.sh != dummysh) {
10465 abcd.loc = 2;
10466 tsbond(abcd, bcdsh);
10467 }
10468 if (cadsh.sh != dummysh) {
10469 abcd.loc = 3;
10470 tsbond(abcd, cadsh);
10471 }
10472 if (baesh.sh != dummysh) {
10473 bace.loc = 1;
10474 tsbond(bace, baesh);
10475 }
10476 if (cbesh.sh != dummysh) {
10477 bace.loc = 3;
10478 tsbond(bace, cbesh);
10479 }
10480 if (acesh.sh != dummysh) {
10481 bace.loc = 2;
10482 tsbond(bace, acesh);
10483 }
10484 } else if (checksubsegs) {
10485 for (i = 0; i < 6; i++) {
10486 abcd.tet[8 + i] = (tetrahedron) dummysh;
10487 }
10488 for (i = 0; i < 6; i++) {
10489 bace.tet[8 + i] = (tetrahedron) dummysh;
10490 }
10491 abcd.loc = abcd.ver = 0;
10492 bace.loc = bace.ver = 0;
10493 tssbond1(abcd, abseg);
10494 enext(abcd, worktet);
10495 tssbond1(worktet, bcseg);
10496 enext2(abcd, worktet);
10497 tssbond1(worktet, caseg);
10498 fnext(abcd, worktet);
10499 enext2self(worktet);
10500 tssbond1(worktet, adseg);
10501 enextfnext(abcd, worktet);
10502 enext2self(worktet);
10503 tssbond1(worktet, bdseg);
10504 enext2fnext(abcd, worktet);
10505 enext2self(worktet);
10506 tssbond1(worktet, cdseg);
10507 tssbond1(bace, abseg);
10508 enext2(bace, worktet);
10509 tssbond1(worktet, bcseg);
10510 enext(bace, worktet);
10511 tssbond1(worktet, caseg);
10512 fnext(bace, worktet);
10513 enextself(worktet);
10514 tssbond1(worktet, aeseg);
10515 enext2fnext(bace, worktet);
10516 enextself(worktet);
10517 tssbond1(worktet, beseg);
10518 enextfnext(bace, worktet);
10519 enextself(worktet);
10520 tssbond1(worktet, ceseg);
10521 }
10522
10523 abcd.loc = 0;
10524 bace.loc = 0;
10525 if (b->verbose > 3) {
10526 printf(" Updating abcd ");
10527 printtet(&abcd);
10528 printf(" Updating bace ");
10529 printtet(&bace);
10530 printf(" Deleting edca ");
10531
10532 }
10533
10534 if (flipqueue != (queue *) NULL) {
10535 fnext(abcd, abdcasing);
10536 enqueueflipface(abdcasing, flipqueue);
10537 fnext(bace, baecasing);
10538 enqueueflipface(baecasing, flipqueue);
10539 enextfnext(abcd, bcdcasing);
10540 enqueueflipface(bcdcasing, flipqueue);
10541 enextfnext(bace, cbecasing);
10542 enqueueflipface(cbecasing, flipqueue);
10543 enext2fnext(abcd, cadcasing);
10544 enqueueflipface(cadcasing, flipqueue);
10545 enext2fnext(bace, acecasing);
10546 enqueueflipface(acecasing, flipqueue);
10547 }
10548
10549
10550 recenttet = abcd;
10551
10552 *flipface = abcd;
10553 }
10554
10556
10557
10558
10559
10560
10561
10562
10563
10564
10565
10566
10567
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10580
10581 void tetgenmesh::flip22(triface* flipface, queue* flipqueue)
10582 {
10583 triface abce, bade;
10584 triface oldbce, oldcae, oldade, olddbe;
10585 triface bcecasing, caecasing, adecasing, dbecasing;
10586 face bcesh, caesh, adesh, dbesh;
10587 triface bacf, abdf;
10588 triface oldacf, oldcbf, oldbdf, olddaf;
10589 triface acfcasing, cbfcasing, bdfcasing, dafcasing;
10590 triface worktet;
10591 face acfsh, cbfsh, bdfsh, dafsh;
10592 face abc, bad;
10593 face adseg, dbseg, bcseg, caseg;
10594 face aeseg, deseg, beseg, ceseg;
10595 face afseg, dfseg, bfseg, cfseg;
10596 point pa, pb, pc, pd;
10597 #ifdef SELF_CHECK
10598 point pe, pf;
10599 #endif
10600 int mirrorflag, i;
10601
10602 adjustedgering(*flipface, CCW);
10603 fnext(*flipface, abce);
10604 esymself(abce);
10605 adjustedgering(*flipface, CW);
10606 fnext(*flipface, bade);
10607 #ifdef SELF_CHECK
10608 assert(bade.tet != dummytet);
10609 #endif
10610 esymself(bade);
10611 pa = org(abce);
10612 pb = dest(abce);
10613 pc = apex(abce);
10614 pd = apex(bade);
10615 #ifdef SELF_CHECK
10616 pe = oppo(bade);
10617 assert(oppo(abce) == pe);
10618 #endif
10619 sym(abce, bacf);
10620 mirrorflag = bacf.tet != dummytet;
10621 if (mirrorflag) {
10622
10623 bacf.ver = 0;
10624 for (i = 0; (i < 3) && (org(bacf) != pb); i++) {
10625 enextself(bacf);
10626 }
10627 sym(bade, abdf);
10628 #ifdef SELF_CHECK
10629 assert(abdf.tet != dummytet);
10630 #endif
10631
10632 abdf.ver = 0;
10633 for (i = 0; (i < 3) && (org(abdf) != pa); i++) {
10634 enextself(abdf);
10635 }
10636
10637 #ifdef SELF_CHECK
10638 pf = oppo(bacf);
10639 assert(oppo(abdf) == pf);
10640 #endif
10641 }
10642
10643 if (b->verbose > 2) {
10644 printf(" Do %s on edge (%d, %d).\n", mirrorflag ? "T44" : "T22",
10645 pointmark(pa), pointmark(pb));
10646 }
10647 mirrorflag ? flip44s++ : flip22s++;
10648
10649
10650 enextfnext(abce, oldbce);
10651 enext2fnext(abce, oldcae);
10652 enextfnext(bade, oldade);
10653 enext2fnext(bade, olddbe);
10654 sym(oldbce, bcecasing);
10655 sym(oldcae, caecasing);
10656 sym(oldade, adecasing);
10657 sym(olddbe, dbecasing);
10658 if (checksubfaces) {
10659 tspivot(oldbce, bcesh);
10660 tspivot(oldcae, caesh);
10661 tspivot(oldade, adesh);
10662 tspivot(olddbe, dbesh);
10663 tspivot(abce, abc);
10664 tspivot(bade, bad);
10665 } else if (checksubsegs) {
10666
10667 enext(bade, worktet);
10668 tsspivot1(worktet, adseg);
10669 enext2(bade, worktet);
10670 tsspivot1(worktet, dbseg);
10671 enext(abce, worktet);
10672 tsspivot1(worktet, bcseg);
10673 enext2(abce, worktet);
10674 tsspivot1(worktet, caseg);
10675
10676 fnext(bade, worktet);
10677 enextself(worktet);
10678 tsspivot1(worktet, aeseg);
10679 enextfnext(bade, worktet);
10680 enextself(worktet);
10681 tsspivot1(worktet, deseg);
10682 enext2fnext(bade, worktet);
10683 enextself(worktet);
10684 tsspivot1(worktet, beseg);
10685 enextfnext(abce, worktet);
10686 enextself(worktet);
10687 tsspivot1(worktet, ceseg);
10688 }
10689 if (mirrorflag) {
10690 enextfnext(bacf, oldacf);
10691 enext2fnext(bacf, oldcbf);
10692 enextfnext(abdf, oldbdf);
10693 enext2fnext(abdf, olddaf);
10694 sym(oldacf, acfcasing);
10695 sym(oldcbf, cbfcasing);
10696 sym(oldbdf, bdfcasing);
10697 sym(olddaf, dafcasing);
10698 if (checksubfaces) {
10699 tspivot(oldacf, acfsh);
10700 tspivot(oldcbf, cbfsh);
10701 tspivot(oldbdf, bdfsh);
10702 tspivot(olddaf, dafsh);
10703 } else if (checksubsegs) {
10704
10705 fnext(abdf, worktet);
10706 enext2self(worktet);
10707 tsspivot1(worktet, afseg);
10708 enext2fnext(abdf, worktet);
10709 enext2self(worktet);
10710 tsspivot1(worktet, dfseg);
10711 enextfnext(abdf, worktet);
10712 enext2self(worktet);
10713 tsspivot1(worktet, bfseg);
10714 enextfnext(bacf, worktet);
10715 enextself(worktet);
10716 tsspivot1(worktet, cfseg);
10717 }
10718 }
10719
10720
10721 bond(oldbce, caecasing);
10722 bond(oldcae, adecasing);
10723 bond(oldade, dbecasing);
10724 bond(olddbe, bcecasing);
10725 if (checksubfaces) {
10726
10727 if (caesh.sh == dummysh) {
10728 tsdissolve(oldbce);
10729 } else {
10730 tsbond(oldbce, caesh);
10731 }
10732 if (adesh.sh == dummysh) {
10733 tsdissolve(oldcae);
10734 } else {
10735 tsbond(oldcae, adesh);
10736 }
10737 if (dbesh.sh == dummysh) {
10738 tsdissolve(oldade);
10739 } else {
10740 tsbond(oldade, dbesh);
10741 }
10742 if (bcesh.sh == dummysh) {
10743 tsdissolve(olddbe);
10744 } else {
10745 tsbond(olddbe, bcesh);
10746 }
10747 } else if (checksubsegs) {
10748
10749 enext(abce, worktet);
10750 if (caseg.sh == dummysh) {
10751 tssdissolve1(worktet);
10752 } else {
10753 tssbond1(worktet, caseg);
10754 }
10755 enext2(abce, worktet);
10756 if (adseg.sh == dummysh) {
10757 tssdissolve1(worktet);
10758 } else {
10759 tssbond1(worktet, adseg);
10760 }
10761 fnext(abce, worktet);
10762 enextself(worktet);
10763 if (ceseg.sh == dummysh) {
10764 tssdissolve1(worktet);
10765 } else {
10766 tssbond1(worktet, ceseg);
10767 }
10768 enextfnext(abce, worktet);
10769 enextself(worktet);
10770 if (aeseg.sh == dummysh) {
10771 tssdissolve1(worktet);
10772 } else {
10773 tssbond1(worktet, aeseg);
10774 }
10775 enext2fnext(abce, worktet);
10776 enextself(worktet);
10777 if (deseg.sh == dummysh) {
10778 tssdissolve1(worktet);
10779 } else {
10780 tssbond1(worktet, deseg);
10781 }
10782
10783 enext(bade, worktet);
10784 if (dbseg.sh == dummysh) {
10785 tssdissolve1(worktet);
10786 } else {
10787 tssbond1(worktet, dbseg);
10788 }
10789 enext2(bade, worktet);
10790 if (bcseg.sh == dummysh) {
10791 tssdissolve1(worktet);
10792 } else {
10793 tssbond1(worktet, bcseg);
10794 }
10795 fnext(bade, worktet);
10796 enextself(worktet);
10797 if (deseg.sh == dummysh) {
10798 tssdissolve1(worktet);
10799 } else {
10800 tssbond1(worktet, deseg);
10801 }
10802 enextfnext(bade, worktet);
10803 enextself(worktet);
10804 if (beseg.sh == dummysh) {
10805 tssdissolve1(worktet);
10806 } else {
10807 tssbond1(worktet, beseg);
10808 }
10809 enext2fnext(bade, worktet);
10810 enextself(worktet);
10811 if (ceseg.sh == dummysh) {
10812 tssdissolve1(worktet);
10813 } else {
10814 tssbond1(worktet, ceseg);
10815 }
10816 }
10817 if (mirrorflag) {
10818
10819 bond(oldcbf, acfcasing);
10820 bond(oldacf, dafcasing);
10821 bond(olddaf, bdfcasing);
10822 bond(oldbdf, cbfcasing);
10823 if (checksubfaces) {
10824
10825 if (acfsh.sh == dummysh) {
10826 tsdissolve(oldcbf);
10827 } else {
10828 tsbond(oldcbf, acfsh);
10829 }
10830 if (dafsh.sh == dummysh) {
10831 tsdissolve(oldacf);
10832 } else {
10833 tsbond(oldacf, dafsh);
10834 }
10835 if (bdfsh.sh == dummysh) {
10836 tsdissolve(olddaf);
10837 } else {
10838 tsbond(olddaf, bdfsh);
10839 }
10840 if (cbfsh.sh == dummysh) {
10841 tsdissolve(oldbdf);
10842 } else {
10843 tsbond(oldbdf, cbfsh);
10844 }
10845 } else if (checksubsegs) {
10846
10847 enext2(bacf, worktet);
10848 if (caseg.sh == dummysh) {
10849 tssdissolve1(worktet);
10850 } else {
10851 tssbond1(worktet, caseg);
10852 }
10853 enext(bacf, worktet);
10854 if (adseg.sh == dummysh) {
10855 tssdissolve1(worktet);
10856 } else {
10857 tssbond1(worktet, adseg);
10858 }
10859 fnext(bacf, worktet);
10860 enext2self(worktet);
10861 if (cfseg.sh == dummysh) {
10862 tssdissolve1(worktet);
10863 } else {
10864 tssbond1(worktet, cfseg);
10865 }
10866 enext2fnext(bacf, worktet);
10867 enext2self(worktet);
10868 if (afseg.sh == dummysh) {
10869 tssdissolve1(worktet);
10870 } else {
10871 tssbond1(worktet, afseg);
10872 }
10873 enextfnext(bacf, worktet);
10874 enext2self(worktet);
10875 if (dfseg.sh == dummysh) {
10876 tssdissolve1(worktet);
10877 } else {
10878 tssbond1(worktet, dfseg);
10879 }
10880
10881 enext2(abdf, worktet);
10882 if (dbseg.sh == dummysh) {
10883 tssdissolve1(worktet);
10884 } else {
10885 tssbond1(worktet, dbseg);
10886 }
10887 enext(abdf, worktet);
10888 if (bcseg.sh == dummysh) {
10889 tssdissolve1(worktet);
10890 } else {
10891 tssbond1(worktet, bcseg);
10892 }
10893 fnext(abdf, worktet);
10894 enext2self(worktet);
10895 if (dfseg.sh == dummysh) {
10896 tssdissolve1(worktet);
10897 } else {
10898 tssbond1(worktet, dfseg);
10899 }
10900 enext2fnext(abdf, worktet);
10901 enext2self(worktet);
10902 if (bfseg.sh == dummysh) {
10903 tssdissolve1(worktet);
10904 } else {
10905 tssbond1(worktet, bfseg);
10906 }
10907 enextfnext(abdf, worktet);
10908 enext2self(worktet);
10909 if (cfseg.sh == dummysh) {
10910 tssdissolve1(worktet);
10911 } else {
10912 tssbond1(worktet, cfseg);
10913 }
10914 }
10915 }
10916
10917
10918 setorg(abce, pd);
10919 setdest(abce, pc);
10920 setapex(abce, pa);
10921 setorg(bade, pc);
10922 setdest(bade, pd);
10923 setapex(bade, pb);
10924 if (mirrorflag) {
10925 setorg(bacf, pc);
10926 setdest(bacf, pd);
10927 setapex(bacf, pa);
10928 setorg(abdf, pd);
10929 setdest(abdf, pc);
10930 setapex(abdf, pb);
10931 }
10932
10933
10934 if (checksubfaces && abc.sh != dummysh) {
10935 #ifdef SELF_CHECK
10936 assert(bad.sh != dummysh);
10937 #endif
10938
10939
10940 findedge(&abc, pa, pb);
10941
10942 flip22sub(&abc, NULL);
10943 }
10944
10945 if (b->verbose > 3) {
10946 printf(" Updating abce ");
10947 printtet(&abce);
10948 printf(" Updating bade ");
10949 printtet(&bade);
10950 if (mirrorflag) {
10951 printf(" Updating bacf ");
10952 printtet(&bacf);
10953 printf(" Updating abdf ");
10954 printtet(&abdf);
10955 }
10956 }
10957
10958 if (flipqueue != (queue *) NULL) {
10959 enextfnext(abce, bcecasing);
10960 enqueueflipface(bcecasing, flipqueue);
10961 enext2fnext(abce, caecasing);
10962 enqueueflipface(caecasing, flipqueue);
10963 enextfnext(bade, adecasing);
10964 enqueueflipface(adecasing, flipqueue);
10965 enext2fnext(bade, dbecasing);
10966 enqueueflipface(dbecasing, flipqueue);
10967 if (mirrorflag) {
10968 enextfnext(bacf, acfcasing);
10969 enqueueflipface(acfcasing, flipqueue);
10970 enext2fnext(bacf, cbfcasing);
10971 enqueueflipface(cbfcasing, flipqueue);
10972 enextfnext(abdf, bdfcasing);
10973 enqueueflipface(bdfcasing, flipqueue);
10974 enext2fnext(abdf, dafcasing);
10975 enqueueflipface(dafcasing, flipqueue);
10976 }
10977
10978
10979
10980
10981
10982 enqueueflipface(abce, flipqueue);
10983 enqueueflipface(bade, flipqueue);
10984 }
10985
10986
10987 recenttet = abce;
10988 }
10989
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
11001
11002
11003
11004
11005
11006
11007
11008
11009
11010
11011
11012
11013
11014
11016
11017 void tetgenmesh::flip22sub(face* flipedge, queue* flipqueue)
11018 {
11019 face abc, bad;
11020 face oldbc, oldca, oldad, olddb;
11021 face bccasin, bccasout, cacasin, cacasout;
11022 face adcasin, adcasout, dbcasin, dbcasout;
11023 face bc, ca, ad, db;
11024 face spinsh;
11025 point pa, pb, pc, pd;
11026
11027 abc = *flipedge;
11028 spivot(abc, bad);
11029 if (sorg(bad) != sdest(abc)) {
11030 sesymself(bad);
11031 }
11032 pa = sorg(abc);
11033 pb = sdest(abc);
11034 pc = sapex(abc);
11035 pd = sapex(bad);
11036
11037 if (b->verbose > 2) {
11038 printf(" Flip sub edge (%d, %d).\n", pointmark(pa), pointmark(pb));
11039 }
11040
11041
11042 senext(abc, oldbc);
11043 senext2(abc, oldca);
11044 senext(bad, oldad);
11045 senext2(bad, olddb);
11046
11047
11048
11049 spivot(oldbc, bccasout);
11050 sspivot(oldbc, bc);
11051 if (bc.sh != dummysh) {
11052
11053 if (bccasout.sh != dummysh) {
11054 if (oldbc.sh != bccasout.sh) {
11055
11056 spinsh = bccasout;
11057 do {
11058 bccasin = spinsh;
11059 spivotself(spinsh);
11060 } while (spinsh.sh != oldbc.sh);
11061 } else {
11062 bccasout.sh = dummysh;
11063 }
11064 }
11065 ssdissolve(oldbc);
11066 }
11067 spivot(oldca, cacasout);
11068 sspivot(oldca, ca);
11069 if (ca.sh != dummysh) {
11070
11071 if (cacasout.sh != dummysh) {
11072 if (oldca.sh != cacasout.sh) {
11073
11074 spinsh = cacasout;
11075 do {
11076 cacasin = spinsh;
11077 spivotself(spinsh);
11078 } while (spinsh.sh != oldca.sh);
11079 } else {
11080 cacasout.sh = dummysh;
11081 }
11082 }
11083 ssdissolve(oldca);
11084 }
11085 spivot(oldad, adcasout);
11086 sspivot(oldad, ad);
11087 if (ad.sh != dummysh) {
11088
11089 if (adcasout.sh != dummysh) {
11090 if (oldad.sh != adcasout.sh) {
11091
11092 spinsh = adcasout;
11093 do {
11094 adcasin = spinsh;
11095 spivotself(spinsh);
11096 } while (spinsh.sh != oldad.sh);
11097 } else {
11098 adcasout.sh = dummysh;
11099 }
11100 }
11101 ssdissolve(oldad);
11102 }
11103 spivot(olddb, dbcasout);
11104 sspivot(olddb, db);
11105 if (db.sh != dummysh) {
11106
11107 if (dbcasout.sh != dummysh) {
11108 if (olddb.sh != dbcasout.sh) {
11109
11110 spinsh = dbcasout;
11111 do {
11112 dbcasin = spinsh;
11113 spivotself(spinsh);
11114 } while (spinsh.sh != olddb.sh);
11115 } else {
11116 dbcasout.sh = dummysh;
11117 }
11118 }
11119 ssdissolve(olddb);
11120 }
11121
11122
11123 if (ca.sh != dummysh) {
11124 if (cacasout.sh != dummysh) {
11125 sbond1(cacasin, oldbc);
11126 sbond1(oldbc, cacasout);
11127 } else {
11128
11129 sbond(oldbc, oldbc);
11130
11131 dummysh[0] = sencode(oldbc);
11132 }
11133 ssbond(oldbc, ca);
11134 } else {
11135 sbond(oldbc, cacasout);
11136 }
11137 if (ad.sh != dummysh) {
11138 if (adcasout.sh != dummysh) {
11139 sbond1(adcasin, oldca);
11140 sbond1(oldca, adcasout);
11141 } else {
11142
11143 sbond(oldca, oldca);
11144
11145 dummysh[0] = sencode(oldca);
11146 }
11147 ssbond(oldca, ad);
11148 } else {
11149 sbond(oldca, adcasout);
11150 }
11151 if (db.sh != dummysh) {
11152 if (dbcasout.sh != dummysh) {
11153 sbond1(dbcasin, oldad);
11154 sbond1(oldad, dbcasout);
11155 } else {
11156
11157 sbond(oldad, oldad);
11158
11159 dummysh[0] = sencode(oldad);
11160 }
11161 ssbond(oldad, db);
11162 } else {
11163 sbond(oldad, dbcasout);
11164 }
11165 if (bc.sh != dummysh) {
11166 if (bccasout.sh != dummysh) {
11167 sbond1(bccasin, olddb);
11168 sbond1(olddb, bccasout);
11169 } else {
11170
11171 sbond(olddb, olddb);
11172
11173 dummysh[0] = sencode(olddb);
11174 }
11175 ssbond(olddb, bc);
11176 } else {
11177 sbond(olddb, bccasout);
11178 }
11179
11180
11181 setsorg(abc, pd);
11182 setsdest(abc, pc);
11183 setsapex(abc, pa);
11184 setsorg(bad, pc);
11185 setsdest(bad, pd);
11186 setsapex(bad, pb);
11187
11188 if (flipqueue != (queue *) NULL) {
11189 enqueueflipedge(bccasout, flipqueue);
11190 enqueueflipedge(cacasout, flipqueue);
11191 enqueueflipedge(adcasout, flipqueue);
11192 enqueueflipedge(dbcasout, flipqueue);
11193 }
11194 }
11195
11197
11198
11199
11200
11201
11202
11203
11204
11205
11206
11207
11208
11209
11210
11212
11213 long tetgenmesh::flip(queue* flipqueue, badface **plastflip)
11214 {
11215 badface *qface, *newflip;
11216 triface flipface, symface;
11217 point pa, pb, pc, pd, pe;
11218 enum fliptype fc;
11219 REAL sign, bakepsilon;
11220 long flipcount;
11221 int epscount, fcount;
11222 int ia, ib, ic, id, ie;
11223
11224 if (b->verbose > 1) {
11225 printf(" Do flipface queue: %ld faces.\n", flipqueue->len());
11226 }
11227
11228 flipcount = flip23s + flip32s + flip22s + flip44s;
11229 if (checksubfaces) {
11230
11231 fcount = 0;
11232 }
11233
11234 if (plastflip != (badface **) NULL) {
11235
11236 flipstackers->restart();
11237 *plastflip = (badface *) NULL;
11238 }
11239
11240
11241 while (!flipqueue->empty()) {
11242 qface = (badface *) flipqueue->pop();
11243 flipface = qface->tt;
11244 if (isdead(&flipface)) continue;
11245 sym(flipface, symface);
11246
11247 if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11248
11249 adjustedgering(flipface, CW);
11250 pa = org(flipface);
11251 pb = dest(flipface);
11252 pc = apex(flipface);
11253 pd = oppo(flipface);
11254 pe = oppo(symface);
11255 if (symbolic) {
11256 ia = pointmark(pa);
11257 ib = pointmark(pb);
11258 ic = pointmark(pc);
11259 id = pointmark(pd);
11260 ie = pointmark(pe);
11261 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
11262 assert(sign != 0.0);
11263 } else {
11264 sign = insphere(pa, pb, pc, pd, pe);
11265 }
11266 } else {
11267 sign = -1.0;
11268 }
11269 if (sign > 0.0) {
11270
11271 if (checksubfaces) {
11272 fcount++;
11273 bakepsilon = b->epsilon;
11274 epscount = 0;
11275 while (epscount < 32) {
11276 fc = categorizeface(flipface);
11277 if (fc == N40) {
11278 b->epsilon *= 1e-1;
11279 epscount++;
11280 continue;
11281 }
11282 break;
11283 }
11284 b->epsilon = bakepsilon;
11285 if (epscount >= 32) {
11286 if (b->verbose > 0) {
11287 printf("Warning: Can't flip a degenerate tetrahedron.\n");
11288 }
11289 fc = N40;
11290 }
11291 } else {
11292 fc = categorizeface(flipface);
11293 #ifdef SELF_CHECK
11294 assert(fc != N40);
11295 #endif
11296 }
11297 switch (fc) {
11298
11299 case T44:
11300 case T22:
11301 flip22(&flipface, flipqueue);
11302 break;
11303 case T23:
11304 flip23(&flipface, flipqueue);
11305 break;
11306 case T32:
11307 flip32(&flipface, flipqueue);
11308 break;
11309
11310 case N32:
11311 break;
11312 case FORBIDDENFACE:
11313 break;
11314 case FORBIDDENEDGE:
11315 break;
11316
11317 case N40:
11318
11319 break;
11320 }
11321 if (plastflip != (badface **) NULL) {
11322 if ((fc == T44) || (fc == T22) || (fc == T23) || (fc == T32)) {
11323
11324 newflip = (badface *) flipstackers->alloc();
11325 newflip->tt = flipface;
11326 newflip->key = (REAL) fc;
11327 newflip->forg = org(flipface);
11328 newflip->fdest = dest(flipface);
11329 newflip->fapex = apex(flipface);
11330 newflip->previtem = *plastflip;
11331 *plastflip = newflip;
11332 }
11333 }
11334 }
11335 }
11336
11337 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11338 if (b->verbose > 1) {
11339 printf(" %ld flips.\n", flipcount);
11340 }
11341
11342 return flipcount;
11343 }
11344
11346
11347
11348
11350
11351 long tetgenmesh::lawson(list *misseglist, queue* flipqueue)
11352 {
11353 badface *qface, *misseg;
11354 triface flipface, symface;
11355 triface starttet, spintet;
11356 face checksh, checkseg;
11357 point pa, pb, pc, pd, pe;
11358 point swappt;
11359 REAL sign, ori;
11360 long flipcount;
11361 int ia, ib, ic, id, ie;
11362 int hitbdry, i;
11363
11364 if (b->verbose > 1) {
11365 printf(" Do flipface queue: %ld faces.\n", flipqueue->len());
11366 }
11367 flipcount = flip23s + flip32s + flip22s + flip44s;
11368
11369
11370
11371
11372 while (!flipqueue->empty()) {
11373 qface = (badface *) flipqueue->pop();
11374 flipface = qface->tt;
11375
11376 if (!isdead(&flipface)) {
11377 sym(flipface, symface);
11378
11379 if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11380 flipface.ver = 0;
11381 pa = org(flipface);
11382 pb = dest(flipface);
11383 pc = apex(flipface);
11384 pd = oppo(flipface);
11385 pe = oppo(symface);
11386 if (symbolic) {
11387 ia = pointmark(pa);
11388 ib = pointmark(pb);
11389 ic = pointmark(pc);
11390 id = pointmark(pd);
11391 ie = pointmark(pe);
11392 sign = insphere_sos(pb, pa, pc, pd, pe, ib, ia, ic, id, ie);
11393 } else {
11394 sign = insphere(pb, pa, pc, pd, pe);
11395 }
11396 if (sign > 0.0) {
11397 for (i = 0; i < 3; i++) {
11398 ori = orient3d(pa, pb, pd, pe);
11399 if (ori > 0.0) {
11400
11401 swappt = pa;
11402 pa = pb;
11403 pb = pc;
11404 pc = swappt;
11405 enextself(flipface);
11406 } else {
11407 break;
11408 }
11409 }
11410 if (ori > 0.0) {
11411
11412 if (checksubfaces) {
11413 tspivot(flipface, checksh);
11414 if (checksh.sh != dummysh) {
11415
11416 continue;
11417 }
11418 }
11419 flip23(&flipface, flipqueue);
11420 } else if (ori < 0.0) {
11421
11422 fnext(flipface, symface);
11423 symself(symface);
11424 if (oppo(symface) == pe) {
11425
11426 if (checksubfaces) {
11427 tsspivot(&flipface, &checkseg);
11428 if (checkseg.sh != dummysh) {
11429
11430 continue;
11431 }
11432 } else if (checksubsegs) {
11433 tsspivot1(flipface, checkseg);
11434 if (checkseg.sh != dummysh) {
11435 if (b->verbose > 2) {
11436 printf(" Queuing missing segment (%d, %d).\n",
11437 pointmark(org(flipface)), pointmark(dest(flipface)));
11438 }
11439 misseg = (badface *) misseglist->append(NULL);
11440 misseg->ss = checkseg;
11441 misseg->forg = sorg(checkseg);
11442 misseg->fdest = sdest(checkseg);
11443
11444 starttet = flipface;
11445 adjustedgering(starttet, CCW);
11446 fnextself(starttet);
11447 spintet = starttet;
11448 hitbdry = 0;
11449 do {
11450 tssdissolve1(spintet);
11451 if (!fnextself(spintet)) {
11452 hitbdry++;
11453 if (hitbdry < 2) {
11454 esym(starttet, spintet);
11455 if (!fnextself(spintet)) {
11456 hitbdry++;
11457 }
11458 }
11459 }
11460 } while ((apex(spintet) != apex(starttet)) && (hitbdry < 2));
11461 }
11462 }
11463 flip32(&flipface, flipqueue);
11464 }
11465 } else {
11466
11467 fnext(flipface, symface);
11468 if (fnextself(symface)) {
11469
11470 fnextself(symface);
11471 if (apex(symface) == pe) {
11472 if (checksubfaces) {
11473 tsspivot(&flipface, &checkseg);
11474 if (checkseg.sh != dummysh) {
11475
11476 continue;
11477 }
11478 } else if (checksubsegs) {
11479 tsspivot1(flipface, checkseg);
11480 if (checkseg.sh != dummysh) {
11481 if (b->verbose > 2) {
11482 printf(" Queuing missing segment (%d, %d).\n",
11483 pointmark(org(flipface)), pointmark(dest(flipface)));
11484 }
11485 misseg = (badface *) misseglist->append(NULL);
11486 misseg->ss = checkseg;
11487 misseg->forg = sorg(checkseg);
11488 misseg->fdest = sdest(checkseg);
11489
11490 starttet = flipface;
11491 adjustedgering(starttet, CCW);
11492 fnextself(starttet);
11493 spintet = starttet;
11494 hitbdry = 0;
11495 do {
11496 tssdissolve1(spintet);
11497 if (!fnextself(spintet)) {
11498 hitbdry++;
11499 if (hitbdry < 2) {
11500 esym(starttet, spintet);
11501 if (!fnextself(spintet)) {
11502 hitbdry++;
11503 }
11504 }
11505 }
11506 } while ((apex(spintet) != apex(starttet)) &&
11507 (hitbdry < 2));
11508 }
11509 }
11510 flip22(&flipface, flipqueue);
11511 }
11512 } else {
11513
11514 esym(flipface, symface);
11515 fnextself(symface);
11516 symself(symface);
11517 if (symface.tet == dummytet) {
11518 if (checksubfaces) {
11519 tsspivot(&flipface, &checkseg);
11520 if (checkseg.sh != dummysh) {
11521
11522 continue;
11523 }
11524 } else if (checksubsegs) {
11525 tsspivot1(flipface, checkseg);
11526 if (checkseg.sh != dummysh) {
11527 if (b->verbose > 2) {
11528 printf(" Queuing missing segment (%d, %d).\n",
11529 pointmark(org(flipface)), pointmark(dest(flipface)));
11530 }
11531 misseg = (badface *) misseglist->append(NULL);
11532 misseg->ss = checkseg;
11533 misseg->forg = sorg(checkseg);
11534 misseg->fdest = sdest(checkseg);
11535
11536 starttet = flipface;
11537 adjustedgering(starttet, CCW);
11538 fnextself(starttet);
11539 spintet = starttet;
11540 hitbdry = 0;
11541 do {
11542 tssdissolve1(spintet);
11543 if (!fnextself(spintet)) {
11544 hitbdry++;
11545 if (hitbdry < 2) {
11546 esym(starttet, spintet);
11547 if (!fnextself(spintet)) {
11548 hitbdry++;
11549 }
11550 }
11551 }
11552 } while ((apex(spintet) != apex(starttet)) &&
11553 (hitbdry < 2));
11554 }
11555 }
11556 flip22(&flipface, flipqueue);
11557 }
11558 }
11559 }
11560 }
11561 }
11562 }
11563 }
11564
11565 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11566 if (b->verbose > 1) {
11567 printf(" %ld flips.\n", flipcount);
11568 }
11569 return flipcount;
11570 }
11571
11573
11574
11575
11576
11577
11578
11579
11581
11582 void tetgenmesh::undoflip(badface *lastflip)
11583 {
11584 enum fliptype fc;
11585
11586 while (lastflip != (badface *) NULL) {
11587
11588 findface(&lastflip->tt, lastflip->forg, lastflip->fdest, lastflip->fapex);
11589 fc = (enum fliptype) (int) lastflip->key;
11590 switch (fc) {
11591 case T23:
11592
11593 flip32(&lastflip->tt, NULL);
11594 break;
11595 case T32:
11596
11597 flip23(&lastflip->tt, NULL);
11598 break;
11599 case T22:
11600 case T44:
11601
11602 flip22(&lastflip->tt, NULL);
11603 break;
11604 default:
11605 break;
11606 }
11607
11608 lastflip = lastflip->previtem;
11609 }
11610 }
11611
11613
11614
11615
11616
11617
11618
11619
11621
11622 long tetgenmesh::flipsub(queue* flipqueue)
11623 {
11624 badface *qedge;
11625 face flipedge, symedge;
11626 face checkseg;
11627 point pa, pb, pc, pd;
11628 REAL vab[3], vac[3], vad[3];
11629 REAL dot1, dot2, lac, lad;
11630 REAL sign, ori;
11631 int edgeflips;
11632 int i;
11633
11634 if (b->verbose > 1) {
11635 printf(" Start do edge queue: %ld edges.\n", flipqueue->len());
11636 }
11637
11638 edgeflips = 0;
11639
11640 while (!flipqueue->empty()) {
11641 qedge = (badface *) flipqueue->pop();
11642 flipedge = qedge->ss;
11643 if (flipedge.sh == dummysh) continue;
11644 if ((sorg(flipedge) != qedge->forg) ||
11645 (sdest(flipedge) != qedge->fdest)) continue;
11646 sspivot(flipedge, checkseg);
11647 if (checkseg.sh != dummysh) continue;
11648 spivot(flipedge, symedge);
11649 if (symedge.sh == dummysh) continue;
11650 pa = sorg(flipedge);
11651 pb = sdest(flipedge);
11652 pc = sapex(flipedge);
11653 pd = sapex(symedge);
11654
11655
11656 for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
11657 for (i = 0; i < 3; i++) vac[i] = pc[i] - pa[i];
11658 for (i = 0; i < 3; i++) vad[i] = pd[i] - pa[i];
11659 dot1 = dot(vac, vab);
11660 dot2 = dot(vad, vab);
11661 dot1 *= dot1;
11662 dot2 *= dot2;
11663 lac = dot(vac, vac);
11664 lad = dot(vad, vad);
11665 if (lad * dot1 <= lac * dot2) {
11666
11667 abovepoint = facetabovepointarray[shellmark(flipedge)];
11668 if (abovepoint == (point) NULL) {
11669 getfacetabovepoint(&flipedge);
11670 }
11671 sign = insphere(pa, pb, pc, abovepoint, pd);
11672 ori = orient3d(pa, pb, pc, abovepoint);
11673 } else {
11674
11675 abovepoint = facetabovepointarray[shellmark(symedge)];
11676 if (abovepoint == (point) NULL) {
11677 getfacetabovepoint(&symedge);
11678 }
11679 sign = insphere(pa, pb, pd, abovepoint, pc);
11680 ori = orient3d(pa, pb, pd, abovepoint);
11681 }
11682
11683 sign = ori > 0.0 ? sign : -sign;
11684 if (sign > 0.0) {
11685
11686 flip22sub(&flipedge, flipqueue);
11687 edgeflips++;
11688 }
11689 }
11690
11691 if (b->verbose > 1) {
11692 printf(" Total %d flips.\n", edgeflips);
11693 }
11694
11695 return edgeflips;
11696 }
11697
11699
11700
11701
11702
11703
11704
11705
11706
11707
11708
11709
11710
11711
11713
11714 bool tetgenmesh::removetetbypeeloff(triface *striptet)
11715 {
11716 triface abcd, badc;
11717 triface dcacasing, cdbcasing;
11718 face abc, bad;
11719 face abseg;
11720 REAL ang;
11721
11722 abcd = *striptet;
11723 adjustedgering(abcd, CCW);
11724
11725 enextfnext(abcd, cdbcasing);
11726 enext2fnext(abcd, dcacasing);
11727 symself(cdbcasing);
11728 symself(dcacasing);
11729
11730
11731 if ((cdbcasing.tet == dummytet) || (dcacasing.tet == dummytet)) {
11732
11733 return false;
11734 }
11735
11736
11737 if (checksubfaces) {
11738
11739 fnext(abcd, badc);
11740 esymself(badc);
11741 tspivot(abcd, abc);
11742 tspivot(badc, bad);
11743 if (abc.sh != dummysh) {
11744 assert(bad.sh != dummysh);
11745 findedge(&abc, org(abcd), dest(abcd));
11746 findedge(&bad, org(badc), dest(badc));
11747
11748 sspivot(abc, abseg);
11749 if (abseg.sh != dummysh) {
11750
11751 if ((b->optlevel > 3) && (b->nobisect == 0)) {
11752
11753
11754
11755 ang = facedihedral(org(abcd), dest(abcd), apex(abcd), oppo(abcd));
11756 ang = ang * 180.0 / PI;
11757 if ((ang + 9.0) > b->maxdihedral) {
11758 if (b->verbose > 1) {
11759 printf(" Remove a segment during peeling.\n");
11760 }
11761 face prevseg, nextseg;
11762
11763 ssdissolve(abc);
11764 ssdissolve(bad);
11765 abseg.shver = 0;
11766 senext(abseg, nextseg);
11767 spivotself(nextseg);
11768 if (nextseg.sh != dummysh) {
11769 ssdissolve(nextseg);
11770 }
11771 senext2(abseg, prevseg);
11772 spivotself(prevseg);
11773 if (prevseg.sh != dummysh) {
11774 ssdissolve(prevseg);
11775 }
11776 shellfacedealloc(subsegs, abseg.sh);
11777 optcount[1]++;
11778 } else {
11779 return false;
11780 }
11781 } else {
11782 return false;
11783 }
11784 }
11785
11786 flip22sub(&abc, NULL);
11787
11788 tsbond(cdbcasing, bad);
11789 tsbond(dcacasing, abc);
11790 }
11791 }
11792
11793
11794 dissolve(cdbcasing);
11795 dissolve(dcacasing);
11796
11797 tetrahedrondealloc(abcd.tet);
11798 return true;
11799 }
11800
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811
11812
11813
11814
11816
11817 bool tetgenmesh::removeedgebyflip22(REAL *key, int n, triface *abtetlist,
11818 queue *flipque)
11819 {
11820 point pa, pb, pc, pd, pe, pf;
11821 REAL cosmaxd, d1, d2, d3;
11822 bool doflip;
11823
11824 cosmaxd = 0.0;
11825 pf = apex(abtetlist[2]);
11826 doflip = true;
11827 adjustedgering(abtetlist[0], CW);
11828 pa = org(abtetlist[0]);
11829 pb = dest(abtetlist[0]);
11830 pe = apex(abtetlist[0]);
11831 pc = oppo(abtetlist[0]);
11832 pd = apex(abtetlist[1]);
11833 if (n == 4) {
11834 pf = apex(abtetlist[2]);
11835 }
11836 if (key && (*key > -1.0)) {
11837 tetalldihedral(pc, pd, pe, pa, NULL, &d1, NULL);
11838 tetalldihedral(pd, pc, pe, pb, NULL, &d2, NULL);
11839 cosmaxd = d1 < d2 ? d1 : d2;
11840 if (n == 4) {
11841 tetalldihedral(pd, pc, pf, pa, NULL, &d1, NULL);
11842 tetalldihedral(pc, pd, pf, pb, NULL, &d2, NULL);
11843 d3 = d1 < d2 ? d1 : d2;
11844 cosmaxd = cosmaxd < d3 ? cosmaxd : d3;
11845 }
11846 doflip = (*key < cosmaxd);
11847 }
11848
11849 if (doflip) {
11850 flip22(&abtetlist[0], NULL);
11851
11852 if (key) *key = cosmaxd;
11853 }
11854
11855 return doflip;
11856 }
11857
11859
11860
11861
11862
11863
11864
11865
11866
11867
11868
11869
11870
11871
11872
11873
11874
11876
11877 bool tetgenmesh::removefacebyflip23(REAL *key, triface *abctetlist,
11878 triface *newtetlist, queue *flipque)
11879 {
11880 triface edab, edbc, edca;
11881 triface newfront, oldfront, adjfront;
11882 face checksh;
11883 point pa, pb, pc, pd, pe;
11884 REAL ori, cosmaxd, d1, d2, d3;
11885 REAL attrib, volume;
11886 bool doflip;
11887 int i;
11888
11889 cosmaxd = 0.0;
11890
11891 adjustedgering(abctetlist[0], CCW);
11892 pa = org(abctetlist[0]);
11893 pb = dest(abctetlist[0]);
11894 pc = apex(abctetlist[0]);
11895 pd = oppo(abctetlist[0]);
11896 pe = oppo(abctetlist[1]);
11897
11898
11899 ori = orient3d(pe, pd, pa, pb);
11900 if (ori < 0.0) {
11901 ori = orient3d(pe, pd, pb, pc);
11902 if (ori < 0.0) {
11903 ori = orient3d(pe, pd, pc, pa);
11904 }
11905 }
11906 doflip = (ori < 0.0);
11907 if (doflip && (key != (REAL *) NULL)) {
11908 if (*key > -1.0) {
11909
11910 tetalldihedral(pe, pd, pa, pb, NULL, &d1, NULL);
11911 tetalldihedral(pe, pd, pb, pc, NULL, &d2, NULL);
11912 tetalldihedral(pe, pd, pc, pa, NULL, &d3, NULL);
11913 cosmaxd = d1 < d2 ? d1 : d2;
11914 cosmaxd = cosmaxd < d3 ? cosmaxd : d3;
11915 doflip = (*key < cosmaxd);
11916 }
11917 }
11918
11919 if (doflip) {
11920
11921 flip23s++;
11922
11923 maketetrahedron(&edab);
11924 setorg(edab, pe);
11925 setdest(edab, pd);
11926 setapex(edab, pa);
11927 setoppo(edab, pb);
11928 maketetrahedron(&edbc);
11929 setorg(edbc, pe);
11930 setdest(edbc, pd);
11931 setapex(edbc, pb);
11932 setoppo(edbc, pc);
11933 maketetrahedron(&edca);
11934 setorg(edca, pe);
11935 setdest(edca, pd);
11936 setapex(edca, pc);
11937 setoppo(edca, pa);
11938
11939 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
11940 attrib = elemattribute(abctetlist[0].tet, i);
11941 setelemattribute(edab.tet, i, attrib);
11942 setelemattribute(edbc.tet, i, attrib);
11943 setelemattribute(edca.tet, i, attrib);
11944 }
11945
11946 if (b->varvolume && !b->refine) {
11947 volume = volumebound(abctetlist[0].tet);
11948 setvolumebound(edab.tet, volume);
11949 setvolumebound(edbc.tet, volume);
11950 setvolumebound(edca.tet, volume);
11951 }
11952
11953 newtetlist[0] = edab;
11954 newtetlist[1] = edbc;
11955 newtetlist[2] = edca;
11956
11957 for (i = 0; i < 3; i++) {
11958 fnext(newtetlist[i], newfront);
11959 bond(newfront, newtetlist[(i + 1) % 3]);
11960 }
11961
11962 for (i = 0; i < 3; i++) {
11963 fnext(abctetlist[0], oldfront);
11964 sym(oldfront, adjfront);
11965 enextfnext(newtetlist[i], newfront);
11966 bond(newfront, adjfront);
11967 if (checksubfaces) {
11968 tspivot(oldfront, checksh);
11969 if (checksh.sh != dummysh) {
11970 tsbond(newfront, checksh);
11971 }
11972 }
11973 if (flipque != (queue *) NULL) {
11974 enqueueflipface(newfront, flipque);
11975 }
11976 enextself(abctetlist[0]);
11977 }
11978 findedge(&(abctetlist[1]), pb, pa);
11979 for (i = 0; i < 3; i++) {
11980 fnext(abctetlist[1], oldfront);
11981 sym(oldfront, adjfront);
11982 enext2fnext(newtetlist[i], newfront);
11983 bond(newfront, adjfront);
11984 if (checksubfaces) {
11985 tspivot(oldfront, checksh);
11986 if (checksh.sh != dummysh) {
11987 tsbond(newfront, checksh);
11988 }
11989 }
11990 if (flipque != (queue *) NULL) {
11991 enqueueflipface(newfront, flipque);
11992 }
11993 enext2self(abctetlist[1]);
11994 }
11995
11996
11997
11998
11999
12000 if (key != (REAL *) NULL) *key = cosmaxd;
12001 return true;
12002 }
12003
12004 return false;
12005 }
12006
12008
12009
12010
12011
12012
12013
12014
12015
12016
12017
12018
12019
12020
12021
12022
12023
12024
12025
12026
12028
12029 bool tetgenmesh::removeedgebyflip32(REAL *key, triface *abtetlist,
12030 triface *newtetlist, queue *flipque)
12031 {
12032 triface dcea, cdeb;
12033 triface newfront, oldfront, adjfront;
12034 face checksh;
12035 point pa, pb, pc, pd, pe;
12036 REAL ori, cosmaxd, d1, d2;
12037 REAL attrib, volume;
12038 bool doflip;
12039 int i;
12040
12041 pa = org(abtetlist[0]);
12042 pb = dest(abtetlist[0]);
12043 pc = apex(abtetlist[0]);
12044 pd = apex(abtetlist[1]);
12045 pe = apex(abtetlist[2]);
12046
12047 ori = orient3d(pd, pc, pe, pa);
12048 if (ori < 0.0) {
12049 ori = orient3d(pc, pd, pe, pb);
12050 }
12051 doflip = (ori < 0.0);
12052
12053
12054 if (doflip && (key != (REAL *) NULL)) {
12055 if (*key > -1.0) {
12056
12057 tetalldihedral(pd, pc, pe, pa, NULL, &d1, NULL);
12058 tetalldihedral(pc, pd, pe, pb, NULL, &d2, NULL);
12059 cosmaxd = d1 < d2 ? d1 : d2;
12060 doflip = (*key < cosmaxd);
12061
12062 *key = cosmaxd;
12063 }
12064 }
12065
12066 if (doflip) {
12067
12068 maketetrahedron(&dcea);
12069 setorg(dcea, pd);
12070 setdest(dcea, pc);
12071 setapex(dcea, pe);
12072 setoppo(dcea, pa);
12073 maketetrahedron(&cdeb);
12074 setorg(cdeb, pc);
12075 setdest(cdeb, pd);
12076 setapex(cdeb, pe);
12077 setoppo(cdeb, pb);
12078
12079 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12080 attrib = elemattribute(abtetlist[0].tet, i);
12081 setelemattribute(dcea.tet, i, attrib);
12082 setelemattribute(cdeb.tet, i, attrib);
12083 }
12084
12085 if (b->varvolume && !b->refine) {
12086 volume = volumebound(abtetlist[0].tet);
12087 setvolumebound(dcea.tet, volume);
12088 setvolumebound(cdeb.tet, volume);
12089 }
12090
12091 newtetlist[0] = dcea;
12092 newtetlist[1] = cdeb;
12093
12094 bond(dcea, cdeb);
12095
12096 for (i = 0; i < 3; i++) {
12097 fnext(dcea, newfront);
12098 esym(abtetlist[(i + 1) % 3], oldfront);
12099 enextfnextself(oldfront);
12100
12101 sym(oldfront, adjfront);
12102 bond(newfront, adjfront);
12103 if (checksubfaces) {
12104 tspivot(oldfront, checksh);
12105 if (checksh.sh != dummysh) {
12106 tsbond(newfront, checksh);
12107 }
12108 }
12109 if (flipque != (queue *) NULL) {
12110 enqueueflipface(newfront, flipque);
12111 }
12112 enext2self(dcea);
12113 }
12114 for (i = 0; i < 3; i++) {
12115 fnext(cdeb, newfront);
12116 esym(abtetlist[(i + 1) % 3], oldfront);
12117 enext2fnextself(oldfront);
12118
12119 sym(oldfront, adjfront);
12120 bond(newfront, adjfront);
12121 if (checksubfaces) {
12122 tspivot(oldfront, checksh);
12123 if (checksh.sh != dummysh) {
12124 tsbond(newfront, checksh);
12125 }
12126 }
12127 if (flipque != (queue *) NULL) {
12128 enqueueflipface(newfront, flipque);
12129 }
12130 enextself(cdeb);
12131 }
12132
12133
12134
12135
12136 return true;
12137 }
12138
12139 return false;
12140 }
12141
12143
12144
12145
12146
12147
12148
12149
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
12182
12183 bool tetgenmesh::removeedgebytranNM(REAL *key, int n, triface *abtetlist,
12184 triface *newtetlist, point e1, point e2, queue *flipque)
12185 {
12186 triface tmpabtetlist[9];
12187 triface newfront, oldfront, adjfront;
12188 face checksh;
12189 point pa, pb, p[10];
12190 REAL ori, cosmaxd, d1, d2;
12191 REAL tmpkey;
12192 REAL attrib, volume;
12193 bool doflip, copflag, success;
12194 int i, j, k;
12195
12196 cosmaxd = 0.0;
12197
12198 assert(n <= 10);
12199
12200 pa = org(abtetlist[0]);
12201 pb = dest(abtetlist[0]);
12202
12203
12204
12205
12206 for (i = 0; i < n; i++) {
12207
12208 for (j = 0; j < n; j++) {
12209 p[j] = apex(abtetlist[(i + j) % n]);
12210 }
12211
12212 if ((e1 != (point) NULL) && (e2 != (point) NULL)) {
12213
12214 if (!(((p[1] == e1) && (p[n - 1] == e2)) ||
12215 ((p[1] == e2) && (p[n - 1] == e1)))) continue;
12216 }
12217
12218
12219
12220
12221
12222
12223 ori = orient3d(pa, pb, p[1], p[n - 1]);
12224 copflag = (ori == 0.0);
12225 if (ori >= 0.0) {
12226
12227 ori = orient3d(pb, p[0], p[1], p[n - 1]);
12228 if (ori > 0.0) {
12229 ori = orient3d(p[0], pa, p[1], p[n - 1]);
12230 }
12231 }
12232
12233 if (ori > 0.0) {
12234
12235 copflag ? flip44s++ : flip23s++;
12236 doflip = true;
12237 if (key != (REAL *) NULL) {
12238 if (*key > -1.0) {
12239
12240
12241
12242 tetalldihedral(p[n - 1], p[1], p[0], pa, NULL, &d1, NULL);
12243 tetalldihedral(p[1], p[n - 1], p[0], pb, NULL, &d2, NULL);
12244 cosmaxd = d1 < d2 ? d1 : d2;
12245 doflip = *key < cosmaxd;
12246 }
12247 }
12248 if (doflip) {
12249 tmpkey = key != NULL ? *key : -1.0;
12250
12251 maketetrahedron(&(newtetlist[0]));
12252 setorg(newtetlist[0], p[n - 1]);
12253 setdest(newtetlist[0], p[1]);
12254 setapex(newtetlist[0], p[0]);
12255 setoppo(newtetlist[0], pa);
12256 maketetrahedron(&(newtetlist[1]));
12257 setorg(newtetlist[1], p[1]);
12258 setdest(newtetlist[1], p[n - 1]);
12259 setapex(newtetlist[1], p[0]);
12260 setoppo(newtetlist[1], pb);
12261
12262 maketetrahedron(&(tmpabtetlist[0]));
12263 setorg(tmpabtetlist[0], pa);
12264 setdest(tmpabtetlist[0], pb);
12265 setapex(tmpabtetlist[0], p[n - 1]);
12266 setoppo(tmpabtetlist[0], p[1]);
12267 for (j = 1; j < n - 1; j++) {
12268 maketetrahedron(&(tmpabtetlist[j]));
12269 setorg(tmpabtetlist[j], pa);
12270 setdest(tmpabtetlist[j], pb);
12271 setapex(tmpabtetlist[j], p[j]);
12272 setoppo(tmpabtetlist[j], p[j + 1]);
12273 }
12274
12275 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12276 attrib = elemattribute(abtetlist[0].tet, j);
12277 setelemattribute(newtetlist[0].tet, j, attrib);
12278 setelemattribute(newtetlist[1].tet, j, attrib);
12279 for (k = 0; k < n - 1; k++) {
12280 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12281 }
12282 }
12283
12284 if (b->varvolume && !b->refine) {
12285 volume = volumebound(abtetlist[0].tet);
12286 setvolumebound(newtetlist[0].tet, volume);
12287 setvolumebound(newtetlist[1].tet, volume);
12288 for (k = 0; k < n - 1; k++) {
12289 setvolumebound(tmpabtetlist[k].tet, volume);
12290 }
12291 }
12292
12293 bond(newtetlist[0], newtetlist[1]);
12294 fnext(newtetlist[0], newfront);
12295 enext2fnext(tmpabtetlist[0], adjfront);
12296 bond(newfront, adjfront);
12297 fnext(newtetlist[1], newfront);
12298 enextfnext(tmpabtetlist[0], adjfront);
12299 bond(newfront, adjfront);
12300
12301 for (j = 0; j < n - 1; j++) {
12302 fnext(tmpabtetlist[j], newfront);
12303 bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]);
12304 }
12305
12306
12307
12308
12309
12310
12311 for (j = 0; j < n; j++) {
12312
12313 oldfront = abtetlist[(i + j) % n];
12314 esymself(oldfront);
12315 enextfnextself(oldfront);
12316
12317 sym(oldfront, adjfront);
12318
12319 if (j == 0) {
12320 enext2fnext(newtetlist[0], newfront);
12321 } else if (j == 1) {
12322 enextfnext(newtetlist[0], newfront);
12323 } else {
12324 enext2fnext(tmpabtetlist[j - 1], newfront);
12325 }
12326 bond(newfront, adjfront);
12327 if (checksubfaces) {
12328 tspivot(oldfront, checksh);
12329 if (checksh.sh != dummysh) {
12330 tsbond(newfront, checksh);
12331 }
12332 }
12333 if (flipque != (queue *) NULL) {
12334
12335 if (j < 2) enqueueflipface(newfront, flipque);
12336 }
12337 }
12338 for (j = 0; j < n; j++) {
12339
12340 oldfront = abtetlist[(i + j) % n];
12341 esymself(oldfront);
12342 enext2fnextself(oldfront);
12343
12344 sym(oldfront, adjfront);
12345
12346 if (j == 0) {
12347 enextfnext(newtetlist[1], newfront);
12348 } else if (j == 1) {
12349 enext2fnext(newtetlist[1], newfront);
12350 } else {
12351 enextfnext(tmpabtetlist[j - 1], newfront);
12352 }
12353 bond(newfront, adjfront);
12354 if (checksubfaces) {
12355 tspivot(oldfront, checksh);
12356 if (checksh.sh != dummysh) {
12357 tsbond(newfront, checksh);
12358 }
12359 }
12360 if (flipque != (queue *) NULL) {
12361
12362 if (j < 2) enqueueflipface(newfront, flipque);
12363 }
12364 }
12365
12366
12367 for (j = 0; j < n - 1; j++) {
12368 fnextself(tmpabtetlist[j]);
12369 }
12370 if (n > 4) {
12371 success = removeedgebytranNM(&tmpkey, n-1, tmpabtetlist,
12372 &(newtetlist[2]), NULL, NULL, flipque);
12373 } else {
12374 success = removeedgebyflip32(&tmpkey, tmpabtetlist,
12375 &(newtetlist[2]), flipque);
12376 }
12377
12378 for (j = 0; j < n - 1; j++) {
12379 tetrahedrondealloc(tmpabtetlist[j].tet);
12380 }
12381 if (success) {
12382
12383
12384
12385
12386
12387
12388 if (key != (REAL *) NULL) {
12389 *key = (tmpkey < cosmaxd ? tmpkey : cosmaxd);
12390 }
12391 return true;
12392 } else {
12393
12394 for (j = 0; j < n; j++) {
12395 oldfront = abtetlist[(i + j) % n];
12396 esymself(oldfront);
12397 enextfnextself(oldfront);
12398 sym(oldfront, adjfront);
12399 bond(oldfront, adjfront);
12400 if (checksubfaces) {
12401 tspivot(oldfront, checksh);
12402 if (checksh.sh != dummysh) {
12403 tsbond(oldfront, checksh);
12404 }
12405 }
12406 }
12407 for (j = 0; j < n; j++) {
12408 oldfront = abtetlist[(i + j) % n];
12409 esymself(oldfront);
12410 enext2fnextself(oldfront);
12411 sym(oldfront, adjfront);
12412 bond(oldfront, adjfront);
12413 if (checksubfaces) {
12414 tspivot(oldfront, checksh);
12415 if (checksh.sh != dummysh) {
12416 tsbond(oldfront, checksh);
12417 }
12418 }
12419 }
12420
12421 tetrahedrondealloc(newtetlist[0].tet);
12422 tetrahedrondealloc(newtetlist[1].tet);
12423
12424
12425 if (key && (tmpkey < *key)) {
12426 *key = tmpkey;
12427 return false;
12428 }
12429 }
12430 }
12431 }
12432 }
12433
12434 return false;
12435 }
12436
12438
12439
12440
12441
12442
12443
12444
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
12478
12479 bool tetgenmesh::removeedgebycombNM(REAL *key, int n, triface *abtetlist,
12480 int *n1, triface *bftetlist, triface *newtetlist, queue *flipque)
12481 {
12482 triface tmpabtetlist[11];
12483 triface newfront, oldfront, adjfront;
12484 face checksh;
12485 point pa, pb, p[10];
12486 REAL ori, tmpkey, tmpkey2;
12487 REAL attrib, volume;
12488 bool doflip, success;
12489 int twice, count;
12490 int i, j, k, m;
12491
12492
12493 assert(n <= 10);
12494
12495
12496
12497 twice = 0;
12498 do {
12499
12500 pa = org(abtetlist[0]);
12501 pb = dest(abtetlist[0]);
12502
12503 for (i = 0; i < n; i++) {
12504
12505 for (j = 0; j < n; j++) {
12506 p[j] = apex(abtetlist[(i + j) % n]);
12507 }
12508
12509 ori = orient3d(pb, p[0], p[1], p[n - 1]);
12510 if ((ori > 0) && (key != (REAL *) NULL)) {
12511
12512
12513
12514 tetalldihedral(pb, p[0], p[n - 1], p[1], NULL, &tmpkey, NULL);
12515 if (tmpkey < *key) ori = 0.0;
12516 }
12517 if (ori <= 0.0) {
12518
12519 bftetlist[0] = abtetlist[i];
12520 enextself(bftetlist[0]);
12521 adjustedgering(bftetlist[0], CW);
12522 assert(apex(bftetlist[0]) == pa);
12523
12524 doflip = true;
12525 *n1 = 0;
12526 do {
12527
12528 if (*n1 == 10) break;
12529 if (checksubfaces) {
12530
12531 tspivot(bftetlist[*n1], checksh);
12532 if (checksh.sh != dummysh) {
12533 doflip = false; break;
12534 }
12535 }
12536
12537 fnext(bftetlist[*n1], bftetlist[(*n1) + 1]);
12538 (*n1)++;
12539 } while (apex(bftetlist[*n1]) != pa);
12540
12541 if (doflip) {
12542 success = false;
12543 tmpkey = -1.0;
12544 if (key != (REAL *) NULL) tmpkey = *key;
12545 m = 0;
12546 if (*n1 == 3) {
12547
12548 success = removeedgebyflip32(&tmpkey,bftetlist,newtetlist,flipque);
12549 m = 2;
12550 } else if ((*n1 > 3) && (*n1 < 7)) {
12551
12552 success = removeedgebytranNM(&tmpkey, *n1, bftetlist, newtetlist,
12553 p[1], p[n - 1], flipque);
12554
12555 m = ((*n1) - 2) * 2;
12556 } else {
12557 if (b->verbose > 1) {
12558 printf(" !! Unhandled case: n1 = %d.\n", *n1);
12559 }
12560 }
12561 if (success) {
12562
12563
12564
12565
12566
12567 setpointmark(pa, -pointmark(pa) - 1);
12568 setpointmark(pb, -pointmark(pb) - 1);
12569 assert(m > 0);
12570 for (j = 0; j < m; j++) {
12571 tmpabtetlist[0] = newtetlist[j];
12572
12573 count = 0;
12574 for (k = 0; k < 4; k++) {
12575 if (pointmark((point)(tmpabtetlist[0].tet[4+k])) < 0) count++;
12576 }
12577 if (count == 2) {
12578
12579 for (tmpabtetlist[0].loc = 0; tmpabtetlist[0].loc < 4;
12580 tmpabtetlist[0].loc++) {
12581 if ((oppo(tmpabtetlist[0]) != pa) &&
12582 (oppo(tmpabtetlist[0]) != pb)) break;
12583 }
12584
12585 assert(tmpabtetlist[0].loc < 4);
12586 findedge(&(tmpabtetlist[0]), pa, pb);
12587 break;
12588 }
12589 }
12590 assert(j < m);
12591
12592 newtetlist[j] = newtetlist[m - 1];
12593 setpointmark(pa, -(pointmark(pa) + 1));
12594 setpointmark(pb, -(pointmark(pb) + 1));
12595
12596 adjustedgering(tmpabtetlist[0], CCW);
12597 if (org(tmpabtetlist[0]) != pa) {
12598 fnextself(tmpabtetlist[0]);
12599 esymself(tmpabtetlist[0]);
12600 }
12601 #ifdef SELF_CHECK
12602
12603 assert(org(tmpabtetlist[0]) == pa);
12604 assert(dest(tmpabtetlist[0]) == pb);
12605 assert(apex(tmpabtetlist[0]) == p[n - 1]);
12606 assert(oppo(tmpabtetlist[0]) == p[1]);
12607 #endif // SELF_CHECK
12608
12609 for (j = 1; j < n - 1; j++) {
12610 maketetrahedron(&(tmpabtetlist[j]));
12611 setorg(tmpabtetlist[j], pa);
12612 setdest(tmpabtetlist[j], pb);
12613 setapex(tmpabtetlist[j], p[j]);
12614 setoppo(tmpabtetlist[j], p[j + 1]);
12615 }
12616
12617 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12618 attrib = elemattribute(abtetlist[0].tet, j);
12619 for (k = 0; k < n - 1; k++) {
12620 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12621 }
12622 }
12623
12624 if (b->varvolume && !b->refine) {
12625 volume = volumebound(abtetlist[0].tet);
12626 for (k = 0; k < n - 1; k++) {
12627 setvolumebound(tmpabtetlist[k].tet, volume);
12628 }
12629 }
12630
12631 for (j = 0; j < n - 1; j++) {
12632 fnext(tmpabtetlist[j], newfront);
12633 bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]);
12634 }
12635
12636
12637
12638
12639
12640
12641 for (j = 2; j < n; j++) {
12642
12643 oldfront = abtetlist[(i + j) % n];
12644 esymself(oldfront);
12645 enextfnextself(oldfront);
12646
12647 sym(oldfront, adjfront);
12648
12649
12650 enext2fnext(tmpabtetlist[j - 1], newfront);
12651 bond(newfront, adjfront);
12652 if (checksubfaces) {
12653 tspivot(oldfront, checksh);
12654 if (checksh.sh != dummysh) {
12655 tsbond(newfront, checksh);
12656 }
12657 }
12658 }
12659 for (j = 2; j < n; j++) {
12660
12661 oldfront = abtetlist[(i + j) % n];
12662 esymself(oldfront);
12663 enext2fnextself(oldfront);
12664
12665 sym(oldfront, adjfront);
12666
12667
12668 enextfnext(tmpabtetlist[j - 1], newfront);
12669 bond(newfront, adjfront);
12670 if (checksubfaces) {
12671 tspivot(oldfront, checksh);
12672 if (checksh.sh != dummysh) {
12673 tsbond(newfront, checksh);
12674 }
12675 }
12676 }
12677
12678
12679 for (j = 0; j < n - 1; j++) {
12680 fnextself(tmpabtetlist[j]);
12681 }
12682 tmpkey2 = -1;
12683 if (key) tmpkey2 = *key;
12684 if ((n - 1) == 3) {
12685 success = removeedgebyflip32(&tmpkey2, tmpabtetlist,
12686 &(newtetlist[m - 1]), flipque);
12687 } else {
12688 success = removeedgebytranNM(&tmpkey2, n - 1, tmpabtetlist,
12689 &(newtetlist[m - 1]), NULL, NULL, flipque);
12690 }
12691
12692 for (j = 0; j < n - 1; j++) {
12693 tetrahedrondealloc(tmpabtetlist[j].tet);
12694 }
12695 if (success) {
12696
12697
12698
12699
12700
12701
12702 if (key != (REAL *) NULL) {
12703 *key = tmpkey2 < tmpkey ? tmpkey2 : tmpkey;
12704 }
12705 return true;
12706 } else {
12707
12708 for (j = 0; j < n; j++) {
12709 oldfront = abtetlist[(i + j) % n];
12710 esymself(oldfront);
12711 enextfnextself(oldfront);
12712 sym(oldfront, adjfront);
12713 bond(oldfront, adjfront);
12714 if (checksubfaces) {
12715 tspivot(oldfront, checksh);
12716 if (checksh.sh != dummysh) {
12717 tsbond(oldfront, checksh);
12718 }
12719 }
12720 }
12721 for (j = 0; j < n; j++) {
12722 oldfront = abtetlist[(i + j) % n];
12723 esymself(oldfront);
12724 enext2fnextself(oldfront);
12725 sym(oldfront, adjfront);
12726 bond(oldfront, adjfront);
12727 if (checksubfaces) {
12728 tspivot(oldfront, checksh);
12729 if (checksh.sh != dummysh) {
12730 tsbond(oldfront, checksh);
12731 }
12732 }
12733 }
12734
12735 for (j = 0; j < *n1; j++) {
12736 oldfront = bftetlist[j];
12737 esymself(oldfront);
12738 enextfnextself(oldfront);
12739 sym(oldfront, adjfront);
12740 bond(oldfront, adjfront);
12741 if (checksubfaces) {
12742 tspivot(oldfront, checksh);
12743 if (checksh.sh != dummysh) {
12744 tsbond(oldfront, checksh);
12745 }
12746 }
12747 }
12748 for (j = 0; j < *n1; j++) {
12749 oldfront = bftetlist[j];
12750 esymself(oldfront);
12751 enext2fnextself(oldfront);
12752 sym(oldfront, adjfront);
12753 bond(oldfront, adjfront);
12754 if (checksubfaces) {
12755 tspivot(oldfront, checksh);
12756 if (checksh.sh != dummysh) {
12757 tsbond(oldfront, checksh);
12758 }
12759 }
12760 }
12761
12762
12763 for (j = 0; j < m - 1; j++) {
12764 tetrahedrondealloc(newtetlist[j].tet);
12765 }
12766 }
12767 }
12768 }
12769 }
12770 }
12771
12772 for (i = 0; i < n; i++) newtetlist[i] = abtetlist[i];
12773 for (i = 0; i < n; i++) {
12774 oldfront = newtetlist[n - i - 1];
12775 esymself(oldfront);
12776 fnextself(oldfront);
12777 abtetlist[i] = oldfront;
12778 }
12779 twice++;
12780 } while (twice < 2);
12781
12782 return false;
12783 }
12784
12786
12787
12788
12789
12790
12791
12792
12793
12794
12795
12796
12797
12798
12800
12801 void tetgenmesh::splittetrahedron(point newpoint, triface* splittet,
12802 queue* flipqueue)
12803 {
12804 triface oldabd, oldbcd, oldcad;
12805 triface abdcasing, bcdcasing, cadcasing;
12806 face abdsh, bcdsh, cadsh;
12807 triface abcv, badv, cbdv, acdv;
12808 triface worktet;
12809 face abseg, bcseg, caseg;
12810 face adseg, bdseg, cdseg;
12811 point pa, pb, pc, pd;
12812 REAL attrib, volume;
12813 int i;
12814
12815 abcv = *splittet;
12816 abcv.ver = 0;
12817
12818 pa = org(abcv);
12819 pb = dest(abcv);
12820 pc = apex(abcv);
12821 pd = oppo(abcv);
12822
12823 if (b->verbose > 1) {
12824 printf(" Inserting point %d in tetrahedron (%d, %d, %d, %d).\n",
12825 pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc),
12826 pointmark(pd));
12827 }
12828
12829 fnext(abcv, oldabd);
12830 enextfnext(abcv, oldbcd);
12831 enext2fnext(abcv, oldcad);
12832 sym(oldabd, abdcasing);
12833 sym(oldbcd, bcdcasing);
12834 sym(oldcad, cadcasing);
12835 maketetrahedron(&badv);
12836 maketetrahedron(&cbdv);
12837 maketetrahedron(&acdv);
12838
12839
12840 setorg (badv, pb);
12841 setdest(badv, pa);
12842 setapex(badv, pd);
12843 setoppo(badv, newpoint);
12844
12845 setorg (cbdv, pc);
12846 setdest(cbdv, pb);
12847 setapex(cbdv, pd);
12848 setoppo(cbdv, newpoint);
12849
12850 setorg (acdv, pa);
12851 setdest(acdv, pc);
12852 setapex(acdv, pd);
12853 setoppo(acdv, newpoint);
12854
12855 setoppo(abcv, newpoint);
12856
12857
12858 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12859 attrib = elemattribute(abcv.tet, i);
12860 setelemattribute(badv.tet, i, attrib);
12861 setelemattribute(cbdv.tet, i, attrib);
12862 setelemattribute(acdv.tet, i, attrib);
12863 }
12864
12865 if (b->varvolume) {
12866 volume = volumebound(abcv.tet);
12867 setvolumebound(badv.tet, volume);
12868 setvolumebound(cbdv.tet, volume);
12869 setvolumebound(acdv.tet, volume);
12870 }
12871
12872
12873 bond(badv, abdcasing);
12874 bond(cbdv, bcdcasing);
12875 bond(acdv, cadcasing);
12876
12877 if (checksubfaces) {
12878 tspivot(oldabd, abdsh);
12879 if (abdsh.sh != dummysh) {
12880 tsdissolve(oldabd);
12881 tsbond(badv, abdsh);
12882 }
12883 tspivot(oldbcd, bcdsh);
12884 if (bcdsh.sh != dummysh) {
12885 tsdissolve(oldbcd);
12886 tsbond(cbdv, bcdsh);
12887 }
12888 tspivot(oldcad, cadsh);
12889 if (cadsh.sh != dummysh) {
12890 tsdissolve(oldcad);
12891 tsbond(acdv, cadsh);
12892 }
12893 } else if (checksubsegs) {
12894 tsspivot1(abcv, abseg);
12895 if (abseg.sh != dummysh) {
12896 tssbond1(badv, abseg);
12897 }
12898 enext(abcv, worktet);
12899 tsspivot1(worktet, bcseg);
12900 if (bcseg.sh != dummysh) {
12901 tssbond1(cbdv, bcseg);
12902 }
12903 enext2(abcv, worktet);
12904 tsspivot1(worktet, caseg);
12905 if (caseg.sh != dummysh) {
12906 tssbond1(acdv, caseg);
12907 }
12908 fnext(abcv, worktet);
12909 enext2self(worktet);
12910 tsspivot1(worktet, adseg);
12911 if (adseg.sh != dummysh) {
12912 tssdissolve1(worktet);
12913 enext(badv, worktet);
12914 tssbond1(worktet, adseg);
12915 enext2(acdv, worktet);
12916 tssbond1(worktet, adseg);
12917 }
12918 enextfnext(abcv, worktet);
12919 enext2self(worktet);
12920 tsspivot1(worktet, bdseg);
12921 if (bdseg.sh != dummysh) {
12922 tssdissolve1(worktet);
12923 enext(cbdv, worktet);
12924 tssbond1(worktet, bdseg);
12925 enext2(badv, worktet);
12926 tssbond1(worktet, bdseg);
12927 }
12928 enext2fnext(abcv, worktet);
12929 enext2self(worktet);
12930 tsspivot1(worktet, cdseg);
12931 if (cdseg.sh != dummysh) {
12932 tssdissolve1(worktet);
12933 enext(acdv, worktet);
12934 tssbond1(worktet, cdseg);
12935 enext2(cbdv, worktet);
12936 tssbond1(worktet, cdseg);
12937 }
12938 }
12939 badv.loc = 3;
12940 cbdv.loc = 2;
12941 bond(badv, cbdv);
12942 cbdv.loc = 3;
12943 acdv.loc = 2;
12944 bond(cbdv, acdv);
12945 acdv.loc = 3;
12946 badv.loc = 2;
12947 bond(acdv, badv);
12948 badv.loc = 1;
12949 bond(badv, oldabd);
12950 cbdv.loc = 1;
12951 bond(cbdv, oldbcd);
12952 acdv.loc = 1;
12953 bond(acdv, oldcad);
12954
12955 badv.loc = 0;
12956 cbdv.loc = 0;
12957 acdv.loc = 0;
12958 if (b->verbose > 3) {
12959 printf(" Updating abcv ");
12960 printtet(&abcv);
12961 printf(" Creating badv ");
12962 printtet(&badv);
12963 printf(" Creating cbdv ");
12964 printtet(&cbdv);
12965 printf(" Creating acdv ");
12966 printtet(&acdv);
12967 }
12968
12969 if (flipqueue != (queue *) NULL) {
12970 enqueueflipface(abcv, flipqueue);
12971 enqueueflipface(badv, flipqueue);
12972 enqueueflipface(cbdv, flipqueue);
12973 enqueueflipface(acdv, flipqueue);
12974 }
12975
12976
12977 recenttet = abcv;
12978
12979 *splittet = abcv;
12980 }
12981
12983
12984
12985
12986
12987
12988
12989
12990
12991
12992
12993
12994
12996
12997 void tetgenmesh::unsplittetrahedron(triface* splittet)
12998 {
12999 triface abcv, badv, cbdv, acdv;
13000 triface oldabv, oldbcv, oldcav;
13001 triface badcasing, cbdcasing, acdcasing;
13002 face badsh, cbdsh, acdsh;
13003
13004 abcv = *splittet;
13005 adjustedgering(abcv, CCW);
13006 fnext(abcv, oldabv);
13007 fnext(oldabv, badv);
13008 esymself(badv);
13009 enextfnext(abcv, oldbcv);
13010 fnext(oldbcv, cbdv);
13011 esymself(cbdv);
13012 enext2fnext(abcv, oldcav);
13013 fnext(oldcav, acdv);
13014 esymself(acdv);
13015
13016 if (b->verbose > 1) {
13017 printf(" Removing point %d in tetrahedron (%d, %d, %d, %d).\n",
13018 pointmark(oppo(abcv)), pointmark(org(abcv)), pointmark(dest(abcv)),
13019 pointmark(apex(abcv)), pointmark(apex(badv)));
13020 }
13021
13022 sym(badv, badcasing);
13023 tspivot(badv, badsh);
13024 sym(cbdv, cbdcasing);
13025 tspivot(cbdv, cbdsh);
13026 sym(acdv, acdcasing);
13027 tspivot(acdv, acdsh);
13028
13029
13030 setoppo(abcv, apex(badv));
13031 bond(oldabv, badcasing);
13032 if (badsh.sh != dummysh) {
13033 tsbond(oldabv, badsh);
13034 }
13035 bond(oldbcv, cbdcasing);
13036 if (cbdsh.sh != dummysh) {
13037 tsbond(oldbcv, cbdsh);
13038 }
13039 bond(oldcav, acdcasing);
13040 if (acdsh.sh != dummysh) {
13041 tsbond(oldcav, acdsh);
13042 }
13043
13044
13045 tetrahedrondealloc(badv.tet);
13046 tetrahedrondealloc(cbdv.tet);
13047 tetrahedrondealloc(acdv.tet);
13048 }
13049
13051
13052
13053
13054
13055
13056
13057
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13070
13071 void tetgenmesh::splittetface(point newpoint, triface* splittet,
13072 queue* flipqueue)
13073 {
13074 triface abcd, bace;
13075 triface oldbcd, oldcad, oldace, oldcbe;
13076 triface bcdcasing, cadcasing, acecasing, cbecasing;
13077 face abcsh, bcdsh, cadsh, acesh, cbesh;
13078 triface abvd, bcvd, cavd, bave, cbve, acve;
13079 triface worktet;
13080 face bcseg, caseg;
13081 face adseg, bdseg, cdseg;
13082 face aeseg, beseg, ceseg;
13083 point pa, pb, pc, pd, pe;
13084 REAL attrib, volume;
13085 bool mirrorflag;
13086 int i;
13087
13088 abcd = *splittet;
13089
13090 adjustedgering(abcd, CCW);
13091 pa = org(abcd);
13092 pb = dest(abcd);
13093 pc = apex(abcd);
13094 pd = oppo(abcd);
13095 pe = (point) NULL;
13096
13097 mirrorflag = issymexist(&abcd);
13098 if (mirrorflag) {
13099
13100 sym(abcd, bace);
13101 findedge(&bace, dest(abcd), org(abcd));
13102 pe = oppo(bace);
13103 }
13104 if (checksubfaces) {
13105
13106 tspivot(abcd, abcsh);
13107 if (abcsh.sh != dummysh) {
13108
13109 findedge(&abcsh, org(abcd), dest(abcd));
13110 }
13111 }
13112
13113 if (b->verbose > 1) {
13114 printf(" Inserting point %d on face (%d, %d, %d).\n", pointmark(newpoint),
13115 pointmark(pa), pointmark(pb), pointmark(pc));
13116 }
13117
13118
13119 enextfnext(abcd, oldbcd);
13120 enext2fnext(abcd, oldcad);
13121 sym(oldbcd, bcdcasing);
13122 sym(oldcad, cadcasing);
13123
13124 maketetrahedron(&bcvd);
13125 maketetrahedron(&cavd);
13126 if (mirrorflag) {
13127
13128 enextfnext(bace, oldace);
13129 enext2fnext(bace, oldcbe);
13130 sym(oldace, acecasing);
13131 sym(oldcbe, cbecasing);
13132
13133 maketetrahedron(&acve);
13134 maketetrahedron(&cbve);
13135 } else {
13136
13137 hullsize += 2;
13138 }
13139
13140
13141 abvd = abcd;
13142 setapex(abvd, newpoint);
13143 setorg (bcvd, pb);
13144 setdest(bcvd, pc);
13145 setapex(bcvd, newpoint);
13146 setoppo(bcvd, pd);
13147 setorg (cavd, pc);
13148 setdest(cavd, pa);
13149 setapex(cavd, newpoint);
13150 setoppo(cavd, pd);
13151
13152 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13153 attrib = elemattribute(abvd.tet, i);
13154 setelemattribute(bcvd.tet, i, attrib);
13155 setelemattribute(cavd.tet, i, attrib);
13156 }
13157 if (b->varvolume) {
13158
13159 volume = volumebound(abvd.tet);
13160 setvolumebound(bcvd.tet, volume);
13161 setvolumebound(cavd.tet, volume);
13162 }
13163 if (mirrorflag) {
13164 bave = bace;
13165 setapex(bave, newpoint);
13166 setorg (acve, pa);
13167 setdest(acve, pc);
13168 setapex(acve, newpoint);
13169 setoppo(acve, pe);
13170 setorg (cbve, pc);
13171 setdest(cbve, pb);
13172 setapex(cbve, newpoint);
13173 setoppo(cbve, pe);
13174
13175 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13176 attrib = elemattribute(bave.tet, i);
13177 setelemattribute(acve.tet, i, attrib);
13178 setelemattribute(cbve.tet, i, attrib);
13179 }
13180 if (b->varvolume) {
13181
13182 volume = volumebound(bave.tet);
13183 setvolumebound(acve.tet, volume);
13184 setvolumebound(cbve.tet, volume);
13185 }
13186 }
13187
13188
13189 bcvd.loc = 1;
13190 bond(bcvd, bcdcasing);
13191 cavd.loc = 1;
13192 bond(cavd, cadcasing);
13193 bcvd.loc = 3;
13194 bond(bcvd, oldbcd);
13195 cavd.loc = 2;
13196 bond(cavd, oldcad);
13197 bcvd.loc = 2;
13198 cavd.loc = 3;
13199 bond(bcvd, cavd);
13200 if (mirrorflag) {
13201 acve.loc = 1;
13202 bond(acve, acecasing);
13203 cbve.loc = 1;
13204 bond(cbve, cbecasing);
13205 acve.loc = 3;
13206 bond(acve, oldace);
13207 cbve.loc = 2;
13208 bond(cbve, oldcbe);
13209 acve.loc = 2;
13210 cbve.loc = 3;
13211 bond(acve, cbve);
13212
13213 bcvd.loc = 0;
13214 cbve.loc = 0;
13215 bond(bcvd, cbve);
13216 cavd.loc = 0;
13217 acve.loc = 0;
13218 bond(cavd, acve);
13219 }
13220
13221
13222 if (checksubfaces) {
13223 tspivot(oldbcd, bcdsh);
13224 if (bcdsh.sh != dummysh) {
13225 tsdissolve(oldbcd);
13226 bcvd.loc = 1;
13227 tsbond(bcvd, bcdsh);
13228 }
13229 tspivot(oldcad, cadsh);
13230 if (cadsh.sh != dummysh) {
13231 tsdissolve(oldcad);
13232 cavd.loc = 1;
13233 tsbond(cavd, cadsh);
13234 }
13235 if (mirrorflag) {
13236 tspivot(oldace, acesh);
13237 if (acesh.sh != dummysh) {
13238 tsdissolve(oldace);
13239 acve.loc = 1;
13240 tsbond(acve, acesh);
13241 }
13242 tspivot(oldcbe, cbesh);
13243 if (cbesh.sh != dummysh) {
13244 tsdissolve(oldcbe);
13245 cbve.loc = 1;
13246 tsbond(cbve, cbesh);
13247 }
13248 }
13249
13250 if (abcsh.sh != dummysh) {
13251
13252 splitsubface(newpoint, &abcsh, (queue *) NULL);
13253 }
13254 } else if (checksubsegs) {
13255
13256 bcvd.loc = bcvd.ver = 0;
13257 cavd.loc = cavd.ver = 0;
13258 if (mirrorflag) {
13259
13260 cbve.loc = cbve.ver = 0;
13261 acve.loc = acve.ver = 0;
13262 }
13263 enext(abvd, worktet);
13264 tsspivot1(worktet, bcseg);
13265 if (bcseg.sh != dummysh) {
13266 tssdissolve1(worktet);
13267 tssbond1(bcvd, bcseg);
13268 if (mirrorflag) {
13269 enext2(bave, worktet);
13270 tssdissolve1(worktet);
13271 tssbond1(cbve, bcseg);
13272 }
13273 }
13274 enext2(abvd, worktet);
13275 tsspivot1(worktet, caseg);
13276 if (caseg.sh != dummysh) {
13277 tssdissolve1(worktet);
13278 tssbond1(cavd, caseg);
13279 if (mirrorflag) {
13280 enext(bave, worktet);
13281 tssdissolve1(worktet);
13282 tssbond1(acve, caseg);
13283 }
13284 }
13285 fnext(abvd, worktet);
13286 enext2self(worktet);
13287 tsspivot1(worktet, adseg);
13288 if (adseg.sh != dummysh) {
13289 fnext(cavd, worktet);
13290 enextself(worktet);
13291 tssbond1(worktet, adseg);
13292 }
13293 fnext(abvd, worktet);
13294 enextself(worktet);
13295 tsspivot1(worktet, bdseg);
13296 if (bdseg.sh != dummysh) {
13297 fnext(bcvd, worktet);
13298 enext2self(worktet);
13299 tssbond1(worktet, bdseg);
13300 }
13301 enextfnext(abvd, worktet);
13302 enextself(worktet);
13303 tsspivot1(worktet, cdseg);
13304 if (cdseg.sh != dummysh) {
13305 tssdissolve1(worktet);
13306 fnext(bcvd, worktet);
13307 enextself(worktet);
13308 tssbond1(worktet, cdseg);
13309 fnext(cavd, worktet);
13310 enext2self(worktet);
13311 tssbond1(worktet, cdseg);
13312 }
13313 if (mirrorflag) {
13314 fnext(bave, worktet);
13315 enextself(worktet);
13316 tsspivot1(worktet, aeseg);
13317 if (aeseg.sh != dummysh) {
13318 fnext(acve, worktet);
13319 enext2self(worktet);
13320 tssbond1(worktet, aeseg);
13321 }
13322 fnext(bave, worktet);
13323 enext2self(worktet);
13324 tsspivot1(worktet, beseg);
13325 if (beseg.sh != dummysh) {
13326 fnext(cbve, worktet);
13327 enextself(worktet);
13328 tssbond1(worktet, beseg);
13329 }
13330 enextfnext(bave, worktet);
13331 enextself(worktet);
13332 tsspivot1(worktet, ceseg);
13333 if (ceseg.sh != dummysh) {
13334 tssdissolve1(worktet);
13335 fnext(cbve, worktet);
13336 enext2self(worktet);
13337 tssbond1(worktet, ceseg);
13338 fnext(acve, worktet);
13339 enextself(worktet);
13340 tssbond1(worktet, ceseg);
13341 }
13342 }
13343 }
13344
13345
13346 recenttet = abvd;
13347
13348 *splittet = abvd;
13349
13350 bcvd.loc = 0;
13351 cavd.loc = 0;
13352 if (mirrorflag) {
13353 cbve.loc = 0;
13354 acve.loc = 0;
13355 }
13356 if (b->verbose > 3) {
13357 printf(" Updating abvd ");
13358 printtet(&abvd);
13359 printf(" Creating bcvd ");
13360 printtet(&bcvd);
13361 printf(" Creating cavd ");
13362 printtet(&cavd);
13363 if (mirrorflag) {
13364 printf(" Updating bave ");
13365 printtet(&bave);
13366 printf(" Creating cbve ");
13367 printtet(&cbve);
13368 printf(" Creating acve ");
13369 printtet(&acve);
13370 }
13371 }
13372
13373 if (flipqueue != (queue *) NULL) {
13374 fnextself(abvd);
13375 enqueueflipface(abvd, flipqueue);
13376 fnextself(bcvd);
13377 enqueueflipface(bcvd, flipqueue);
13378 fnextself(cavd);
13379 enqueueflipface(cavd, flipqueue);
13380 if (mirrorflag) {
13381 fnextself(bave);
13382 enqueueflipface(bave, flipqueue);
13383 fnextself(cbve);
13384 enqueueflipface(cbve, flipqueue);
13385 fnextself(acve);
13386 enqueueflipface(acve, flipqueue);
13387 }
13388 }
13389 }
13390
13392
13393
13394
13395
13396
13397
13398
13399
13400
13401
13402
13403
13404
13405
13406
13407
13409
13410 void tetgenmesh::unsplittetface(triface* splittet)
13411 {
13412 triface abvd, bcvd, cavd, bave, cbve, acve;
13413 triface oldbvd, oldvad, oldvbe, oldave;
13414 triface bcdcasing, cadcasing, cbecasing, acecasing;
13415 face bcdsh, cadsh, cbesh, acesh;
13416 face abvsh;
13417 bool mirrorflag;
13418
13419 abvd = *splittet;
13420 adjustedgering(abvd, CCW);
13421 enextfnext(abvd, oldbvd);
13422 fnext(oldbvd, bcvd);
13423 esymself(bcvd);
13424 enextself(bcvd);
13425 enext2fnext(abvd, oldvad);
13426 fnext(oldvad, cavd);
13427 esymself(cavd);
13428 enext2self(cavd);
13429
13430 sym(abvd, bave);
13431 mirrorflag = bave.tet != dummytet;
13432 if (mirrorflag) {
13433 findedge(&bave, dest(abvd), org(abvd));
13434 enextfnext(bave, oldave);
13435 fnext(oldave, acve);
13436 esymself(acve);
13437 enextself(acve);
13438 enext2fnext(bave, oldvbe);
13439 fnext(oldvbe, cbve);
13440 esymself(cbve);
13441 enext2self(cbve);
13442 } else {
13443
13444 hullsize -= 2;
13445 }
13446
13447 tspivot(abvd, abvsh);
13448 if (abvsh.sh != dummysh) {
13449
13450 findedge(&abvsh, org(abvd), dest(abvd));
13451 }
13452
13453 if (b->verbose > 1) {
13454 printf(" Removing point %d on face (%d, %d, %d).\n",
13455 pointmark(apex(abvd)), pointmark(org(abvd)), pointmark(dest(abvd)),
13456 pointmark(dest(bcvd)));
13457 }
13458
13459 fnextself(bcvd);
13460 sym(bcvd, bcdcasing);
13461 tspivot(bcvd, bcdsh);
13462 fnextself(cavd);
13463 sym(cavd, cadcasing);
13464 tspivot(cavd, cadsh);
13465 if (mirrorflag) {
13466 fnextself(acve);
13467 sym(acve, acecasing);
13468 tspivot(acve, acesh);
13469 fnextself(cbve);
13470 sym(cbve, cbecasing);
13471 tspivot(cbve, cbesh);
13472 }
13473
13474
13475 setapex(abvd, dest(bcvd));
13476 bond(oldbvd, bcdcasing);
13477 if (bcdsh.sh != dummysh) {
13478 tsbond(oldbvd, bcdsh);
13479 }
13480 bond(oldvad, cadcasing);
13481 if (cadsh.sh != dummysh) {
13482 tsbond(oldvad, cadsh);
13483 }
13484 if (mirrorflag) {
13485
13486 setapex(bave, dest(acve));
13487 bond(oldave, acecasing);
13488 if (acesh.sh != dummysh) {
13489 tsbond(oldave, acesh);
13490 }
13491 bond(oldvbe, cbecasing);
13492 if (cbesh.sh != dummysh) {
13493 tsbond(oldvbe, cbesh);
13494 }
13495 }
13496
13497
13498 if (abvsh.sh != dummysh) {
13499 unsplitsubface(&abvsh);
13500 }
13501
13502
13503 tetrahedrondealloc(bcvd.tet);
13504 tetrahedrondealloc(cavd.tet);
13505 if (mirrorflag) {
13506 tetrahedrondealloc(acve.tet);
13507 tetrahedrondealloc(cbve.tet);
13508 }
13509 }
13510
13512
13513
13514
13515
13516
13517
13518
13519
13520
13521
13522
13523
13524
13525
13526
13527
13528
13529
13530
13531
13532
13534
13535 void tetgenmesh::splitsubface(point newpoint, face* splitface,
13536 queue* flipqueue)
13537 {
13538 triface abvd, bcvd, cavd, bave, cbve, acve;
13539 face abc, oldbc, oldca, bc, ca, spinsh;
13540 face bccasin, bccasout, cacasin, cacasout;
13541 face abv, bcv, cav;
13542 point pa, pb, pc;
13543
13544 abc = *splitface;
13545
13546 adjustedgering(abc, CCW);
13547 pa = sorg(abc);
13548 pb = sdest(abc);
13549 pc = sapex(abc);
13550
13551 if (b->verbose > 1) {
13552 printf(" Inserting point %d on subface (%d, %d, %d).\n",
13553 pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc));
13554 }
13555
13556
13557
13558 senext(abc, oldbc);
13559 senext2(abc, oldca);
13560 spivot(oldbc, bccasout);
13561 sspivot(oldbc, bc);
13562 if (bc.sh != dummysh) {
13563 if (oldbc.sh != bccasout.sh) {
13564
13565 spinsh = bccasout;
13566 do {
13567 bccasin = spinsh;
13568 spivotself(spinsh);
13569 } while (spinsh.sh != oldbc.sh);
13570 } else {
13571 bccasout.sh = dummysh;
13572 }
13573 ssdissolve(oldbc);
13574 }
13575 spivot(oldca, cacasout);
13576 sspivot(oldca, ca);
13577 if (ca.sh != dummysh) {
13578 if (oldca.sh != cacasout.sh) {
13579
13580 spinsh = cacasout;
13581 do {
13582 cacasin = spinsh;
13583 spivotself(spinsh);
13584 } while (spinsh.sh != oldca.sh);
13585 } else {
13586 cacasout.sh = dummysh;
13587 }
13588 ssdissolve(oldca);
13589 }
13590
13591 makeshellface(subfaces, &bcv);
13592 makeshellface(subfaces, &cav);
13593
13594
13595 abv = abc;
13596 setsapex(abv, newpoint);
13597 setsorg(bcv, pb);
13598 setsdest(bcv, pc);
13599 setsapex(bcv, newpoint);
13600 setsorg(cav, pc);
13601 setsdest(cav, pa);
13602 setsapex(cav, newpoint);
13603 if (b->quality && varconstraint) {
13604
13605 setareabound(bcv, areabound(abv));
13606 setareabound(cav, areabound(abv));
13607 }
13608
13609 setshellmark(bcv, shellmark(abv));
13610 setshellmark(cav, shellmark(abv));
13611
13612 setshelltype(bcv, shelltype(abv));
13613 setshelltype(cav, shelltype(abv));
13614 if (checkpbcs) {
13615
13616 setshellpbcgroup(bcv, shellpbcgroup(abv));
13617 setshellpbcgroup(cav, shellpbcgroup(abv));
13618 }
13619
13620 if (bc.sh != dummysh) {
13621 if (bccasout.sh != dummysh) {
13622 sbond1(bccasin, bcv);
13623 sbond1(bcv, bccasout);
13624 } else {
13625
13626 sbond(bcv, bcv);
13627 }
13628 ssbond(bcv, bc);
13629 } else {
13630 sbond(bcv, bccasout);
13631 }
13632 if (ca.sh != dummysh) {
13633 if (cacasout.sh != dummysh) {
13634 sbond1(cacasin, cav);
13635 sbond1(cav, cacasout);
13636 } else {
13637
13638 sbond(cav, cav);
13639 }
13640 ssbond(cav, ca);
13641 } else {
13642 sbond(cav, cacasout);
13643 }
13644 senext2self(bcv);
13645 sbond(bcv, oldbc);
13646 senextself(cav);
13647 sbond(cav, oldca);
13648 senext2self(bcv);
13649 senextself(cav);
13650 sbond(bcv, cav);
13651
13652
13653 stpivot(abv, abvd);
13654 if (abvd.tet != dummytet) {
13655
13656 findedge(&abvd, sorg(abv), sdest(abv));
13657 enextfnext(abvd, bcvd);
13658 #ifdef SELF_CHECK
13659 assert(bcvd.tet != dummytet);
13660 #endif
13661 fnextself(bcvd);
13662 enext2fnext(abvd, cavd);
13663 #ifdef SELF_CHECK
13664 assert(cavd.tet != dummytet);
13665 #endif
13666 fnextself(cavd);
13667
13668 tsbond(bcvd, bcv);
13669 tsbond(cavd, cav);
13670 }
13671
13672 sesymself(abv);
13673 stpivot(abv, bave);
13674 if (bave.tet != dummytet) {
13675 sesymself(bcv);
13676 sesymself(cav);
13677
13678 findedge(&bave, sorg(abv), sdest(abv));
13679 enextfnext(bave, acve);
13680 #ifdef SELF_CHECK
13681 assert(acve.tet != dummytet);
13682 #endif
13683 fnextself(acve);
13684 enext2fnext(bave, cbve);
13685 #ifdef SELF_CHECK
13686 assert(cbve.tet != dummytet);
13687 #endif
13688 fnextself(cbve);
13689
13690 tsbond(acve, cav);
13691 tsbond(cbve, bcv);
13692 }
13693
13694 bcv.shver = 0;
13695 cav.shver = 0;
13696 if (b->verbose > 3) {
13697 printf(" Updating abv ");
13698 printsh(&abv);
13699 printf(" Creating bcv ");
13700 printsh(&bcv);
13701 printf(" Creating cav ");
13702 printsh(&cav);
13703 }
13704
13705 if (flipqueue != (queue *) NULL) {
13706 enqueueflipedge(abv, flipqueue);
13707 enqueueflipedge(bcv, flipqueue);
13708 enqueueflipedge(cav, flipqueue);
13709 }
13710
13711
13712 *splitface = abv;
13713 }
13714
13716
13717
13718
13719
13720
13721
13722
13723
13724
13725
13726
13727
13729
13730 void tetgenmesh::unsplitsubface(face* splitsh)
13731 {
13732 face abv, bcv, cav;
13733 face oldbv, oldva, bc, ca, spinsh;
13734 face bccasin, bccasout, cacasin, cacasout;
13735
13736 abv = *splitsh;
13737 senext(abv, oldbv);
13738 spivot(oldbv, bcv);
13739 if (sorg(bcv) != sdest(oldbv)) {
13740 sesymself(bcv);
13741 }
13742 senextself(bcv);
13743 senext2(abv, oldva);
13744 spivot(oldva, cav);
13745 if (sorg(cav) != sdest(oldva)) {
13746 sesymself(cav);
13747 }
13748 senext2self(cav);
13749
13750 if (b->verbose > 1) {
13751 printf(" Removing point %d on subface (%d, %d, %d).\n",
13752 pointmark(sapex(abv)), pointmark(sorg(abv)), pointmark(sdest(abv)),
13753 pointmark(sdest(bcv)));
13754 }
13755
13756 spivot(bcv, bccasout);
13757 sspivot(bcv, bc);
13758 if (bc.sh != dummysh) {
13759 if (bcv.sh != bccasout.sh) {
13760
13761 spinsh = bccasout;
13762 do {
13763 bccasin = spinsh;
13764 spivotself(spinsh);
13765 } while (spinsh.sh != bcv.sh);
13766 } else {
13767 bccasout.sh = dummysh;
13768 }
13769 }
13770 spivot(cav, cacasout);
13771 sspivot(cav, ca);
13772 if (ca.sh != dummysh) {
13773 if (cav.sh != cacasout.sh) {
13774
13775 spinsh = cacasout;
13776 do {
13777 cacasin = spinsh;
13778 spivotself(spinsh);
13779 } while (spinsh.sh != cav.sh);
13780 } else {
13781 cacasout.sh = dummysh;
13782 }
13783 }
13784
13785
13786 setsapex(abv, sdest(bcv));
13787 if (bc.sh != dummysh) {
13788 if (bccasout.sh != dummysh) {
13789 sbond1(bccasin, oldbv);
13790 sbond1(oldbv, bccasout);
13791 } else {
13792
13793 sbond(oldbv, oldbv);
13794 }
13795 ssbond(oldbv, bc);
13796 } else {
13797 sbond(oldbv, bccasout);
13798 }
13799 if (ca.sh != dummysh) {
13800 if (cacasout.sh != dummysh) {
13801 sbond1(cacasin, oldva);
13802 sbond1(oldva, cacasout);
13803 } else {
13804
13805 sbond(oldva, oldva);
13806 }
13807 ssbond(oldva, ca);
13808 } else {
13809 sbond(oldva, cacasout);
13810 }
13811
13812
13813 shellfacedealloc(subfaces, bcv.sh);
13814 shellfacedealloc(subfaces, cav.sh);
13815 }
13816
13818
13819
13820
13821
13822
13823
13824
13825
13826
13827
13828
13829
13830
13831
13832
13833
13834
13835
13836
13837
13838
13840
13841 void tetgenmesh::splittetedge(point newpoint, triface* splittet,
13842 queue* flipqueue)
13843 {
13844 triface *bots, *newtops;
13845 triface oldtop, topcasing;
13846 triface spintet, tmpbond0, tmpbond1;
13847 face abseg, splitsh, topsh, spinsh;
13848 triface worktet;
13849 face n1n2seg, n2vseg, n1vseg;
13850 point pa, pb, n1, n2;
13851 REAL attrib, volume;
13852 int wrapcount, hitbdry;
13853 int i, j;
13854
13855 if (checksubfaces) {
13856
13857 tsspivot(splittet, &abseg);
13858 if (abseg.sh != dummysh) {
13859 abseg.shver = 0;
13860
13861 if (org(*splittet) != sorg(abseg)) {
13862 esymself(*splittet);
13863 }
13864 }
13865 }
13866 spintet = *splittet;
13867 pa = org(spintet);
13868 pb = dest(spintet);
13869
13870 if (b->verbose > 1) {
13871 printf(" Inserting point %d on edge (%d, %d).\n",
13872 pointmark(newpoint), pointmark(pa), pointmark(pb));
13873 }
13874
13875
13876 n1 = apex(spintet);
13877 hitbdry = 0;
13878 wrapcount = 1;
13879 if (checksubfaces && abseg.sh != dummysh) {
13880
13881
13882
13883 while (true) {
13884 if (!fnextself(spintet)) {
13885
13886 hitbdry ++;
13887 tspivot(spintet, spinsh);
13888 #ifdef SELF_CHECK
13889 assert(spinsh.sh != dummysh);
13890 #endif
13891 findedge(&spinsh, pa, pb);
13892 sfnextself(spinsh);
13893 stpivot(spinsh, spintet);
13894 #ifdef SELF_CHECK
13895 assert(spintet.tet != dummytet);
13896 #endif
13897 findedge(&spintet, pa, pb);
13898
13899 *splittet = spintet;
13900
13901 hullsize += 2;
13902 }
13903 if (apex(spintet) == n1) break;
13904 wrapcount ++;
13905 }
13906 if (hitbdry > 0) {
13907 wrapcount -= hitbdry;
13908 }
13909 } else {
13910
13911
13912 splitsh.sh = dummysh;
13913 while (hitbdry < 2) {
13914 if (checksubfaces && splitsh.sh == dummysh) {
13915 tspivot(spintet, splitsh);
13916 }
13917 if (fnextself(spintet)) {
13918 if (apex(spintet) == n1) break;
13919 wrapcount++;
13920 } else {
13921 hitbdry ++;
13922 if (hitbdry < 2) {
13923 esym(*splittet, spintet);
13924 }
13925 }
13926 }
13927 if (hitbdry > 0) {
13928
13929 wrapcount -= 1;
13930
13931 esym(spintet, *splittet);
13932
13933 hullsize += 2;
13934 }
13935 }
13936
13937
13938 bots = new triface[wrapcount];
13939 newtops = new triface[wrapcount];
13940
13941 spintet = *splittet;
13942 for (i = 0; i < wrapcount; i++) {
13943
13944 enext2fnext(spintet, bots[i]);
13945 esymself(bots[i]);
13946
13947 maketetrahedron(&(newtops[i]));
13948
13949 fnextself(spintet);
13950 if (checksubfaces && abseg.sh != dummysh) {
13951 if (!issymexist(&spintet)) {
13952
13953 tspivot(spintet, spinsh);
13954 #ifdef SELF_CHECK
13955 assert(spinsh.sh != dummysh);
13956 #endif
13957 findedge(&spinsh, pa, pb);
13958 sfnextself(spinsh);
13959 stpivot(spinsh, spintet);
13960 #ifdef SELF_CHECK
13961 assert(spintet.tet != dummytet);
13962 #endif
13963 findedge(&spintet, pa, pb);
13964 }
13965 }
13966 }
13967
13968
13969 for (i = 0; i < wrapcount; i++) {
13970
13971 setoppo(bots[i], newpoint);
13972
13973 n1 = dest(bots[i]);
13974 n2 = apex(bots[i]);
13975
13976 setorg(newtops[i], pb);
13977 setdest(newtops[i], n2);
13978 setapex(newtops[i], n1);
13979 setoppo(newtops[i], newpoint);
13980
13981 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
13982 attrib = elemattribute(bots[i].tet, j);
13983 setelemattribute(newtops[i].tet, j, attrib);
13984 }
13985 if (b->varvolume) {
13986
13987 volume = volumebound(bots[i].tet);
13988 setvolumebound(newtops[i].tet, volume);
13989 }
13990 #ifdef SELF_CHECK
13991
13992
13993
13994
13995
13996
13997
13998
13999
14000 #endif
14001 }
14002
14003
14004 for (i = 0; i < wrapcount; i++) {
14005
14006 enextfnext(bots[i], oldtop);
14007 sym(oldtop, topcasing);
14008 bond(newtops[i], topcasing);
14009 if (checksubfaces) {
14010 tspivot(oldtop, topsh);
14011 if (topsh.sh != dummysh) {
14012 tsdissolve(oldtop);
14013 tsbond(newtops[i], topsh);
14014 }
14015 }
14016 enextfnext(newtops[i], tmpbond0);
14017 bond(oldtop, tmpbond0);
14018 }
14019
14020 fnext(newtops[0], tmpbond0);
14021 enext2fnext(bots[0], spintet);
14022 for (i = 1; i < wrapcount; i ++) {
14023 if (issymexist(&spintet)) {
14024 enext2fnext(newtops[i], tmpbond1);
14025 bond(tmpbond0, tmpbond1);
14026 }
14027 fnext(newtops[i], tmpbond0);
14028 enext2fnext(bots[i], spintet);
14029 }
14030
14031 if (issymexist(&spintet)) {
14032 enext2fnext(newtops[0], tmpbond1);
14033 bond(tmpbond0, tmpbond1);
14034 }
14035 if (checksubsegs) {
14036 for (i = 0; i < wrapcount; i++) {
14037 enextfnext(bots[i], worktet);
14038 tsspivot1(worktet, n1n2seg);
14039 if (n1n2seg.sh != dummysh) {
14040 enext(newtops[i], tmpbond0);
14041 tssbond1(tmpbond0, n1n2seg);
14042 }
14043 enextself(worktet);
14044 tsspivot1(worktet, n2vseg);
14045 if (n2vseg.sh != dummysh) {
14046 tssdissolve1(worktet);
14047 tssbond1(newtops[i], n2vseg);
14048 }
14049 enextself(worktet);
14050 tsspivot1(worktet, n1vseg);
14051 if (n1vseg.sh != dummysh) {
14052 tssdissolve1(worktet);
14053 enext2(newtops[i], tmpbond0);
14054 tssbond1(tmpbond0, n1vseg);
14055 }
14056 }
14057 }
14058
14059
14060 if (checksubfaces) {
14061 if (abseg.sh != dummysh) {
14062
14063 spivot(abseg, splitsh);
14064 #ifdef SELF_CHECK
14065 assert(splitsh.sh != dummysh);
14066 #endif
14067 }
14068 if (splitsh.sh != dummysh) {
14069
14070 findedge(&splitsh, pa, pb);
14071 splitsubedge(newpoint, &splitsh, (queue *) NULL);
14072 }
14073 }
14074
14075 if (b->verbose > 3) {
14076 for (i = 0; i < wrapcount; i++) {
14077 printf(" Updating bots[%i] ", i);
14078 printtet(&(bots[i]));
14079 printf(" Creating newtops[%i] ", i);
14080 printtet(&(newtops[i]));
14081 }
14082 }
14083
14084 if (flipqueue != (queue *) NULL) {
14085 for (i = 0; i < wrapcount; i++) {
14086 enqueueflipface(bots[i], flipqueue);
14087 enqueueflipface(newtops[i], flipqueue);
14088 }
14089 }
14090
14091
14092
14093 fnext(bots[0], spintet);
14094 esymself(spintet);
14095 enextself(spintet);
14096 *splittet = spintet;
14097
14098 delete [] bots;
14099 delete [] newtops;
14100 }
14101
14103
14104
14105
14106
14107
14108
14109
14110
14111
14112
14113
14114
14115
14116
14117
14119
14120 void tetgenmesh::unsplittetedge(triface* splittet)
14121 {
14122 triface *bots, *newtops;
14123 triface oldtop, topcasing;
14124 triface spintet;
14125 face avseg, splitsh, topsh, spinsh;
14126 point pa, pv, n1;
14127 int wrapcount, hitbdry;
14128 int i;
14129
14130 spintet = *splittet;
14131 pa = org(spintet);
14132 pv = dest(spintet);
14133 if (checksubfaces) {
14134
14135 tsspivot(splittet, &avseg);
14136 if (avseg.sh != dummysh) {
14137
14138 if (sorg(avseg) != pa) {
14139 sesymself(avseg);
14140 }
14141 }
14142 }
14143
14144 n1 = apex(spintet);
14145 hitbdry = 0;
14146 wrapcount = 1;
14147 if (checksubfaces && avseg.sh != dummysh) {
14148
14149
14150
14151 while (true) {
14152 if (!fnextself(spintet)) {
14153
14154 hitbdry ++;
14155 tspivot(spintet, spinsh);
14156 #ifdef SELF_CHECK
14157 assert(spinsh.sh != dummysh);
14158 #endif
14159 findedge(&spinsh, pa, pv);
14160 sfnextself(spinsh);
14161 stpivot(spinsh, spintet);
14162 #ifdef SELF_CHECK
14163 assert(spintet.tet != dummytet);
14164 #endif
14165 findedge(&spintet, pa, pv);
14166
14167 *splittet = spintet;
14168
14169 hullsize += 2;
14170 }
14171 if (apex(spintet) == n1) break;
14172 wrapcount ++;
14173 }
14174 if (hitbdry > 0) {
14175 wrapcount -= hitbdry;
14176 }
14177 } else {
14178
14179
14180 splitsh.sh = dummysh;
14181 while (hitbdry < 2) {
14182 if (checksubfaces && splitsh.sh == dummysh) {
14183 tspivot(spintet, splitsh);
14184 }
14185 if (fnextself(spintet)) {
14186 if (apex(spintet) == n1) break;
14187 wrapcount++;
14188 } else {
14189 hitbdry ++;
14190 if (hitbdry < 2) {
14191 esym(*splittet, spintet);
14192 }
14193 }
14194 }
14195 if (hitbdry > 0) {
14196
14197 wrapcount -= 1;
14198
14199 esym(spintet, *splittet);
14200
14201 hullsize += 2;
14202 }
14203 }
14204
14205
14206 bots = new triface[wrapcount];
14207 newtops = new triface[wrapcount];
14208
14209 spintet = *splittet;
14210 for (i = 0; i < wrapcount; i++) {
14211
14212 enext2fnext(spintet, bots[i]);
14213 esymself(bots[i]);
14214
14215 enextfnext(bots[i], oldtop);
14216
14217 fnext(oldtop, newtops[i]);
14218 esymself(newtops[i]);
14219 enext2self(newtops[i]);
14220
14221 fnextself(spintet);
14222 if (checksubfaces && avseg.sh != dummysh) {
14223 if (!issymexist(&spintet)) {
14224
14225 tspivot(spintet, spinsh);
14226 #ifdef SELF_CHECK
14227 assert(spinsh.sh != dummysh);
14228 #endif
14229 findedge(&spinsh, pa, pv);
14230 sfnextself(spinsh);
14231 stpivot(spinsh, spintet);
14232 #ifdef SELF_CHECK
14233 assert(spintet.tet != dummytet);
14234 #endif
14235 findedge(&spintet, pa, pv);
14236 }
14237 }
14238 }
14239
14240 if (b->verbose > 1) {
14241 printf(" Removing point %d from edge (%d, %d).\n",
14242 pointmark(oppo(bots[0])), pointmark(org(bots[0])),
14243 pointmark(org(newtops[0])));
14244 }
14245
14246 for (i = 0; i < wrapcount; i++) {
14247
14248 setoppo(bots[i], org(newtops[i]));
14249
14250 enextfnext(bots[i], oldtop);
14251
14252 sym(newtops[i], topcasing);
14253
14254 bond(oldtop, topcasing);
14255 if (checksubfaces) {
14256 tspivot(newtops[i], topsh);
14257 if (topsh.sh != dummysh) {
14258 tsbond(oldtop, topsh);
14259 }
14260 }
14261
14262 tetrahedrondealloc(newtops[i].tet);
14263 }
14264
14265
14266 if (checksubfaces) {
14267 if (avseg.sh != dummysh) {
14268 spivot(avseg, splitsh);
14269 #ifdef SELF_CHECK
14270 assert(splitsh.sh != dummysh);
14271 #endif
14272 }
14273 if (splitsh.sh != dummysh) {
14274 findedge(&splitsh, pa, pv);
14275 unsplitsubedge(&splitsh);
14276 }
14277 }
14278
14279 delete [] bots;
14280 delete [] newtops;
14281 }
14282
14284
14285
14286
14287
14288
14289
14290
14291
14292
14293
14294
14295
14296
14297
14298
14299
14300
14301
14302
14303
14305
14306 void tetgenmesh::splitsubedge(point newpoint, face* splitsh, queue* flipqueue)
14307 {
14308 triface abcd, bace, vbcd, bvce;
14309 face startabc, spinabc, spinsh;
14310 face oldbc, bccasin, bccasout;
14311 face ab, bc;
14312 face avc, vbc, vbc1;
14313 face av, vb;
14314 point pa, pb;
14315
14316 startabc = *splitsh;
14317
14318 sspivot(startabc, ab);
14319 if (ab.sh != dummysh) {
14320 ab.shver = 0;
14321 if (sorg(startabc) != sorg(ab)) {
14322 sesymself(startabc);
14323 }
14324 }
14325 pa = sorg(startabc);
14326 pb = sdest(startabc);
14327
14328 if (b->verbose > 1) {
14329 printf(" Inserting point %d on subedge (%d, %d) %s.\n",
14330 pointmark(newpoint), pointmark(pa), pointmark(pb),
14331 (ab.sh != dummysh ? "(seg)" : " "));
14332 }
14333
14334
14335 spinabc = startabc;
14336 do {
14337
14338 if (sorg(spinabc) != pa) {
14339 sesymself(spinabc);
14340 }
14341
14342
14343 senext(spinabc, oldbc);
14344 spivot(oldbc, bccasout);
14345 sspivot(oldbc, bc);
14346 if (bc.sh != dummysh) {
14347 if (spinabc.sh != bccasout.sh) {
14348
14349 spinsh = bccasout;
14350 do {
14351 bccasin = spinsh;
14352 spivotself(spinsh);
14353 } while (spinsh.sh != oldbc.sh);
14354 } else {
14355 bccasout.sh = dummysh;
14356 }
14357 ssdissolve(oldbc);
14358 }
14359
14360 makeshellface(subfaces, &vbc);
14361
14362 avc = spinabc;
14363 setsdest(avc, newpoint);
14364
14365 vbc.shver = avc.shver;
14366 setsorg(vbc, newpoint);
14367 setsdest(vbc, pb);
14368 setsapex(vbc, sapex(avc));
14369 if (b->quality && varconstraint) {
14370
14371 setareabound(vbc, areabound(avc));
14372 }
14373
14374 setshellmark(vbc, shellmark(avc));
14375 setshelltype(vbc, shelltype(avc));
14376 if (checkpbcs) {
14377
14378 setshellpbcgroup(vbc, shellpbcgroup(avc));
14379 }
14380
14381 senext2self(vbc);
14382 sbond(vbc, oldbc);
14383
14384 senext2self(vbc);
14385 if (bc.sh != dummysh) {
14386 if (bccasout.sh != dummysh) {
14387
14388 sbond1(bccasin, vbc);
14389 sbond1(vbc, bccasout);
14390 } else {
14391
14392 sbond(vbc, vbc);
14393 }
14394 ssbond(vbc, bc);
14395 } else {
14396 sbond(vbc, bccasout);
14397 }
14398
14399 spivotself(spinabc);
14400 if (spinabc.sh == dummysh) {
14401 break;
14402 }
14403 } while (spinabc.sh != startabc.sh);
14404
14405
14406 senext(startabc, oldbc);
14407 spivot(oldbc, vbc);
14408 if (sorg(vbc) == newpoint) {
14409 sesymself(vbc);
14410 }
14411 #ifdef SELF_CHECK
14412 assert(sorg(vbc) == sdest(oldbc) && sdest(vbc) == sorg(oldbc));
14413 #endif
14414 senextself(vbc);
14415
14416 spinabc = startabc;
14417 do {
14418
14419 spivotself(spinabc);
14420 if (spinabc.sh == dummysh) {
14421 break;
14422 }
14423 if (sorg(spinabc) != pa) {
14424 sesymself(spinabc);
14425 }
14426
14427 senext(spinabc, oldbc);
14428 spivot(oldbc, vbc1);
14429 if (sorg(vbc1) == newpoint) {
14430 sesymself(vbc1);
14431 }
14432 #ifdef SELF_CHECK
14433 assert(sorg(vbc1) == sdest(oldbc) && sdest(vbc1) == sorg(oldbc));
14434 #endif
14435 senextself(vbc1);
14436
14437 sbond1(vbc, vbc1);
14438
14439 vbc = vbc1;
14440 } while (spinabc.sh != startabc.sh);
14441
14442
14443 if (ab.sh != dummysh) {
14444
14445 av = ab;
14446 setsdest(av, newpoint);
14447
14448 makeshellface(subsegs, &vb);
14449 setsorg(vb, newpoint);
14450 setsdest(vb, pb);
14451
14452 setshellmark(vb, shellmark(av));
14453 setshelltype(vb, shelltype(av));
14454 if (b->quality && varconstraint) {
14455
14456 setareabound(vb, areabound(av));
14457 }
14458
14459 senext(av, oldbc);
14460 spivot(oldbc, bccasout);
14461
14462 senext2(vb, bccasin);
14463 sbond(bccasin, oldbc);
14464 if (bccasout.sh != dummysh) {
14465
14466
14467 bccasout.shver = 0;
14468 if (sorg(bccasout) != pb) sesymself(bccasout);
14469 #ifdef SELF_CHECK
14470 assert(sorg(bccasout) == pb);
14471 #endif
14472 senext2self(bccasout);
14473 senext(vb, bccasin);
14474 sbond(bccasin, bccasout);
14475 }
14476
14477 spinabc = startabc;
14478 do {
14479
14480 if (sorg(spinabc) != pa) {
14481 sesymself(spinabc);
14482 }
14483
14484 senext(spinabc, oldbc);
14485 spivot(oldbc, vbc);
14486 if (sorg(vbc) == newpoint) {
14487 sesymself(vbc);
14488 }
14489 senextself(vbc);
14490
14491 ssbond(vbc, vb);
14492
14493 spivotself(spinabc);
14494 #ifdef SELF_CHECK
14495 assert(spinabc.sh != dummysh);
14496 #endif
14497 } while (spinabc.sh != startabc.sh);
14498 }
14499
14500
14501
14502 spinabc = startabc;
14503 do {
14504
14505 if (sorg(spinabc) != pa) {
14506 sesymself(spinabc);
14507 }
14508
14509 senext(spinabc, oldbc);
14510 spivot(oldbc, vbc);
14511 if (sorg(vbc) == newpoint) {
14512 sesymself(vbc);
14513 }
14514 senextself(vbc);
14515
14516 stpivot(spinabc, abcd);
14517 if (abcd.tet != dummytet) {
14518 findedge(&abcd, sorg(spinabc), sdest(spinabc));
14519 enextfnext(abcd, vbcd);
14520 fnextself(vbcd);
14521 #ifdef SELF_CHECK
14522 assert(vbcd.tet != dummytet);
14523 #endif
14524 tsbond(vbcd, vbc);
14525 sym(vbcd, bvce);
14526 sesymself(vbc);
14527 tsbond(bvce, vbc);
14528 } else {
14529
14530 sesymself(spinabc);
14531 stpivot(spinabc, bace);
14532 if (bace.tet != dummytet) {
14533 findedge(&bace, sorg(spinabc), sdest(spinabc));
14534 enext2fnext(bace, bvce);
14535 fnextself(bvce);
14536 #ifdef SELF_CHECK
14537 assert(bvce.tet != dummytet);
14538 #endif
14539 sesymself(vbc);
14540 tsbond(bvce, vbc);
14541 }
14542 }
14543
14544 spivotself(spinabc);
14545 if (spinabc.sh == dummysh) {
14546 break;
14547 }
14548 } while (spinabc.sh != startabc.sh);
14549
14550 if (b->verbose > 3) {
14551 spinabc = startabc;
14552 do {
14553
14554 if (sorg(spinabc) != pa) {
14555 sesymself(spinabc);
14556 }
14557 printf(" Updating abc:\n");
14558 printsh(&spinabc);
14559
14560 senext(spinabc, oldbc);
14561 spivot(oldbc, vbc);
14562 if (sorg(vbc) == newpoint) {
14563 sesymself(vbc);
14564 }
14565 senextself(vbc);
14566 printf(" Creating vbc:\n");
14567 printsh(&vbc);
14568
14569 spivotself(spinabc);
14570 if (spinabc.sh == dummysh) {
14571 break;
14572 }
14573 } while (spinabc.sh != startabc.sh);
14574 }
14575
14576 if (flipqueue != (queue *) NULL) {
14577 spinabc = startabc;
14578 do {
14579
14580 if (sorg(spinabc) != pa) {
14581 sesymself(spinabc);
14582 }
14583 senext2(spinabc, oldbc);
14584 enqueueflipedge(oldbc, flipqueue);
14585
14586 senext(spinabc, oldbc);
14587 spivot(oldbc, vbc);
14588 if (sorg(vbc) == newpoint) {
14589 sesymself(vbc);
14590 }
14591 senextself(vbc);
14592 senext(vbc, oldbc);
14593 enqueueflipedge(oldbc, flipqueue);
14594
14595 spivotself(spinabc);
14596 if (spinabc.sh == dummysh) {
14597 break;
14598 }
14599 } while (spinabc.sh != startabc.sh);
14600 }
14601 }
14602
14604
14605
14606
14607
14608
14609
14610
14611
14612
14613
14614
14615
14616
14617
14619
14620 void tetgenmesh::unsplitsubedge(face* splitsh)
14621 {
14622 face startavc, spinavc, spinbcv;
14623 face oldvc, bccasin, bccasout, spinsh;
14624 face av, vb, bc;
14625 point pa, pv, pb;
14626
14627 startavc = *splitsh;
14628 sspivot(startavc, av);
14629 if (av.sh != dummysh) {
14630
14631 if (sorg(av) != sorg(startavc)) {
14632 sesymself(av);
14633 }
14634 #ifdef SELF_CHECK
14635 assert(av.shver == 0);
14636 #endif
14637 }
14638 senext(startavc, oldvc);
14639 spivot(oldvc, vb);
14640 if (sorg(vb) != sdest(oldvc)) {
14641 sesymself(vb);
14642 }
14643 senextself(vb);
14644 pa = sorg(startavc);
14645 pv = sdest(startavc);
14646 pb = sdest(vb);
14647
14648 if (b->verbose > 1) {
14649 printf(" Removing point %d from subedge (%d, %d).\n",
14650 pointmark(pv), pointmark(pa), pointmark(pb));
14651 }
14652
14653
14654 spinavc = startavc;
14655 do {
14656
14657 if (sorg(spinavc) != pa) {
14658 sesymself(spinavc);
14659 }
14660
14661
14662 senext(spinavc, oldvc);
14663 spivot(oldvc, spinbcv);
14664 if (sorg(spinbcv) != sdest(oldvc)) {
14665 sesymself(spinbcv);
14666 }
14667 senext2self(spinbcv);
14668 spivot(spinbcv, bccasout);
14669 sspivot(spinbcv, bc);
14670 if (bc.sh != dummysh) {
14671 if (spinbcv.sh != bccasout.sh) {
14672
14673 spinsh = bccasout;
14674 do {
14675 bccasin = spinsh;
14676 spivotself(spinsh);
14677 } while (spinsh.sh != spinbcv.sh);
14678 } else {
14679 bccasout.sh = dummysh;
14680 }
14681 }
14682
14683 setsdest(spinavc, pb);
14684 if (bc.sh != dummysh) {
14685 if (bccasout.sh != dummysh) {
14686 sbond1(bccasin, oldvc);
14687 sbond1(oldvc, bccasout);
14688 } else {
14689
14690 sbond(oldvc, oldvc);
14691 }
14692 ssbond(oldvc, bc);
14693 } else {
14694 sbond(oldvc, bccasout);
14695 }
14696
14697 shellfacedealloc(subfaces, spinbcv.sh);
14698
14699 spivotself(spinavc);
14700 if (spinavc.sh == dummysh) {
14701 break;
14702 }
14703 } while (spinavc.sh != startavc.sh);
14704
14705
14706 if (av.sh != dummysh) {
14707 senext(av, oldvc);
14708 spivot(oldvc, vb);
14709 vb.shver = 0;
14710 #ifdef SELF_CHECK
14711 assert(sdest(av) == sorg(vb));
14712 #endif
14713 senext(vb, spinbcv);
14714 spivot(spinbcv, bccasout);
14715
14716 setsdest(av, pb);
14717 sbond(oldvc, bccasout);
14718
14719 shellfacedealloc(subsegs, vb.sh);
14720 }
14721 }
14722
14724
14725
14726
14727
14728
14729
14730
14731
14732
14733
14734
14735
14736
14737
14738
14739
14740
14741
14742
14744
14745 enum tetgenmesh::insertsiteresult tetgenmesh::insertsite(point newpoint,
14746 triface* searchtet, bool approx, queue* flipqueue)
14747 {
14748 enum locateresult intersect, exactloc;
14749 point checkpt;
14750 REAL epspp, checklen;
14751 int count;
14752
14753 if (b->verbose > 1) {
14754 printf(" Insert point to mesh: (%.12g, %.12g, %.12g) %d.\n",
14755 newpoint[0], newpoint[1], newpoint[2], pointmark(newpoint));
14756 }
14757
14758 if (searchtet->tet == (tetrahedron *) NULL) {
14759
14760 searchtet->tet = dummytet;
14761 exactloc = locate(newpoint, searchtet);
14762 } else {
14763
14764 exactloc = preciselocate(newpoint, searchtet, tetrahedrons->items);
14765 }
14766 intersect = exactloc;
14767 if (approx && (exactloc != ONVERTEX)) {
14768
14769 epspp = b->epsilon;
14770 count = 0;
14771 while (count < 16) {
14772 intersect = adjustlocate(newpoint, searchtet, exactloc, epspp);
14773 if (intersect == ONVERTEX) {
14774 checkpt = org(*searchtet);
14775 checklen = distance(checkpt, newpoint);
14776 if (checklen / longest > b->epsilon) {
14777 epspp *= 1e-2;
14778 count++;
14779 continue;
14780 }
14781 }
14782 break;
14783 }
14784 }
14785
14786 recenttet = *searchtet;
14787
14788
14789 switch (intersect) {
14790 case ONVERTEX:
14791
14792
14793 if (b->verbose > 1) {
14794 printf(" Not insert for duplicating point.\n");
14795 }
14796 return DUPLICATEPOINT;
14797
14798 case OUTSIDE:
14799 if (b->verbose > 1) {
14800 printf(" Not insert for locating outside the mesh.\n");
14801 }
14802 return OUTSIDEPOINT;
14803
14804 case ONEDGE:
14805
14806 splittetedge(newpoint, searchtet, flipqueue);
14807 return SUCCESSONEDGE;
14808
14809 case ONFACE:
14810
14811 splittetface(newpoint, searchtet, flipqueue);
14812 return SUCCESSONFACE;
14813
14814 case INTETRAHEDRON:
14815
14816 splittetrahedron(newpoint, searchtet, flipqueue);
14817 return SUCCESSINTET;
14818
14819 default:
14820
14821 return OUTSIDEPOINT;
14822 }
14823 }
14824
14826
14827
14828
14829
14830
14831
14832
14833
14834
14835
14837
14838 void tetgenmesh::undosite(enum insertsiteresult insresult, triface* splittet,
14839 point torg, point tdest, point tapex, point toppo)
14840 {
14841
14842 findface(splittet, torg, tdest, tapex);
14843 if (oppo(*splittet) != toppo) {
14844 symself(*splittet);
14845 #ifdef SELF_CHECK
14846 assert(oppo(*splittet) == toppo);
14847 #endif
14848
14849 findedge(splittet, torg, tdest);
14850 }
14851
14852
14853 switch (insresult) {
14854 case SUCCESSINTET:
14855
14856 unsplittetrahedron(splittet);
14857 break;
14858 case SUCCESSONFACE:
14859
14860
14861 unsplittetface(splittet);
14862 break;
14863 case SUCCESSONEDGE:
14864
14865 unsplittetedge(splittet);
14866 break;
14867 default:
14868 break;
14869 }
14870 }
14871
14873
14874
14875
14876
14877
14878
14879
14880
14881
14883
14884 void tetgenmesh::closeopenface(triface* openface, queue* flipque)
14885 {
14886 triface newtet, oldhull;
14887 triface newopenface, closeface;
14888 point inspoint, pa, pb, pc;
14889 REAL attrib, volume;
14890 int i;
14891
14892
14893 inspoint = apex(*openface);
14894
14895 esym(*openface, oldhull);
14896 while (fnextself(oldhull)) ;
14897 if (apex(oldhull) != inspoint) {
14898
14899 pa = org(oldhull);
14900 pb = dest(oldhull);
14901 pc = apex(oldhull);
14902 if (orient3d(pa, pb, pc, inspoint) < 0.0) {
14903
14904 maketetrahedron(&newtet);
14905 setorg(newtet, pa);
14906 setdest(newtet, pb);
14907 setapex(newtet, pc);
14908 setoppo(newtet, inspoint);
14909 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14910 attrib = elemattribute(oldhull.tet, i);
14911 setelemattribute(newtet.tet, i, attrib);
14912 }
14913 if (b->varvolume) {
14914 volume = volumebound(oldhull.tet);
14915 setvolumebound(newtet.tet, volume);
14916 }
14917
14918 bond(newtet, oldhull);
14919
14920 fnext(newtet, newopenface);
14921 bond(newopenface, *openface);
14922
14923 enqueueflipface(oldhull, flipque);
14924
14925 hullsize--;
14926
14927 enextself(newtet);
14928 for (i = 0; i < 2; i++) {
14929 fnext(newtet, newopenface);
14930 sym(newopenface, closeface);
14931 if (closeface.tet == dummytet) {
14932 closeopenface(&newopenface, flipque);
14933 }
14934 enextself(newtet);
14935 }
14936 } else {
14937
14938 hullsize++;
14939
14940 dummytet[0] = encode(*openface);
14941 }
14942 } else {
14943
14944 bond(*openface, oldhull);
14945
14946 enqueueflipface(*openface, flipque);
14947 }
14948 }
14949
14951
14952
14953
14954
14955
14956
14957
14958
14959
14960
14961
14962
14963
14964
14966
14967 void tetgenmesh::inserthullsite(point inspoint, triface* horiz, queue* flipque)
14968 {
14969 triface firstnewtet;
14970 triface openface, closeface;
14971 REAL attrib, volume;
14972 int i;
14973
14974
14975 adjustedgering(*horiz, CW);
14976
14977 maketetrahedron(&firstnewtet);
14978 setorg (firstnewtet, org(*horiz));
14979 setdest(firstnewtet, dest(*horiz));
14980 setapex(firstnewtet, apex(*horiz));
14981 setoppo(firstnewtet, inspoint);
14982 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14983 attrib = elemattribute(horiz->tet, i);
14984 setelemattribute(firstnewtet.tet, i, attrib);
14985 }
14986 if (b->varvolume) {
14987 volume = volumebound(horiz->tet);
14988 setvolumebound(firstnewtet.tet, volume);
14989 }
14990
14991 bond(firstnewtet, *horiz);
14992
14993 enqueueflipface(*horiz, flipque);
14994
14995 hullsize--;
14996
14997
14998 for (i = 0; i < 3; i++) {
14999
15000 fnext(firstnewtet, openface);
15001
15002 sym(openface, closeface);
15003 if (closeface.tet == dummytet) {
15004 closeopenface(&openface, flipque);
15005 }
15006
15007 enextself(firstnewtet);
15008 }
15009 }
15010
15012
15013
15014
15015
15016
15017
15018
15019
15020
15021
15022
15023
15024
15025
15026
15027
15029
15031
15032
15033
15034
15035
15036
15037
15038
15039
15041
15042 void tetgenmesh::formbowatcavitysub(point bp, face* bpseg, list* sublist,
15043 list* subceillist)
15044 {
15045 triface adjtet;
15046 face startsh, neighsh;
15047 face checkseg;
15048 point pa, pb, pc, pd;
15049 REAL sign;
15050 int i, j;
15051
15052
15053 for (i = 0; i < sublist->len(); i++) {
15054 startsh = * (face *)(* sublist)[i];
15055
15056 for (j = 0; j < 3; j++) {
15057 sspivot(startsh, checkseg);
15058 if (checkseg.sh == dummysh) {
15059
15060 spivot(startsh, neighsh);
15061
15062 if (!sinfected(neighsh)) {
15063 stpivot(neighsh, adjtet);
15064 if (adjtet.tet == dummytet) {
15065 sesymself(neighsh);
15066 stpivot(neighsh, adjtet);
15067 }
15068
15069 adjustedgering(adjtet, CW);
15070 pa = org(adjtet);
15071 pb = dest(adjtet);
15072 pc = apex(adjtet);
15073 pd = oppo(adjtet);
15074 sign = insphere(pa, pb, pc, pd, bp);
15075 if (sign >= 0.0) {
15076
15077 if (sorg(neighsh) != sdest(startsh)) sesymself(neighsh);
15078
15079 sinfect(neighsh);
15080 sublist->append(&neighsh);
15081 } else {
15082 subceillist->append(&startsh);
15083 }
15084 }
15085 } else {
15086
15087 if (bpseg != (face *) NULL) {
15088 if (checkseg.sh != bpseg->sh) {
15089 subceillist->append(&startsh);
15090 }
15091 } else {
15092 subceillist->append(&startsh);
15093 }
15094 }
15095 senextself(startsh);
15096 }
15097 }
15098
15099 if (b->verbose > 2) {
15100 printf(" Collect CBC(%d): %d subfaces, %d edges.\n", pointmark(bp),
15101 sublist->len(), subceillist->len());
15102 }
15103 }
15104
15106
15107
15108
15109
15110
15111
15112
15113
15114
15115
15116
15118
15119 void tetgenmesh::formbowatcavityquad(point bp, list* tetlist, list* ceillist)
15120 {
15121 triface starttet, neightet;
15122 face checksh;
15123 point pa, pb, pc, pd;
15124 REAL sign;
15125 int i;
15126
15127
15128 for (i = 0; i < tetlist->len(); i++) {
15129 starttet = * (triface *)(* tetlist)[i];
15130 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15131
15132 tspivot(starttet, checksh);
15133 if (checksh.sh == dummysh) {
15134
15135 sym(starttet, neightet);
15136
15137 if (!infected(neightet)) {
15138
15139 adjustedgering(neightet, CW);
15140 pa = org(neightet);
15141 pb = dest(neightet);
15142 pc = apex(neightet);
15143 pd = oppo(neightet);
15144 sign = insphere(pa, pb, pc, pd, bp);
15145 if (sign >= 0.0) {
15146
15147 infect(neightet);
15148 tetlist->append(&neightet);
15149 } else {
15150 ceillist->append(&starttet);
15151 }
15152 }
15153 } else {
15154
15155 if (!sinfected(checksh)) {
15156 ceillist->append(&starttet);
15157 }
15158 }
15159 }
15160 }
15161
15162 if (b->verbose > 2) {
15163 printf(" Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15164 tetlist->len(), ceillist->len());
15165 }
15166 }
15167
15169
15170
15171
15172
15173
15174
15175
15176
15177
15178
15179
15180
15181
15182
15184
15185 void tetgenmesh::formbowatcavitysegquad(point bp, list* tetlist,list* ceillist)
15186 {
15187 triface starttet, neightet, cavtet;
15188 face checksh;
15189 point pa, pb, pc, pd, pe;
15190 REAL sign;
15191 int i;
15192
15193
15194 for (i = 0; i < tetlist->len(); i++) {
15195 starttet = * (triface *)(* tetlist)[i];
15196 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15197
15198 tspivot(starttet, checksh);
15199 if (checksh.sh == dummysh) {
15200
15201 sym(starttet, neightet);
15202
15203 if (!infected(neightet)) {
15204
15205 adjustedgering(neightet, CW);
15206 pa = org(neightet);
15207 pb = dest(neightet);
15208 pc = apex(neightet);
15209 pd = oppo(neightet);
15210 sign = insphere(pa, pb, pc, pd, bp);
15211 if (sign >= 0.0) {
15212
15213 infect(neightet);
15214 tetlist->append(&neightet);
15215 } else {
15216
15217 pe = oppo(starttet);
15218 sign = insphere(pa, pb, pc, pd, pe);
15219 if (sign >= 0.0) {
15220
15221 infect(neightet);
15222 tetlist->append(&neightet);
15223 }
15224 }
15225 }
15226 }
15227 }
15228 }
15229
15230
15231 for (i = 0; i < tetlist->len(); i++) {
15232 cavtet = * (triface *)(* tetlist)[i];
15233 for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15234 tspivot(cavtet, checksh);
15235 if (checksh.sh == dummysh) {
15236 sym(cavtet, neightet);
15237 if (!infected(neightet)) {
15238 ceillist->append(&cavtet);
15239 }
15240 } else {
15241
15242 if (!sinfected(checksh)) {
15243 ceillist->append(&cavtet);
15244 }
15245 }
15246 }
15247 }
15248
15249 if (b->verbose > 2) {
15250 printf(" Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15251 tetlist->len(), ceillist->len());
15252 }
15253 }
15254
15256
15257
15258
15259
15260
15261
15262
15264
15265 void tetgenmesh::formbowatcavity(point bp, face* bpseg, face* bpsh, int* n,
15266 int* nmax, list** sublists, list** subceillists, list** tetlists,
15267 list** ceillists)
15268 {
15269 list *sublist;
15270 triface adjtet;
15271 face startsh, spinsh;
15272 point pa, pb;
15273 int i, j;
15274
15275 *n = 0;
15276 if (bpseg != (face *) NULL) {
15277
15278 bpseg->shver = 0;
15279 pa = sorg(*bpseg);
15280 pb = sdest(*bpseg);
15281
15282 spivot(*bpseg, startsh);
15283 spinsh = startsh;
15284 do {
15285 (*n)++;
15286 spivotself(spinsh);
15287 } while (spinsh.sh != startsh.sh);
15288
15289 if (*n > *nmax) {
15290
15291 delete [] tetlists;
15292 delete [] ceillists;
15293 delete [] sublists;
15294 delete [] subceillists;
15295 tetlists = new list*[*n];
15296 ceillists = new list*[*n];
15297 sublists = new list*[*n];
15298 subceillists = new list*[*n];
15299 *nmax = *n;
15300 }
15301
15302 spinsh = startsh;
15303 for (i = 0; i < *n; i++) {
15304 sublists[i] = new list(sizeof(face), NULL, 256);
15305 subceillists[i] = new list(sizeof(face), NULL, 256);
15306
15307 startsh = spinsh;
15308
15309 findedge(&startsh, pa, pb);
15310 sinfect(startsh);
15311 sublists[i]->append(&startsh);
15312 formbowatcavitysub(bp, bpseg, sublists[i], subceillists[i]);
15313
15314 spivotself(spinsh);
15315 }
15316 } else if (sublists != (list **) NULL) {
15317
15318 *n = 2;
15319
15320 sublists[0] = new list(sizeof(face), NULL, 256);
15321 subceillists[0] = new list(sizeof(face), NULL, 256);
15322 sinfect(*bpsh);
15323 sublists[0]->append(bpsh);
15324 formbowatcavitysub(bp, NULL, sublists[0], subceillists[0]);
15325 } else {
15326
15327 *n = 1;
15328 }
15329
15330
15331 for (i = 0; i < *n; i++) {
15332 tetlists[i] = new list(sizeof(triface), NULL, 256);
15333 ceillists[i] = new list(sizeof(triface), NULL, 256);
15334 if (sublists != (list **) NULL) {
15335
15336 sublist = ((bpseg == (face *) NULL) ? sublists[0] : sublists[i]);
15337
15338 for (j = 0; j < sublist->len(); j++) {
15339 startsh = * (face *)(* sublist)[j];
15340
15341 if ((bpseg == (face *) NULL) && (i == 1)) sesymself(startsh);
15342 stpivot(startsh, adjtet);
15343 if (adjtet.tet != dummytet) {
15344 if (!infected(adjtet)) {
15345 infect(adjtet);
15346 tetlists[i]->append(&adjtet);
15347 }
15348 }
15349 }
15350 if (bpseg != (face *) NULL) {
15351
15352 sublist = ((i < *n - 1) ? sublists[i + 1] : sublists[0]);
15353 for (j = 0; j < sublist->len(); j++) {
15354 startsh = * (face *)(* sublist)[j];
15355
15356 sesymself(startsh);
15357 stpivot(startsh, adjtet);
15358 if (adjtet.tet != dummytet) {
15359 if (!infected(adjtet)) {
15360 infect(adjtet);
15361 tetlists[i]->append(&adjtet);
15362 }
15363 }
15364 }
15365 }
15366 }
15367
15368 if (tetlists[i]->len() == 0) continue;
15369
15370
15371
15372
15373 formbowatcavityquad(bp, tetlists[i], ceillists[i]);
15374
15375 }
15376 }
15377
15379
15380
15381
15382
15384
15385 void tetgenmesh::releasebowatcavity(face* bpseg, int n, list** sublists,
15386 list** subceillist, list** tetlists, list** ceillists)
15387 {
15388 triface oldtet;
15389 face oldsh;
15390 int i, j;
15391
15392 if (sublists != (list **) NULL) {
15393
15394 for (i = 0; i < n; i++) {
15395
15396 for (j = 0; j < sublists[i]->len(); j++) {
15397 oldsh = * (face *)(* (sublists[i]))[j];
15398 #ifdef SELF_CHECK
15399 assert(sinfected(oldsh));
15400 #endif
15401 suninfect(oldsh);
15402 }
15403 delete sublists[i];
15404 delete subceillist[i];
15405 sublists[i] = (list *) NULL;
15406 subceillist[i] = (list *) NULL;
15407 if (bpseg == (face *) NULL) break;
15408 }
15409 }
15410
15411 for (i = 0; i < n; i++) {
15412
15413 for (j = 0; j < tetlists[i]->len(); j++) {
15414 oldtet = * (triface *)(* (tetlists[i]))[j];
15415 #ifdef SELF_CHECK
15416 assert(infected(oldtet));
15417 #endif
15418 uninfect(oldtet);
15419 }
15420 delete tetlists[i];
15421 delete ceillists[i];
15422 tetlists[i] = (list *) NULL;
15423 ceillists[i] = (list *) NULL;
15424 }
15425 }
15426
15428
15429
15430
15431
15432
15433
15434
15435
15436
15438
15439 bool tetgenmesh::validatebowatcavityquad(point bp,list* ceillist,REAL maxcosd)
15440 {
15441 triface ceiltet;
15442 point pa, pb, pc;
15443 REAL ori, cosd;
15444 int remcount, i;
15445
15446
15447 remcount = 0;
15448 for (i = 0; i < ceillist->len(); i++) {
15449 ceiltet = * (triface *)(* ceillist)[i];
15450 if (infected(ceiltet)) {
15451 adjustedgering(ceiltet, CCW);
15452 pa = org(ceiltet);
15453 pb = dest(ceiltet);
15454 pc = apex(ceiltet);
15455 ori = orient3d(pa, pb, pc, bp);
15456 if (ori >= 0.0) {
15457
15458 uninfect(ceiltet);
15459 remcount++;
15460 continue;
15461 }
15462
15463 if (maxcosd > -1.0) {
15464
15465 tetalldihedral(pa, pb, pc, bp, NULL, &cosd, NULL);
15466
15467 if (cosd < maxcosd) {
15468 uninfect(ceiltet);
15469 remcount++;
15470 }
15471 }
15472 }
15473 }
15474 return remcount == 0;
15475 }
15476
15478
15479
15480
15481
15482
15483
15484
15486
15487 void tetgenmesh::updatebowatcavityquad(list* tetlist, list* ceillist)
15488 {
15489 triface cavtet, neightet;
15490 face checksh;
15491 int remcount, i;
15492
15493 remcount = 0;
15494 for (i = 0; i < tetlist->len(); i++) {
15495 cavtet = * (triface *)(* tetlist)[i];
15496 if (!infected(cavtet)) {
15497 tetlist->del(i, 1);
15498 remcount++;
15499 i--;
15500 }
15501 }
15502
15503
15504 if (remcount > 0) {
15505
15506 ceillist->clear();
15507 for (i = 0; i < tetlist->len(); i++) {
15508 cavtet = * (triface *)(* tetlist)[i];
15509 for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15510 tspivot(cavtet, checksh);
15511 if (checksh.sh == dummysh) {
15512 sym(cavtet, neightet);
15513 if (!infected(neightet)) {
15514 ceillist->append(&cavtet);
15515 }
15516 } else {
15517
15518 if (!sinfected(checksh)) {
15519 ceillist->append(&cavtet);
15520 }
15521 }
15522 }
15523 }
15524 if (b->verbose > 2) {
15525 printf(" Update BC_i(p): %d tets, %d faces.\n", tetlist->len(),
15526 ceillist->len());
15527 }
15528 }
15529 }
15530
15532
15533
15534
15535
15536
15537
15538
15539
15540
15541
15542
15543
15544
15545
15546
15547
15548
15549
15550
15551
15552
15553
15554
15556
15557 void tetgenmesh::updatebowatcavitysub(list* sublist, list* subceillist,
15558 int* cutcount)
15559 {
15560 triface adjtet, rotface;
15561 face checksh, neighsh;
15562 face checkseg;
15563 point pa, pb, pc;
15564 REAL ori1, ori2;
15565 int remcount;
15566 int i, j;
15567
15568 remcount = 0;
15569
15570 for (i = 0; i < sublist->len(); i++) {
15571 checksh = * (face *)(* sublist)[i];
15572
15573 for (j = 0; j < 2; j++) {
15574 stpivot(checksh, adjtet);
15575 if (adjtet.tet != dummytet) {
15576 if (!infected(adjtet)) {
15577
15578 suninfect(checksh);
15579
15580 sesymself(checksh);
15581 stpivot(checksh, adjtet);
15582 if (adjtet.tet != dummytet) {
15583 if (infected(adjtet)) {
15584
15585 uninfect(adjtet);
15586 (*cutcount)++;
15587 }
15588 }
15589
15590 sublist->del(i, 1);
15591 i--;
15592 remcount++;
15593 break;
15594 }
15595 }
15596 sesymself(checksh);
15597 }
15598 }
15599 if (remcount > 0) {
15600 if (b->verbose > 2) {
15601 printf(" Removed %d subfaces from CBC(p).\n", remcount);
15602 }
15603
15604 subceillist->clear();
15605 for (i = 0; i < sublist->len(); i++) {
15606 checksh = * (face *)(* sublist)[i];
15607 for (j = 0; j < 3; j++) {
15608 spivot(checksh, neighsh);
15609 if (!sinfected(neighsh)) {
15610 subceillist->append(&checksh);
15611 }
15612 senextself(checksh);
15613 }
15614 }
15615 if (b->verbose > 2) {
15616 printf(" Update CBC(p): %d subs, %d edges.\n", sublist->len(),
15617 subceillist->len());
15618 }
15619 }
15620
15621
15622 for (i = 0; i < subceillist->len(); i++) {
15623 checksh = * (face *)(* subceillist)[i];
15624 sspivot(checksh, checkseg);
15625 if (checkseg.sh != dummysh) {
15626
15627 stpivot(checksh, adjtet);
15628 if (adjtet.tet == dummytet) {
15629 sesym(checksh, neighsh);
15630 stpivot(neighsh, adjtet);
15631 }
15632 findedge(&adjtet, sorg(checkseg), sdest(checkseg));
15633 adjustedgering(adjtet, CCW);
15634 fnext(adjtet, rotface);
15635
15636
15637
15638
15639 do {
15640 if (!infected(rotface)) break;
15641 tspivot(rotface, neighsh);
15642 if (neighsh.sh != dummysh) break;
15643
15644 fnextself(rotface);
15645 } while (apex(rotface) != apex(adjtet));
15646
15647 if (apex(rotface) == apex(adjtet)) {
15648
15649 pa = org(adjtet);
15650 pb = dest(adjtet);
15651 pc = apex(adjtet);
15652
15653
15654
15655 fnext(adjtet, rotface);
15656 do {
15657 fnextself(rotface);
15658 assert(infected(rotface));
15659 ori1 = orient3d(pa, pb, pc, apex(rotface));
15660 ori2 = orient3d(pa, pb, pc, oppo(rotface));
15661 } while (ori1 * ori2 > 0.0);
15662
15663 uninfect(rotface);
15664 (*cutcount)++;
15665 }
15666 } else {
15667
15668
15669
15670
15671
15672
15673
15674
15675
15676
15677
15678
15679
15680
15681
15682
15683
15684 }
15685 }
15686 }
15687
15689
15690
15691
15692
15693
15694
15695
15696
15697
15698
15699
15700
15701
15702
15703
15704
15705
15706
15707
15708
15709
15710
15712
15713 bool tetgenmesh::trimbowatcavity(point bp, face* bpseg, int n, list** sublists,
15714 list** subceillists, list** tetlists, list** ceillists, REAL maxcosd)
15715 {
15716 bool valflag;
15717 int oldnum, cutnum, cutcount;
15718 int i;
15719
15720 cutnum = 0;
15721 valflag = true;
15722
15723 do {
15724
15725 for (i = 0; i < n && valflag; i++) {
15726 oldnum = tetlists[i]->len();
15727
15728 while (!validatebowatcavityquad(bp, ceillists[i], maxcosd)) {
15729
15730 updatebowatcavityquad(tetlists[i], ceillists[i]);
15731 valflag = tetlists[i]->len() > 0;
15732 }
15733 cutnum += (oldnum - tetlists[i]->len());
15734 }
15735 if (valflag && (sublists != (list **) NULL)) {
15736
15737 cutcount = 0;
15738 for (i = 0; i < n; i++) {
15739 updatebowatcavitysub(sublists[i], subceillists[i], &cutcount);
15740
15741 if (bpseg == (face *) NULL) break;
15742 }
15743
15744 if (cutcount > 0) {
15745
15746 for (i = 0; i < n; i++) {
15747 if (tetlists[i]->len() > 0) {
15748 updatebowatcavityquad(tetlists[i], ceillists[i]);
15749 if (valflag) {
15750 valflag = tetlists[i]->len() > 0;
15751 }
15752 }
15753 }
15754 cutnum += cutcount;
15755
15756 continue;
15757 }
15758 }
15759 break;
15760 } while (true);
15761
15762
15763 if (valflag && (sublists != (list **) NULL)) {
15764 for (i = 0; i < n && valflag; i++) {
15765 valflag = (sublists[i]->len() > 0);
15766 if (bpseg == (face *) NULL) break;
15767 }
15768 }
15769
15770 if (valflag && (cutnum > 0)) {
15771
15772 if (bpseg != (face *) NULL) {
15773 updsegcount++;
15774 } else if (sublists != (list **) NULL) {
15775 updsubcount++;
15776 } else {
15777 updvolcount++;
15778 }
15779 }
15780
15781 if (!valflag) {
15782
15783 if (bpseg != (face *) NULL) {
15784 failsegcount++;
15785 } else if (sublists != (list **) NULL) {
15786 failsubcount++;
15787 } else {
15788 failvolcount++;
15789 }
15790 }
15791
15792 return valflag;
15793 }
15794
15796
15797
15798
15799
15800
15801
15802
15803
15804
15805
15806
15807
15808
15809
15810
15811
15812
15813
15814
15815
15816
15817
15818
15819
15820
15821
15822
15823
15824
15825
15826
15828
15829 void tetgenmesh::bowatinsertsite(point bp,face* splitseg,int n,list** sublists,
15830 list** subceillists, list** tetlists, list** ceillists, list* verlist,
15831 queue* flipque, bool chkencseg, bool chkencsub, bool chkbadtet)
15832 {
15833 list *ceillist, *subceillist;
15834 triface oldtet, newtet, newface, rotface, neightet;
15835 face oldsh, newsh, newedge, checksh;
15836 face spinsh, casingin, casingout;
15837 face *apsegshs, *pbsegshs;
15838 face apseg, pbseg, checkseg;
15839 point pa, pb, pc;
15840 REAL attrib, volume;
15841 int idx, i, j, k;
15842
15843 apsegshs = NULL;
15844 pbsegshs = NULL;
15845
15846 if (b->verbose > 1) {
15847 printf(" Insert point %d (%.12g, %.12g, %.12g)", pointmark(bp), bp[0],
15848 bp[1], bp[2]);
15849 }
15850 if (splitseg != (face *) NULL) {
15851 if (b->verbose > 1) {
15852 printf(" on segment.\n");
15853 }
15854 bowatsegcount++;
15855 } else {
15856 if (subceillists != (list **) NULL) {
15857 if (b->verbose > 1) {
15858 printf(" on facet.\n");
15859 }
15860 bowatsubcount++;
15861 } else {
15862 if (b->verbose > 1) {
15863 printf(" in volume.\n");
15864 }
15865 bowatvolcount++;
15866 }
15867 }
15868
15869
15870 for (k = 0; k < n; k++) {
15871
15872 ceillist = ceillists[k];
15873 for (i = 0; i < ceillist->len(); i++) {
15874 oldtet = * (triface *)(* ceillist)[i];
15875 adjustedgering(oldtet, CCW);
15876 pa = org(oldtet);
15877 pb = dest(oldtet);
15878 pc = apex(oldtet);
15879 maketetrahedron(&newtet);
15880 setorg(newtet, pa);
15881 setdest(newtet, pb);
15882 setapex(newtet, pc);
15883 setoppo(newtet, bp);
15884 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
15885 attrib = elemattribute(oldtet.tet, j);
15886 setelemattribute(newtet.tet, j, attrib);
15887 }
15888 if (b->varvolume) {
15889 volume = volumebound(oldtet.tet);
15890 if (volume > 0.0) {
15891 if (!b->fixedvolume && b->refine) {
15892
15893
15894
15895 volume *= 1.2;
15896 }
15897 }
15898 setvolumebound(newtet.tet, volume);
15899 }
15900 sym(oldtet, neightet);
15901 tspivot(oldtet, checksh);
15902 if (neightet.tet != dummytet) {
15903 bond(newtet, neightet);
15904 }
15905 if (checksh.sh != dummysh) {
15906 tsbond(newtet, checksh);
15907 }
15908 if (verlist != (list *) NULL) {
15909
15910 idx = pointmark(pa);
15911 if (idx >= 0) {
15912 setpointmark(pa, -idx - 1);
15913 verlist->append(&pa);
15914 }
15915 idx = pointmark(pb);
15916 if (idx >= 0) {
15917 setpointmark(pb, -idx - 1);
15918 verlist->append(&pb);
15919 }
15920 idx = pointmark(pc);
15921 if (idx >= 0) {
15922 setpointmark(pc, -idx - 1);
15923 verlist->append(&pc);
15924 }
15925 }
15926
15927 * (triface *)(* ceillist)[i] = newtet;
15928 }
15929 }
15930 if (verlist != (list *) NULL) {
15931
15932 for (i = 0; i < verlist->len(); i++) {
15933 pa = * (point *)(* verlist)[i];
15934 idx = pointmark(pa);
15935 setpointmark(pa, -(idx + 1));
15936 }
15937 }
15938
15939
15940
15941 for (k = 0; k < n; k++) {
15942 ceillist = ceillists[k];
15943 for (i = 0; i < ceillist->len(); i++) {
15944 newtet = * (triface *)(* ceillist)[i];
15945 newtet.ver = 0;
15946 for (j = 0; j < 3; j++) {
15947 fnext(newtet, newface);
15948 sym(newface, neightet);
15949 if (neightet.tet == dummytet) {
15950
15951 esym(newtet, rotface);
15952 pa = org(rotface);
15953 pb = dest(rotface);
15954 while (fnextself(rotface));
15955
15956 tspivot(rotface, checksh);
15957 if (checksh.sh != dummysh) {
15958
15959 do {
15960 findedge(&checksh, pa, pb);
15961 sfnextself(checksh);
15962 assert((sorg(checksh) == pa) && (sdest(checksh) == pb));
15963 stpivot(checksh, rotface);
15964 if (infected(rotface)) {
15965
15966
15967 break;
15968 }
15969 findedge(&rotface, pa, pb);
15970 while (fnextself(rotface));
15971 tspivot(rotface, checksh);
15972 } while (checksh.sh != dummysh);
15973 }
15974
15975 if (apex(rotface) == apex(newface)) {
15976
15977 bond(newface, rotface);
15978
15979 if (flipque != (queue *) NULL) {
15980 enqueueflipface(newface, flipque);
15981 }
15982 }
15983 }
15984 enextself(newtet);
15985 }
15986 }
15987 }
15988
15989 if (subceillists != (list **) NULL) {
15990
15991 if (splitseg != (face *) NULL) {
15992
15993 splitseg->shver = 0;
15994 pa = sorg(*splitseg);
15995 pb = sdest(*splitseg);
15996
15997
15998 apsegshs = new face[n];
15999 pbsegshs = new face[n];
16000 }
16001
16002
16003
16004
16005 for (k = 0; k < n; k++) {
16006 subceillist = subceillists[k];
16007
16008
16009 oldsh = * (face *)(* subceillist)[0];
16010 stpivot(oldsh, neightet);
16011 if (neightet.tet != dummytet) {
16012 sesymself(oldsh);
16013 stpivot(oldsh, neightet);
16014 }
16015 if (neightet.tet == dummytet) {
16016
16017 hullsize += (subceillist->len() - sublists[k]->len());
16018 }
16019
16020
16021 for (i = 0; i < subceillist->len(); i++) {
16022 oldsh = * (face *)(* subceillist)[i];
16023 makeshellface(subfaces, &newsh);
16024 setsorg(newsh, sorg(oldsh));
16025 setsdest(newsh, sdest(oldsh));
16026 setsapex(newsh, bp);
16027 if (b->quality && varconstraint) {
16028 setareabound(newsh, areabound(oldsh));
16029 }
16030 setshellmark(newsh, shellmark(oldsh));
16031 setshelltype(newsh, shelltype(oldsh));
16032 if (checkpbcs) {
16033 setshellpbcgroup(newsh, shellpbcgroup(oldsh));
16034 }
16035
16036 spivot(oldsh, casingout);
16037 sspivot(oldsh, checkseg);
16038 if (checkseg.sh != dummysh) {
16039
16040 if (oldsh.sh != casingout.sh) {
16041
16042 spinsh = casingout;
16043 do {
16044 casingin = spinsh;
16045 spivotself(spinsh);
16046 } while (sapex(spinsh) != sapex(oldsh));
16047 assert(casingin.sh != oldsh.sh);
16048
16049 sbond1(casingin, newsh);
16050 sbond1(newsh, casingout);
16051 } else {
16052
16053 sbond(newsh, newsh);
16054 }
16055
16056 ssbond(newsh, checkseg);
16057 } else {
16058
16059 sbond(newsh, casingout);
16060 }
16061
16062
16063 stpivot(oldsh, neightet);
16064 if (neightet.tet == dummytet) {
16065 sesymself(oldsh);
16066 sesymself(newsh);
16067 stpivot(oldsh, neightet);
16068 }
16069 assert(infected(neightet));
16070
16071 findedge(&neightet, sorg(oldsh), sdest(oldsh));
16072
16073 adjustedgering(neightet, CCW);
16074 rotface = neightet;
16075
16076
16077
16078 do {
16079 fnextself(rotface);
16080 sym(rotface, neightet);
16081 if (neightet.tet == dummytet) {
16082 tspivot(rotface, checksh);
16083 assert(checksh.sh != dummysh);
16084 stpivot(checksh, newtet);
16085 break;
16086 } else if (!infected(neightet)) {
16087 sym(neightet, newtet);
16088 break;
16089 }
16090 } while (true);
16091 assert(newtet.tet != rotface.tet);
16092
16093 findedge(&newtet, sorg(oldsh), sdest(oldsh));
16094
16095 adjustedgering(newtet, CCW);
16096 fnext(newtet, newface);
16097 assert(apex(newface) == bp);
16098
16099 tsbond(newface, newsh);
16100 sym(newface, neightet);
16101 sesymself(newsh);
16102 tsbond(neightet, newsh);
16103
16104
16105 * (face *)(* subceillist)[i] = newsh;
16106 }
16107
16108
16109 for (i = 0; i < subceillist->len(); i++) {
16110
16111 newsh = * (face *)(* subceillist)[i];
16112
16113 stpivot(newsh, newtet);
16114 if (newtet.tet == dummytet) {
16115 sesymself(newsh);
16116 stpivot(newsh, newtet);
16117 }
16118 for (j = 0; j < 2; j++) {
16119 if (j == 0) {
16120 senext(newsh, newedge);
16121 } else {
16122 senext2(newsh, newedge);
16123 sesymself(newedge);
16124 }
16125 if (splitseg != (face *) NULL) {
16126
16127 if (sorg(newedge) == pa) {
16128 apsegshs[k] = newedge;
16129 continue;
16130 } else if (sorg(newedge) == pb) {
16131 pbsegshs[k] = newedge;
16132 continue;
16133 }
16134 }
16135
16136 sspivot(newedge, checkseg);
16137 assert(checkseg.sh == dummysh);
16138 spivot(newedge, casingout);
16139 if (casingout.sh == dummysh) {
16140 rotface = newtet;
16141 findedge(&rotface, sorg(newedge), sdest(newedge));
16142
16143
16144 adjustedgering(rotface, CCW);
16145 do {
16146 fnextself(rotface);
16147 tspivot(rotface, checksh);
16148 if (checksh.sh != dummysh) break;
16149 } while (true);
16150 findedge(&checksh, sorg(newedge), sdest(newedge));
16151 sbond(newedge, checksh);
16152 }
16153 }
16154 }
16155
16156 if (splitseg == (face *) NULL) break;
16157 }
16158
16159 if (splitseg != (face *) NULL) {
16160
16161 apseg = *splitseg;
16162 setsdest(apseg, bp);
16163
16164 makeshellface(subsegs, &pbseg);
16165 setsorg(pbseg, bp);
16166 setsdest(pbseg, pb);
16167
16168 setshellmark(pbseg, shellmark(apseg));
16169 setshelltype(pbseg, shelltype(apseg));
16170 if (b->quality && varconstraint) {
16171
16172 setareabound(pbseg, areabound(apseg));
16173 }
16174 senext(apseg, checkseg);
16175
16176 spivot(checkseg, casingout);
16177
16178 senext2(pbseg, casingin);
16179 sbond(casingin, checkseg);
16180 if (casingout.sh != dummysh) {
16181
16182 casingout.shver = 0;
16183 #ifdef SELF_CHECK
16184 assert(sorg(casingout) == pb);
16185 #endif
16186 senext2self(casingout);
16187 senext(pbseg, casingin);
16188 sbond(casingin, casingout);
16189 }
16190
16191
16192 for (i = 0; i < n; i++) {
16193 spinsh = apsegshs[i];
16194 findedge(&spinsh, pa, bp);
16195 ssbond(spinsh, apseg);
16196 spinsh = pbsegshs[i];
16197 findedge(&spinsh, bp, pb);
16198 ssbond(spinsh, pbseg);
16199 }
16200
16201 for (i = 0; i < n; i++) {
16202 spinsh = apsegshs[i];
16203 if (i < (n - 1)) {
16204 casingout = apsegshs[i + 1];
16205 } else {
16206 casingout = apsegshs[0];
16207 }
16208 sbond1(spinsh, casingout);
16209 }
16210
16211 for (i = 0; i < n; i++) {
16212 spinsh = pbsegshs[i];
16213 if (i < (n - 1)) {
16214 casingout = pbsegshs[i + 1];
16215 } else {
16216 casingout = pbsegshs[0];
16217 }
16218 sbond1(spinsh, casingout);
16219 }
16220 delete [] apsegshs;
16221 delete [] pbsegshs;
16222
16223
16224 if (chkencseg) {
16225
16226 checkseg4encroach(&apseg, NULL, NULL, true);
16227 checkseg4encroach(&pbseg, NULL, NULL, true);
16228
16229 tallencsegs(bp, n, ceillists);
16230 }
16231 }
16232
16233
16234 for (k = 0; k < n; k++) {
16235 for (i = 0; i < sublists[k]->len(); i++) {
16236 oldsh = * (face *)(* (sublists[k]))[i];
16237 shellfacedealloc(subfaces, oldsh.sh);
16238 }
16239
16240
16241 sublists[k]->clear();
16242
16243 if (splitseg == (face *) NULL) break;
16244 }
16245
16246
16247 if (chkencsub) {
16248
16249 for (k = 0; k < n; k++) {
16250 subceillist = subceillists[k];
16251 for (i = 0; i < subceillist->len(); i++) {
16252 newsh = * (face *)(* subceillist)[i];
16253 checksub4encroach(&newsh, NULL, true);
16254 }
16255
16256 if (splitseg == (face *) NULL) break;
16257 }
16258
16259 tallencsubs(bp, n, ceillists);
16260 }
16261 }
16262
16263
16264 for (k = 0; k < n; k++) {
16265 for (i = 0; i < tetlists[k]->len(); i++) {
16266 oldtet = * (triface *)(* (tetlists[k]))[i];
16267 tetrahedrondealloc(oldtet.tet);
16268 }
16269
16270
16271 tetlists[k]->clear();
16272 }
16273
16274
16275 if (chkbadtet) {
16276 for (k = 0; k < n; k++) {
16277 ceillist = ceillists[k];
16278 for (i = 0; i < ceillist->len(); i++) {
16279 newtet = * (triface *)(* ceillist)[i];
16280 checktet4badqual(&newtet, true);
16281 }
16282 }
16283 }
16284
16285 if (flipque != (queue *) NULL) {
16286
16287
16288
16289 repairflipcount += flip(flipque, NULL);
16290 }
16291 }
16292
16293
16294
16295
16296
16297
16298
16299
16300
16302
16303
16304
16305
16306
16307
16308
16309
16310
16311
16312
16314
16315 void tetgenmesh::formstarpolyhedron(point pt, list* tetlist, list* verlist,
16316 bool complete)
16317 {
16318 triface starttet, neightet;
16319 face checksh;
16320 point ver[3];
16321 int idx, i, j;
16322
16323
16324 starttet = * (triface *)(* tetlist)[0];
16325
16326 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
16327 if (oppo(starttet) == pt) break;
16328 }
16329 assert(starttet.loc < 4);
16330
16331 * (triface *)(* tetlist)[0] = starttet;
16332 infect(starttet);
16333 if (verlist != (list *) NULL) {
16334
16335 ver[0] = org(starttet);
16336 ver[1] = dest(starttet);
16337 ver[2] = apex(starttet);
16338 for (i = 0; i < 3; i++) {
16339
16340 idx = pointmark(ver[i]);
16341 setpointmark(ver[i], -idx - 1);
16342 verlist->append(&(ver[i]));
16343 }
16344 }
16345
16346
16347 for (i = 0; i < tetlist->len(); i++) {
16348 starttet = * (triface *)(* tetlist)[i];
16349 starttet.ver = 0;
16350 for (j = 0; j < 3; j++) {
16351 fnext(starttet, neightet);
16352 tspivot(neightet, checksh);
16353
16354 if ((checksh.sh == dummysh) || complete) {
16355
16356 symself(neightet);
16357 if ((neightet.tet != dummytet) && !infected(neightet)) {
16358
16359 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
16360 if (oppo(neightet) == pt) break;
16361 }
16362 assert(neightet.loc < 4);
16363
16364 infect(neightet);
16365 tetlist->append(&neightet);
16366 if (verlist != (list *) NULL) {
16367
16368 ver[0] = org(starttet);
16369 ver[1] = dest(starttet);
16370 findedge(&neightet, ver[0], ver[1]);
16371 ver[2] = apex(neightet);
16372 idx = pointmark(ver[2]);
16373 if (idx >= 0) {
16374 setpointmark(ver[2], -idx - 1);
16375 verlist->append(&(ver[2]));
16376 }
16377 }
16378 }
16379 }
16380 enextself(starttet);
16381 }
16382 }
16383
16384
16385 for (i = 0; i < tetlist->len(); i++) {
16386 starttet = * (triface *)(* tetlist)[i];
16387 uninfect(starttet);
16388 }
16389 if (verlist != (list *) NULL) {
16390
16391 for (i = 0; i < verlist->len(); i++) {
16392 ver[0] = * (point *)(* verlist)[i];
16393 idx = pointmark(ver[0]);
16394 setpointmark(ver[0], -(idx + 1));
16395 }
16396 }
16397 }
16398
16400
16401
16402
16403
16404
16405
16406
16407
16408
16410
16411 bool tetgenmesh::unifypoint(point testpt, triface *starttet, enum locateresult
16412 loc, REAL eps)
16413 {
16414 triface symtet, spintet;
16415 point checkpt, tapex;
16416 REAL tol;
16417 bool merged;
16418 int hitbdry;
16419 int i;
16420
16421 merged = false;
16422 tol = longest * eps;
16423 if ((loc == OUTSIDE) || (loc == INTETRAHEDRON) || (loc == ONFACE)) {
16424
16425 for (i = 0; i < 4; i++) {
16426 checkpt = (point) starttet->tet[4 + i];
16427 if (distance(testpt, checkpt) < tol) {
16428 merged = true;
16429 break;
16430 }
16431 }
16432 if (!merged && (loc == ONFACE)) {
16433
16434 sym(*starttet, symtet);
16435 if (symtet.tet != dummytet) {
16436 checkpt = oppo(symtet);
16437 if (distance(testpt, checkpt) < tol) {
16438 merged = true;
16439 }
16440 }
16441 }
16442 } else if (loc == ONEDGE) {
16443
16444 checkpt = org(*starttet);
16445 if (distance(testpt, checkpt) < tol) {
16446 merged = true;
16447 }
16448 if (!merged) {
16449 checkpt = dest(*starttet);
16450 if (distance(testpt, checkpt) < tol) {
16451 merged = true;
16452 }
16453 }
16454 if (!merged) {
16455
16456 spintet = *starttet;
16457 tapex = apex(*starttet);
16458 hitbdry = 0;
16459 do {
16460 checkpt = apex(spintet);
16461 if (distance(testpt, checkpt) < tol) {
16462 merged = true;
16463 break;
16464 }
16465 if (!fnextself(spintet)) {
16466 hitbdry++;
16467 if (hitbdry < 2) {
16468 esym(*starttet, spintet);
16469 if (!fnextself(spintet)) {
16470 hitbdry++;
16471 }
16472 }
16473 }
16474 } while ((apex(spintet) != tapex) && (hitbdry < 2));
16475 }
16476 }
16477 if (merged) {
16478 if (b->object != tetgenbehavior::STL) {
16479 if (!b->quiet) {
16480 printf("Warning: Point %d is unified to point %d.\n",
16481 pointmark(testpt), pointmark(checkpt));
16482 }
16483
16484 dupverts++;
16485 }
16486
16487 setpointtype(testpt, DUPLICATEDVERTEX);
16488
16489 setpoint2ppt(testpt, checkpt);
16490 }
16491 return merged;
16492 }
16493
16495
16496
16497
16498
16499
16500
16501
16502
16503
16504
16505
16506
16507
16508
16509
16510
16512
16513 void tetgenmesh::incrflipdelaunay(triface* oldtet, point* insertarray,
16514 long arraysize, bool jump, bool merge, REAL eps, queue* flipque)
16515 {
16516 triface newtet, searchtet;
16517 point swappt, lastpt;
16518 enum locateresult loc;
16519 REAL det, n[3];
16520 REAL attrib, volume;
16521 int i, j;
16522 #ifdef SELF_CHECK
16523 clock_t loc_start, loc_end;
16524 #endif
16525
16526 det = 0.0;
16527 if (b->verbose > 0) {
16528 printf(" Creating initial tetrahedralization.\n");
16529 }
16530
16531
16532
16533
16534
16535
16536 for (i = 1; i < arraysize; i++) {
16537 det = distance(insertarray[0], insertarray[i]);
16538 if (det > (longest * eps)) break;
16539 }
16540 if (i == arraysize) {
16541 printf("\nAll points seem to be identical.\n");
16542 return;
16543 } else {
16544
16545 swappt = insertarray[i];
16546 insertarray[i] = insertarray[1];
16547 insertarray[1] = swappt;
16548 }
16549
16550 for (i++; i < arraysize; i++) {
16551 if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
16552 break;
16553 }
16554 if (i == arraysize) {
16555 printf("\nAll points seem to be collinear.\n");
16556 return;
16557 } else {
16558
16559 swappt = insertarray[i];
16560 insertarray[i] = insertarray[2];
16561 insertarray[2] = swappt;
16562 }
16563
16564 for (i++; i < arraysize; i++) {
16565 det = orient3d(insertarray[0], insertarray[1], insertarray[2],
16566 insertarray[i]);
16567 if (det == 0.0) continue;
16568 if (!iscoplanar(insertarray[0], insertarray[1], insertarray[2],
16569 insertarray[i], det, eps)) break;
16570 }
16571 if (i == arraysize) {
16572
16573 in->mesh_dim = 2;
16574
16575 if (b->plc) {
16576
16577 facenormal(insertarray[0], insertarray[1], insertarray[2], n, &det);
16578 if (det != 0.0) for (j = 0; j < 3; j++) n[j] /= det;
16579
16580 det = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
16581
16582 makepoint(&lastpt);
16583 for (j = 0; j < 3; j++) lastpt[j] = insertarray[0][j] + det * n[j];
16584 abovepoint = lastpt;
16585 det = orient3d(insertarray[0], insertarray[1], insertarray[2], lastpt);
16586
16587 i = 3;
16588 } else {
16589 printf("\nAll points seem to be coplanar.\n");
16590 return;
16591 }
16592 } else {
16593
16594 swappt = insertarray[i];
16595 insertarray[i] = insertarray[3];
16596 insertarray[3] = swappt;
16597 lastpt = insertarray[3];
16598
16599 i = 4;
16600 }
16601
16602
16603 maketetrahedron(&newtet);
16604 if (det > 0.0) {
16605
16606 swappt = insertarray[0];
16607 insertarray[0] = insertarray[1];
16608 insertarray[1] = swappt;
16609 }
16610 if (b->verbose > 2) {
16611 printf(" Create the first tet (%d, %d, %d, %d).\n",
16612 pointmark(insertarray[0]), pointmark(insertarray[1]),
16613 pointmark(insertarray[2]), pointmark(lastpt));
16614 }
16615 setorg(newtet, insertarray[0]);
16616 setdest(newtet, insertarray[1]);
16617 setapex(newtet, insertarray[2]);
16618 setoppo(newtet, lastpt);
16619 if (oldtet != (triface *) NULL) {
16620 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
16621 attrib = elemattribute(oldtet->tet, j);
16622 setelemattribute(newtet.tet, j, attrib);
16623 }
16624 if (b->varvolume) {
16625 volume = volumebound(oldtet->tet);
16626 setvolumebound(newtet.tet, volume);
16627 }
16628 }
16629
16630 if (pointtype(insertarray[0]) == UNUSEDVERTEX) {
16631 setpointtype(insertarray[0], FREEVOLVERTEX);
16632 }
16633 if (pointtype(insertarray[1]) == UNUSEDVERTEX) {
16634 setpointtype(insertarray[1], FREEVOLVERTEX);
16635 }
16636 if (pointtype(insertarray[2]) == UNUSEDVERTEX) {
16637 setpointtype(insertarray[2], FREEVOLVERTEX);
16638 }
16639 if (pointtype(lastpt) == UNUSEDVERTEX) {
16640 setpointtype(lastpt, FREEVOLVERTEX);
16641 }
16642
16643 dummytet[0] = encode(newtet);
16644 if (b->verbose > 3) {
16645 printf(" Creating tetra ");
16646 printtet(&newtet);
16647 }
16648
16649 hullsize = 4;
16650
16651 if (b->verbose > 0) {
16652 printf(" Incrementally inserting points.\n");
16653 }
16654
16655 flip23s = flip32s = flip22s = flip44s = 0;
16656 searchtet.tet = (tetrahedron *) NULL;
16657
16658
16659 for (; i < arraysize; i++) {
16660
16661 #ifdef SELF_CHECK
16662 loc_start = clock();
16663 #endif
16664 if (jump) {
16665 loc = locate(insertarray[i], &searchtet);
16666 } else {
16667 loc = preciselocate(insertarray[i], &searchtet, tetrahedrons->items);
16668 }
16669 #ifdef SELF_CHECK
16670 loc_end = clock();
16671 tloctime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16672 #endif
16673
16674 recenttet = searchtet;
16675 if (loc == ONVERTEX) {
16676 if (b->object != tetgenbehavior::STL) {
16677 if (!b->quiet) {
16678 printf("Warning: Point %d is identical with point %d.\n",
16679 pointmark(insertarray[i]), pointmark(org(searchtet)));
16680 }
16681 }
16682
16683 dupverts++;
16684
16685 setpointtype(insertarray[i], DUPLICATEDVERTEX);
16686 if (b->plc || b->refine) {
16687
16688 setpoint2ppt(insertarray[i], org(searchtet));
16689 }
16690 continue;
16691 }
16692 if (merge) {
16693
16694 if (unifypoint(insertarray[i], &searchtet, loc, eps)) {
16695 continue;
16696 }
16697 }
16698
16699 if (loc != OUTSIDE) {
16700 if (b->verbose > 1) {
16701 printf(" Insert point %d in tetrahedralization.\n",
16702 pointmark(insertarray[i]));
16703 }
16704 if (loc == INTETRAHEDRON) {
16705 splittetrahedron(insertarray[i], &searchtet, flipque);
16706 } else if (loc == ONFACE) {
16707 splittetface(insertarray[i], &searchtet, flipque);
16708 } else if (loc == ONEDGE) {
16709 splittetedge(insertarray[i], &searchtet, flipque);
16710 }
16711 } else {
16712 if (b->verbose > 1) {
16713 printf(" Insert point %d on convex hull.\n",
16714 pointmark(insertarray[i]));
16715 }
16716 inserthullsite(insertarray[i], &searchtet, flipque);
16717 }
16718 if (pointtype(insertarray[i]) == UNUSEDVERTEX) {
16719
16720 setpointtype(insertarray[i], FREEVOLVERTEX);
16721 }
16722 #ifdef SELF_CHECK
16723 loc_start = clock();
16724 #endif
16725 if (!b->noflip) {
16726
16727 flip(flipque, NULL);
16728 } else {
16729 lawson(NULL, flipque);
16730
16731
16732 }
16733 #ifdef SELF_CHECK
16734 loc_end = clock();
16735 tfliptime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16736 #endif
16737 }
16738
16739 if (b->verbose > 0) {
16740 printf(" %ld Flips (T23 %ld, T32 %ld, T22 %ld, T44 %ld)\n",
16741 flip23s+flip32s+flip22s+flip44s, flip23s, flip32s, flip22s, flip44s);
16742 }
16743 }
16744
16746
16747
16748
16749
16750
16751
16752
16754
16755 long tetgenmesh::delaunizevertices()
16756 {
16757 queue *flipque;
16758 point *insertarray;
16759 long arraysize;
16760 int i, j;
16761
16762 if (!b->quiet) {
16763 if (!b->noflip) {
16764 printf("Constructing Delaunay tetrahedralization.\n");
16765 } else {
16766 printf("Constructing regular tetrahedralization.\n");
16767 }
16768 }
16769
16770 flipque = new queue(sizeof(badface));
16771
16772 arraysize = points->items;
16773 insertarray = new point[arraysize];
16774 points->traversalinit();
16775
16776
16777
16778 for (i = 0; i < arraysize; i++) {
16779 j = (int) randomnation(i + 1);
16780 insertarray[i] = insertarray[j];
16781 insertarray[j] = pointtraverse();
16782 }
16783
16784
16785 b->noflip = 1;
16786
16787
16788 incrflipdelaunay(NULL, insertarray, arraysize, true, b->plc, b->epsilon,
16789 flipque);
16790
16791 b->noflip = 0;
16792
16793 delete [] insertarray;
16794 delete flipque;
16795 return hullsize;
16796 }
16797
16798
16799
16800
16801
16802
16803
16804
16805
16807
16808
16809
16810
16811
16812
16813
16814
16815
16816
16818
16819 void tetgenmesh::formstarpolygon(point pt, list* trilist, list* vertlist)
16820 {
16821 face steinsh, lnextsh, rnextsh;
16822 face checkseg;
16823 point pa, pb, pc, pd;
16824 int i;
16825
16826
16827 steinsh = * (face *)(* trilist)[0];
16828 steinsh.shver = 0;
16829
16830 for (i = 0; i < 3; i++) {
16831 if (sapex(steinsh) == pt) break;
16832 senextself(steinsh);
16833 }
16834 assert(i < 3);
16835
16836 * (face *)(* trilist)[0] = steinsh;
16837 pa = sorg(steinsh);
16838 pb = sdest(steinsh);
16839 if (vertlist != (list *) NULL) {
16840
16841 vertlist->append(&pa);
16842 vertlist->append(&pb);
16843 }
16844
16845
16846 lnextsh = steinsh;
16847 pc = pa;
16848 do {
16849 senext2self(lnextsh);
16850 assert(sorg(lnextsh) == pt);
16851 sspivot(lnextsh, checkseg);
16852 if (checkseg.sh != dummysh) break;
16853
16854 spivotself(lnextsh);
16855 if (lnextsh.sh == dummysh) break;
16856
16857 if (sdest(lnextsh) != pt) sesymself(lnextsh);
16858 assert(sdest(lnextsh) == pt);
16859 senext2self(lnextsh);
16860
16861 trilist->append(&lnextsh);
16862
16863 pc = sorg(lnextsh);
16864 if (pc == pb) break;
16865 if (vertlist != (list *) NULL) {
16866
16867 vertlist->append(&pc);
16868 }
16869 } while (true);
16870
16871 if (pc != pb) {
16872
16873 rnextsh = steinsh;
16874 do {
16875 senextself(rnextsh);
16876 assert(sdest(rnextsh) == pt);
16877 sspivot(rnextsh, checkseg);
16878 if (checkseg.sh != dummysh) break;
16879
16880 spivotself(rnextsh);
16881 if (rnextsh.sh == dummysh) break;
16882
16883 if (sorg(rnextsh) != pt) sesymself(rnextsh);
16884 assert(sorg(rnextsh) == pt);
16885 senextself(rnextsh);
16886
16887 trilist->append(&rnextsh);
16888
16889 pd = sdest(rnextsh);
16890 if (pd == pa) break;
16891 if (vertlist != (list *) NULL) {
16892
16893 vertlist->append(&pd);
16894 }
16895 } while (true);
16896 }
16897 }
16898
16900
16901
16902
16903
16904
16905
16906
16907
16908
16909
16910
16911
16912
16913
16914
16916
16918
16919
16920
16921
16922
16923
16925
16926 void tetgenmesh::getfacetabovepoint(face* facetsh)
16927 {
16928 list *verlist, *trilist, *tetlist;
16929 triface adjtet;
16930 face symsh;
16931 point p1, p2, p3, pa;
16932 enum locateresult loc;
16933 REAL smallcos, cosa;
16934 REAL largevol, volume;
16935 REAL v1[3], v2[3], len;
16936 int smallidx, largeidx;
16937 int shmark;
16938 int i, j;
16939
16940 abovecount++;
16941
16942 verlist = new list(sizeof(point *), NULL);
16943 trilist = new list(sizeof(face), NULL);
16944 tetlist = new list(sizeof(triface), NULL);
16945
16946
16947
16948
16949
16950 p1 = sorg(*facetsh);
16951 pa = sdest(*facetsh);
16952 if (pointmark(pa) < pointmark(p1)) p1 = pa;
16953 pa = sapex(*facetsh);
16954 if (pointmark(pa) < pointmark(p1)) p1 = pa;
16955
16956 trilist->append(facetsh);
16957 formstarpolygon(p1, trilist, verlist);
16958
16959
16960 p2 = * (point *)(* verlist)[0];
16961
16962 for (i = 0; i < 3; i++) v1[i] = p2[i] - p1[i];
16963 len = sqrt(dot(v1, v1));
16964 assert(len > 0.0);
16965 for (i = 0; i < 3; i++) v1[i] /= len;
16966
16967
16968
16969 smallcos = 1.0;
16970 smallidx = 1;
16971 for (i = 1; i < verlist->len(); i++) {
16972 p3 = * (point *)(* verlist)[i];
16973 for (j = 0; j < 3; j++) v2[j] = p3[j] - p1[j];
16974 len = sqrt(dot(v2, v2));
16975 if (len > 0.0) {
16976 cosa = fabs(dot(v1, v2)) / len;
16977 if (cosa < smallcos) {
16978 smallidx = i;
16979 smallcos = cosa;
16980 }
16981 }
16982 }
16983 assert(smallcos < 1.0);
16984 p3 = * (point *)(* verlist)[smallidx];
16985 verlist->clear();
16986
16987 if (tetrahedrons->items > 0l) {
16988
16989 stpivot(*facetsh, adjtet);
16990 if (adjtet.tet == dummytet) {
16991 sesym(*facetsh, symsh);
16992 stpivot(symsh, adjtet);
16993 }
16994 if (adjtet.tet == dummytet) {
16995 decode(point2tet(p1), adjtet);
16996 if (isdead(&adjtet)) {
16997 adjtet.tet = dummytet;
16998 } else {
16999 if (!findorg(&adjtet, p1)) {
17000 adjtet.tet = dummytet;
17001 }
17002 }
17003 }
17004 if (adjtet.tet == dummytet) {
17005 loc = locate(p1, &adjtet);
17006 if (loc == ONVERTEX) {
17007 setpoint2tet(p1, encode(adjtet));
17008 } else {
17009 adjtet.tet = dummytet;
17010 }
17011 }
17012 if (adjtet.tet != dummytet) {
17013
17014 tetlist->append(&adjtet);
17015 formstarpolyhedron(p1, tetlist, verlist, false);
17016 }
17017 }
17018
17019
17020
17021 largevol = 0.0;
17022 largeidx = 0;
17023 for (i = 0; i < verlist->len(); i++) {
17024 pa = * (point *)(* verlist)[i];
17025 volume = orient3d(p1, p2, p3, pa);
17026 if (!iscoplanar(p1, p2, p3, pa, volume, b->epsilon * 1e+2)) {
17027 if (fabs(volume) > largevol) {
17028 largevol = fabs(volume);
17029 largeidx = i;
17030 }
17031 }
17032 }
17033
17034
17035 if (largevol > 0.0) {
17036 abovepoint = * (point *)(* verlist)[largeidx];
17037 if (b->verbose > 1) {
17038 printf(" Chosen abovepoint %d for facet %d.\n", pointmark(abovepoint),
17039 shellmark(*facetsh));
17040 }
17041 } else {
17042
17043 facenormal(p1, p2, p3, v1, &len);
17044 if (len != 0.0) for (i = 0; i < 3; i++) v1[i] /= len;
17045
17046 len = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
17047
17048 makepoint(&abovepoint);
17049 setpointtype(abovepoint, UNUSEDVERTEX);
17050 unuverts++;
17051 for (i = 0; i < 3; i++) abovepoint[i] = p1[i] + len * v1[i];
17052 if (b->verbose > 1) {
17053 printf(" Calculated abovepoint %d for facet %d.\n",
17054 pointmark(abovepoint), shellmark(*facetsh));
17055 }
17056 }
17057
17058 shmark = shellmark(*facetsh);
17059 facetabovepointarray[shmark] = abovepoint;
17060
17061 delete trilist;
17062 delete tetlist;
17063 delete verlist;
17064 }
17065
17067
17068
17069
17070
17071
17072
17074
17075 void tetgenmesh::collectcavsubs(point newpoint, list* cavsublist)
17076 {
17077 face startsub, neighsub;
17078 face checkseg;
17079 point pa, pb, pc;
17080 REAL sign, ori;
17081 int i, j;
17082
17083
17084 for (i = 0; i < cavsublist->len(); i++) {
17085 startsub = * (face *)(* cavsublist)[i];
17086 sinfect(startsub);
17087 }
17088
17089 for (i = 0; i < cavsublist->len(); i++) {
17090 startsub = * (face *)(* cavsublist)[i];
17091 for (j = 0; j < 3; j++) {
17092 sspivot(startsub, checkseg);
17093
17094 if (checkseg.sh == dummysh) {
17095
17096 spivot(startsub, neighsub);
17097 if (!sinfected(neighsub)) {
17098 pa = sorg(neighsub);
17099 pb = sdest(neighsub);
17100 pc = sapex(neighsub);
17101 sign = insphere(pa, pb, pc, abovepoint, newpoint);
17102 ori = orient3d(pa, pb, pc, abovepoint);
17103 if (sign != 0.0) {
17104
17105 sign = ori > 0.0 ? sign : -sign;
17106 }
17107 if (sign > 0.0) {
17108
17109 sinfect(neighsub);
17110 cavsublist->append(&neighsub);
17111 }
17112 }
17113 }
17114 senextself(startsub);
17115 }
17116 }
17117
17118 for (i = 0; i < cavsublist->len(); i++) {
17119 startsub = * (face *)(* cavsublist)[i];
17120 suninfect(startsub);
17121 }
17122 }
17123
17125
17126
17127
17128
17129
17130
17131
17132
17133
17135
17136 void tetgenmesh::collectvisiblesubs(int shmark, point inspoint, face* horiz,
17137 queue* flipqueue)
17138 {
17139 face newsh, hullsh;
17140 face rightsh, leftsh, spinedge;
17141 point horg, hdest;
17142 bool aboveflag;
17143 REAL ori, sign;
17144
17145
17146 adjustedgering(*horiz, CCW);
17147 horg = sorg(*horiz);
17148 hdest = sdest(*horiz);
17149 ori = orient3d(horg, hdest, sapex(*horiz), abovepoint);
17150 sign = ori > 0.0 ? -1 : 1;
17151
17152
17153 makeshellface(subfaces, &newsh);
17154 setsorg(newsh, hdest);
17155 setsdest(newsh, horg);
17156 setsapex(newsh, inspoint);
17157 setshellmark(newsh, shmark);
17158 if (b->quality && varconstraint) {
17159 setareabound(newsh, areabound(*horiz));
17160 }
17161 if (checkpbcs) {
17162 setshellpbcgroup(newsh, shellpbcgroup(*horiz));
17163 }
17164
17165 sbond(newsh, *horiz);
17166
17167 enqueueflipedge(*horiz, flipqueue);
17168
17169
17170 hullsh = *horiz;
17171 while (1) {
17172 senext(newsh, rightsh);
17173
17174
17175 spinedge = hullsh;
17176 do {
17177 hullsh = spinedge;
17178 senext2self(hullsh);
17179 spivot(hullsh, spinedge);
17180 if (spinedge.sh == dummysh) break;
17181 if (sorg(spinedge) != horg) sesymself(spinedge);
17182 assert(sorg(spinedge) == horg);
17183 } while (true);
17184 horg = sorg(hullsh);
17185
17186 ori = orient3d(horg, sdest(hullsh), abovepoint, inspoint);
17187 ori *= sign;
17188 aboveflag = ori < 0.0;
17189 if (aboveflag) {
17190
17191 makeshellface(subfaces, &newsh);
17192 setsorg(newsh, sdest(hullsh));
17193 setsdest(newsh, horg);
17194 setsapex(newsh, inspoint);
17195 setshellmark(newsh, shmark);
17196 if (b->quality && varconstraint) {
17197 setareabound(newsh, areabound(hullsh));
17198 }
17199 if (checkpbcs) {
17200 setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17201 }
17202
17203 sbond(newsh, hullsh);
17204 senext2(newsh, leftsh);
17205 sbond(leftsh, rightsh);
17206
17207 enqueueflipedge(hullsh, flipqueue);
17208 } else {
17209
17210 dummysh[0] = sencode(rightsh);
17211 break;
17212 }
17213 }
17214
17215
17216 hullsh = *horiz;
17217 spivot(*horiz, newsh);
17218 while (1) {
17219 senext2(newsh, leftsh);
17220
17221 spinedge = hullsh;
17222 do {
17223 hullsh = spinedge;
17224 senextself(hullsh);
17225 spivot(hullsh, spinedge);
17226 if (spinedge.sh == dummysh) break;
17227 if (sdest(spinedge) != hdest) sesymself(spinedge);
17228 assert(sdest(spinedge) == hdest);
17229 } while (true);
17230
17231 hdest = sdest(hullsh);
17232
17233 ori = orient3d(sorg(hullsh), hdest, abovepoint, inspoint);
17234 ori *= sign;
17235 aboveflag = ori < 0.0;
17236 if (aboveflag) {
17237
17238 makeshellface(subfaces, &newsh);
17239 setsorg(newsh, hdest);
17240 setsdest(newsh, sorg(hullsh));
17241 setsapex(newsh, inspoint);
17242 setshellmark(newsh, shmark);
17243 if (b->quality && varconstraint) {
17244 setareabound(newsh, areabound(hullsh));
17245 }
17246 if (checkpbcs) {
17247 setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17248 }
17249
17250 sbond(newsh, hullsh);
17251 senext(newsh, rightsh);
17252 sbond(rightsh, leftsh);
17253
17254 enqueueflipedge(hullsh, flipqueue);
17255 } else {
17256
17257 dummysh[0] = sencode(leftsh);
17258 break;
17259 }
17260 }
17261 }
17262
17264
17265
17266
17267
17268
17269
17270
17272
17273 void tetgenmesh::incrflipdelaunaysub(int shmark, REAL eps, list* ptlist,
17274 int holes, REAL* holelist, queue* flipque)
17275 {
17276 face newsh, startsh;
17277 point *insertarray;
17278 point swappt;
17279 pbcdata *pd;
17280 enum locateresult loc;
17281 REAL det, area;
17282 bool aboveflag;
17283 int arraysize;
17284 int epscount;
17285 int fmarker;
17286 int idx, i, j, k;
17287
17288
17289 insertarray = (point *) ptlist->base;
17290 arraysize = ptlist->len();
17291 if (arraysize < 3) return;
17292
17293
17294 aboveflag = (arraysize > 3);
17295
17296
17297
17298
17299
17300 epscount = 0;
17301 while (true) {
17302 for (i = 1; i < arraysize; i++) {
17303 det = distance(insertarray[0], insertarray[i]);
17304 if (det > (longest * eps)) break;
17305 }
17306 if (i < arraysize) {
17307
17308 swappt = insertarray[i];
17309 insertarray[i] = insertarray[1];
17310 insertarray[1] = swappt;
17311 }
17312
17313 for (i++; i < arraysize; i++) {
17314 if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
17315 break;
17316 }
17317 if (i < arraysize) {
17318
17319 swappt = insertarray[i];
17320 insertarray[i] = insertarray[2];
17321 insertarray[2] = swappt;
17322 i = 3;
17323 } else {
17324
17325
17326
17327 if ((eps == 0.0) || (epscount > 16)) {
17328 printf("Error: Invalid PLC.\n");
17329 printf(" Facet (%d, %d, %d", pointmark(insertarray[0]),
17330 pointmark(insertarray[1]), pointmark(insertarray[2]));
17331 if (ptlist->len() > 3) {
17332 printf(", ...");
17333 }
17334 printf(") (%d) is not a valid polygon.\n", shmark);
17335 terminatetetgen(1);
17336 }
17337
17338 eps *= 1e-2;
17339 epscount++;
17340 continue;
17341 }
17342 break;
17343 }
17344
17345
17346 makeshellface(subfaces, &newsh);
17347 setsorg(newsh, insertarray[0]);
17348 setsdest(newsh, insertarray[1]);
17349 setsapex(newsh, insertarray[2]);
17350
17351 setshellmark(newsh, shmark);
17352
17353 if (pointtype(insertarray[0]) == FREEVOLVERTEX) {
17354 setpointtype(insertarray[0], FREESUBVERTEX);
17355 }
17356 if (pointtype(insertarray[1]) == FREEVOLVERTEX) {
17357 setpointtype(insertarray[1], FREESUBVERTEX);
17358 }
17359 if (pointtype(insertarray[2]) == FREEVOLVERTEX) {
17360 setpointtype(insertarray[2], FREESUBVERTEX);
17361 }
17362
17363 dummysh[0] = sencode(newsh);
17364
17365
17366 if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
17367 idx = in->facetmarkerlist[shmark - 1];
17368 for (k = 0; k < in->numberoffacetconstraints; k++) {
17369 fmarker = (int) in->facetconstraintlist[k * 2];
17370 if (fmarker == idx) {
17371 area = in->facetconstraintlist[k * 2 + 1];
17372 setareabound(newsh, area);
17373 break;
17374 }
17375 }
17376 }
17377
17378
17379 if (checkpbcs) {
17380 idx = in->facetmarkerlist[shmark - 1];
17381 for (k = 0; k < in->numberofpbcgroups; k++) {
17382 pd = &subpbcgrouptable[k];
17383 for (j = 0; j < 2; j++) {
17384 if (pd->fmark[j] == idx) {
17385 setshellpbcgroup(newsh, k);
17386 pd->ss[j] = newsh;
17387 }
17388 }
17389 }
17390 }
17391
17392 if (aboveflag) {
17393
17394 abovepoint = facetabovepointarray[shmark];
17395 if (abovepoint == (point) NULL) {
17396 getfacetabovepoint(&newsh);
17397 }
17398 }
17399
17400 if (holes > 0) {
17401
17402 REAL prj[3];
17403 for (k = 0; k < holes; k++) {
17404 projpt2face(&(holelist[k * 3]), insertarray[0], insertarray[1],
17405 insertarray[2], prj);
17406 for (j = 0; j < 3; j++) holelist[k * 3 + j] = prj[j];
17407 }
17408 }
17409
17410
17411 for (; i < arraysize; i++) {
17412
17413 startsh.sh = dummysh;
17414 loc = locatesub(insertarray[i], &startsh, 0, 0.0);
17415 if (loc == ONFACE) {
17416 splitsubface(insertarray[i], &startsh, flipque);
17417 } else if (loc == ONEDGE) {
17418 splitsubedge(insertarray[i], &startsh, flipque);
17419 } else if (loc == OUTSIDE) {
17420 collectvisiblesubs(shmark, insertarray[i], &startsh, flipque);
17421 } else if (loc == ONVERTEX) {
17422
17423 }
17424
17425 if (pointtype(insertarray[i]) == FREEVOLVERTEX) {
17426 setpointtype(insertarray[i], FREESUBVERTEX);
17427 }
17428 flipsub(flipque);
17429 }
17430 }
17431
17433
17434
17435
17436
17437
17438
17439
17440
17441
17442
17443
17444
17446
17447 enum tetgenmesh::finddirectionresult tetgenmesh::finddirectionsub(
17448 face* searchsh, point tend)
17449 {
17450 face checksh;
17451 point startpoint, leftpoint, rightpoint;
17452 REAL leftccw, rightccw;
17453 REAL ori, sign;
17454 int leftflag, rightflag;
17455
17456 startpoint = sorg(*searchsh);
17457
17458 adjustedgering(*searchsh, CCW);
17459
17460 if (sorg(*searchsh) != startpoint) senextself(*searchsh);
17461 rightpoint = sdest(*searchsh);
17462 leftpoint = sapex(*searchsh);
17463 ori = orient3d(startpoint, rightpoint, leftpoint, abovepoint);
17464 sign = ori > 0.0 ? -1 : 1;
17465
17466
17467 ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17468 leftccw = ori * sign;
17469 leftflag = leftccw > 0.0;
17470
17471 ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17472 rightccw = ori * sign;
17473 rightflag = rightccw > 0.0;
17474 if (leftflag && rightflag) {
17475
17476
17477 senext2(*searchsh, checksh);
17478 spivotself(checksh);
17479 if (checksh.sh == dummysh) {
17480 leftflag = 0;
17481 } else {
17482 rightflag = 0;
17483 }
17484 }
17485 while (leftflag) {
17486
17487 senext2self(*searchsh);
17488 spivotself(*searchsh);
17489 if (searchsh->sh == dummysh) {
17490 printf("Internal error in finddirectionsub(): Unable to find a\n");
17491 printf(" subface leading from %d to %d.\n", pointmark(startpoint),
17492 pointmark(tend));
17493 internalerror();
17494 }
17495 if (sorg(*searchsh) != startpoint) sesymself(*searchsh);
17496 assert(sorg(*searchsh) == startpoint);
17497 leftpoint = sapex(*searchsh);
17498 rightccw = leftccw;
17499 ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17500 leftccw = ori * sign;
17501 leftflag = leftccw > 0.0;
17502 }
17503 while (rightflag) {
17504
17505 spivotself(*searchsh);
17506 if (searchsh->sh == dummysh) {
17507 printf("Internal error in finddirectionsub(): Unable to find a\n");
17508 printf(" subface leading from %d to %d.\n", pointmark(startpoint),
17509 pointmark(tend));
17510 internalerror();
17511 }
17512 if (sdest(*searchsh) != startpoint) sesymself(*searchsh);
17513 assert(sdest(*searchsh) == startpoint);
17514 senextself(*searchsh);
17515 rightpoint = sdest(*searchsh);
17516 leftccw = rightccw;
17517 ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17518 rightccw = ori * sign;
17519 rightflag = rightccw > 0.0;
17520 }
17521 if (leftccw == 0.0) {
17522 return LEFTCOLLINEAR;
17523 } else if (rightccw == 0.0) {
17524 return RIGHTCOLLINEAR;
17525 } else {
17526 return ACROSSEDGE;
17527 }
17528 }
17529
17531
17532
17533
17534
17535
17536
17537
17538
17540
17541 void tetgenmesh::insertsubseg(face* tri)
17542 {
17543 face oppotri;
17544 face newsubseg;
17545 point pa, pb;
17546 REAL len;
17547 int e1, e2;
17548 int i;
17549
17550
17551 sspivot(*tri, newsubseg);
17552 if (newsubseg.sh == dummysh) {
17553
17554 makeshellface(subsegs, &newsubseg);
17555 pa = sorg(*tri);
17556 pb = sdest(*tri);
17557 setsorg(newsubseg, pa);
17558 setsdest(newsubseg, pb);
17559
17560 if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
17561 for (i = 0; i < in->numberofsegmentconstraints; i++) {
17562 e1 = (int) in->segmentconstraintlist[i * 3];
17563 e2 = (int) in->segmentconstraintlist[i * 3 + 1];
17564 if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
17565 ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
17566 len = in->segmentconstraintlist[i * 3 + 2];
17567 setareabound(newsubseg, len);
17568 break;
17569 }
17570 }
17571 }
17572
17573 ssbond(*tri, newsubseg);
17574 spivot(*tri, oppotri);
17575
17576 if (oppotri.sh != dummysh) {
17577 ssbond(oppotri, newsubseg);
17578 }
17579
17580
17581
17582 }
17583 }
17584
17586
17587
17588
17589
17590
17591
17592
17593
17594
17596
17597 bool tetgenmesh::scoutsegmentsub(face* searchsh, point tend)
17598 {
17599 face newsubseg;
17600 face crosssub, crosssubseg;
17601 point leftpoint, rightpoint;
17602 enum finddirectionresult collinear;
17603
17604 collinear = finddirectionsub(searchsh, tend);
17605 rightpoint = sdest(*searchsh);
17606 leftpoint = sapex(*searchsh);
17607 if (rightpoint == tend || leftpoint == tend) {
17608
17609 if (leftpoint == tend) {
17610 senext2self(*searchsh);
17611 }
17612
17613 insertsubseg(searchsh);
17614 return true;
17615 } else if (collinear == LEFTCOLLINEAR) {
17616
17617
17618 senextself(*searchsh);
17619
17620 insertsubseg(searchsh);
17621
17622 return scoutsegmentsub(searchsh, tend);
17623 } else if (collinear == RIGHTCOLLINEAR) {
17624
17625
17626 insertsubseg(searchsh);
17627
17628 senextself(*searchsh);
17629
17630 return scoutsegmentsub(searchsh, tend);
17631 } else {
17632 senext(*searchsh, crosssub);
17633
17634 sspivot(crosssub, crosssubseg);
17635 #ifdef SELF_CHECK
17636 assert(crosssubseg.sh == dummysh);
17637 #endif
17638 return false;
17639 }
17640 }
17641
17643
17644
17645
17646
17647
17648
17649
17650
17651
17653
17654 void tetgenmesh::flipedgerecursive(face* flipedge, queue* flipqueue)
17655 {
17656 face fixupsh;
17657 point pa, pb, pc, pd;
17658 REAL oria, orib;
17659 bool doflip;
17660
17661 pa = sorg(*flipedge);
17662 pb = sdest(*flipedge);
17663 pc = sapex(*flipedge);
17664 do {
17665 spivot(*flipedge, fixupsh);
17666 pd = sapex(fixupsh);
17667 oria = orient3d(pc, pd, abovepoint, pa);
17668 orib = orient3d(pc, pd, abovepoint, pb);
17669 doflip = (oria * orib < 0.0);
17670 if (doflip) {
17671
17672 flip22sub(flipedge, flipqueue);
17673
17674 findedge(flipedge, pc, pd);
17675 } else {
17676
17677 if (sorg(fixupsh) != pb) sesymself(fixupsh);
17678 assert(sdest(fixupsh) == pa);
17679 if (fabs(oria) > fabs(orib)) {
17680
17681 senextself(fixupsh);
17682 } else {
17683
17684 senext2self(fixupsh);
17685 }
17686
17687 flipedgerecursive(&fixupsh, flipqueue);
17688 }
17689 } while (!doflip);
17690 }
17691
17693
17694
17695
17696
17697
17698
17699
17700
17701
17703
17704 void tetgenmesh::constrainededge(face* startsh, point tend, queue* flipqueue)
17705 {
17706 point tstart, tright, tleft;
17707 REAL rori, lori;
17708 bool collision;
17709
17710 tstart = sorg(*startsh);
17711 do {
17712
17713 do {
17714 tright = sdest(*startsh);
17715 tleft = sapex(*startsh);
17716
17717 rori = orient3d(tstart, tright, abovepoint, tend);
17718 collision = (rori == 0.0);
17719 if (collision) break;
17720 lori = orient3d(tstart, tleft, abovepoint, tend);
17721 collision = (lori == 0.0);
17722 if (collision) {
17723 senext2self(*startsh);
17724 break;
17725 }
17726 if (rori * lori < 0.0) break;
17727
17728 finddirectionsub(startsh, tend);
17729 } while (true);
17730 if (collision) break;
17731
17732 senextself(*startsh);
17733
17734 flipedgerecursive(startsh, flipqueue);
17735
17736 assert(sorg(*startsh) == tstart);
17737 } while (sdest(*startsh) != tend);
17738
17739
17740 insertsubseg(startsh);
17741
17742
17743 if (collision) {
17744
17745 if (!scoutsegmentsub(startsh, tend)) {
17746 constrainededge(startsh, tend, flipqueue);
17747 }
17748 }
17749 }
17750
17752
17753
17754
17756
17757 void tetgenmesh::recoversegment(point tstart, point tend, queue* flipqueue)
17758 {
17759 face searchsh;
17760
17761 if (b->verbose > 2) {
17762 printf(" Insert seg (%d, %d).\n", pointmark(tstart), pointmark(tend));
17763 }
17764
17765
17766 searchsh.sh = dummysh;
17767
17768 if (locatesub(tstart, &searchsh, 0, 0.0) != ONVERTEX) {
17769
17770 list *newshlist;
17771 int i, j;
17772 newshlist = new list(sizeof(face), NULL, 256);
17773
17774 retrievenewsubs(newshlist, false);
17775
17776 for (i = 0; i < newshlist->len(); i++) {
17777 searchsh = * (face *)(* newshlist)[i];
17778 for (j = 0; j < 3; j++) {
17779 if (sorg(searchsh) == tstart) break;
17780 senextself(searchsh);
17781 }
17782 if (j < 3) break;
17783 }
17784 delete newshlist;
17785 if (sorg(searchsh) != tstart) {
17786 printf("Internal error in recoversegment(): Vertex location failed.\n");
17787 internalerror();
17788 }
17789 }
17790
17791 if (scoutsegmentsub(&searchsh, tend)) {
17792
17793 return;
17794 }
17795
17796 constrainededge(&searchsh, tend, flipqueue);
17797
17798 flipsub(flipqueue);
17799 }
17800
17802
17803
17804
17805
17807
17808 void tetgenmesh::infecthullsub(memorypool* viri)
17809 {
17810 face hulltri, nexttri, starttri;
17811 face hullsubseg;
17812 shellface **deadshellface;
17813
17814
17815 hulltri.sh = dummysh;
17816 hulltri.shver = 0;
17817 spivotself(hulltri);
17818 adjustedgering(hulltri, CCW);
17819
17820 starttri = hulltri;
17821
17822 do {
17823
17824 if (!sinfected(hulltri)) {
17825
17826 sspivot(hulltri, hullsubseg);
17827 if (hullsubseg.sh == dummysh) {
17828
17829 if (!sinfected(hulltri)) {
17830 sinfect(hulltri);
17831 deadshellface = (shellface **) viri->alloc();
17832 *deadshellface = hulltri.sh;
17833 }
17834 }
17835 }
17836
17837 senextself(hulltri);
17838 spivot(hulltri, nexttri);
17839 if (nexttri.sh == hulltri.sh) {
17840 nexttri.sh = dummysh;
17841 } else {
17842 adjustedgering(nexttri, CCW);
17843 senextself(nexttri);
17844 }
17845 while (nexttri.sh != dummysh) {
17846 hulltri = nexttri;
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 }
17855 } while (hulltri != starttri);
17856 }
17857
17859
17860
17861
17862
17863
17864
17865
17867
17868 void tetgenmesh::plaguesub(memorypool* viri)
17869 {
17870 face testtri, neighbor, ghostsh;
17871 face neighborsubseg;
17872 shellface **virusloop;
17873 shellface **deadshellface;
17874 int i;
17875
17876
17877
17878 viri->traversalinit();
17879 virusloop = (shellface **) viri->traverse();
17880 while (virusloop != (shellface **) NULL) {
17881 testtri.sh = *virusloop;
17882
17883 for (i = 0; i < 3; i++) {
17884
17885 spivot(testtri, neighbor);
17886
17887 sspivot(testtri, neighborsubseg);
17888
17889 if ((neighbor.sh == dummysh) || sinfected(neighbor)) {
17890 if (neighborsubseg.sh != dummysh) {
17891
17892
17893
17894 shellfacedealloc(subsegs, neighborsubseg.sh);
17895 if (neighbor.sh != dummysh) {
17896
17897
17898 ssdissolve(neighbor);
17899 }
17900 }
17901 } else {
17902 if (neighborsubseg.sh == dummysh) {
17903
17904
17905 sinfect(neighbor);
17906
17907 deadshellface = (shellface **) viri->alloc();
17908 *deadshellface = neighbor.sh;
17909 } else {
17910
17911 ssbond(neighbor, neighborsubseg);
17912 }
17913 }
17914 senextself(testtri);
17915 }
17916 virusloop = (shellface **) viri->traverse();
17917 }
17918
17919 ghostsh.sh = dummysh;
17920 viri->traversalinit();
17921 virusloop = (shellface **) viri->traverse();
17922 while (virusloop != (shellface **) NULL) {
17923 testtri.sh = *virusloop;
17924
17925
17926 for (i = 0; i < 3; i++) {
17927 spivot(testtri, neighbor);
17928 if (neighbor.sh != dummysh) {
17929
17930
17931 sbond(neighbor, ghostsh);
17932 }
17933 senextself(testtri);
17934 }
17935
17936 shellfacedealloc(subfaces, testtri.sh);
17937 virusloop = (shellface **) viri->traverse();
17938 }
17939
17940 viri->restart();
17941 }
17942
17944
17945
17946
17947
17948
17949
17950
17951
17953
17954 void tetgenmesh::carveholessub(int holes, REAL* holelist, memorypool *viri)
17955 {
17956 face searchtri, triangleloop;
17957 shellface **holetri;
17958 enum locateresult intersect;
17959 int i;
17960
17961
17962
17963 infecthullsub(viri);
17964
17965 if (holes > 0) {
17966
17967 for (i = 0; i < 3 * holes; i += 3) {
17968
17969 if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
17970 && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)
17971 && (holelist[i + 2] >= zmin) && (holelist[i + 2] <= zmax)) {
17972
17973 searchtri.sh = dummysh;
17974
17975 intersect = locatesub(&holelist[i], &searchtri, 0, 0.0);
17976 if ((intersect != OUTSIDE) && (!sinfected(searchtri))) {
17977
17978
17979 sinfect(searchtri);
17980 holetri = (shellface **) viri->alloc();
17981 *holetri = searchtri.sh;
17982 }
17983 }
17984 }
17985 }
17986
17987 if (viri->items > 0) {
17988
17989 plaguesub(viri);
17990 }
17991
17992 }
17993
17995
17996
17997
17998
17999
18000
18001
18002
18003
18004
18005
18006
18007
18008
18009
18011
18012 void tetgenmesh::triangulate(int shmark, REAL eps, list* ptlist, list* conlist,
18013 int holes, REAL* holelist, memorypool* viri, queue* flipqueue)
18014 {
18015 face newsh;
18016 point *cons;
18017 int i;
18018
18019 if (b->verbose > 1) {
18020 printf(" %d vertices, %d segments", ptlist->len(), conlist->len());
18021 if (holes > 0) {
18022 printf(", %d holes", holes);
18023 }
18024 printf(", shmark: %d.\n", shmark);
18025 }
18026
18027
18028 incrflipdelaunaysub(shmark, eps, ptlist, holes, holelist, flipqueue);
18029
18030 if (ptlist->len() > 3) {
18031
18032 for (i = 0; i < conlist->len(); i++) {
18033 cons = (point *)(* conlist)[i];
18034 recoversegment(cons[0], cons[1], flipqueue);
18035 }
18036
18037 carveholessub(holes, holelist, viri);
18038 } else if (ptlist->len() == 3) {
18039
18040 newsh.sh = dummysh;
18041 newsh.shver = 0;
18042 spivotself(newsh);
18043 for (i = 0; i < 3; i++) {
18044 insertsubseg(&newsh);
18045 senextself(newsh);
18046 }
18047 } else if (ptlist->len() == 2) {
18048
18049
18050
18051 cons = (point *)(* conlist)[0];
18052 makeshellface(subsegs, &newsh);
18053 setsorg(newsh, cons[0]);
18054 setsdest(newsh, cons[1]);
18055 }
18056 }
18057
18059
18060
18061
18062
18063
18064
18065
18066
18067
18068
18070
18071 void tetgenmesh::retrievenewsubs(list* newshlist, bool removeseg)
18072 {
18073 face startsh, neighsh;
18074 face deadseg;
18075 int i, j;
18076
18077
18078 startsh.sh = dummysh;
18079 startsh.shver = 0;
18080 spivotself(startsh);
18081 assert(startsh.sh != dummysh);
18082 sinfect(startsh);
18083 newshlist->append(&startsh);
18084
18085
18086 for (i = 0; i < newshlist->len(); i++) {
18087
18088 startsh = * (face *)(* newshlist)[i];
18089 for (j = 0; j < 3; j++) {
18090 spivot(startsh, neighsh);
18091 if (neighsh.sh != dummysh) {
18092 if (!sinfected(neighsh)) {
18093
18094 sinfect(neighsh);
18095 newshlist->append(&neighsh);
18096 }
18097 } else {
18098
18099 if (removeseg) {
18100
18101 sspivot(startsh, deadseg);
18102 if (deadseg.sh != dummysh) {
18103
18104 ssdissolve(startsh);
18105
18106 shellfacedealloc(subsegs, deadseg.sh);
18107 }
18108 }
18109 }
18110 senextself(startsh);
18111 }
18112 }
18113 for (i = 0; i < newshlist->len(); i++) {
18114 startsh = * (face *)(* newshlist)[i];
18115 suninfect(startsh);
18116 }
18117 }
18118
18120
18121
18122
18123
18124
18125
18126
18127
18128
18129
18130
18131
18132
18133
18135
18136 void tetgenmesh::unifysegments()
18137 {
18138 list *sfacelist;
18139 shellface **facesperverlist;
18140 face subsegloop, testseg;
18141 face sface, sface1, sface2;
18142 point torg, tdest;
18143 REAL da1, da2;
18144 int *idx2facelist;
18145 int segmarker;
18146 int idx, k, m;
18147
18148 if (b->verbose > 0) {
18149 printf(" Unifying segments.\n");
18150 }
18151
18152
18153 makesubfacemap(idx2facelist, facesperverlist);
18154
18155 sfacelist = new list(sizeof(face), NULL);
18156
18157 segmarker = 1;
18158 subsegs->traversalinit();
18159 subsegloop.sh = shellfacetraverse(subsegs);
18160 while (subsegloop.sh != (shellface *) NULL) {
18161 subsegloop.shver = 0;
18162 torg = sorg(subsegloop);
18163 tdest = sdest(subsegloop);
18164 idx = pointmark(torg) - in->firstnumber;
18165
18166
18167
18168
18169 for (k = idx2facelist[idx]; k < idx2facelist[idx + 1]; k++) {
18170 sface.sh = facesperverlist[k];
18171 sface.shver = 0;
18172
18173 if (!isdead(&sface) && isfacehasedge(&sface, torg, tdest)) {
18174
18175 findedge(&sface, torg, tdest);
18176
18177 if (sfacelist->len() < 2) {
18178 sfacelist->append(&sface);
18179 } else {
18180 for (m = 0; m < sfacelist->len() - 1; m++) {
18181 sface1 = * (face *)(* sfacelist)[m];
18182 sface2 = * (face *)(* sfacelist)[m + 1];
18183 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(sface));
18184 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
18185 if (da1 < da2) {
18186 break;
18187 }
18188 }
18189 sfacelist->insert(m + 1, &sface);
18190 }
18191 }
18192 }
18193 if (b->verbose > 1) {
18194 printf(" Identifying %d segments of (%d %d).\n", sfacelist->len(),
18195 pointmark(torg), pointmark(tdest));
18196 }
18197
18198
18199 for (k = 0; k < sfacelist->len(); k++) {
18200 sface = *(face *)(* sfacelist)[k];
18201 sspivot(sface, testseg);
18202
18203
18204
18205 if ((testseg.sh != subsegloop.sh) && !isdead(&testseg)) {
18206 shellfacedealloc(subsegs, testseg.sh);
18207 }
18208
18209
18210 ssbond(sface, subsegloop);
18211 }
18212
18213 sface = *(face *)(* sfacelist)[0];
18214 for (k = 1; k <= sfacelist->len(); k++) {
18215 if (k < sfacelist->len()) {
18216 sface1 = *(face *)(* sfacelist)[k];
18217 } else {
18218 sface1 = *(face *)(* sfacelist)[0];
18219 }
18220
18221
18222
18223
18224
18225
18226
18227
18228
18229
18230
18231
18232
18233
18234
18235
18236
18237
18238
18239
18240
18241
18242
18243
18244
18245
18246
18247 if (b->verbose > 2) {
18248 printf(" Bond subfaces (%d, %d, %d) and (%d, %d, %d).\n",
18249 pointmark(torg), pointmark(tdest), pointmark(sapex(sface)),
18250 pointmark(torg), pointmark(tdest), pointmark(sapex(sface1)));
18251 }
18252 sbond1(sface, sface1);
18253 sface = sface1;
18254 }
18255
18256 setshellmark(subsegloop, segmarker);
18257
18258 segmarker++;
18259
18260 sfacelist->clear();
18261 subsegloop.sh = shellfacetraverse(subsegs);
18262 }
18263
18264 delete [] idx2facelist;
18265 delete [] facesperverlist;
18266 delete sfacelist;
18267 }
18268
18270
18271
18272
18273
18274
18275
18276
18277
18278
18280
18281 void tetgenmesh::mergefacets(queue* flipqueue)
18282 {
18283 face parentsh, neighsh, neineighsh;
18284 face segloop;
18285 point eorg, edest;
18286 REAL ori;
18287 bool mergeflag, pbcflag;
18288 int* segspernodelist;
18289 int fidx1, fidx2;
18290 int i, j;
18291
18292 if (b->verbose > 0) {
18293 printf(" Merging coplanar facets.\n");
18294 }
18295
18296 segspernodelist = new int[points->items + 1];
18297 for (i = 0; i < points->items + 1; i++) segspernodelist[i] = 0;
18298
18299
18300 subsegs->traversalinit();
18301 segloop.sh = shellfacetraverse(subsegs);
18302 while (segloop.sh != (shellface *) NULL) {
18303
18304 for (i = 0; i < 2; i++) {
18305 j = pointmark((point) segloop.sh[3 + i]);
18306 segspernodelist[j]++;
18307 }
18308 segloop.sh = shellfacetraverse(subsegs);
18309 }
18310
18311
18312 subsegs->traversalinit();
18313 segloop.sh = shellfacetraverse(subsegs);
18314 while (segloop.sh != (shellface *) NULL) {
18315 eorg = sorg(segloop);
18316 edest = sdest(segloop);
18317 spivot(segloop, parentsh);
18318 spivot(parentsh, neighsh);
18319 spivot(neighsh, neineighsh);
18320 if (parentsh.sh != neighsh.sh && parentsh.sh == neineighsh.sh) {
18321
18322 fidx1 = shellmark(parentsh) - 1;
18323 fidx2 = shellmark(neighsh) - 1;
18324 pbcflag = false;
18325 if (checkpbcs) {
18326 pbcflag = (shellpbcgroup(parentsh) >= 0)
18327 || (shellpbcgroup(neighsh) >= 0);
18328 }
18329
18330 if ((fidx1 != fidx2) && !pbcflag) {
18331
18332 ori = orient3d(eorg, edest, sapex(parentsh), sapex(neighsh));
18333 if (ori != 0.0) {
18334 if (iscoplanar(eorg, edest, sapex(parentsh), sapex(neighsh), ori,
18335 b->epsilon)) {
18336 ori = 0.0;
18337 }
18338 }
18339 if (ori == 0.0) {
18340 mergeflag = (in->facetmarkerlist == (int *) NULL ||
18341 in->facetmarkerlist[fidx1] == in->facetmarkerlist[fidx2]);
18342 if (mergeflag) {
18343
18344 if (b->verbose > 1) {
18345 printf(" Removing segment (%d, %d).\n", pointmark(eorg),
18346 pointmark(edest));
18347 }
18348 ssdissolve(parentsh);
18349 ssdissolve(neighsh);
18350 shellfacedealloc(subsegs, segloop.sh);
18351 j = pointmark(eorg);
18352 segspernodelist[j]--;
18353 if (segspernodelist[j] == 0) {
18354 setpointtype(eorg, FREESUBVERTEX);
18355 }
18356 j = pointmark(edest);
18357 segspernodelist[j]--;
18358 if (segspernodelist[j] == 0) {
18359 setpointtype(edest, FREESUBVERTEX);
18360 }
18361
18362 enqueueflipedge(parentsh, flipqueue);
18363 }
18364 }
18365 }
18366 }
18367 segloop.sh = shellfacetraverse(subsegs);
18368 }
18369
18370 if (!flipqueue->empty()) {
18371
18372 flipsub(flipqueue);
18373 }
18374
18375 delete [] segspernodelist;
18376 }
18377
18379
18380
18381
18382
18383
18384
18385
18386
18387
18388
18389
18390
18391
18392
18393
18394
18395
18397
18398 long tetgenmesh::meshsurface()
18399 {
18400 list *ptlist, *conlist;
18401 queue *flipqueue;
18402 tetgenio::facet *f;
18403 tetgenio::polygon *p;
18404 memorypool *viri;
18405 point *idx2verlist;
18406 point tstart, tend, *cons;
18407 int *worklist;
18408 int end1, end2;
18409 int shmark, i, j;
18410
18411 if (!b->quiet) {
18412 printf("Creating surface mesh.\n");
18413 }
18414
18415
18416 makeindex2pointmap(idx2verlist);
18417
18418 makepoint2tetmap();
18419
18420 facetabovepointarray = new point[in->numberoffacets + 1];
18421 for (i = 0; i < in->numberoffacets + 1; i++) {
18422 facetabovepointarray[i] = (point) NULL;
18423 }
18424 if (checkpbcs) {
18425
18426 createsubpbcgrouptable();
18427 }
18428
18429
18430 viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
18431 flipqueue = new queue(sizeof(badface));
18432 ptlist = new list(sizeof(point *), NULL, 256);
18433 conlist = new list(sizeof(point *) * 2, NULL, 256);
18434 worklist = new int[points->items + 1];
18435 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
18436
18437
18438
18439
18440 for (shmark = 1; shmark <= in->numberoffacets; shmark++) {
18441
18442 f = &in->facetlist[shmark - 1];
18443
18444
18445
18446
18447
18448 if ((b->object == tetgenbehavior::STL) || dupverts) {
18449
18450 for (i = 0; i < f->numberofpolygons; i++) {
18451 p = &(f->polygonlist[i]);
18452
18453 for (j = 0; j < p->numberofvertices; j++) {
18454 end1 = p->vertexlist[j];
18455 tstart = idx2verlist[end1 - in->firstnumber];
18456 if (pointtype(tstart) == DUPLICATEDVERTEX) {
18457
18458 tend = point2ppt(tstart);
18459 end2 = pointmark(tend);
18460 p->vertexlist[j] = end2;
18461 }
18462 }
18463 }
18464 }
18465
18466
18467 for (i = 0; i < f->numberofpolygons; i++) {
18468
18469 p = &(f->polygonlist[i]);
18470
18471 end1 = p->vertexlist[0];
18472 if ((end1 < in->firstnumber) ||
18473 (end1 >= in->firstnumber + in->numberofpoints)) {
18474 if (!b->quiet) {
18475 printf("Warning: Invalid the 1st vertex %d of polygon", end1);
18476 printf(" %d in facet %d.\n", i + 1, shmark);
18477 }
18478 continue;
18479 }
18480 tstart = idx2verlist[end1 - in->firstnumber];
18481
18482 if (worklist[end1] == 0) {
18483 ptlist->append(&tstart);
18484 worklist[end1] = 1;
18485 }
18486
18487 for (j = 1; j <= p->numberofvertices; j++) {
18488
18489 if (j < p->numberofvertices) {
18490 end2 = p->vertexlist[j];
18491 } else {
18492 end2 = p->vertexlist[0];
18493 }
18494 if ((end2 < in->firstnumber) ||
18495 (end2 >= in->firstnumber + in->numberofpoints)) {
18496 if (!b->quiet) {
18497 printf("Warning: Invalid vertex %d in polygon %d", end2, i + 1);
18498 printf(" in facet %d.\n", shmark);
18499 }
18500 } else {
18501 if (end1 != end2) {
18502
18503 tend = idx2verlist[end2 - in->firstnumber];
18504
18505 if (worklist[end2] == 0) {
18506 ptlist->append(&tend);
18507 worklist[end2] = 1;
18508 }
18509
18510 cons = (point *) conlist->append(NULL);
18511 cons[0] = tstart;
18512 cons[1] = tend;
18513
18514 end1 = end2;
18515 tstart = tend;
18516 } else {
18517
18518 if (p->numberofvertices > 2) {
18519
18520
18521 if (!b->quiet) {
18522 printf("Warning: Polygon %d has two identical verts", i + 1);
18523 printf(" in facet %d.\n", shmark);
18524 }
18525 }
18526
18527 }
18528 }
18529
18530 if (p->numberofvertices == 2) break;
18531 }
18532 }
18533
18534 for (i = 0; i < ptlist->len(); i++) {
18535 tstart = * (point *)(* ptlist)[i];
18536 end1 = pointmark(tstart);
18537 assert(worklist[end1] == 1);
18538 worklist[end1] = 0;
18539 }
18540
18541
18542 triangulate(shmark, b->epsilon * 1e+2, ptlist, conlist, f->numberofholes,
18543 f->holelist, viri, flipqueue);
18544
18545 ptlist->clear();
18546 conlist->clear();
18547 viri->restart();
18548 }
18549
18550
18551
18552 unifysegments();
18553
18554 insegments = subsegs->items;
18555
18556 if (checkpbcs) {
18557
18558 createsegpbcgrouptable();
18559 }
18560
18561 if (b->object == tetgenbehavior::STL) {
18562
18563 jettisonnodes();
18564 }
18565
18566 if (!b->nomerge && !b->nobisect && !checkpbcs) {
18567
18568 mergefacets(flipqueue);
18569 }
18570
18571 delete [] idx2verlist;
18572 delete [] worklist;
18573 delete ptlist;
18574 delete conlist;
18575 delete flipqueue;
18576 delete viri;
18577
18578 return subsegs->items;
18579 }
18580
18581
18582
18583
18584
18586
18587
18588
18589
18590
18591
18592
18593
18594
18595
18596
18597
18598
18599
18600
18601
18602
18603
18604
18605
18606
18608
18609 void tetgenmesh::
18610 interecursive(shellface** subfacearray, int arraysize, int axis, REAL bxmin,
18611 REAL bxmax, REAL bymin, REAL bymax, REAL bzmin, REAL bzmax,
18612 int* internum)
18613 {
18614 shellface **leftarray, **rightarray;
18615 face sface1, sface2;
18616 point p1, p2, p3;
18617 point p4, p5, p6;
18618 enum interresult intersect;
18619 REAL split;
18620 bool toleft, toright;
18621 int leftsize, rightsize;
18622 int i, j;
18623
18624 if (b->verbose > 1) {
18625 printf(" Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
18626 arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
18627 axis == 0 ? "x" : (axis == 1 ? "y" : "z"));
18628 }
18629
18630 leftarray = new shellface*[arraysize];
18631 if (leftarray == NULL) {
18632 printf("Error in interecursive(): Insufficient memory.\n");
18633 terminatetetgen(1);
18634 }
18635 rightarray = new shellface*[arraysize];
18636 if (rightarray == NULL) {
18637 printf("Error in interecursive(): Insufficient memory.\n");
18638 terminatetetgen(1);
18639 }
18640 leftsize = rightsize = 0;
18641
18642 if (axis == 0) {
18643
18644 split = 0.5 * (bxmin + bxmax);
18645 } else if (axis == 1) {
18646
18647 split = 0.5 * (bymin + bymax);
18648 } else {
18649
18650 split = 0.5 * (bzmin + bzmax);
18651 }
18652
18653 for (i = 0; i < arraysize; i++) {
18654 sface1.sh = subfacearray[i];
18655 p1 = (point) sface1.sh[3];
18656 p2 = (point) sface1.sh[4];
18657 p3 = (point) sface1.sh[5];
18658 toleft = toright = false;
18659 if (p1[axis] < split) {
18660 toleft = true;
18661 if (p2[axis] >= split || p3[axis] >= split) {
18662 toright = true;
18663 }
18664 } else if (p1[axis] > split) {
18665 toright = true;
18666 if (p2[axis] <= split || p3[axis] <= split) {
18667 toleft = true;
18668 }
18669 } else {
18670
18671 toleft = true;
18672 toright = true;
18673 }
18674
18675 #ifdef SELF_CHECK
18676 assert(!(toleft == false && toright == false));
18677 #endif
18678 if (toleft) {
18679 leftarray[leftsize] = sface1.sh;
18680 leftsize++;
18681 }
18682 if (toright) {
18683 rightarray[rightsize] = sface1.sh;
18684 rightsize++;
18685 }
18686 }
18687
18688 if (leftsize < arraysize && rightsize < arraysize) {
18689
18690
18691
18692
18693 delete [] subfacearray;
18694
18695 if (axis == 0) {
18696 interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax,
18697 bzmin, bzmax, internum);
18698 interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax,
18699 bzmin, bzmax, internum);
18700 } else if (axis == 1) {
18701 interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split,
18702 bzmin, bzmax, internum);
18703 interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax,
18704 bzmin, bzmax, internum);
18705 } else {
18706 interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax,
18707 bzmin, split, internum);
18708 interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax,
18709 split, bzmax, internum);
18710 }
18711 } else {
18712 if (b->verbose > 1) {
18713 printf(" Checking intersecting faces.\n");
18714 }
18715
18716 for (i = 0; i < arraysize; i++) {
18717 sface1.sh = subfacearray[i];
18718 p1 = (point) sface1.sh[3];
18719 p2 = (point) sface1.sh[4];
18720 p3 = (point) sface1.sh[5];
18721 for (j = i + 1; j < arraysize; j++) {
18722 sface2.sh = subfacearray[j];
18723 p4 = (point) sface2.sh[3];
18724 p5 = (point) sface2.sh[4];
18725 p6 = (point) sface2.sh[5];
18726 intersect = tri_tri_inter(p1, p2, p3, p4, p5, p6);
18727 if (intersect == INTERSECT || intersect == SHAREFACE) {
18728 if (!b->quiet) {
18729 if (intersect == INTERSECT) {
18730 printf(" Facet #%d intersects facet #%d at triangles:\n",
18731 shellmark(sface1), shellmark(sface2));
18732 printf(" (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
18733 pointmark(p1), pointmark(p2), pointmark(p3),
18734 pointmark(p4), pointmark(p5), pointmark(p6));
18735 } else {
18736 printf(" Facet #%d duplicates facet #%d at triangle:\n",
18737 shellmark(sface1), shellmark(sface2));
18738 printf(" (%4d, %4d, %4d)\n", pointmark(p1), pointmark(p2),
18739 pointmark(p3));
18740 }
18741 }
18742
18743 (*internum)++;
18744
18745 sinfect(sface1);
18746 sinfect(sface2);
18747 }
18748 }
18749 }
18750
18751 delete [] leftarray;
18752 delete [] rightarray;
18753 delete [] subfacearray;
18754 }
18755 }
18756
18758
18759
18760
18761
18762
18763
18764
18765
18766
18767
18768
18769
18770
18771
18772
18773
18774
18775
18776
18777
18778
18779
18781
18782 void tetgenmesh::detectinterfaces()
18783 {
18784 shellface **subfacearray;
18785 face shloop;
18786 int internum;
18787 int i;
18788
18789 if (!b->quiet) {
18790 printf("Detecting intersecting facets.\n");
18791 }
18792
18793
18794 subfacearray = new shellface*[subfaces->items];
18795 subfaces->traversalinit();
18796 shloop.sh = shellfacetraverse(subfaces);
18797 i = 0;
18798 while (shloop.sh != (shellface *) NULL) {
18799 subfacearray[i] = shloop.sh;
18800 shloop.sh = shellfacetraverse(subfaces);
18801 i++;
18802 }
18803
18804 internum = 0;
18805
18806
18807
18808 interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax,
18809 zmin, zmax, &internum);
18810
18811 if (!b->quiet) {
18812 if (internum > 0) {
18813 printf("\n!! Found %d pairs of faces are intersecting.\n\n", internum);
18814 } else {
18815 printf("\nNo faces are intersecting.\n\n");
18816 }
18817 }
18818
18819 if (internum > 0) {
18820
18821
18822
18823 subfaces->traversalinit();
18824 shloop.sh = shellfacetraverse(subfaces);
18825 while (shloop.sh != (shellface *) NULL) {
18826 if (sinfected(shloop)) {
18827 suninfect(shloop);
18828 } else {
18829 shellfacedealloc(subfaces, shloop.sh);
18830 }
18831 shloop.sh = shellfacetraverse(subfaces);
18832 }
18833 } else {
18834
18835 subfaces->restart();
18836 }
18837 }
18838
18839
18840
18841
18842
18844
18845
18846
18847
18848
18849
18850
18851
18852
18853
18854
18856
18857 void tetgenmesh::createsubpbcgrouptable()
18858 {
18859 tetgenio::pbcgroup *pg;
18860 pbcdata *pd;
18861 REAL A[4][4], rhs[4], D;
18862 int indx[4];
18863 int i, j, k;
18864
18865 subpbcgrouptable = new pbcdata[in->numberofpbcgroups];
18866 for (i = 0; i < in->numberofpbcgroups; i++) {
18867 pg = &(in->pbcgrouplist[i]);
18868 pd = &(subpbcgrouptable[i]);
18869
18870 pd->fmark[0] = pg->fmark1;
18871 pd->fmark[1] = pg->fmark2;
18872
18873 pd->ss[0].sh = dummysh;
18874 pd->ss[1].sh = dummysh;
18875
18876 for (j = 0; j < 4; j++) {
18877 for (k = 0; k < 4; k++) {
18878 pd->transmat[0][j][k] = pg->transmat[j][k];
18879
18880 A[j][k] = pg->transmat[j][k];
18881 }
18882 }
18883
18884 lu_decmp(A, 4, indx, &D, 0);
18885 for (j = 0; j < 4; j++) {
18886 for (k = 0; k < 4; k++) rhs[k] = 0.0;
18887 rhs[j] = 1.0;
18888 lu_solve(A, 4, indx, rhs, 0);
18889 for (k = 0; k < 4; k++) pd->transmat[1][k][j] = rhs[k];
18890 }
18891 }
18892 }
18893
18895
18896
18897
18898
18899
18900
18901
18903
18904 void tetgenmesh::getsubpbcgroup(face* pbcsub, pbcdata** pd, int *f1, int *f2)
18905 {
18906 int groupid, fmark, idx;
18907
18908 groupid = shellpbcgroup(*pbcsub);
18909 *pd = &subpbcgrouptable[groupid];
18910
18911
18912 idx = shellmark(*pbcsub);
18913
18914 fmark = in->facetmarkerlist[idx - 1];
18915 if ((*pd)->fmark[0] == fmark) {
18916 *f1 = 0;
18917 } else {
18918 #ifdef SELF_CHECK
18919 assert((*pd)->fmark[1] == fmark);
18920 #endif
18921 *f1 = 1;
18922 }
18923 *f2 = 1 - (*f1);
18924 }
18925
18927
18928
18929
18930
18931
18932
18933
18935
18936 enum tetgenmesh::locateresult tetgenmesh:: getsubpbcsympoint(point newpoint,
18937 face* splitsub, point sympoint, face* symsplitsub)
18938 {
18939 pbcdata *pd;
18940 face subloop;
18941 point pa, pb, pc;
18942 enum locateresult symloc;
18943 REAL ori;
18944 int f1, f2, i;
18945
18946
18947 getsubpbcgroup(splitsub, &pd, &f1, &f2);
18948
18949
18950 for (i = 0; i < 3; i++) {
18951 sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
18952 + pd->transmat[f1][i][1] * newpoint[1]
18953 + pd->transmat[f1][i][2] * newpoint[2]
18954 + pd->transmat[f1][i][3] * 1.0;
18955 }
18956
18957 symloc = OUTSIDE;
18958 *symsplitsub = pd->ss[f2];
18959
18960 if ((symsplitsub->sh != dummysh) && !isdead(symsplitsub)) {
18961
18962 i = shellmark(*symsplitsub);
18963 if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18964
18965 pa = sorg(*symsplitsub);
18966 pb = sdest(*symsplitsub);
18967 pc = sapex(*symsplitsub);
18968
18969
18970 ori = orient3d(pa, pb, pc, sympoint);
18971 if (iscoplanar(pa, pb, pc, sympoint, ori, b->epsilon * 1e+2)) {
18972
18973 abovepoint = facetabovepointarray[shellmark(*symsplitsub)];
18974 if (abovepoint == (point) NULL) {
18975 getfacetabovepoint(symsplitsub);
18976 }
18977 symloc = locatesub(sympoint, symsplitsub, 0, b->epsilon * 1e+2);
18978 }
18979 }
18980 }
18981 if (symloc == OUTSIDE) {
18982
18983 REAL epspp = b->epsilon * 1e+2;
18984 int lcount = 0;
18985 do {
18986
18987 subfaces->traversalinit();
18988 subloop.sh = shellfacetraverse(subfaces);
18989 while (subloop.sh != (shellface *) NULL) {
18990 i = shellmark(subloop);
18991 if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18992
18993 pa = sorg(subloop);
18994 pb = sdest(subloop);
18995 pc = sapex(subloop);
18996
18997
18998 ori = orient3d(pa, pb, pc, sympoint);
18999 if (iscoplanar(pa, pb, pc, sympoint, ori, epspp)) {
19000
19001
19002 abovepoint = facetabovepointarray[shellmark(subloop)];
19003
19004 if (abovepoint == (point) NULL) {
19005 getfacetabovepoint(&subloop);
19006 }
19007
19008 symloc = locatesub(sympoint, &subloop, 0, epspp);
19009 if (symloc != OUTSIDE) break;
19010 }
19011 }
19012 subloop.sh = shellfacetraverse(subfaces);
19013 }
19014 lcount++;
19015 epspp *= 10.0;
19016 } while ((symloc == OUTSIDE) && (lcount < 3));
19017 #ifdef SELF_CHECK
19018
19019 assert(symloc != OUTSIDE);
19020 #endif
19021
19022 *symsplitsub = subloop;
19023
19024 pd->ss[f2] = *symsplitsub;
19025 }
19026
19027 return adjustlocatesub(sympoint, symsplitsub, symloc, b->epsilon);
19028 }
19029
19031
19032
19033
19034
19035
19036
19037
19038
19039
19040
19042
19043 void tetgenmesh::createsegpbcgrouptable()
19044 {
19045 shellface** segsperverlist;
19046 pbcdata *pd, *ppd, pd1, pd2;
19047 face segloop, symseg;
19048 face startsh, spinsh, symsh;
19049 point pa, pb, syma, symb;
19050 enum locateresult symloc;
19051 REAL testpt[3], sympt[3];
19052 bool inflag;
19053 int *idx2seglist;
19054 int segid1, segid2;
19055 int f1, f2;
19056 int i, j, k, l;
19057
19058
19059 segpbcgrouptable = new list(sizeof(pbcdata), NULL, 256);
19060
19061 if (b->refine) {
19062
19063 makesegmentmap(idx2seglist, segsperverlist);
19064 }
19065
19066
19067 subsegs->traversalinit();
19068 segloop.sh = shellfacetraverse(subsegs);
19069 while (segloop.sh != (shellface *) NULL) {
19070
19071 pa = sorg(segloop);
19072 pb = sdest(segloop);
19073 segid1 = shellmark(segloop);
19074 spivot(segloop, startsh);
19075 spinsh = startsh;
19076 do {
19077
19078 if (sorg(spinsh) != pa) {
19079 sesymself(spinsh);
19080 }
19081
19082 if (shellpbcgroup(spinsh) != -1) {
19083
19084 if (b->refine) {
19085 getsubpbcgroup(&spinsh, &pd, &f1, &f2);
19086
19087 for (i = 0; i < 3; i++) {
19088 sympt[i] = pd->transmat[f1][i][0] * pa[0]
19089 + pd->transmat[f1][i][1] * pa[1]
19090 + pd->transmat[f1][i][2] * pa[2]
19091 + pd->transmat[f1][i][3] * 1.0;
19092 }
19093 syma = point2pbcpt(pa);
19094
19095 if (distance(sympt, syma) > (longest * b->epsilon)) {
19096
19097 symloc = getsubpbcsympoint(pa, &spinsh, sympt, &symsh);
19098 syma = sorg(symsh);
19099 if (symloc != ONVERTEX) {
19100
19101 assert(0);
19102 }
19103 }
19104
19105 for (i = 0; i < 3; i++) {
19106 sympt[i] = pd->transmat[f1][i][0] * pb[0]
19107 + pd->transmat[f1][i][1] * pb[1]
19108 + pd->transmat[f1][i][2] * pb[2]
19109 + pd->transmat[f1][i][3] * 1.0;
19110 }
19111
19112 symseg.shver = 0;
19113 j = pointmark(syma) - in->firstnumber;
19114 for (i = idx2seglist[j]; i < idx2seglist[j + 1]; i++) {
19115 symseg.sh = segsperverlist[i];
19116 if (sorg(symseg) == syma) symb = sdest(symseg);
19117 else symb = sorg(symseg);
19118 if (distance(sympt, symb) <= (longest * b->epsilon)) break;
19119 }
19120 assert(i < idx2seglist[j + 1]);
19121 } else {
19122
19123 for (i = 0; i < 3; i++) testpt[i] = 0.5 * (pa[i] + pb[i]);
19124 symloc = getsubpbcsympoint(testpt, &spinsh, sympt, &symsh);
19125 #ifdef SELF_CHECK
19126 assert(symloc == ONEDGE);
19127 #endif
19128 sspivot(symsh, symseg);
19129 }
19130 #ifdef SELF_CHECK
19131 assert(symseg.sh != dummysh);
19132 #endif
19133
19134 segid2 = shellmark(symseg);
19135 inflag = false;
19136 for (i = 0; i < segpbcgrouptable->len() && !inflag; i++) {
19137 pd = (pbcdata *)(* segpbcgrouptable)[i];
19138 if (pd->segid[0] == segid1) {
19139 if (pd->segid[1] == segid2) inflag = true;
19140 } else if (pd->segid[0] == segid2) {
19141 if (pd->segid[1] == segid1) inflag = true;
19142 }
19143 }
19144 if (!inflag) {
19145
19146 pd = (pbcdata *) segpbcgrouptable->append(NULL);
19147
19148 pd->segid[0] = segid1;
19149 pd->segid[1] = segid2;
19150
19151 pd->ss[0] = segloop;
19152 pd->ss[1] = symseg;
19153
19154 getsubpbcgroup(&spinsh, &ppd, &f1, &f2);
19155 pd->fmark[0] = ppd->fmark[f1];
19156 pd->fmark[1] = ppd->fmark[f2];
19157
19158 for (i = 0; i < 4; i++) {
19159 for (j = 0; j < 4; j++) {
19160 pd->transmat[0][i][j] = ppd->transmat[f1][i][j];
19161 }
19162 }
19163
19164 for (i = 0; i < 4; i++) {
19165 for (j = 0; j < 4; j++) {
19166 pd->transmat[1][i][j] = ppd->transmat[f2][i][j];
19167 }
19168 }
19169 }
19170 }
19171
19172 spivotself(spinsh);
19173 } while (spinsh.sh != startsh.sh);
19174 segloop.sh = shellfacetraverse(subsegs);
19175 }
19176
19177 if (b->refine) {
19178 delete [] segsperverlist;
19179 delete [] idx2seglist;
19180 }
19181
19182
19183
19184
19185
19186 for (i = 0; i < segpbcgrouptable->len(); i++) {
19187 pd1 = * (pbcdata *)(* segpbcgrouptable)[i];
19188 for (f1 = 0; f1 < 2; f1++) {
19189
19190 for (j = 0; j < segpbcgrouptable->len(); j++) {
19191 if (j == i) continue;
19192 pd2 = * (pbcdata *)(* segpbcgrouptable)[j];
19193 f2 = -1;
19194 if (pd1.segid[f1] == pd2.segid[0]) {
19195 f2 = 0;
19196 } else if (pd1.segid[f1] == pd2.segid[1]) {
19197 f2 = 1;
19198 }
19199 if (f2 != -1) {
19200 #ifdef SELF_CHECK
19201 assert(pd1.segid[f1] == pd2.segid[f2]);
19202 #endif
19203 segid1 = pd1.segid[1 - f1];
19204 segid2 = pd2.segid[1 - f2];
19205
19206 inflag = false;
19207 for (k = 0; k < segpbcgrouptable->len() && !inflag; k++) {
19208 pd = (pbcdata *)(* segpbcgrouptable)[k];
19209 if (pd->segid[0] == segid1) {
19210 if (pd->segid[1] == segid2) inflag = true;
19211 } else if (pd->segid[0] == segid2) {
19212 if (pd->segid[1] == segid1) inflag = true;
19213 }
19214 }
19215 if (!inflag) {
19216 pd = (pbcdata *) segpbcgrouptable->append(NULL);
19217 pd->segid[0] = pd1.segid[1 - f1];
19218 pd->segid[1] = pd2.segid[1 - f2];
19219 pd->ss[0] = pd1.ss[1 - f1];
19220 pd->ss[1] = pd2.ss[1 - f2];
19221
19222 pd->fmark[0] = pd->fmark[1] = 0;
19223
19224
19225 for (k = 0; k < 4; k++) {
19226 for (l = 0; l < 4; l++) {
19227 pd->transmat[0][k][l] = pd2.transmat[f2][k][l];
19228 }
19229 }
19230 m4xm4(pd->transmat[0], pd1.transmat[1 - f1]);
19231
19232
19233 for (k = 0; k < 4; k++) {
19234 for (l = 0; l < 4; l++) {
19235 pd->transmat[1][k][l] = pd1.transmat[f1][k][l];
19236 }
19237 }
19238 m4xm4(pd->transmat[1], pd2.transmat[1 - f2]);
19239 }
19240 }
19241 }
19242 }
19243 }
19244
19245
19246 idx2segpglist = new int[subsegs->items + 1];
19247 for (i = 0; i < subsegs->items + 1; i++) idx2segpglist[i] = 0;
19248
19249
19250 for (i = 0; i < segpbcgrouptable->len(); i++) {
19251 pd = (pbcdata *)(* segpbcgrouptable)[i];
19252 for (j = 0; j < 2; j++) {
19253 k = pd->segid[j] - 1;
19254 idx2segpglist[k]++;
19255 }
19256 }
19257
19258 j = idx2segpglist[0];
19259 idx2segpglist[0] = 0;
19260 for (i = 0; i < subsegs->items; i++) {
19261 k = idx2segpglist[i + 1];
19262 idx2segpglist[i + 1] = idx2segpglist[i] + j;
19263 j = k;
19264 }
19265
19266 segpglist = new int[idx2segpglist[i]];
19267
19268 for (i = 0; i < segpbcgrouptable->len(); i++) {
19269 pd = (pbcdata *)(* segpbcgrouptable)[i];
19270 for (j = 0; j < 2; j++) {
19271 k = pd->segid[j] - 1;
19272 segpglist[idx2segpglist[k]] = i;
19273 idx2segpglist[k]++;
19274 }
19275 }
19276
19277 for (i = subsegs->items - 1; i >= 0; i--) {
19278 idx2segpglist[i + 1] = idx2segpglist[i];
19279 }
19280 idx2segpglist[0] = 0;
19281 }
19282
19284
19285
19286
19287
19288
19289
19290
19292
19293 enum tetgenmesh::locateresult tetgenmesh::
19294 getsegpbcsympoint(point newpoint, face* splitseg, point sympoint,
19295 face* symsplitseg, int groupid)
19296 {
19297 pbcdata *pd;
19298 enum locateresult symloc;
19299 int segid, f1, f2, i;
19300
19301 pd = (pbcdata *)(* segpbcgrouptable)[groupid];
19302 segid = shellmark(*splitseg);
19303 if (pd->segid[0] == segid) {
19304 f1 = 0;
19305 } else {
19306 #ifdef SELF_CHECK
19307 assert(pd->segid[1] == segid);
19308 #endif
19309 f1 = 1;
19310 }
19311 f2 = 1 - f1;
19312
19313
19314 for (i = 0; i < 3; i++) {
19315 sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
19316 + pd->transmat[f1][i][1] * newpoint[1]
19317 + pd->transmat[f1][i][2] * newpoint[2]
19318 + pd->transmat[f1][i][3] * 1.0;
19319 }
19320
19321 *symsplitseg = pd->ss[f2];
19322 #ifdef SELF_CHECK
19323 assert(symsplitseg->sh != dummysh);
19324 #endif
19325
19326 symloc = locateseg(sympoint, symsplitseg);
19327 symloc = adjustlocateseg(sympoint, symsplitseg, symloc, b->epsilon * 1e+2);
19328 return symloc;
19329 }
19330
19331
19332
19333
19334
19335
19336
19337
19338
19340
19341
19342
19344
19345 REAL tetgenmesh::randgenerator(REAL range)
19346 {
19347 REAL worknumber, result;
19348 int expo;
19349
19350 if (range == 0.0) return 0.0;
19351
19352 expo = 0;
19353 worknumber = fabs(range);
19354
19355 if (worknumber > 10.0) {
19356 while (worknumber > 10.0) {
19357 worknumber /= 10.0;
19358 expo++;
19359 }
19360 } else if (worknumber < 1.0) {
19361 while (worknumber < 1.0) {
19362 worknumber *= 10.0;
19363 expo--;
19364 }
19365 }
19366 #ifdef SELF_CHECK
19367 assert(worknumber >= 1.0 && worknumber <= 10.0);
19368 #endif
19369
19370
19371 worknumber *= 1e+3;
19372 expo -= 3;
19373
19374 result = (double) randomnation((int) worknumber);
19375
19376
19377 if (expo > 0) {
19378 while (expo != 0) {
19379 result *= 10.0;
19380 expo--;
19381 }
19382 } else if (expo < 0) {
19383 while (expo != 0) {
19384 result /= 10.0;
19385 expo++;
19386 }
19387 }
19388 #ifdef SELF_CHECK
19389 assert((result >= 0.0) && (result <= fabs(range)));
19390 #endif
19391
19392 return result;
19393 }
19394
19396
19397
19398
19399
19400
19401
19402
19403
19404
19405
19406
19407
19408
19410
19411 bool tetgenmesh::checksub4cocir(face* testsub, REAL eps, bool once,
19412 bool enqflag)
19413 {
19414 badface *cocirsub;
19415 face subloop, neighsub;
19416 face checkseg;
19417 point pa, pb, pc, pd;
19418 REAL sign;
19419 int i;
19420
19421 subloop = *testsub;
19422 subloop.shver = 0;
19423
19424 abovepoint = facetabovepointarray[shellmark(subloop)];
19425
19426 if (abovepoint == (point) NULL) {
19427 getfacetabovepoint(&subloop);
19428 }
19429
19430 for (i = 0; i < 3; i++) {
19431 sspivot(subloop, checkseg);
19432 if (checkseg.sh == dummysh) {
19433
19434 spivot(subloop, neighsub);
19435
19436 if (!once || (once && (neighsub.sh > subloop.sh))) {
19437 pa = sorg(subloop);
19438 pb = sdest(subloop);
19439 pc = sapex(subloop);
19440 pd = sapex(neighsub);
19441 sign = insphere(pa, pb, pc, abovepoint, pd);
19442 if ((sign != 0.0) && (eps > 0.0)) {
19443 if (iscospheric(pa, pb, pc, abovepoint, pd, sign, eps)) sign = 0.0;
19444 }
19445 if (sign == 0.0) {
19446
19447 if (enqflag && badsubfaces != (memorypool *) NULL) {
19448
19449 cocirsub = (badface *) badsubfaces->alloc();
19450 cocirsub->ss = subloop;
19451 cocirsub->forg = pa;
19452 cocirsub->fdest = pb;
19453 cocirsub->fapex = pc;
19454 cocirsub->foppo = pd;
19455 setshell2badface(cocirsub->ss, cocirsub);
19456 }
19457 if (b->verbose > 1) {
19458 printf(" Found set (%d, %d, %d, %d).\n", pointmark(pa),
19459 pointmark(pb), pointmark(pc), pointmark(pd));
19460 }
19461 return true;
19462 }
19463 }
19464 }
19465 senextself(subloop);
19466 }
19467
19468 return false;
19469 }
19470
19472
19473
19474
19476
19477 void tetgenmesh::tallcocirsubs(REAL eps, bool enqflag)
19478 {
19479 face subloop;
19480
19481
19482 subfaces->traversalinit();
19483 subloop.sh = shellfacetraverse(subfaces);
19484 while (subloop.sh != (shellface *) NULL) {
19485 checksub4cocir(&subloop, eps, true, enqflag);
19486 subloop.sh = shellfacetraverse(subfaces);
19487 }
19488 }
19489
19491
19492
19493
19495
19496 bool tetgenmesh::tallencsegsfsubs(point testpt, list* cavsublist)
19497 {
19498 face startsub, checkseg;
19499 long oldencnum;
19500 int i, j;
19501
19502
19503 oldencnum = badsubsegs->items;
19504
19505
19506 for (i = 0; i < cavsublist->len(); i++) {
19507 startsub = * (face *)(* cavsublist)[i];
19508
19509 for (j = 0; j < 3; j++) {
19510 sspivot(startsub, checkseg);
19511 if (checkseg.sh != dummysh) {
19512 if (!shell2badface(checkseg)) {
19513 checkseg4encroach(&checkseg, testpt, NULL, true);
19514 }
19515 }
19516 senextself(startsub);
19517 }
19518 }
19519
19520 return (badsubsegs->items > oldencnum);
19521 }
19522
19524
19525
19526
19527
19528
19529
19530
19531
19533
19534 void tetgenmesh::
19535 collectflipedges(point inspoint, face* splitseg, queue* flipqueue)
19536 {
19537 face startsh, spinsh, checksh;
19538 face nextseg;
19539 point pa, pb;
19540
19541
19542 splitseg->shver = 0;
19543 if (sdest(*splitseg) != inspoint) {
19544 sesymself(*splitseg);
19545 }
19546 #ifdef SELF_CHECK
19547 assert(sdest(*splitseg) == inspoint);
19548 #endif
19549 pa = sorg(*splitseg);
19550 spivot(*splitseg, startsh);
19551 spinsh = startsh;
19552 do {
19553 findedge(&spinsh, pa, inspoint);
19554 senext2(spinsh, checksh);
19555 enqueueflipedge(checksh, flipqueue);
19556 spivotself(spinsh);
19557 } while (spinsh.sh != startsh.sh);
19558
19559
19560 senext(*splitseg, nextseg);
19561 spivotself(nextseg);
19562 #ifdef SELF_CHECK
19563 assert(nextseg.sh != (shellface *) NULL);
19564 #endif
19565
19566
19567 nextseg.shver = 0;
19568 if (sorg(nextseg) != inspoint) {
19569 sesymself(nextseg);
19570 }
19571 #ifdef SELF_CHECK
19572 assert(sorg(nextseg) == inspoint);
19573 #endif
19574 pb = sdest(nextseg);
19575 spivot(nextseg, startsh);
19576 spinsh = startsh;
19577 do {
19578 findedge(&spinsh, inspoint, pb);
19579 senext(spinsh, checksh);
19580 enqueueflipedge(checksh, flipqueue);
19581 spivotself(spinsh);
19582 } while (spinsh.sh != startsh.sh);
19583 }
19584
19586
19587
19588
19589
19590
19591
19593
19594 void tetgenmesh::perturbrepairencsegs(queue* flipqueue)
19595 {
19596 badface *encloop;
19597 tetrahedron encodedtet;
19598 triface splittet;
19599 face splitsub, symsplitsub;
19600 face splitseg, symsplitseg;
19601 point newpoint, sympoint;
19602 point pa, pb, pc;
19603 enum insertsiteresult success;
19604 enum locateresult loc, symloc;
19605 REAL cent[3], d1, ps, rs;
19606 int i, j;
19607
19608
19609
19610 badsubsegs->traversalinit();
19611 encloop = badfacetraverse(badsubsegs);
19612 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19613 splitseg = encloop->ss;
19614 #ifdef SELF_CHECK
19615 assert(shell2badface(splitseg) == encloop);
19616 #endif
19617 setshell2badface(splitseg, NULL);
19618 pa = sorg(splitseg);
19619 pb = sdest(splitseg);
19620 if ((pa == encloop->forg) && (pb == encloop->fdest)) {
19621 if (b->verbose > 1) {
19622 printf(" Get seg (%d, %d).\n", pointmark(pa), pointmark(pb));
19623 }
19624
19625 makepoint(&newpoint);
19626
19627 for (i = 0; i < 3; i++) cent[i] = 0.5 * (pa[i] + pb[i]);
19628 d1 = 0.5 * distance(pa, pb);
19629
19630 ps = randgenerator(d1 * 1.0e-3);
19631 rs = ps / d1;
19632
19633 for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19634 setpointtype(newpoint, FREESEGVERTEX);
19635
19636 setpoint2sh(newpoint, sencode(splitseg));
19637
19638
19639 if (checkpbcs) {
19640
19641 i = shellmark(splitseg) - 1;
19642 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
19643 makepoint(&sympoint);
19644 symloc = getsegpbcsympoint(newpoint, &splitseg, sympoint,
19645 &symsplitseg, segpglist[j]);
19646 #ifdef SELF_CHECK
19647 assert(symloc != OUTSIDE);
19648 #endif
19649
19650
19651 if ((symloc == ONEDGE) && (symsplitseg.sh != splitseg.sh)) {
19652 setpointtype(sympoint, FREESEGVERTEX);
19653 setpoint2sh(sympoint, sencode(symsplitseg));
19654
19655 pc = sorg(symsplitseg);
19656 splittet.tet = dummytet;
19657
19658 encodedtet = point2tet(pc);
19659 if (encodedtet != (tetrahedron) NULL) {
19660 decode(encodedtet, splittet);
19661 if (isdead(&splittet)) {
19662 splittet.tet = dummytet;
19663 }
19664 }
19665
19666 success = insertsite(sympoint, &splittet, false, flipqueue);
19667 #ifdef SELF_CHECK
19668 assert(success != DUPLICATEPOINT);
19669 #endif
19670 if (success == OUTSIDEPOINT) {
19671 inserthullsite(sympoint, &splittet, flipqueue);
19672 }
19673 if (steinerleft > 0) steinerleft--;
19674
19675 setpoint2tet(sympoint, encode(splittet));
19676
19677 flip(flipqueue, NULL);
19678
19679 symloc = locateseg(sympoint, &symsplitseg);
19680 if (symloc == ONEDGE) {
19681 symsplitseg.shver = 0;
19682 spivot(symsplitseg, symsplitsub);
19683
19684 splitsubedge(sympoint, &symsplitsub, flipqueue);
19685 } else {
19686
19687 #ifdef SELF_CHECK
19688 assert(symloc == ONVERTEX);
19689 assert(checksubfaces);
19690 #endif
19691
19692 collectflipedges(sympoint, &symsplitseg, flipqueue);
19693 }
19694
19695 flipsub(flipqueue);
19696 } else {
19697
19698
19699 pointdealloc(sympoint);
19700 }
19701 }
19702 }
19703
19704
19705 splittet.tet = dummytet;
19706
19707 encodedtet = point2tet(pa);
19708 if (encodedtet != (tetrahedron) NULL) {
19709 decode(encodedtet, splittet);
19710 if (isdead(&splittet)) {
19711 splittet.tet = dummytet;
19712 }
19713 }
19714 if (splittet.tet == dummytet) {
19715 encodedtet = point2tet(pb);
19716 if (encodedtet != (tetrahedron) NULL) {
19717 decode(encodedtet, splittet);
19718 if (isdead(&splittet)) {
19719 splittet.tet = dummytet;
19720 }
19721 }
19722 }
19723
19724 success = insertsite(newpoint, &splittet, false, flipqueue);
19725 #ifdef SELF_CHECK
19726 assert(success != DUPLICATEPOINT);
19727 #endif
19728 if (success == OUTSIDEPOINT) {
19729
19730
19731
19732 inserthullsite(newpoint, &splittet, flipqueue);
19733 }
19734 if (steinerleft > 0) steinerleft--;
19735
19736 setpoint2tet(newpoint, encode(splittet));
19737
19738 flip(flipqueue, NULL);
19739
19740 loc = locateseg(newpoint, &splitseg);
19741 if (loc == ONEDGE) {
19742 splitseg.shver = 0;
19743 spivot(splitseg, splitsub);
19744
19745 splitsubedge(newpoint, &splitsub, flipqueue);
19746 } else {
19747
19748 #ifdef SELF_CHECK
19749 assert(loc == ONVERTEX);
19750 assert(checksubfaces);
19751 #endif
19752
19753 collectflipedges(newpoint, &splitseg, flipqueue);
19754 }
19755
19756 flipsub(flipqueue);
19757 }
19758
19759 badfacedealloc(badsubsegs, encloop);
19760
19761 encloop = badfacetraverse(badsubsegs);
19762 }
19763 }
19764
19766
19767
19768
19769
19770
19771
19772
19773
19775
19776 void tetgenmesh::perturbrepairencsubs(list* cavsublist, queue* flipqueue)
19777 {
19778 badface *encloop, *encsubseg;
19779 tetrahedron encodedtet;
19780 triface splittet;
19781 face splitsub, symsplitsub;
19782 face checkseg, symsplitseg;
19783 point newpoint, sympoint;
19784 point pa, pb, pc, pd;
19785 enum insertsiteresult success;
19786 enum locateresult loc, symloc;
19787 REAL cent[3], d1, ps, rs;
19788 bool reject;
19789 int i;
19790
19791
19792
19793 while ((badsubfaces->items > 0) && (steinerleft != 0)) {
19794 badsubfaces->traversalinit();
19795 encloop = badfacetraverse(badsubfaces);
19796 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19797 splitsub = encloop->ss;
19798 #ifdef SELF_CHECK
19799 assert(shell2badface(splitsub) == encloop);
19800 #endif
19801 setshell2badface(splitsub, NULL);
19802 pa = sorg(splitsub);
19803 pb = sdest(splitsub);
19804 pc = sapex(splitsub);
19805
19806
19807
19808 if ((pa == encloop->forg) && (pb == encloop->fdest) &&
19809 (pc == encloop->fapex)) {
19810 if (b->verbose > 1) {
19811 printf(" Get subface (%d, %d, %d).\n", pointmark(pa),
19812 pointmark(pb), pointmark(pc));
19813 }
19814
19815 makepoint(&newpoint);
19816
19817 circumsphere(pa, pb, pc, NULL, cent, &d1);
19818 #ifdef SELF_CHECK
19819 assert(d1 > 0.0);
19820 #endif
19821
19822
19823 ps = randgenerator(d1 * 1.0e-3);
19824 rs = ps / d1;
19825
19826 for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19827
19828 abovepoint = facetabovepointarray[shellmark(splitsub)];
19829
19830 if (abovepoint == (point) NULL) {
19831 getfacetabovepoint(&splitsub);
19832 }
19833 loc = locatesub(newpoint, &splitsub, 1, 0.0);
19834 #ifdef SELF_CHECK
19835 assert(loc != ONVERTEX);
19836 #endif
19837 if (loc != OUTSIDE) {
19838
19839 cavsublist->append(&splitsub);
19840
19841 collectcavsubs(newpoint, cavsublist);
19842
19843 reject = tallencsegsfsubs(newpoint, cavsublist);
19844
19845 cavsublist->clear();
19846 } else {
19847
19848 sspivot(splitsub, checkseg);
19849 #ifdef SELF_CHECK
19850 assert(checkseg.sh != dummysh);
19851 #endif
19852
19853 if (b->verbose > 2) {
19854 printf(" Queuing boundary segment (%d, %d).\n",
19855 pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
19856 }
19857 encsubseg = (badface *) badsubsegs->alloc();
19858 encsubseg->ss = checkseg;
19859 encsubseg->forg = sorg(checkseg);
19860 encsubseg->fdest = sdest(checkseg);
19861 encsubseg->foppo = (point) NULL;
19862 setshell2badface(encsubseg->ss, encsubseg);
19863
19864 reject = true;
19865 }
19866
19867 if (!reject) {
19868
19869
19870
19871 if (checkpbcs) {
19872 if (shellpbcgroup(splitsub) >= 0) {
19873
19874 makepoint(&sympoint);
19875
19876 symloc = getsubpbcsympoint(newpoint, &splitsub, sympoint,
19877 &symsplitsub);
19878 #ifdef SELF_CHECK
19879 assert(symloc != ONVERTEX);
19880 #endif
19881 setpoint2pbcpt(newpoint, sympoint);
19882 setpoint2pbcpt(sympoint, newpoint);
19883 setpointtype(sympoint, FREESUBVERTEX);
19884
19885
19886 pd = sorg(symsplitsub);
19887 splittet.tet = dummytet;
19888
19889 encodedtet = point2tet(pd);
19890 if (encodedtet != (tetrahedron) NULL) {
19891 decode(encodedtet, splittet);
19892 if (isdead(&splittet)) {
19893 splittet.tet = dummytet;
19894 }
19895 }
19896
19897 success = insertsite(sympoint, &splittet, false, flipqueue);
19898 #ifdef SELF_CHECK
19899 assert(success != DUPLICATEPOINT);
19900 #endif
19901 if (success == OUTSIDEPOINT) {
19902 inserthullsite(sympoint, &splittet, flipqueue);
19903 }
19904 if (steinerleft > 0) steinerleft--;
19905
19906 setpoint2tet(sympoint, encode(splittet));
19907
19908 flip(flipqueue, NULL);
19909
19910
19911
19912 if (symloc == ONFACE) {
19913 splitsubface(sympoint, &symsplitsub, flipqueue);
19914 } else if (symloc == ONEDGE) {
19915 splitsubedge(sympoint, &symsplitsub, flipqueue);
19916 } else {
19917
19918 #ifdef SELF_CHECK
19919 assert(symloc == ONVERTEX);
19920 assert(checksubfaces);
19921 #endif
19922
19923 flipqueue->clear();
19924 }
19925
19926 flipsub(flipqueue);
19927 }
19928 }
19929
19930
19931 splittet.tet = dummytet;
19932
19933 encodedtet = point2tet(pa);
19934 if (encodedtet != (tetrahedron) NULL) {
19935 decode(encodedtet, splittet);
19936 if (isdead(&splittet)) {
19937 splittet.tet = dummytet;
19938 }
19939 }
19940 if (splittet.tet == dummytet) {
19941 encodedtet = point2tet(pb);
19942 if (encodedtet != (tetrahedron) NULL) {
19943 decode(encodedtet, splittet);
19944 if (isdead(&splittet)) {
19945 splittet.tet = dummytet;
19946 }
19947 }
19948 }
19949
19950 success = insertsite(newpoint, &splittet, false, flipqueue);
19951 #ifdef SELF_CHECK
19952 assert(success != DUPLICATEPOINT);
19953 #endif
19954 if (success == OUTSIDEPOINT) {
19955 inserthullsite(newpoint, &splittet, flipqueue);
19956 }
19957 if (steinerleft > 0) steinerleft--;
19958
19959 setpoint2tet(newpoint, encode(splittet));
19960
19961 flip(flipqueue, NULL);
19962
19963
19964
19965
19966
19967
19968 if (loc == ONFACE) {
19969
19970 splitsubface(newpoint, &splitsub, flipqueue);
19971 } else if (loc == ONEDGE) {
19972
19973 splitsubedge(newpoint, &splitsub, flipqueue);
19974 } else {
19975
19976 #ifdef SELF_CHECK
19977 assert(loc == ONVERTEX);
19978 assert(checksubfaces);
19979 #endif
19980
19981 flipqueue->clear();
19982 }
19983
19984 setpointtype(newpoint, FREESUBVERTEX);
19985
19986
19987
19988 flipsub(flipqueue);
19989
19990
19991 badfacedealloc(badsubfaces, encloop);
19992 } else {
19993
19994 pointdealloc(newpoint);
19995
19996 perturbrepairencsegs(flipqueue);
19997
19998 setshell2badface(encloop->ss, encloop);
19999 }
20000 } else {
20001
20002 badfacedealloc(badsubfaces, encloop);
20003
20004
20005 }
20006
20007 encloop = badfacetraverse(badsubfaces);
20008 }
20009 }
20010 }
20011
20013
20014
20015
20016
20017
20018
20019
20020
20021
20022
20023
20024
20026
20027 void tetgenmesh::incrperturbvertices(REAL eps)
20028 {
20029 queue *flipqueue;
20030 list *cavsublist;
20031 long vertcount;
20032
20033 if (!b->quiet) {
20034 printf("Perturbing vertices.\n");
20035 }
20036
20037 vertcount = points->items;
20038
20039
20040
20041
20042 flipqueue = new queue(sizeof(badface));
20043 cavsublist = new list(sizeof(face), NULL, 256);
20044
20045 badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20046 badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20047
20048 tallcocirsubs(eps, true);
20049 if (b->verbose && badsubfaces->items > 0) {
20050 printf(" Removing degenerate subfaces.\n");
20051 }
20052 perturbrepairencsubs(cavsublist, flipqueue);
20053
20054 if (b->verbose > 0) {
20055 printf(" %ld break points.\n", points->items - vertcount);
20056 }
20057
20058 delete cavsublist;
20059 delete flipqueue;
20060 delete badsubfaces;
20061 delete badsubsegs;
20062 badsubsegs = (memorypool *) NULL;
20063 badsubfaces = (memorypool *) NULL;
20064 }
20065
20066
20067
20068
20069
20070
20071
20072
20073
20075
20076
20077
20078
20079
20080
20081
20082
20083
20084
20085
20086
20087
20088
20090
20091 void tetgenmesh::markacutevertices(REAL acuteangle)
20092 {
20093 shellface **segsperverlist;
20094 face segloop, nextseg;
20095 point pointloop, edest, eapex;
20096 REAL cosbound, anglearc;
20097 REAL v1[3], v2[3], L, D;
20098 bool isacute;
20099 int *idx2seglist;
20100 int acutecount;
20101 int idx, i, j, k;
20102
20103 if (b->verbose > 0) {
20104 printf(" Marking acute vertices.\n");
20105 }
20106
20107 anglearc = acuteangle * PI / 180.0;
20108 cosbound = cos(anglearc);
20109 acutecount = 0;
20110
20111 makesegmentmap(idx2seglist, segsperverlist);
20112
20113
20114 points->traversalinit();
20115 pointloop = pointtraverse();
20116 while (pointloop != (point) NULL) {
20117 idx = pointmark(pointloop) - in->firstnumber;
20118
20119 if (idx2seglist[idx + 1] > idx2seglist[idx]) {
20120
20121 setpointtype(pointloop, NACUTEVERTEX);
20122 isacute = false;
20123
20124 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isacute; i++) {
20125 segloop.sh = segsperverlist[i];
20126
20127 if (sorg(segloop) != pointloop) sesymself(segloop);
20128 edest = sdest(segloop);
20129 for (j = i + 1; j < idx2seglist[idx + 1] && !isacute; j++) {
20130 nextseg.sh = segsperverlist[j];
20131
20132 if (sorg(nextseg) != pointloop) sesymself(nextseg);
20133 eapex = sdest(nextseg);
20134
20135 for (k = 0; k < 3; k++) {
20136 v1[k] = edest[k] - pointloop[k];
20137 v2[k] = eapex[k] - pointloop[k];
20138 }
20139 L = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
20140 for (k = 0; k < 3; k++) v1[k] /= L;
20141 L = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
20142 for (k = 0; k < 3; k++) v2[k] /= L;
20143 D = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
20144
20145 isacute = (D >= cosbound);
20146 }
20147 }
20148 if (isacute) {
20149
20150 setpointtype(pointloop, ACUTEVERTEX);
20151 acutecount++;
20152 }
20153 }
20154 pointloop = pointtraverse();
20155 }
20156
20157 delete [] idx2seglist;
20158 delete [] segsperverlist;
20159
20160 if ((b->verbose > 0) && (acutecount > 0)) {
20161 printf(" %d acute vertices.\n", acutecount);
20162 }
20163 }
20164
20166
20167
20168
20169
20170
20171
20172
20173
20174
20175
20176
20177
20178
20179
20180
20181
20182
20183
20184
20185
20186
20187
20188
20189
20190
20191
20192
20193
20194
20195
20197
20198 enum tetgenmesh::finddirectionresult tetgenmesh::
20199 finddirection(triface *searchtet, point tend, long maxtetnumber)
20200 {
20201 triface neightet;
20202 point tstart, tdest, tapex, toppo;
20203 REAL ori1, ori2, ori3;
20204 long tetnumber;
20205
20206 tstart = org(*searchtet);
20207 #ifdef SELF_CHECK
20208 assert(tstart != tend);
20209 #endif
20210 adjustedgering(*searchtet, CCW);
20211 if (tstart != org(*searchtet)) {
20212 enextself(*searchtet);
20213 }
20214 tdest = dest(*searchtet);
20215 if (tdest == tend) {
20216 return RIGHTCOLLINEAR;
20217 }
20218 tapex = apex(*searchtet);
20219 if (tapex == tend) {
20220 return LEFTCOLLINEAR;
20221 }
20222
20223 ori1 = orient3d(tstart, tdest, tapex, tend);
20224 if (ori1 > 0.0) {
20225
20226 sym(*searchtet, neightet);
20227 if (neightet.tet != dummytet) {
20228 findorg(&neightet, tstart);
20229 adjustedgering(neightet, CCW);
20230 if (org(neightet) != tstart) {
20231 enextself(neightet);
20232 }
20233
20234 *searchtet = neightet;
20235 ori1 = -1.0;
20236 tdest = dest(*searchtet);
20237 tapex = apex(*searchtet);
20238 } else {
20239
20240 #ifdef SELF_CHECK
20241 assert(nonconvex);
20242 #endif
20243 return BELOWHULL;
20244 }
20245 }
20246
20247
20248
20249
20250 tetnumber = 0l;
20251 while ((maxtetnumber > 0) && (tetnumber <= maxtetnumber)) {
20252 tetnumber++;
20253 toppo = oppo(*searchtet);
20254 if (toppo == tend) {
20255 return TOPCOLLINEAR;
20256 }
20257 ori2 = orient3d(tstart, toppo, tdest, tend);
20258 if (ori2 > 0.0) {
20259
20260 fnext(*searchtet, neightet);
20261 symself(neightet);
20262 if (neightet.tet != dummytet) {
20263 findorg(&neightet, tstart);
20264 adjustedgering(neightet, CCW);
20265 if (org(neightet) != tstart) {
20266 enextself(neightet);
20267 }
20268
20269 *searchtet = neightet;
20270 ori1 = -1.0;
20271 tdest = dest(*searchtet);
20272 tapex = apex(*searchtet);
20273
20274 continue;
20275 } else {
20276
20277 #ifdef SELF_CHECK
20278 assert(nonconvex);
20279 #endif
20280 return BELOWHULL;
20281 }
20282 }
20283 ori3 = orient3d(tapex, toppo, tstart, tend);
20284 if (ori3 > 0.0) {
20285
20286 enext2fnext(*searchtet, neightet);
20287 symself(neightet);
20288 if (neightet.tet != dummytet) {
20289 findorg(&neightet, tstart);
20290 adjustedgering(neightet, CCW);
20291 if (org(neightet) != tstart) {
20292 enextself(neightet);
20293 }
20294
20295 *searchtet = neightet;
20296 ori1 = -1.0;
20297 tdest = dest(*searchtet);
20298 tapex = apex(*searchtet);
20299
20300 continue;
20301 } else {
20302
20303 #ifdef SELF_CHECK
20304 assert(nonconvex);
20305 #endif
20306 return BELOWHULL;
20307 }
20308 }
20309
20310 if (ori1 < 0.0) {
20311
20312 if (ori2 < 0.0) {
20313 if (ori3 < 0.0) {
20314 return ACROSSFACE;
20315 } else {
20316
20317 enext2fnextself(*searchtet);
20318 esymself(*searchtet);
20319 return ACROSSEDGE;
20320 }
20321 } else {
20322 if (ori3 < 0.0) {
20323
20324 fnextself(*searchtet);
20325 esymself(*searchtet);
20326 enextself(*searchtet);
20327 return ACROSSEDGE;
20328 } else {
20329
20330 return TOPCOLLINEAR;
20331 }
20332 }
20333 } else {
20334
20335 if (ori2 < 0.0) {
20336 if (ori3 < 0.0) {
20337
20338 return ACROSSEDGE;
20339 } else {
20340
20341 return LEFTCOLLINEAR;
20342 }
20343 } else {
20344 #ifdef SELF_CHECK
20345 assert(ori3 != 0.0);
20346 #endif
20347
20348 return RIGHTCOLLINEAR;
20349 }
20350 }
20351 }
20352
20353 return BELOWHULL;
20354 }
20355
20357
20358
20359
20360
20361
20362
20363
20365
20366 void tetgenmesh::getsearchtet(point p1, point p2, triface* searchtet,
20367 point* tend)
20368 {
20369 tetrahedron encodedtet1, encodedtet2;
20370
20371
20372 if ((searchtet->tet != (tetrahedron *) NULL) && !isdead(searchtet)) {
20373
20374 if (findorg(searchtet, p1)) {
20375 *tend = p2;
20376 return;
20377 } else {
20378 if (findorg(searchtet, p2)) {
20379 *tend = p1;
20380 return;
20381 }
20382 }
20383 }
20384
20385 *tend = (point) NULL;
20386 encodedtet1 = point2tet(p1);
20387 encodedtet2 = point2tet(p2);
20388 if (encodedtet1 != (tetrahedron) NULL) {
20389 decode(encodedtet1, *searchtet);
20390
20391 if (findorg(searchtet, p1)) {
20392 *tend = p2;
20393 }
20394 } else if (encodedtet2 != (tetrahedron) NULL) {
20395 decode(encodedtet2, *searchtet);
20396
20397 if (findorg(searchtet, p2)) {
20398 *tend = p1;
20399 }
20400 }
20401
20402
20403
20404 if (*tend == (point) NULL) {
20405 if (encodedtet1 != (tetrahedron) NULL) {
20406 decode(encodedtet1, *searchtet);
20407
20408 }
20409 if (isdead(searchtet)) {
20410 if (encodedtet2 != (tetrahedron) NULL) {
20411 decode(encodedtet2, *searchtet);
20412
20413 }
20414 if (isdead(searchtet)) {
20415 searchtet->tet = dummytet;
20416 searchtet->loc = 0;
20417 symself(*searchtet);
20418 }
20419 #ifdef SELF_CHECK
20420 assert(!isdead(searchtet));
20421 #endif
20422 }
20423 if (locate(p1, searchtet) != ONVERTEX) {
20424 printf("Internal error in getsearchtet(): Failed to locate point\n");
20425 internalerror();
20426 }
20427
20428 setpoint2tet(p1, encode(*searchtet));
20429 *tend = p2;
20430 }
20431 }
20432
20434
20435
20436
20437
20438
20439
20440
20441
20443
20444 bool tetgenmesh::isedgeencroached(point p1, point p2, point testpt,
20445 bool degflag)
20446 {
20447 REAL dotproduct;
20448
20449
20450 dotproduct = (p1[0] - testpt[0]) * (p2[0] - testpt[0])
20451 + (p1[1] - testpt[1]) * (p2[1] - testpt[1])
20452 + (p1[2] - testpt[2]) * (p2[2] - testpt[2]);
20453 if (dotproduct < 0) {
20454 return true;
20455 } else if (dotproduct == 0 && degflag) {
20456 return true;
20457 } else {
20458 return false;
20459 }
20460 }
20461
20463
20464
20465
20466
20467
20468
20469
20470
20471
20472
20473
20474
20475
20477
20478 tetgenmesh::point tetgenmesh::scoutrefpoint(triface* searchtet, point tend)
20479 {
20480 triface checkface;
20481 point tstart, testpt, refpoint;
20482 REAL cent[3], radius, largest;
20483 REAL ahead;
20484 bool ncollinear;
20485 int sides;
20486
20487 if (b->verbose > 2) {
20488 printf(" Scout the reference point of segment (%d, %d).\n",
20489 pointmark(org(*searchtet)), pointmark(tend));
20490 }
20491
20492 tstart = org(*searchtet);
20493 refpoint = (point) NULL;
20494 largest = 0;
20495
20496
20497 testpt = apex(*searchtet);
20498 if (isedgeencroached(tstart, tend, testpt, true)) {
20499 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20500 #ifdef SELF_CHECK
20501 assert(ncollinear);
20502 #endif
20503 refpoint = testpt;
20504 largest = radius;
20505 }
20506 testpt = dest(*searchtet);
20507 if (isedgeencroached(tstart, tend, testpt, true)) {
20508 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20509 #ifdef SELF_CHECK
20510 assert(ncollinear);
20511 #endif
20512 if (refpoint == (point) NULL) {
20513 refpoint = testpt;
20514 largest = radius;
20515 } else {
20516 if (radius > largest) {
20517 refpoint = testpt;
20518 largest = radius;
20519 }
20520 }
20521 }
20522 testpt = oppo(*searchtet);
20523 if (isedgeencroached(tstart, tend, testpt, true)) {
20524 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20525 #ifdef SELF_CHECK
20526 assert(ncollinear);
20527 #endif
20528 if (refpoint == (point) NULL) {
20529 refpoint = testpt;
20530 largest = radius;
20531 } else {
20532 if (radius > largest) {
20533 refpoint = testpt;
20534 largest = radius;
20535 }
20536 }
20537 }
20538
20539
20540 sym(*searchtet, checkface);
20541 if (checkface.tet != dummytet) {
20542 testpt = oppo(checkface);
20543 if (isedgeencroached(tstart, tend, testpt, true)) {
20544 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20545 #ifdef SELF_CHECK
20546 assert(ncollinear);
20547 #endif
20548 if (refpoint == (point) NULL) {
20549 refpoint = testpt;
20550 largest = radius;
20551 } else {
20552 if (radius > largest) {
20553 refpoint = testpt;
20554 largest = radius;
20555 }
20556 }
20557 }
20558 }
20559
20560
20561 enextfnext(*searchtet, checkface);
20562 sym(checkface, *searchtet);
20563 while (true) {
20564
20565 #ifdef SELF_CHECK
20566 assert(searchtet->tet != dummytet);
20567 #endif
20568
20569 searchtet->ver = 0;
20570
20571 testpt = oppo(*searchtet);
20572 if (testpt == tend) {
20573
20574 break;
20575 } else {
20576
20577 if ((testpt != tstart) && (testpt != refpoint)) {
20578 if (isedgeencroached(tstart, tend, testpt, true)) {
20579 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20580 if (!ncollinear) {
20581
20582
20583
20584
20585
20586 refpoint = testpt;
20587 break;
20588 }
20589 if (refpoint == (point) NULL) {
20590 refpoint = testpt;
20591 largest = radius;
20592 } else {
20593 if (radius > largest) {
20594 refpoint = testpt;
20595 largest = radius;
20596 }
20597 }
20598 }
20599 }
20600 }
20601
20602
20603 for (sides = 0; sides < 3; sides++) {
20604 fnext(*searchtet, checkface);
20605 ahead = orient3d(org(checkface), dest(checkface), testpt, tend);
20606 if (ahead < 0.0) {
20607
20608 sym(checkface, *searchtet);
20609 break;
20610 }
20611 enextself(*searchtet);
20612 }
20613 #ifdef SELF_CHECK
20614 assert (sides < 3);
20615 #endif
20616 }
20617
20618 #ifdef SELF_CHECK
20619 assert(refpoint != (point) NULL);
20620 #endif
20621 return refpoint;
20622 }
20623
20625
20626
20627
20628
20629
20630
20631
20632
20634
20635 tetgenmesh::point tetgenmesh::getsegmentorigin(face* splitseg)
20636 {
20637 face workseg;
20638 point farorg;
20639
20640 farorg = sorg(*splitseg);
20641 if ((pointtype(farorg) != ACUTEVERTEX) &&
20642 (pointtype(farorg) != NACUTEVERTEX)) {
20643 workseg = *splitseg;
20644 do {
20645 senext2self(workseg);
20646 spivotself(workseg);
20647 if (workseg.sh != dummysh) {
20648 workseg.shver = 0;
20649 if (sdest(workseg) != farorg) {
20650 sesymself(workseg);
20651 #ifdef SELF_CHECK
20652 assert(sdest(workseg) == farorg);
20653 #endif
20654 }
20655 farorg = sorg(workseg);
20656 if ((pointtype(farorg) == ACUTEVERTEX) ||
20657 (pointtype(farorg) == NACUTEVERTEX)) break;
20658 }
20659 } while (workseg.sh != dummysh);
20660 }
20661 #ifdef SELF_CHECK
20662 assert((pointtype(farorg) == ACUTEVERTEX) ||
20663 (pointtype(farorg) == NACUTEVERTEX));
20664 #endif
20665 return farorg;
20666 }
20667
20669
20670
20671
20672
20673
20674
20675
20676
20677
20678
20679
20680
20681
20682
20684
20685 tetgenmesh::point tetgenmesh::getsplitpoint(face* splitseg, point refpoint)
20686 {
20687 point splitpoint;
20688 point farorg, fardest;
20689 point ei, ej, ek, c;
20690 REAL v[3], r, split;
20691 REAL d1, d2, ps, rs;
20692 bool acuteorg, acutedest;
20693 int stype, rule;
20694 int i;
20695
20696
20697 farorg = getsegmentorigin(splitseg);
20698 acuteorg = (pointtype(farorg) == ACUTEVERTEX);
20699 sesymself(*splitseg);
20700 fardest = getsegmentorigin(splitseg);
20701 acutedest = (pointtype(fardest) == ACUTEVERTEX);
20702 sesymself(*splitseg);
20703
20704 ek = (point) NULL;
20705
20706 if (acuteorg) {
20707 if (acutedest) {
20708 stype = 3;
20709 } else {
20710 stype = 2;
20711 ek = farorg;
20712 }
20713 } else {
20714 if (acutedest) {
20715 stype = 2;
20716
20717 sesymself(*splitseg);
20718 ek = fardest;
20719 } else {
20720 stype = 1;
20721 }
20722 }
20723 ei = sorg(*splitseg);
20724 ej = sdest(*splitseg);
20725
20726 if (b->verbose > 1) {
20727 printf(" Splitting segment (%d, %d) type-%d with refpoint %d.\n",
20728 pointmark(ei), pointmark(ej), stype, pointmark(refpoint));
20729 }
20730
20731 if (stype == 1 || stype == 3) {
20732
20733 REAL eij, eip, ejp;
20734 eij = distance(ei, ej);
20735 eip = distance(ei, refpoint);
20736 ejp = distance(ej, refpoint);
20737 if ((eip < ejp) && (eip < 0.5 * eij)) {
20738 c = ei;
20739 r = eip;
20740 } else if ((eip > ejp) && (ejp < 0.5 * eij)) {
20741 c = ej;
20742 ej = ei;
20743 r = ejp;
20744 } else {
20745 c = ei;
20746 r = 0.5 * eij;
20747 }
20748 split = r / eij;
20749 for (i = 0; i < 3; i++) {
20750 v[i] = c[i] + split * (ej[i] - c[i]);
20751 }
20752 rule = 1;
20753 } else {
20754
20755 REAL eki, ekj, ekp, evj, evp, eiv;
20756 c = ek;
20757 eki = distance(ek, ei);
20758 ekj = distance(ek, ej);
20759 ekp = distance(ek, refpoint);
20760
20761 r = ekp;
20762
20763 if (!(eki < r && r < ekj)) {
20764 printf("Error: Invalid PLC.\n");
20765 printf(" Hint: Use -d switch to check it.\n");
20766 terminatetetgen(1);
20767 }
20768 split = r / ekj;
20769 for (i = 0; i < 3; i++) {
20770 v[i] = c[i] + split * (ej[i] - c[i]);
20771 }
20772 rule = 2;
20773 evj = ekj - r;
20774 evp = distance(v, refpoint);
20775 if (evj < evp) {
20776
20777 eiv = distance(ei, v);
20778 if (evp <= 0.5 * eiv) {
20779 r = eki + eiv - evp;
20780 } else {
20781 r = eki + 0.5 * eiv;
20782 }
20783 #ifdef SELF_CHECK
20784 assert(eki < r && r < ekj);
20785 #endif
20786 split = r / ekj;
20787 for (i = 0; i < 3; i++) {
20788 v[i] = c[i] + split * (ej[i] - c[i]);
20789 }
20790 if (b->verbose > 1) {
20791 printf(" Using rule-3.\n");
20792 }
20793 rule = 3;
20794 }
20795 }
20796
20797
20798 if (rule == 1) r1count++;
20799 else if (rule == 2) r2count++;
20800 else if (rule == 3) r3count++;
20801
20802 if (b->verbose > 1) {
20803 if (stype == 2) {
20804 printf(" Split = %.12g.\n", distance(ei, v) / distance(ei, ej));
20805 } else {
20806 printf(" Split = %.12g.\n", distance(c, v) / distance(c, ej));
20807 }
20808 }
20809
20810
20811 makepoint(&splitpoint);
20812
20813 d1 = distance(c, v);
20814 d2 = distance(refpoint, v);
20815 if (stype == 1 || stype == 3) {
20816 ps = randgenerator(d1 * 1.0e-3);
20817 } else {
20818
20819
20820
20821 ps = randgenerator(d2 * 1.0e-5);
20822 }
20823 rs = ps / d1;
20824
20825 for (i = 0; i < 3; i++) {
20826 splitpoint[i] = c[i] + (1.0 + rs) * (v[i] - c[i]);
20827 }
20828
20829
20830
20831 if (stype == 3) {
20832
20833 setpointtype(splitpoint, NACUTEVERTEX);
20834 } else {
20835
20836 setpointtype(splitpoint, FREESEGVERTEX);
20837 }
20838 setpoint2sh(splitpoint, sencode(*splitseg));
20839
20840 return splitpoint;
20841 }
20842
20844
20845
20846
20848
20849 bool tetgenmesh::insertsegment(face *insseg, list *misseglist)
20850 {
20851 badface *misseg;
20852 triface searchtet, spintet;
20853 point tend, checkpoint;
20854 point p1, p2;
20855 enum finddirectionresult collinear;
20856 int hitbdry;
20857
20858
20859 p1 = (point) insseg->sh[3];
20860 p2 = (point) insseg->sh[4];
20861 getsearchtet(p1, p2, &searchtet, &tend);
20862 collinear = finddirection(&searchtet, tend, tetrahedrons->items);
20863 if (collinear == LEFTCOLLINEAR) {
20864 checkpoint = apex(searchtet);
20865 enext2self(searchtet);
20866 esymself(searchtet);
20867 } else if (collinear == RIGHTCOLLINEAR) {
20868 checkpoint = dest(searchtet);
20869 } else if (collinear == TOPCOLLINEAR) {
20870 checkpoint = oppo(searchtet);
20871 fnextself(searchtet);
20872 enext2self(searchtet);
20873 esymself(searchtet);
20874 } else {
20875
20876 checkpoint = (point) NULL;
20877 }
20878 if (checkpoint == tend) {
20879
20880 hitbdry = 0;
20881 adjustedgering(searchtet, CCW);
20882 fnextself(searchtet);
20883 spintet = searchtet;
20884 do {
20885 tssbond1(spintet, *insseg);
20886 if (!fnextself(spintet)) {
20887 hitbdry++;
20888 if (hitbdry < 2) {
20889 esym(searchtet, spintet);
20890 if (!fnextself(spintet)) {
20891 hitbdry++;
20892 }
20893 }
20894 }
20895 } while ((apex(spintet) != apex(searchtet)) && (hitbdry < 2));
20896 return true;
20897 } else {
20898
20899 if (misseglist != (list *) NULL) {
20900 if (b->verbose > 2) {
20901 printf(" Queuing missing segment (%d, %d).\n", pointmark(p1),
20902 pointmark(p2));
20903 }
20904 misseg = (badface *) misseglist->append(NULL);
20905 misseg->ss = *insseg;
20906 misseg->forg = p1;
20907 misseg->fdest = p2;
20908 misseg->foppo = (point) NULL;
20909
20910 }
20911 return false;
20912 }
20913 }
20914
20916
20917
20918
20920
20921 void tetgenmesh::tallmissegs(list *misseglist)
20922 {
20923 face segloop;
20924
20925 if (b->verbose) {
20926 printf(" Queuing missing segments.\n");
20927 }
20928
20929 subsegs->traversalinit();
20930 segloop.sh = shellfacetraverse(subsegs);
20931 while (segloop.sh != (shellface *) NULL) {
20932 insertsegment(&segloop, misseglist);
20933 segloop.sh = shellfacetraverse(subsegs);
20934 }
20935 }
20936
20938
20939
20940
20941
20942
20943
20944
20945
20946
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
20973
20974 void tetgenmesh::delaunizesegments()
20975 {
20976 list *misseglist;
20977 queue *flipqueue;
20978 badface *misloop;
20979 tetrahedron encodedtet;
20980 triface searchtet, splittet;
20981 face splitsh, symsplitsub;
20982 face segloop, symsplitseg;
20983 point refpoint, splitpoint, sympoint;
20984 point tend, checkpoint;
20985 point p1, p2, pa;
20986 enum finddirectionresult collinear;
20987 enum insertsiteresult success;
20988 enum locateresult symloc;
20989 bool coll;
20990 long vertcount;
20991 int i, j;
20992
20993 if (!b->quiet) {
20994 printf("Delaunizing segments.\n");
20995 }
20996
20997
20998 makepoint2tetmap();
20999
21000 flipqueue = new queue(sizeof(badface));
21001
21002 misseglist = new list(sizeof(badface), NULL, SUBPERBLOCK);
21003
21004 tallmissegs(misseglist);
21005
21006 checksubsegs = 1;
21007
21008 vertcount = points->items;
21009
21010 r1count = r2count = r3count = 0l;
21011
21012
21013 while (misseglist->items > 0) {
21014
21015 i = randomnation(misseglist->items);
21016 misloop = (badface *)(* misseglist)[i];
21017 segloop = misloop->ss;
21018
21019 *misloop = *(badface *)(* misseglist)[misseglist->items - 1];
21020 misseglist->items--;
21021
21022 p1 = (point) segloop.sh[3];
21023 p2 = (point) segloop.sh[4];
21024 if (b->verbose > 1) {
21025 printf(" Recover segment (%d, %d).\n", pointmark(p1), pointmark(p2));
21026 }
21027 getsearchtet(p1, p2, &searchtet, &tend);
21028 collinear = finddirection(&searchtet, tend, tetrahedrons->items);
21029 if (collinear == LEFTCOLLINEAR) {
21030 checkpoint = apex(searchtet);
21031 } else if (collinear == RIGHTCOLLINEAR) {
21032 checkpoint = dest(searchtet);
21033 } else if (collinear == TOPCOLLINEAR) {
21034 checkpoint = oppo(searchtet);
21035 } else {
21036 #ifdef SELF_CHECK
21037 assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
21038 #endif
21039 checkpoint = (point) NULL;
21040 }
21041 if (checkpoint != tend) {
21042
21043 splitpoint = (point) NULL;
21044 if (checkpoint != (point) NULL) {
21045
21046
21047
21048 splitpoint = checkpoint;
21049 if (pointtype(checkpoint) == FREEVOLVERTEX) {
21050
21051 setpointtype(splitpoint, NACUTEVERTEX);
21052 } else if (pointtype(checkpoint) == ACUTEVERTEX) {
21053
21054 } else if (pointtype(checkpoint) == NACUTEVERTEX) {
21055
21056 } else {
21057
21058 }
21059 } else {
21060
21061 refpoint = scoutrefpoint(&searchtet, tend);
21062 if (pointtype(refpoint) == FREEVOLVERTEX) {
21063
21064 coll = iscollinear(p1, p2, refpoint, b->epsilon);
21065 if (coll) {
21066
21067
21068 splitpoint = refpoint;
21069 setpointtype(splitpoint, NACUTEVERTEX);
21070 }
21071 }
21072 if (splitpoint == (point) NULL) {
21073
21074 splitpoint = getsplitpoint(&segloop, refpoint);
21075
21076
21077 if (checkpbcs) {
21078
21079 i = shellmark(segloop) - 1;
21080 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
21081 makepoint(&sympoint);
21082 symloc = getsegpbcsympoint(splitpoint, &segloop, sympoint,
21083 &symsplitseg, segpglist[j]);
21084 #ifdef SELF_CHECK
21085 assert(symloc != OUTSIDE);
21086 #endif
21087 if ((symloc == ONEDGE) && (symsplitseg.sh != segloop.sh)) {
21088 #ifdef SELF_CHECK
21089 assert(symsplitseg.sh != dummysh);
21090 #endif
21091 setpointtype(sympoint, FREESEGVERTEX);
21092 setpoint2sh(sympoint, sencode(symsplitseg));
21093
21094 pa = sorg(symsplitseg);
21095 splittet.tet = dummytet;
21096
21097 encodedtet = point2tet(pa);
21098 if (encodedtet != (tetrahedron) NULL) {
21099 decode(encodedtet, splittet);
21100 if (isdead(&splittet)) {
21101 splittet.tet = dummytet;
21102 }
21103 }
21104
21105 success = insertsite(sympoint, &splittet, false, flipqueue);
21106 #ifdef SELF_CHECK
21107 assert(success != DUPLICATEPOINT);
21108 #endif
21109 if (success == OUTSIDEPOINT) {
21110 inserthullsite(sympoint, &splittet, flipqueue);
21111 }
21112 if (steinerleft > 0) steinerleft--;
21113
21114 setpoint2tet(sympoint, encode(splittet));
21115
21116 lawson(misseglist, flipqueue);
21117
21118 symsplitseg.shver = 0;
21119 spivot(symsplitseg, symsplitsub);
21120
21121 splitsubedge(sympoint, &symsplitsub, flipqueue);
21122
21123 flipsub(flipqueue);
21124
21125 symsplitseg.shver = 0;
21126 insertsegment(&symsplitseg, misseglist);
21127 senextself(symsplitseg);
21128 spivotself(symsplitseg);
21129 symsplitseg.shver = 0;
21130 insertsegment(&symsplitseg, misseglist);
21131 } else {
21132
21133
21134 pointdealloc(sympoint);
21135 }
21136 }
21137 }
21138
21139
21140 if (isdead(&searchtet)) searchtet.tet = dummytet;
21141 success = insertsite(splitpoint, &searchtet, false, flipqueue);
21142 if (success == OUTSIDEPOINT) {
21143
21144
21145
21146 inserthullsite(splitpoint, &searchtet, flipqueue);
21147 }
21148 if (steinerleft > 0) steinerleft--;
21149
21150
21151 setpoint2tet(splitpoint, encode(searchtet));
21152
21153 lawson(misseglist, flipqueue);
21154 }
21155 }
21156
21157 spivot(segloop, splitsh);
21158 splitsubedge(splitpoint, &splitsh, flipqueue);
21159 flipsub(flipqueue);
21160
21161 segloop.shver = 0;
21162 insertsegment(&segloop, misseglist);
21163 senextself(segloop);
21164 spivotself(segloop);
21165 segloop.shver = 0;
21166 insertsegment(&segloop, misseglist);
21167 }
21168 }
21169
21170
21171 tetrahedrons->traversalinit();
21172 searchtet.tet = tetrahedrontraverse();
21173 while (searchtet.tet != (tetrahedron *) NULL) {
21174 for (i = 0; i < 6; i++) {
21175 searchtet.tet[8 + i] = (tetrahedron) dummysh;
21176 }
21177 searchtet.tet = tetrahedrontraverse();
21178 }
21179
21180 checksubsegs = 0;
21181
21182 if (b->verbose > 0) {
21183 printf(" %ld protect points.\n", points->items - vertcount);
21184 printf(" R1: %ld, R2: %ld, R3: %ld.\n", r1count, r2count, r3count);
21185 }
21186
21187 delete flipqueue;
21188 delete misseglist;
21189 }
21190
21191
21192
21193
21194
21195
21196
21197
21198
21200
21201
21202
21203
21204
21205
21207
21208 bool tetgenmesh::insertsubface(face* insertsh, triface* searchtet)
21209 {
21210 triface spintet, symtet;
21211 face testsh, testseg;
21212 face spinsh, casin, casout;
21213 point tapex, checkpoint;
21214 enum finddirectionresult collinear;
21215 int hitbdry;
21216
21217
21218 getsearchtet(sorg(*insertsh), sdest(*insertsh), searchtet, &checkpoint);
21219 collinear = finddirection(searchtet, checkpoint, tetrahedrons->items);
21220 if (collinear == LEFTCOLLINEAR) {
21221 enext2self(*searchtet);
21222 esymself(*searchtet);
21223 } else if (collinear == TOPCOLLINEAR) {
21224 fnextself(*searchtet);
21225 enext2self(*searchtet);
21226 esymself(*searchtet);
21227 }
21228 if (dest(*searchtet) != checkpoint) {
21229
21230 return false;
21231 }
21232
21233
21234 tapex = sapex(*insertsh);
21235 spintet = *searchtet;
21236 hitbdry = 0;
21237 do {
21238 if (apex(spintet) == tapex) {
21239
21240 tspivot(spintet, testsh);
21241 if (testsh.sh == dummysh) {
21242 adjustedgering(spintet, CCW);
21243 findedge(insertsh, org(spintet), dest(spintet));
21244 tsbond(spintet, *insertsh);
21245 sym(spintet, symtet);
21246 sesymself(*insertsh);
21247 tsbond(symtet, *insertsh);
21248 } else {
21249
21250 if (!b->quiet) {
21251 printf("Warning: Two subfaces are found duplicated at ");
21252 printf("(%d, %d, %d)\n", pointmark(sorg(testsh)),
21253 pointmark(sdest(testsh)), pointmark(sapex(testsh)));
21254 printf(" Subface of facet #%d is deleted.\n", shellmark(*insertsh));
21255
21256 }
21257 shellfacedealloc(subfaces, insertsh->sh);
21258 }
21259 return true;
21260 }
21261 if (!fnextself(spintet)) {
21262 hitbdry ++;
21263 if (hitbdry < 2) {
21264 esym(*searchtet, spintet);
21265 if (!fnextself(spintet)) {
21266 hitbdry ++;
21267 }
21268 }
21269 }
21270 } while (hitbdry < 2 && apex(spintet) != apex(*searchtet));
21271
21272
21273 return false;
21274 }
21275
21277
21278
21279
21280
21281
21282
21283
21284
21286
21287 bool tetgenmesh::tritritest(triface* checktet, point p1, point p2, point p3)
21288 {
21289 point forg, fdest, fapex;
21290 enum interresult intersect;
21291
21292 forg = org(*checktet);
21293 fdest = dest(*checktet);
21294 fapex = apex(*checktet);
21295
21296 #ifdef SELF_CHECK
21297 REAL ax, ay, az, bx, by, bz;
21298 REAL n[3];
21299
21300
21301 ax = forg[0] - fdest[0];
21302 ay = forg[1] - fdest[1];
21303 az = forg[2] - fdest[2];
21304 bx = forg[0] - fapex[0];
21305 by = forg[1] - fapex[1];
21306 bz = forg[2] - fapex[2];
21307 n[0] = ay * bz - by * az;
21308 n[1] = az * bx - bz * ax;
21309 n[2] = ax * by - bx * ay;
21310 assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21311
21312
21313 ax = p1[0] - p2[0];
21314 ay = p1[1] - p2[1];
21315 az = p1[2] - p2[2];
21316 bx = p1[0] - p3[0];
21317 by = p1[1] - p3[1];
21318 bz = p1[2] - p3[2];
21319 n[0] = ay * bz - by * az;
21320 n[1] = az * bx - bz * ax;
21321 n[2] = ax * by - bx * ay;
21322 assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21323
21324 #endif
21325
21326 intersect = tri_tri_inter(forg, fdest, fapex, p1, p2, p3);
21327 return intersect == INTERSECT;
21328 }
21329
21331
21332
21333
21334
21335
21336
21337
21338
21339
21340
21341
21342
21343
21345
21346 void tetgenmesh::initializecavity(list* floorlist, list* ceillist,
21347 list* frontlist)
21348 {
21349 triface neightet, casingtet;
21350 triface faketet;
21351 face worksh;
21352 int i;
21353
21354
21355 for (i = 0; i < floorlist->len(); i++) {
21356
21357 worksh = * (face *)(* floorlist)[i];
21358 #ifdef SELF_CHECK
21359
21360 stpivot(worksh, neightet);
21361 assert(neightet.tet == dummytet);
21362 #endif
21363
21364 sesymself(worksh);
21365 stpivot(worksh, casingtet);
21366
21367 if (casingtet.tet == dummytet) {
21368
21369 maketetrahedron(&faketet);
21370 setorg(faketet, sorg(worksh));
21371 setdest(faketet, sdest(worksh));
21372 setapex(faketet, sapex(worksh));
21373 setoppo(faketet, (point) NULL);
21374 tsbond(faketet, worksh);
21375 frontlist->append(&faketet);
21376 } else {
21377 frontlist->append(&casingtet);
21378 }
21379 }
21380
21381 for (i = 0; i < ceillist->len(); i++) {
21382
21383 neightet = * (triface *) (* ceillist)[i];
21384 #ifdef SELF_CHECK
21385
21386 assert(infected(neightet));
21387 #endif
21388
21389 sym(neightet, casingtet);
21390
21391 if (casingtet.tet == dummytet) {
21392
21393 maketetrahedron(&faketet);
21394
21395 adjustedgering(neightet, CW);
21396 setorg(faketet, org(neightet));
21397 setdest(faketet, dest(neightet));
21398 setapex(faketet, apex(neightet));
21399 setoppo(faketet, (point) NULL);
21400
21401 tspivot(neightet, worksh);
21402 if (worksh.sh != dummysh) {
21403 sesymself(worksh);
21404 tsbond(faketet, worksh);
21405 }
21406
21407 bond(faketet, neightet);
21408
21409 infect(neightet);
21410 frontlist->append(&faketet);
21411 } else {
21412 frontlist->append(&casingtet);
21413 }
21414 }
21415 }
21416
21418
21419
21420
21421
21422
21423
21425
21426 void tetgenmesh::retrievenewtets(list* newtetlist)
21427 {
21428 triface searchtet, casingtet;
21429 int i;
21430
21431
21432 for (i = 0; i < newtetlist->len(); i++) {
21433 searchtet = * (triface *)(* newtetlist)[i];
21434 if (isdead(&searchtet)) {
21435 newtetlist->del(i, 0); i--;
21436 continue;
21437 }
21438 infect(searchtet);
21439 }
21440
21441 for (i = 0; i < newtetlist->len(); i++) {
21442 searchtet = * (triface *)(* newtetlist)[i];
21443 for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
21444 sym(searchtet, casingtet);
21445 if ((casingtet.tet != dummytet) && !infected(casingtet)) {
21446 infect(casingtet);
21447 newtetlist->append(&casingtet);
21448 }
21449 }
21450 }
21451
21452 for (i = 0; i < newtetlist->len(); i++) {
21453 searchtet = * (triface *)(* newtetlist)[i];
21454 uninfect(searchtet);
21455 }
21456 }
21457
21459
21460
21461
21462
21463
21464
21465
21466
21467
21468
21470
21471 void tetgenmesh::delaunizecavvertices(triface* oldtet, list* floorptlist,
21472 list* ceilptlist, list* newtetlist, queue* flipque)
21473 {
21474 point *insertarray;
21475 triface bakhulltet, newtet;
21476 long bakhullsize;
21477 long arraysize;
21478 int bakchksub;
21479 int i, j;
21480
21481
21482 arraysize = floorptlist->len();
21483 if (ceilptlist != (list *) NULL) {
21484 arraysize += ceilptlist->len();
21485 }
21486 insertarray = new point[arraysize];
21487 for (i = 0; i < floorptlist->len(); i++) {
21488 insertarray[i] = * (point *)(* floorptlist)[i];
21489 }
21490 if (ceilptlist != (list *) NULL) {
21491 for (j = 0; j < ceilptlist->len(); j++) {
21492 insertarray[i + j] = * (point *)(* ceilptlist)[j];
21493 }
21494 }
21495
21496
21497 decode(dummytet[0], bakhulltet);
21498 bakhullsize = hullsize;
21499 bakchksub = checksubfaces;
21500 checksubfaces = 0;
21501 b->verbose--;
21502
21503
21504
21505 incrflipdelaunay(oldtet, insertarray, arraysize, false, false, 0.0, flipque);
21506
21507
21508 decode(dummytet[0], newtet);
21509 newtetlist->append(&newtet);
21510
21511 retrievenewtets(newtetlist);
21512
21513
21514 dummytet[0] = encode(bakhulltet);
21515 hullsize = bakhullsize;
21516 checksubfaces = bakchksub;
21517 b->verbose++;
21518
21519 delete [] insertarray;
21520 }
21521
21523
21524
21525
21526
21527
21528
21529
21530
21531
21532
21533
21535
21536 void tetgenmesh::insertauxsubface(triface* front, triface* idfront)
21537 {
21538 triface neightet;
21539 face auxsh;
21540
21541
21542 makeshellface(subfaces, &auxsh);
21543
21544 tsbond(*idfront, auxsh);
21545
21546 sym(*idfront, neightet);
21547 if (neightet.tet != dummytet) {
21548
21549 sesymself(auxsh);
21550 tsbond(neightet, auxsh);
21551 }
21552
21553 auxsh.sh[0] = (shellface) encode(*front);
21554 }
21555
21557
21558
21559
21560
21561
21562
21564
21565 bool tetgenmesh::scoutfront(triface* front, triface* idfront, list* newtetlist)
21566 {
21567 triface spintet;
21568 point pa, pb, pc;
21569 enum locateresult loc;
21570 enum finddirectionresult col;
21571 int hitbdry;
21572 int i;
21573
21574
21575 pa = org(*front);
21576 pb = dest(*front);
21577
21578 *idfront = recenttet;
21579
21580 if (isdead(idfront)) {
21581
21582 for (i = 0; i < newtetlist->len(); i++) {
21583 recenttet = * (triface *)(* newtetlist)[i];
21584 if (!isdead(&recenttet)) break;
21585 }
21586 assert(i < newtetlist->len());
21587 }
21588
21589
21590 loc = preciselocate(pa, idfront, (long) newtetlist->len());
21591 assert(loc == ONVERTEX);
21592 recenttet = *idfront;
21593
21594 col = finddirection(idfront, pb, (long) newtetlist->len());
21595 if (col == RIGHTCOLLINEAR) {
21596
21597 } else if (col == LEFTCOLLINEAR) {
21598 enext2self(*idfront);
21599 esymself(*idfront);
21600 } else if (col == TOPCOLLINEAR) {
21601 fnextself(*idfront);
21602 enext2self(*idfront);
21603 esymself(*idfront);
21604 }
21605
21606 if (dest(*idfront) == pb) {
21607
21608 pc = apex(*front);
21609 spintet = *idfront;
21610 hitbdry = 0;
21611 do {
21612 if (apex(spintet) == pc) {
21613
21614
21615 *idfront = spintet;
21616 return true;
21617 }
21618 if (!fnextself(spintet)) {
21619 hitbdry ++;
21620 if (hitbdry < 2) {
21621 esym(*idfront, spintet);
21622 if (!fnextself(spintet)) {
21623 hitbdry ++;
21624 }
21625 }
21626 }
21627 if (apex(spintet) == apex(*idfront)) break;
21628 } while (hitbdry < 2);
21629 }
21630
21631
21632 if (b->verbose > 2) {
21633 printf(" Front (%d, %d, %d) is missing.\n", pointmark(pa),
21634 pointmark(pb), pointmark(apex(*front)));
21635 }
21636 return false;
21637 }
21638
21640
21641
21642
21643
21644
21645
21646
21647
21649
21650 void tetgenmesh::gluefronts(triface* front, triface* front1)
21651 {
21652 face consh;
21653
21654
21655
21656
21657
21658
21659
21660
21661
21662 tspivot(*front, consh);
21663 if (consh.sh != dummysh) {
21664 sesymself(consh);
21665 tsbond(*front1, consh);
21666 sesymself(consh);
21667 }
21668
21669 if (oppo(*front) == (point) NULL) {
21670
21671 assert(oppo(*front1) != (point) NULL);
21672
21673 if (consh.sh != dummysh) {
21674 stdissolve(consh);
21675 }
21676
21677 tetrahedrondealloc(front->tet);
21678
21679 dummytet[0] = encode(*front1);
21680 } else {
21681
21682 bond(*front, *front1);
21683 }
21684
21685 if (!isdead(front)) {
21686
21687 tspivot(*front1, consh);
21688
21689 if (oppo(*front1) == (point) NULL) {
21690
21691 assert(oppo(*front) != (point) NULL);
21692
21693 if (consh.sh != dummysh) {
21694 stdissolve(consh);
21695 sesymself(consh);
21696 tsbond(*front, consh);
21697 }
21698
21699 dissolve(*front);
21700
21701 tetrahedrondealloc(front1->tet);
21702
21703 dummytet[0] = encode(*front);
21704 } else {
21705
21706 if (consh.sh != dummysh) {
21707 sesymself(consh);
21708 tsbond(*front, consh);
21709 }
21710 }
21711 }
21712 }
21713
21715
21716
21717
21718
21719
21720
21721
21722
21724
21725 bool tetgenmesh::identifyfronts(list* frontlist, list* misfrontlist,
21726 list* newtetlist)
21727 {
21728 triface front, front1, tfront;
21729 triface idfront, neightet;
21730 face auxsh;
21731 int len, i, j;
21732
21733 misfrontlist->clear();
21734
21735 recenttet = * (triface *)(* newtetlist)[0];
21736
21737
21738 for (i = 0; i < frontlist->len(); i++) {
21739
21740 front = * (triface *)( *frontlist)[i];
21741 if (scoutfront(&front, &idfront, newtetlist)) {
21742
21743 assert((idfront.tet != dummytet) && !isdead(&idfront));
21744
21745 tspivot(idfront, auxsh);
21746 if (auxsh.sh != dummysh) {
21747
21748 decode((tetrahedron) auxsh.sh[0], front1);
21749 assert((front1.tet != dummytet) && !infected(front1));
21750
21751 tsdissolve(idfront);
21752 sym(idfront, neightet);
21753 if (neightet.tet != dummytet) {
21754 tsdissolve(neightet);
21755 }
21756
21757 shellfacedealloc(subfaces, auxsh.sh);
21758
21759 frontlist->del(i, 1); i--;
21760
21761 len = frontlist->len();
21762 for (j = 0; j < frontlist->len(); j++) {
21763 tfront = * (triface *)(* frontlist)[j];
21764 if ((tfront.tet == front1.tet) && (tfront.loc == front1.loc)) {
21765
21766 assert((tfront.tet != front.tet) || (tfront.loc != front.loc));
21767 frontlist->del(j, 1); i--;
21768 break;
21769 }
21770 }
21771 assert((frontlist->len() + 1) == len);
21772
21773 gluefronts(&front, &front1);
21774 } else {
21775
21776 insertauxsubface(&front, &idfront);
21777 }
21778 } else {
21779
21780 frontlist->del(i, 1); i--;
21781
21782 for (j = 0; j < misfrontlist->len(); j++) {
21783 front1 = * (triface *)(* misfrontlist)[j];
21784 if (isfacehaspoint(&front1, org(front)) &&
21785 isfacehaspoint(&front1, dest(front)) &&
21786 isfacehaspoint(&front1, apex(front))) break;
21787 }
21788 if (j < misfrontlist->len()) {
21789
21790 misfrontlist->del(j, 1);
21791
21792 gluefronts(&front, &front1);
21793 } else {
21794
21795 misfrontlist->append(&front);
21796 }
21797 }
21798 }
21799 return misfrontlist->len() == 0;
21800 }
21801
21803
21804
21805
21806
21807
21808
21809
21810
21812
21813 void tetgenmesh::detachauxsubfaces(list* newtetlist)
21814 {
21815 triface newtet, neightet;
21816 face auxsh;
21817 int i;
21818
21819 for (i = 0; i < newtetlist->len(); i++) {
21820
21821 newtet = * (triface *)(* newtetlist)[i];
21822
21823 if (isdead(&newtet)) continue;
21824 assert(!infected(newtet));
21825
21826 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
21827 tspivot(newtet, auxsh);
21828 if (auxsh.sh != dummysh) {
21829
21830 assert(sorg(auxsh) == (point) NULL);
21831 tsdissolve(newtet);
21832 sym(newtet, neightet);
21833 if (neightet.tet != dummytet) {
21834 assert(!isdead(&neightet));
21835 tsdissolve(neightet);
21836 }
21837
21838 shellfacedealloc(subfaces, auxsh.sh);
21839 }
21840 }
21841 }
21842 }
21843
21845
21846
21847
21848
21849
21850
21851
21852
21853
21855
21856 void tetgenmesh::expandcavity(list* frontlist, list* misfrontlist,
21857 list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
21858 {
21859 triface misfront, newfront, casingtet, crosstet;
21860 triface searchtet, faketet, bakhulltet;
21861 face checksh;
21862 point pd;
21863 enum insertsiteresult success;
21864 long bakhullsize;
21865 int bakchksub;
21866 int i, j, k;
21867
21868 if (b->verbose > 1) {
21869 printf(" Expand cavity (%d missing fronts).\n", misfrontlist->len());
21870 }
21871
21872 expcavcount++;
21873
21874 decode(dummytet[0], bakhulltet);
21875 bakhullsize = hullsize;
21876 bakchksub = checksubfaces;
21877 checksubfaces = 0;
21878 b->verbose--;
21879
21880
21881 recenttet = * (triface *)(* newtetlist)[0];
21882 assert((recenttet.tet != dummytet) && !isdead(&recenttet));
21883
21884
21885 for (i = 0; i < misfrontlist->len(); i++) {
21886
21887 misfront = * (triface *)(* misfrontlist)[i];
21888
21889 if (b->verbose > 1) {
21890 printf(" Get misfront (%d, %d, %d).\n", pointmark(org(misfront)),
21891 pointmark(dest(misfront)), pointmark(apex(misfront)));
21892 }
21893
21894 tspivot(misfront, checksh);
21895 if (checksh.sh != dummysh) {
21896
21897 sym(misfront, crosstet);
21898 if (!infected(crosstet)) {
21899
21900
21901 assert(checkpbcs);
21902
21903 continue;
21904 }
21905
21906 if (b->verbose > 1) {
21907 printf(" Queuing subface (%d, %d, %d).\n",
21908 pointmark(sorg(checksh)), pointmark(sdest(checksh)),
21909 pointmark(sapex(checksh)));
21910 }
21911
21912 tsdissolve(misfront);
21913 tsdissolve(crosstet);
21914
21915 stdissolve(checksh);
21916 sesymself(checksh);
21917 stdissolve(checksh);
21918
21919 sinfect(checksh);
21920 missingshqueue->push(&checksh);
21921 }
21922
21923 if (infected(misfront)) continue;
21924
21925 pd = oppo(misfront);
21926 #ifdef SELF_CHECK
21927
21928 assert(pd != (point) NULL);
21929 #endif
21930
21931
21932
21933 searchtet = recenttet;
21934
21935 if (isdead(&searchtet)) {
21936
21937 for (j = 0; j < newtetlist->len(); j++) {
21938 recenttet = * (triface *)(* newtetlist)[j];
21939 if (!isdead(&recenttet)) break;
21940 }
21941 assert(j < newtetlist->len());
21942 searchtet = recenttet;
21943 }
21944 success = insertsite(pd, &searchtet, false, flipque);
21945 if (success == OUTSIDEPOINT) {
21946
21947 inserthullsite(pd, &searchtet, flipque);
21948 }
21949 if (success != DUPLICATEPOINT) {
21950
21951 flip(flipque, NULL);
21952 }
21953
21954
21955
21956 adjustedgering(misfront, CCW);
21957 for (j = 0; j < 3; j++) {
21958
21959
21960
21961 fnext(misfront, newfront);
21962
21963 sym(newfront, casingtet);
21964
21965 if (!infected(casingtet)) {
21966
21967
21968 if (casingtet.tet == dummytet) {
21969
21970 maketetrahedron(&faketet);
21971
21972 adjustedgering(newfront, CW);
21973 setorg(faketet, org(newfront));
21974 setdest(faketet, dest(newfront));
21975 setapex(faketet, apex(newfront));
21976 setoppo(faketet, (point) NULL);
21977
21978 tspivot(newfront, checksh);
21979 if (checksh.sh != dummysh) {
21980 sesymself(checksh);
21981 tsbond(faketet, checksh);
21982 }
21983
21984 bond(faketet, newfront);
21985 frontlist->append(&faketet);
21986 } else {
21987
21988 frontlist->append(&casingtet);
21989 }
21990 } else {
21991
21992
21993
21994 for (k = frontlist->len() - 1; k >= 0; k--) {
21995 searchtet = * (triface *)(* frontlist)[k];
21996 if ((newfront.tet == searchtet.tet) &&
21997 (newfront.loc == searchtet.loc)) {
21998 frontlist->del(k, 0);
21999 break;
22000 }
22001 }
22002
22003 tspivot(newfront, checksh);
22004 if (checksh.sh != dummysh) {
22005
22006 if (b->verbose > 2) {
22007 printf(" Queuing subface (%d, %d, %d).\n",
22008 pointmark(sorg(checksh)), pointmark(sdest(checksh)),
22009 pointmark(sapex(checksh)));
22010 }
22011 tsdissolve(newfront);
22012 tsdissolve(casingtet);
22013
22014 stdissolve(checksh);
22015 sesymself(checksh);
22016 stdissolve(checksh);
22017 sinfect(checksh);
22018 missingshqueue->push(&checksh);
22019 }
22020 }
22021 enextself(misfront);
22022 }
22023
22024 if (!infected(misfront)) {
22025
22026 infect(misfront);
22027 crosstetlist->append(&misfront);
22028 }
22029 }
22030
22031
22032 for (i = 0; i < misfrontlist->len(); i++) {
22033 misfront = * (triface *)(* misfrontlist)[i];
22034 if (infected(misfront)) {
22035
22036 misfrontlist->del(i, 1);
22037 i--;
22038 }
22039 }
22040
22041
22042 if (misfrontlist->len() > 0) {
22043
22044
22045 assert(0);
22046 }
22047
22048
22049 retrievenewtets(newtetlist);
22050
22051
22052 dummytet[0] = encode(bakhulltet);
22053 hullsize = bakhullsize;
22054 checksubfaces = bakchksub;
22055 b->verbose++;
22056 }
22057
22059
22060
22061
22062
22063
22064
22065
22066
22067
22068
22069
22070
22071
22072
22073
22074
22076
22077 void tetgenmesh::carvecavity(list* newtetlist, list* outtetlist,
22078 queue* flipque)
22079 {
22080 triface newtet, neightet, front, outtet;
22081 face auxsh, consh;
22082 point pointptr;
22083 REAL ori;
22084 int i;
22085
22086
22087 outtetlist->clear();
22088
22089
22090 for (i = 0; i < newtetlist->len(); i++) {
22091
22092 newtet = * (triface *)(* newtetlist)[i];
22093 assert(!isdead(&newtet));
22094
22095 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22096 tspivot(newtet, auxsh);
22097 if (auxsh.sh != dummysh) {
22098
22099 sym(newtet, neightet);
22100 if (neightet.tet != dummytet) {
22101
22102
22103 decode((tetrahedron) auxsh.sh[0], front);
22104
22105 adjustedgering(front, CW);
22106 ori = orient3d(org(front), dest(front), apex(front), oppo(newtet));
22107 assert(ori != 0.0);
22108 if (ori < 0.0) {
22109
22110 outtet = neightet;
22111 } else {
22112
22113 outtet = newtet;
22114 }
22115
22116 if (!infected(outtet)) {
22117 infect(outtet);
22118 outtetlist->append(&outtet);
22119 }
22120 }
22121 }
22122 }
22123 }
22124
22125
22126 for (i = 0; i < outtetlist->len(); i++) {
22127 outtet = * (triface *)(* outtetlist)[i];
22128 for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22129 sym(outtet, neightet);
22130
22131 if ((neightet.tet != dummytet) && !infected(neightet)) {
22132
22133 tspivot(outtet, auxsh);
22134 if (auxsh.sh == dummysh) {
22135
22136 infect(neightet);
22137 outtetlist->append(&neightet);
22138 }
22139 }
22140 }
22141 }
22142
22143
22144 for (i = 0; i < outtetlist->len(); i++) {
22145
22146 outtet = * (triface *)(* outtetlist)[i];
22147
22148 for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22149
22150 tspivot(outtet, auxsh);
22151 if (auxsh.sh != dummysh) {
22152
22153 sym(outtet, neightet);
22154 assert(!infected(neightet));
22155
22156 dissolve(neightet);
22157 }
22158 }
22159
22160 tetrahedrondealloc(outtet.tet);
22161 }
22162
22163
22164 for (i = 0; i < newtetlist->len(); i++) {
22165
22166 newtet = * (triface *)(* newtetlist)[i];
22167
22168 if (isdead(&newtet)) continue;
22169
22170 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22171
22172 tspivot(newtet, auxsh);
22173 if (auxsh.sh != dummysh) {
22174
22175 decode((tetrahedron) auxsh.sh[0], front);
22176 assert((front.tet != dummytet) && !infected(front));
22177
22178 tsdissolve(newtet);
22179
22180 shellfacedealloc(subfaces, auxsh.sh);
22181
22182
22183 tspivot(front, consh);
22184 if (consh.sh != dummysh) {
22185 sesymself(consh);
22186
22187 tsbond(newtet, consh);
22188 }
22189
22190 if (oppo(front) == (point) NULL) {
22191
22192 if (consh.sh != dummysh) {
22193 sesymself(consh);
22194
22195 stdissolve(consh);
22196 }
22197
22198 tetrahedrondealloc(front.tet);
22199
22200 dummytet[0] = encode(newtet);
22201 } else {
22202
22203 bond(newtet, front);
22204 }
22205
22206 if (flipque != (queue *) NULL) {
22207 enqueueflipface(newtet, flipque);
22208 }
22209 }
22210 }
22211
22212 pointptr = org(newtet);
22213 setpoint2tet(pointptr, encode(newtet));
22214 pointptr = dest(newtet);
22215 setpoint2tet(pointptr, encode(newtet));
22216 pointptr = apex(newtet);
22217 setpoint2tet(pointptr, encode(newtet));
22218 pointptr = oppo(newtet);
22219 setpoint2tet(pointptr, encode(newtet));
22220 }
22221
22222 }
22223
22225
22226
22227
22228
22229
22230
22231
22233
22234 void tetgenmesh::delaunizecavity(list* floorlist, list* ceillist,
22235 list* ceilptlist, list* floorptlist, list* frontlist, list* misfrontlist,
22236 list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
22237 {
22238 int vertnum;
22239
22240 vertnum = floorptlist->len();
22241 vertnum += (ceilptlist != (list *) NULL ? ceilptlist->len() : 0);
22242 if (b->verbose > 1) {
22243 printf(" Delaunizing cavity (%d floors, %d ceilings, %d vertices).\n",
22244 floorlist->len(), ceillist->len(), vertnum);
22245 }
22246
22247 if ((floorlist->len() + ceillist->len()) > maxcavfaces) {
22248 maxcavfaces = floorlist->len() + ceillist->len();
22249 }
22250 if (vertnum > maxcavverts) {
22251 maxcavverts = vertnum;
22252 }
22253
22254
22255 frontlist->clear();
22256 misfrontlist->clear();
22257 newtetlist->clear();
22258
22259
22260 initializecavity(floorlist, ceillist, frontlist);
22261
22262 delaunizecavvertices(NULL, floorptlist, ceilptlist, newtetlist, flipque);
22263
22264 while (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
22265
22266 detachauxsubfaces(newtetlist);
22267
22268 expandcavity(frontlist, misfrontlist, newtetlist, crosstetlist,
22269 missingshqueue, flipque);
22270 }
22271
22272
22273 carvecavity(newtetlist, misfrontlist, NULL);
22274 }
22275
22277
22278
22279
22280
22281
22282
22283
22284
22285
22286
22287
22288
22289
22291
22292 void tetgenmesh::formmissingregion(face* missingsh, list* missingshlist,
22293 list* equatptlist, int* worklist)
22294 {
22295 face neighsh, worksh, workseg;
22296 point workpt[3];
22297 int idx, i, j;
22298
22299
22300 missingshlist->append(missingsh);
22301
22302 workpt[0] = sorg(*missingsh);
22303 workpt[1] = sdest(*missingsh);
22304 workpt[2] = sapex(*missingsh);
22305 for (i = 0; i < 3; i++) {
22306 idx = pointmark(workpt[i]) - in->firstnumber;
22307 worklist[idx] = 1;
22308 equatptlist->append(&workpt[i]);
22309 }
22310
22311 suninfect(*missingsh);
22312
22313
22314 for (i = 0; i < missingshlist->len(); i++) {
22315
22316 worksh = * (face *)(* missingshlist)[i];
22317
22318 for (j = 0; j < 3; j++) {
22319 sspivot(worksh, workseg);
22320 if (workseg.sh == dummysh) {
22321 spivot(worksh, neighsh);
22322 if (sinfected(neighsh)) {
22323
22324 if (sorg(neighsh) != sdest(worksh)) {
22325 sesymself(neighsh);
22326 }
22327 if (b->verbose > 2) {
22328 printf(" Add missing subface (%d, %d, %d).\n",
22329 pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
22330 pointmark(sapex(neighsh)));
22331 }
22332 missingshlist->append(&neighsh);
22333
22334 workpt[0] = sapex(neighsh);
22335 idx = pointmark(workpt[0]) - in->firstnumber;
22336
22337 if (worklist[idx] == 0) {
22338 worklist[idx] = 1;
22339 equatptlist->append(&workpt[0]);
22340 }
22341
22342 suninfect(neighsh);
22343 }
22344 }
22345 senextself(worksh);
22346 }
22347 }
22348
22349
22350 for (i = 0; i < missingshlist->len(); i++) {
22351 worksh = * (face *)(* missingshlist)[i];
22352 sinfect(worksh);
22353 }
22354 }
22355
22357
22358
22359
22360
22361
22362
22363
22364
22365
22366
22367
22368
22369
22370
22371
22373
22374 void tetgenmesh::rearrangesubfaces(list* missingshlist, list* boundedgelist,
22375 list* equatptlist, int* worklist)
22376 {
22377 link *boundedgelink;
22378 link *newshlink;
22379 triface starttet, spintet, neightet, worktet;
22380 face shloop, newsh, neighsh, spinsh, worksh;
22381 face workseg, casingin, casingout;
22382 point torg, tdest, workpt;
22383 point spt1, spt2, spt3;
22384 enum finddirectionresult collinear;
22385 enum shestype shtype;
22386 REAL area;
22387 bool matchflag, finishflag;
22388 int shmark, pbcgp, idx, hitbdry;
22389 int i, j;
22390
22391
22392 boundedgelink = new link(sizeof(face), NULL, 256);
22393
22394 newshlink = new link(sizeof(face), NULL, 256);
22395
22396
22397 worksh = * (face *)(* missingshlist)[0];
22398 shtype = shelltype(worksh);
22399
22400 for (i = 1; i < missingshlist->len(); i++) {
22401 worksh = * (face *)(* missingshlist)[i];
22402 assert(shelltype(worksh) == shtype);
22403 }
22404
22405 shmark = pbcgp = 0;
22406 area = 0.0;
22407
22408
22409 for (i = 0; i < boundedgelist->len(); i++) {
22410 shloop = * (face *)(* boundedgelist)[i];
22411 if (i == 0) {
22412
22413 shmark = shellmark(shloop);
22414 if (b->quality && varconstraint) {
22415
22416 area = areabound(shloop);
22417 }
22418 if (checkpbcs) {
22419
22420 pbcgp = shellpbcgroup(shloop);
22421 }
22422
22423 abovepoint = facetabovepointarray[shellmark(shloop)];
22424 if (abovepoint == (point) NULL) {
22425 getfacetabovepoint(&shloop);
22426 }
22427 }
22428 sspivot(shloop, workseg);
22429 if (workseg.sh == dummysh) {
22430
22431 spivot(shloop, neighsh);
22432 boundedgelink->add(&neighsh);
22433 } else {
22434
22435 boundedgelink->add(&shloop);
22436 }
22437 }
22438
22439
22440
22441
22442
22443
22444
22445
22446
22447
22448
22449 while (boundedgelink->len() > 0) {
22450
22451 shloop = * (face *) boundedgelink->del(1);
22452
22453 sspivot(shloop, workseg);
22454 torg = sorg(shloop);
22455 tdest = sdest(shloop);
22456
22457 getsearchtet(torg, tdest, &starttet, &workpt);
22458 collinear = finddirection(&starttet, workpt, tetrahedrons->items);
22459 if (collinear == LEFTCOLLINEAR) {
22460 enext2self(starttet);
22461 esymself(starttet);
22462 } else if (collinear == TOPCOLLINEAR) {
22463 fnextself(starttet);
22464 enext2self(starttet);
22465 esymself(starttet);
22466 }
22467 assert(dest(starttet) == workpt);
22468
22469 matchflag = false;
22470 spintet = starttet;
22471 hitbdry = 0;
22472 do {
22473 workpt = apex(spintet);
22474 idx = pointmark(workpt) - in->firstnumber;
22475 if (worklist[idx] == 1) {
22476
22477 finishflag = false;
22478 for (i = 0; i < missingshlist->len(); i++) {
22479 worksh = * (face *)(* missingshlist)[i];
22480 spt1 = sorg(worksh);
22481 spt2 = sdest(worksh);
22482 spt3 = sapex(worksh);
22483
22484 if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22485 == INTERSECT) {
22486 finishflag = true; break;
22487 }
22488
22489 if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22490 == INTERSECT) {
22491 finishflag = true; break;
22492 }
22493
22494 if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22495 == INTERSECT) {
22496 finishflag = true; break;
22497 }
22498 }
22499 if (finishflag) {
22500
22501 matchflag = true;
22502 for (i = 0; i < newshlink->len() && matchflag; i++) {
22503 worksh = * (face *) newshlink->getnitem(i + 1);
22504 spt1 = sorg(worksh);
22505 spt2 = sdest(worksh);
22506 spt3 = sapex(worksh);
22507
22508 if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22509 == INTERSECT) {
22510 matchflag = false; break;
22511 }
22512
22513 if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22514 == INTERSECT) {
22515 matchflag = false; break;
22516 }
22517
22518 if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22519 == INTERSECT) {
22520 matchflag = false; break;
22521 }
22522 }
22523 }
22524 if (matchflag == true) {
22525
22526 break;
22527 }
22528 }
22529 if (!fnextself(spintet)) {
22530 hitbdry ++;
22531 if (hitbdry < 2) {
22532 esym(starttet, spintet);
22533 if (!fnextself(spintet)) {
22534 hitbdry ++;
22535 }
22536 }
22537 }
22538 } while (hitbdry < 2 && apex(spintet) != apex(starttet));
22539 assert(matchflag == true);
22540 tspivot(spintet, neighsh);
22541 if (neighsh.sh != dummysh) {
22542 printf("Error: Invalid PLC.\n");
22543 printf(" Facet #%d and facet #%d overlap each other.\n",
22544 shellmark(neighsh), shellmark(shloop));
22545 printf(" It might be caused by a facet is defined more than once.\n");
22546 printf(" Hint: Use -d switch to find all overlapping facets.\n");
22547 exit(1);
22548 }
22549
22550 adjustedgering(spintet, CCW);
22551
22552 makeshellface(subfaces, &newsh);
22553 setsorg(newsh, org(spintet));
22554 setsdest(newsh, dest(spintet));
22555 setsapex(newsh, apex(spintet));
22556 if (b->quality && varconstraint) {
22557 setareabound(newsh, area);
22558 }
22559 if (checkpbcs) {
22560 setshellpbcgroup(newsh, pbcgp);
22561 }
22562 setshellmark(newsh, shmark);
22563 setshelltype(newsh, shtype);
22564
22565 newshlink->add(&newsh);
22566
22567 tsbond(spintet, newsh);
22568 sym(spintet, neightet);
22569 if (neightet.tet != dummytet) {
22570 sesym(newsh, neighsh);
22571 tsbond(neightet, neighsh);
22572 }
22573
22574 sspivot(shloop, workseg);
22575 if (workseg.sh == dummysh) {
22576 sbond(shloop, newsh);
22577 } else {
22578
22579
22580
22581
22582
22583
22584
22585 spivot(shloop, casingout);
22586 if (shloop.sh != casingout.sh) {
22587
22588 spinsh = casingout;
22589 do {
22590 casingin = spinsh;
22591 spivotself(spinsh);
22592 } while (sapex(spinsh) != sapex(shloop));
22593 assert(casingin.sh != shloop.sh);
22594
22595 sbond1(casingin, newsh);
22596 sbond1(newsh, casingout);
22597 } else {
22598
22599 sbond(newsh, newsh);
22600 }
22601
22602 ssbond(newsh, workseg);
22603 }
22604
22605
22606 for (i = 0; i < 2; i++) {
22607 if (i == 0) {
22608 senext(newsh, worksh);
22609 } else {
22610 senext2(newsh, worksh);
22611 }
22612 torg = sorg(worksh);
22613 tdest = sdest(worksh);
22614 finishflag = false;
22615 for (j = 0; j < boundedgelink->len() && !finishflag; j++) {
22616 neighsh = * (face *) boundedgelink->getnitem(j + 1);
22617 if ((sorg(neighsh) == torg && sdest(neighsh) == tdest) ||
22618 (sorg(neighsh) == tdest && sdest(neighsh) == torg)) {
22619
22620 sspivot(neighsh, workseg);
22621 if (workseg.sh == dummysh) {
22622 sbond(neighsh, worksh);
22623 } else {
22624
22625
22626 spivot(neighsh, casingout);
22627 if (neighsh.sh != casingout.sh) {
22628
22629 spinsh = casingout;
22630 do {
22631 casingin = spinsh;
22632 spivotself(spinsh);
22633 } while (sapex(spinsh) != sapex(neighsh));
22634 assert(casingin.sh != neighsh.sh);
22635
22636 sbond1(casingin, worksh);
22637 sbond1(worksh, casingout);
22638 } else {
22639
22640 sbond(worksh, worksh);
22641 }
22642
22643 ssbond(worksh, workseg);
22644 }
22645
22646 boundedgelink->del(j + 1);
22647 finishflag = true;
22648 }
22649 }
22650 if (!finishflag) {
22651
22652 boundedgelink->add(&worksh);
22653 }
22654 }
22655 }
22656
22657
22658 for (i = 0; i < missingshlist->len(); i++) {
22659 worksh = * (face *)(* missingshlist)[i];
22660 shellfacedealloc(subfaces, worksh.sh);
22661 }
22662
22663 for (i = 0; i < equatptlist->len(); i++) {
22664 workpt = * (point *)(* equatptlist)[i];
22665 idx = pointmark(workpt) - in->firstnumber;
22666 worklist[idx] = 0;
22667 }
22668
22669 delete boundedgelink;
22670 delete newshlink;
22671 }
22672
22674
22675
22676
22677
22678
22679
22680
22681
22682
22683
22684
22685
22687
22688 bool tetgenmesh::scoutcrossingedge(list* missingshlist, list* boundedgelist,
22689 list* crossedgelist, int* worklist)
22690 {
22691 triface starttet, spintet, worktet;
22692 face startsh, neighsh, worksh, workseg;
22693 point torg, tdest, tapex;
22694 point workpt[3], pa, pb, pc;
22695 enum finddirectionresult collinear;
22696 REAL ori1, ori2;
22697 bool crossflag;
22698 int hitbdry;
22699 int i, j, k;
22700
22701
22702
22703
22704 for (i = 0; i < missingshlist->len(); i++) {
22705 worksh = * (face *)(* missingshlist)[i];
22706 for (j = 0; j < 3; j++) {
22707 sspivot(worksh, workseg);
22708 if (workseg.sh == dummysh) {
22709 spivot(worksh, neighsh);
22710 if (!sinfected(neighsh)) {
22711 boundedgelist->append(&worksh);
22712 }
22713 } else {
22714 boundedgelist->append(&worksh);
22715 }
22716 senextself(worksh);
22717 }
22718 }
22719
22720 crossflag = false;
22721
22722
22723 for (i = 0; i < boundedgelist->len() && !crossflag; i++) {
22724 startsh = * (face *)(* boundedgelist)[i];
22725
22726 torg = sorg(startsh);
22727 tdest = sdest(startsh);
22728 tapex = sapex(startsh);
22729 getsearchtet(torg, tdest, &starttet, &workpt[0]);
22730 collinear = finddirection(&starttet, workpt[0], tetrahedrons->items);
22731 if (collinear == LEFTCOLLINEAR) {
22732 enext2self(starttet);
22733 esymself(starttet);
22734 } else if (collinear == TOPCOLLINEAR) {
22735 fnextself(starttet);
22736 enext2self(starttet);
22737 esymself(starttet);
22738 }
22739 #ifdef SELF_CHECK
22740 assert(dest(starttet) == workpt[0]);
22741 #endif
22742
22743 spintet = starttet;
22744 hitbdry = 0;
22745 do {
22746 if (fnextself(spintet)) {
22747
22748 workpt[1] = apex(spintet);
22749 workpt[2] = oppo(spintet);
22750 j = pointmark(workpt[1]) - in->firstnumber;
22751 k = pointmark(workpt[2]) - in->firstnumber;
22752 if (worklist[j] == 1) {
22753 ori1 = 0.0;
22754 } else {
22755
22756 ori1 = orient3d(torg, tdest, tapex, workpt[1]);
22757 }
22758 if (worklist[k] == 1) {
22759 ori2 = 0.0;
22760 } else {
22761
22762 ori2 = orient3d(torg, tdest, tapex, workpt[2]);
22763 }
22764
22765 if (ori1 * ori2 < 0.0) {
22766
22767 for (j = 0; j < missingshlist->len(); j++) {
22768 worksh = * (face *)(* missingshlist)[j];
22769 pa = sorg(worksh);
22770 pb = sdest(worksh);
22771 pc = sapex(worksh);
22772 crossflag = (tri_tri_inter(pa, pb, pc, workpt[0], workpt[1],
22773 workpt[2]) == INTERSECT);
22774 if (crossflag) {
22775
22776 worktet = spintet;
22777 adjustedgering(worktet, CCW);
22778 enextfnextself(worktet);
22779 enextself(worktet);
22780
22781 crossedgelist->append(&worktet);
22782 break;
22783 }
22784 }
22785 if (crossflag) break;
22786 }
22787 if (apex(spintet) == apex(starttet)) break;
22788 } else {
22789 hitbdry++;
22790
22791 if (hitbdry < 2) {
22792 esym(starttet, spintet);
22793 }
22794 }
22795 } while (hitbdry < 2);
22796 }
22797
22798 return crossflag;
22799 }
22800
22802
22803
22804
22805
22806
22807
22808
22809
22810
22811
22812
22813
22814
22815
22816
22817
22818
22819
22820
22821
22822
22823
22824
22825
22826
22827
22828
22830
22831 void tetgenmesh::formcavity(list* missingshlist, list* crossedgelist,
22832 list* equatptlist, list* crossshlist, list* crosstetlist,
22833 list* belowfacelist, list* abovefacelist, list* horizptlist,
22834 list* belowptlist, list* aboveptlist, queue* missingshqueue, int* worklist)
22835 {
22836 triface starttet, spintet, neightet, worktet;
22837 face startsh, neighsh, worksh, workseg;
22838 point torg, tdest, tapex, workpt[3];
22839 REAL checksign, orgori, destori;
22840 bool crossflag, inlistflag;
22841 bool belowflag, aboveflag;
22842 int idx, share;
22843 int i, j, k;
22844
22845
22846 startsh = * (face *)(* missingshlist)[0];
22847 torg = sorg(startsh);
22848 tdest = sdest(startsh);
22849 tapex = sapex(startsh);
22850
22851
22852 for (i = 0; i < crossedgelist->len(); i++) {
22853
22854 starttet = * (triface *)(* crossedgelist)[i];
22855 adjustedgering(starttet, CCW);
22856 if (b->verbose > 2) {
22857 printf(" Collect tets containing edge (%d, %d).\n",
22858 pointmark(org(starttet)), pointmark(dest(starttet)));
22859 }
22860 orgori = orient3d(torg, tdest, tapex, org(starttet));
22861 destori = orient3d(torg, tdest, tapex, dest(starttet));
22862 #ifdef SELF_CHECK
22863 assert(orgori * destori < 0.0);
22864 #endif
22865 spintet = starttet;
22866 do {
22867
22868 fnextself(spintet);
22869
22870 tspivot(spintet, worksh);
22871 if (worksh.sh != dummysh) {
22872 printf("Error: Invalid PLC.\n");
22873 printf(" Two subfaces (%d, %d, %d) and (%d, %d, %d)\n",
22874 pointmark(torg), pointmark(tdest), pointmark(tapex),
22875 pointmark(sorg(worksh)), pointmark(sdest(worksh)),
22876 pointmark(sapex(worksh)));
22877 printf(" are found intersecting each other.\n");
22878 printf(" Hint: Use -d switch to find all intersecting facets.\n");
22879 terminatetetgen(1);
22880 }
22881 if (!infected(spintet)) {
22882 if (b->verbose > 2) {
22883 printf(" Add crossing tet (%d, %d, %d, %d).\n",
22884 pointmark(org(spintet)), pointmark(dest(spintet)),
22885 pointmark(apex(spintet)), pointmark(oppo(spintet)));
22886 }
22887 infect(spintet);
22888 crosstetlist->append(&spintet);
22889 }
22890
22891
22892
22893 workpt[0] = apex(spintet);
22894 idx = pointmark(workpt[0]) - in->firstnumber;
22895 if (worklist[idx] != 1) {
22896
22897 checksign = orient3d(torg, tdest, tapex, workpt[0]);
22898 #ifdef SELF_CHECK
22899 assert(checksign != 0.0);
22900 #endif
22901 if (checksign * orgori < 0.0) {
22902 enext2(spintet, worktet);
22903 workpt[1] = org(spintet);
22904 } else {
22905
22906 assert(checksign * destori < 0.0);
22907
22908 enext(spintet, worktet);
22909 workpt[1] = dest(spintet);
22910 }
22911
22912
22913 inlistflag = false;
22914 for (j = 0; j < crossedgelist->len() && !inlistflag; j++) {
22915 neightet = * (triface *)(* crossedgelist)[j];
22916 if (org(neightet) == workpt[0]) {
22917 if (dest(neightet) == workpt[1]) inlistflag = true;
22918 } else if (org(neightet) == workpt[1]) {
22919 if (dest(neightet) == workpt[0]) inlistflag = true;
22920 }
22921 }
22922 if (!inlistflag) {
22923 crossedgelist->append(&worktet);
22924 }
22925 }
22926 } while (apex(spintet) != apex(starttet));
22927 }
22928
22929
22930
22931
22932 for (i = 0; i < crosstetlist->len(); i++) {
22933
22934 starttet = * (triface *)(* crosstetlist)[i];
22935 #ifdef SELF_CHECK
22936 assert(infected(starttet));
22937 #endif
22938 adjustedgering(starttet, CCW);
22939
22940
22941 for (j = 0; j < 2; j++) {
22942 if (j == 0) {
22943 enextfnext(starttet, worktet);
22944 } else {
22945 enext2fnext(starttet, worktet);
22946 }
22947 sym(worktet, neightet);
22948
22949
22950 if ((neightet.tet == dummytet) || !infected(neightet)) {
22951 workpt[0] = org(worktet);
22952 workpt[1] = dest(worktet);
22953 workpt[2] = apex(worktet);
22954 belowflag = aboveflag = false;
22955 share = 0;
22956 for (k = 0; k < 3; k++) {
22957 idx = pointmark(workpt[k]) - in->firstnumber;
22958 if (worklist[idx] == 0) {
22959
22960 checksign = orient3d(torg, tdest, tapex, workpt[k]);
22961 #ifdef SELF_CHECK
22962 assert(checksign != 0.0);
22963 #endif
22964 if (checksign > 0.0) {
22965
22966 worklist[idx] = 2;
22967 belowptlist->append(&workpt[k]);
22968 } else if (checksign < 0.0) {
22969
22970 worklist[idx] = 3;
22971 aboveptlist->append(&workpt[k]);
22972 }
22973 }
22974 if (worklist[idx] == 2) {
22975
22976 belowflag = true;
22977 } else if (worklist[idx] == 3) {
22978
22979 aboveflag = true;
22980 } else {
22981 #ifdef SELF_CHECK
22982
22983 assert(worklist[idx] == 1);
22984 #endif
22985 share++;
22986 }
22987 }
22988 #ifdef SELF_CHECK
22989
22990 assert(share < 3);
22991
22992 assert(belowflag ^ aboveflag);
22993 #endif
22994 if (belowflag) {
22995 belowfacelist->append(&worktet);
22996 } else if (aboveflag) {
22997 abovefacelist->append(&worktet);
22998 }
22999 }
23000 }
23001 }
23002
23003
23004
23005
23006 for (i = 0; i < missingshlist->len(); i++) {
23007 worksh = * (face *)(* missingshlist)[i];
23008 #ifdef SELF_CHECK
23009 assert(sinfected(worksh));
23010 #endif
23011 workpt[0] = sorg(worksh);
23012 workpt[1] = sdest(worksh);
23013 workpt[2] = sapex(worksh);
23014 crossflag = false;
23015 for (j = 0; j < crosstetlist->len() && !crossflag; j++) {
23016
23017 starttet = * (triface *)(* crosstetlist)[j];
23018 adjustedgering(starttet, CCW);
23019
23020 for (k = 0; k < 2 && !crossflag; k++) {
23021 if (k == 0) {
23022 worktet = starttet;
23023 } else {
23024 fnext(starttet, worktet);
23025 }
23026 crossflag = tritritest(&worktet, workpt[0], workpt[1], workpt[2]);
23027 }
23028 }
23029 if (crossflag) {
23030
23031 suninfect(worksh);
23032 crossshlist->append(&worksh);
23033
23034 for (k = 0; k < 3; k++) {
23035 idx = pointmark(workpt[k]) - in->firstnumber;
23036 if (worklist[idx] != 4) {
23037 worklist[idx] = 4;
23038 horizptlist->append(&workpt[k]);
23039 }
23040 }
23041 }
23042 }
23043
23044
23045 for (i = 0; i < crosstetlist->len(); i++) {
23046 starttet = * (triface *)(* crosstetlist)[i];
23047 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
23048 sym(starttet, neightet);
23049
23050 if ((neightet.tet != dummytet) && infected(neightet)) {
23051 tspivot(starttet, worksh);
23052 if (worksh.sh != dummysh) {
23053
23054 if (b->verbose > 2) {
23055 printf(" Queuing subface (%d, %d, %d).\n",
23056 pointmark(sorg(worksh)), pointmark(sdest(worksh)),
23057 pointmark(sapex(worksh)));
23058 }
23059 tsdissolve(neightet);
23060 tsdissolve(starttet);
23061
23062 stdissolve(worksh);
23063 sesymself(worksh);
23064 stdissolve(worksh);
23065 sinfect(worksh);
23066 missingshqueue->push(&worksh);
23067 }
23068 }
23069 }
23070 }
23071
23072
23073 for (i = 0; i < equatptlist->len(); i++) {
23074 workpt[0] = * (point *)(* equatptlist)[i];
23075 idx = pointmark(workpt[0]) - in->firstnumber;
23076 #ifdef SELF_CHECK
23077 assert((worklist[idx] == 1) || (worklist[idx] == 4));
23078 #endif
23079 worklist[idx] = 0;
23080 }
23081 for (i = 0; i < belowptlist->len(); i++) {
23082 workpt[0] = * (point *)(* belowptlist)[i];
23083 idx = pointmark(workpt[0]) - in->firstnumber;
23084 #ifdef SELF_CHECK
23085 assert(worklist[idx] == 2);
23086 #endif
23087 worklist[idx] = 0;
23088 }
23089 for (i = 0; i < aboveptlist->len(); i++) {
23090 workpt[0] = * (point *)(* aboveptlist)[i];
23091 idx = pointmark(workpt[0]) - in->firstnumber;
23092 #ifdef SELF_CHECK
23093 assert(worklist[idx] == 3);
23094 #endif
23095 worklist[idx] = 0;
23096 }
23097 }
23098
23100
23101
23102
23103
23104
23105
23106
23108
23109 void tetgenmesh::insertallsubfaces(queue* missingshqueue)
23110 {
23111 triface searchtet;
23112 face subloop;
23113
23114 searchtet.tet = (tetrahedron *) NULL;
23115 subfaces->traversalinit();
23116 subloop.sh = shellfacetraverse(subfaces);
23117 while (subloop.sh != (shellface *) NULL) {
23118 if (!insertsubface(&subloop, &searchtet)) {
23119 if (b->verbose > 1) {
23120 printf(" Queuing subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23121 pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23122 }
23123 sinfect(subloop);
23124 missingshqueue->push(&subloop);
23125 }
23126 subloop.sh = shellfacetraverse(subfaces);
23127 }
23128 }
23129
23131
23132
23133
23134
23135
23136
23137
23138
23139
23140
23141
23142
23143
23144
23145
23146
23147
23148
23149
23150
23151
23153
23154 void tetgenmesh::constrainedfacets()
23155 {
23156 queue *missingshqueue, *flipque;
23157 list *missingshlist, *equatptlist;
23158 list *boundedgelist, *crossedgelist, *crosstetlist;
23159 list *crossshlist, *belowfacelist, *abovefacelist;
23160 list *horizptlist, *belowptlist, *aboveptlist;
23161 list *frontlist, *misfrontlist, *newtetlist;
23162 triface searchtet, worktet;
23163 face subloop, worksh;
23164 int *worklist;
23165 int i;
23166
23167 if (!b->quiet) {
23168 printf("Constraining facets.\n");
23169 }
23170
23171
23172 missingshqueue = new queue(sizeof(face));
23173 flipque = new queue(sizeof(badface));
23174
23175 missingshlist = new list(sizeof(face), NULL);
23176 boundedgelist = new list(sizeof(face), NULL);
23177 crossedgelist = new list(sizeof(triface), NULL);
23178 equatptlist = new list((char*) "point *");
23179 crossshlist = new list(sizeof(face), NULL);
23180 crosstetlist = new list(sizeof(triface), NULL);
23181 belowfacelist = new list(sizeof(triface), NULL);
23182 abovefacelist = new list(sizeof(triface), NULL);
23183 horizptlist = new list((char*)"point *");
23184 belowptlist = new list((char*)"point *");
23185 aboveptlist = new list((char*)"point *");
23186 frontlist = new list(sizeof(triface), NULL);
23187 misfrontlist = new list(sizeof(triface), NULL);
23188 newtetlist = new list(sizeof(triface), NULL);
23189
23190 worklist = new int[points->items + 1];
23191 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
23192
23193
23194 makepoint2tetmap();
23195
23196
23197 insertallsubfaces(missingshqueue);
23198
23199
23200 while (!missingshqueue->empty()) {
23201
23202 subloop = * (face *) missingshqueue->pop();
23203
23204 if (isdead(&subloop)) continue;
23205
23206 if (!sinfected(subloop)) continue;
23207
23208 if (insertsubface(&subloop, &searchtet)) {
23209 suninfect(subloop);
23210 continue;
23211 }
23212 if (b->verbose > 1) {
23213 printf(" Recover subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23214 pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23215 }
23216
23217 formmissingregion(&subloop, missingshlist, equatptlist, worklist);
23218
23219 if (scoutcrossingedge(missingshlist, boundedgelist, crossedgelist,
23220 worklist)) {
23221
23222 formcavity(missingshlist, crossedgelist, equatptlist, crossshlist,
23223 crosstetlist, belowfacelist, abovefacelist, horizptlist,
23224 belowptlist, aboveptlist, missingshqueue, worklist);
23225
23226 delaunizecavity(crossshlist, abovefacelist, aboveptlist, horizptlist,
23227 frontlist, misfrontlist, newtetlist, crosstetlist,
23228 missingshqueue, flipque);
23229
23230 for (i = 0; i < crossshlist->len(); i++) {
23231 worksh = * (face *)(* crossshlist)[i];
23232 sesymself(worksh);
23233 * (face *)(* crossshlist)[i] = worksh;
23234 }
23235
23236 delaunizecavity(crossshlist, belowfacelist, belowptlist, horizptlist,
23237 frontlist, misfrontlist, newtetlist, crosstetlist,
23238 missingshqueue, flipque);
23239
23240 for (i = 0; i < crosstetlist->len(); i++) {
23241 worktet = * (triface *)(* crosstetlist)[i];
23242 tetrahedrondealloc(worktet.tet);
23243 }
23244
23245
23246 for (i = 0; i < missingshlist->len(); i++) {
23247 worksh = * (face *)(* missingshlist)[i];
23248 if (sinfected(worksh)) {
23249
23250 missingshqueue->push(&worksh);
23251 }
23252 }
23253 crossshlist->clear();
23254 belowfacelist->clear();
23255 abovefacelist->clear();
23256 horizptlist->clear();
23257 belowptlist->clear();
23258 aboveptlist->clear();
23259 crosstetlist->clear();
23260 } else {
23261
23262
23263 rearrangesubfaces(missingshlist, boundedgelist, equatptlist, worklist);
23264 }
23265
23266 missingshlist->clear();
23267 boundedgelist->clear();
23268 crossedgelist->clear();
23269 equatptlist->clear();
23270 }
23271
23272
23273 checksubfaces = 1;
23274
23275 if (b->verbose > 0) {
23276 printf(" The biggest cavity: %d faces, %d vertices\n", maxcavfaces,
23277 maxcavverts);
23278 printf(" Enlarged %d times\n", expcavcount);
23279 }
23280
23281 delete missingshqueue;
23282 delete flipque;
23283 delete missingshlist;
23284 delete boundedgelist;
23285 delete crossedgelist;
23286 delete equatptlist;
23287 delete crossshlist;
23288 delete crosstetlist;
23289 delete belowfacelist;
23290 delete abovefacelist;
23291 delete horizptlist;
23292 delete belowptlist;
23293 delete aboveptlist;
23294 delete frontlist;
23295 delete misfrontlist;
23296 delete newtetlist;
23297 delete [] worklist;
23298 }
23299
23300
23301
23302
23303
23304
23305
23306
23307
23309
23310
23311
23312
23313
23314
23315
23317
23318 void tetgenmesh::infecthull(memorypool *viri)
23319 {
23320 triface tetloop, tsymtet;
23321 tetrahedron **deadtet;
23322 face hullface;
23323
23324
23325 if (b->verbose > 0) {
23326 printf(" Marking concavities for elimination.\n");
23327 }
23328 tetrahedrons->traversalinit();
23329 tetloop.tet = tetrahedrontraverse();
23330 while (tetloop.tet != (tetrahedron *) NULL) {
23331
23332 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
23333 sym(tetloop, tsymtet);
23334 if (tsymtet.tet == dummytet) {
23335
23336 tspivot(tetloop, hullface);
23337 if (hullface.sh == dummysh) {
23338
23339 if (!infected(tetloop)) {
23340 infect(tetloop);
23341 deadtet = (tetrahedron **) viri->alloc();
23342 *deadtet = tetloop.tet;
23343 break;
23344 }
23345 } else {
23346
23347 if (shellmark(hullface) == 0) {
23348 setshellmark(hullface, 1);
23349
23350
23351
23352
23353
23354
23355
23356
23357
23358
23359
23360
23361
23362
23363 }
23364 }
23365 }
23366 }
23367 tetloop.tet = tetrahedrontraverse();
23368 }
23369 }
23370
23372
23373
23374
23375
23376
23377
23378
23379
23380
23382
23383 void tetgenmesh::plague(memorypool *viri)
23384 {
23385 tetrahedron **virusloop;
23386 tetrahedron **deadtet;
23387 triface testtet, neighbor;
23388 face neighsh, testseg;
23389 face spinsh, casingin, casingout;
23390 int firstdadsub;
23391 int i;
23392
23393 if (b->verbose > 0) {
23394 printf(" Marking neighbors of marked tetrahedra.\n");
23395 }
23396 firstdadsub = 0;
23397
23398
23399 viri->traversalinit();
23400 virusloop = (tetrahedron **) viri->traverse();
23401 while (virusloop != (tetrahedron **) NULL) {
23402 testtet.tet = *virusloop;
23403
23404 uninfect(testtet);
23405
23406 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23407
23408 sym(testtet, neighbor);
23409
23410 tspivot(testtet, neighsh);
23411
23412 if ((neighbor.tet == dummytet) || infected(neighbor)) {
23413 if (neighsh.sh != dummysh) {
23414
23415
23416
23417
23418 neighsh.shver = 0;
23419 if (!firstdadsub) {
23420 firstdadsub = 1;
23421 if (!b->quiet) {
23422 printf("Warning: Detecting an open face (%d, %d, %d).\n",
23423 pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
23424 pointmark(sapex(neighsh)));
23425 }
23426 }
23427
23428 findedge(&testtet, sorg(neighsh), sdest(neighsh));
23429 for (i = 0; i < 3; i++) {
23430 sspivot(neighsh, testseg);
23431 if (testseg.sh != dummysh) {
23432
23433
23434 testseg.shver = 0;
23435 spinsh = neighsh;
23436 if (sorg(spinsh) != sorg(testseg)) {
23437 sesymself(spinsh);
23438 }
23439 spivot(spinsh, casingout);
23440 if (casingout.sh == spinsh.sh) {
23441
23442
23443 shellfacedealloc(subsegs, testseg.sh);
23444 } else {
23445 spinsh = casingout;
23446 do {
23447 casingin = spinsh;
23448 spivotself(spinsh);
23449 } while (spinsh.sh != neighsh.sh);
23450
23451 sbond1(casingin, casingout);
23452
23453 ssbond(casingin, testseg);
23454 }
23455 }
23456 senextself(neighsh);
23457 enextself(testtet);
23458 }
23459 if (neighbor.tet != dummytet) {
23460
23461
23462 tsdissolve(neighbor);
23463 }
23464
23465 if (in->mesh_dim > 2) {
23466 shellfacedealloc(subfaces, neighsh.sh);
23467 } else {
23468
23469
23470 stdissolve(neighsh);
23471 sesymself(neighsh);
23472 stdissolve(neighsh);
23473 }
23474 }
23475 } else {
23476 if (neighsh.sh == dummysh) {
23477
23478 infect(neighbor);
23479
23480 deadtet = (tetrahedron **) viri->alloc();
23481 *deadtet = neighbor.tet;
23482 } else {
23483
23484 stdissolve(neighsh);
23485
23486 if (shellmark(neighsh) == 0) {
23487 setshellmark(neighsh, 1);
23488 }
23489
23490 dummytet[0] = encode(neighbor);
23491 }
23492 }
23493 }
23494
23495
23496 infect(testtet);
23497 virusloop = (tetrahedron **) viri->traverse();
23498 }
23499 }
23500
23502
23503
23504
23505
23506
23507
23508
23509
23511
23512 void tetgenmesh::
23513 regionplague(memorypool *regionviri, REAL attribute, REAL volume)
23514 {
23515 tetrahedron **virusloop;
23516 tetrahedron **regiontet;
23517 triface testtet, neighbor;
23518 face neighsh;
23519
23520 if (b->verbose > 1) {
23521 printf(" Marking neighbors of marked tetrahedra.\n");
23522 }
23523
23524
23525
23526 regionviri->traversalinit();
23527 virusloop = (tetrahedron **) regionviri->traverse();
23528 while (virusloop != (tetrahedron **) NULL) {
23529 testtet.tet = *virusloop;
23530
23531 uninfect(testtet);
23532 if (b->regionattrib) {
23533
23534 setelemattribute(testtet.tet, in->numberoftetrahedronattributes,
23535 attribute);
23536 }
23537 if (b->varvolume) {
23538
23539 setvolumebound(testtet.tet, volume);
23540 }
23541
23542 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23543
23544 sym(testtet, neighbor);
23545
23546 tspivot(testtet, neighsh);
23547
23548
23549
23550 if ((neighbor.tet != dummytet) && !infected(neighbor)
23551 && (neighsh.sh == dummysh)) {
23552
23553 infect(neighbor);
23554
23555 regiontet = (tetrahedron **) regionviri->alloc();
23556 *regiontet = neighbor.tet;
23557 }
23558 }
23559
23560
23561 infect(testtet);
23562 virusloop = (tetrahedron **) regionviri->traverse();
23563 }
23564
23565
23566 if (b->verbose > 1) {
23567 printf(" Unmarking marked tetrahedra.\n");
23568 }
23569 regionviri->traversalinit();
23570 virusloop = (tetrahedron **) regionviri->traverse();
23571 while (virusloop != (tetrahedron **) NULL) {
23572 testtet.tet = *virusloop;
23573 uninfect(testtet);
23574 virusloop = (tetrahedron **) regionviri->traverse();
23575 }
23576
23577 regionviri->restart();
23578 }
23579
23581
23582
23583
23585
23586 void tetgenmesh::removeholetets(memorypool* viri)
23587 {
23588 tetrahedron **virusloop;
23589 triface testtet, neighbor;
23590 point checkpt;
23591 int *tetspernodelist;
23592 int i, j;
23593
23594 if (b->verbose > 0) {
23595 printf(" Deleting marked tetrahedra.\n");
23596 }
23597
23598
23599 tetspernodelist = new int[points->items + 1];
23600 for (i = 0; i < points->items + 1; i++) tetspernodelist[i] = 0;
23601
23602
23603 tetrahedrons->traversalinit();
23604 testtet.tet = tetrahedrontraverse();
23605 while (testtet.tet != (tetrahedron *) NULL) {
23606
23607 for (i = 0; i < 4; i++) {
23608 j = pointmark((point) testtet.tet[4 + i]);
23609 tetspernodelist[j]++;
23610 }
23611 testtet.tet = tetrahedrontraverse();
23612 }
23613
23614 viri->traversalinit();
23615 virusloop = (tetrahedron **) viri->traverse();
23616 while (virusloop != (tetrahedron **) NULL) {
23617 testtet.tet = *virusloop;
23618
23619
23620 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23621 sym(testtet, neighbor);
23622 if (neighbor.tet == dummytet) {
23623
23624
23625
23626 hullsize--;
23627 } else {
23628
23629 dissolve(neighbor);
23630
23631
23632 hullsize++;
23633 }
23634 }
23635
23636 for (i = 0; i < 4; i++) {
23637 checkpt = (point) testtet.tet[4 + i];
23638 j = pointmark(checkpt);
23639 tetspernodelist[j]--;
23640 if (tetspernodelist[j] == 0) {
23641
23642 if ((pointtype(checkpt) == FREEVOLVERTEX) || !b->nojettison) {
23643 setpointtype(checkpt, UNUSEDVERTEX);
23644 unuverts++;
23645 }
23646 }
23647 }
23648
23649 tetrahedrondealloc(testtet.tet);
23650 virusloop = (tetrahedron **) viri->traverse();
23651 }
23652
23653 delete [] tetspernodelist;
23654 }
23655
23657
23658
23659
23660
23661
23662
23663
23664
23665
23667
23668 void tetgenmesh::assignregionattribs()
23669 {
23670 list *regionnumlist;
23671 list *regiontetlist;
23672 triface tetloop, regiontet, neightet;
23673 face checksh;
23674 bool flag;
23675 int regionnum, num;
23676 int attridx, count;
23677 int i;
23678
23679 if (b->verbose > 0) {
23680 printf(" Assign region numbers.\n");
23681 }
23682
23683 regionnumlist = new list(sizeof(int), NULL, 256);
23684 regiontetlist = new list(sizeof(triface), NULL, 1024);
23685 attridx = in->numberoftetrahedronattributes;
23686
23687
23688
23689 tetrahedrons->traversalinit();
23690 tetloop.tet = tetrahedrontraverse();
23691 while (tetloop.tet != (tetrahedron *) NULL) {
23692 if (!infected(tetloop)) {
23693 regionnum = (int) elemattribute(tetloop.tet, attridx);
23694 if (regionnum != 0.0) {
23695
23696 infect(tetloop);
23697 regiontetlist->append(&tetloop);
23698
23699 for (i = 0; i < regiontetlist->len(); i++) {
23700 regiontet = * (triface *)(* regiontetlist)[i];
23701 for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23702
23703 tspivot(regiontet, checksh);
23704 if (checksh.sh == dummysh) {
23705 sym(regiontet, neightet);
23706 if ((neightet.tet != dummytet) && !infected(neightet)) {
23707 #ifdef SELF_CHECK
23708
23709 num = (int) elemattribute(neightet.tet, attridx);
23710 assert(num == regionnum);
23711 #endif
23712 infect(neightet);
23713 regiontetlist->append(&neightet);
23714 }
23715 }
23716 }
23717 }
23718
23719 flag = false;
23720 for (i = 0; i < regionnumlist->len() && !flag; i++) {
23721 num = * (int *)(* regionnumlist)[i];
23722 flag = (num == regionnum);
23723 }
23724 if (!flag) regionnumlist->append(®ionnum);
23725
23726 regiontetlist->clear();
23727 }
23728 }
23729 tetloop.tet = tetrahedrontraverse();
23730 }
23731
23732 if (b->verbose > 0) {
23733 printf(" %d user-specified regions.\n", regionnumlist->len());
23734 }
23735
23736
23737 tetrahedrons->traversalinit();
23738 tetloop.tet = tetrahedrontraverse();
23739 regionnum = 1;
23740 count = 0;
23741 while (tetloop.tet != (tetrahedron *) NULL) {
23742 if (!infected(tetloop)) {
23743
23744 count++;
23745 do {
23746 flag = false;
23747
23748 for (i = 0; i < regionnumlist->len() && !flag; i++) {
23749 num = * (int *)(* regionnumlist)[i];
23750 flag = (num == regionnum);
23751 }
23752 if (flag) regionnum++;
23753 } while (flag);
23754 setelemattribute(tetloop.tet, attridx, (REAL) regionnum);
23755 infect(tetloop);
23756 regiontetlist->append(&tetloop);
23757
23758 for (i = 0; i < regiontetlist->len(); i++) {
23759 regiontet = * (triface *)(* regiontetlist)[i];
23760 for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23761
23762 tspivot(regiontet, checksh);
23763 if (checksh.sh == dummysh) {
23764 sym(regiontet, neightet);
23765 if ((neightet.tet != dummytet) && !infected(neightet)) {
23766 #ifdef SELF_CHECK
23767
23768 num = (int) elemattribute(neightet.tet, attridx);
23769 assert(num == 0);
23770 #endif
23771 setelemattribute(neightet.tet, attridx, (REAL) regionnum);
23772 infect(neightet);
23773 regiontetlist->append(&neightet);
23774 }
23775 }
23776 }
23777 }
23778 regiontetlist->clear();
23779 regionnum++;
23780 }
23781 tetloop.tet = tetrahedrontraverse();
23782 }
23783
23784
23785 tetrahedrons->traversalinit();
23786 tetloop.tet = tetrahedrontraverse();
23787 while (tetloop.tet != (tetrahedron *) NULL) {
23788 #ifdef SELF_CHECK
23789 assert(infected(tetloop));
23790 #endif
23791 uninfect(tetloop);
23792 tetloop.tet = tetrahedrontraverse();
23793 }
23794
23795 if (b->verbose > 0) {
23796 printf(" %d regions are numbered.\n", count);
23797 }
23798
23799 delete regionnumlist;
23800 delete regiontetlist;
23801 }
23802
23804
23805
23806
23807
23808
23809
23810
23811
23813
23814 void tetgenmesh::carveholes()
23815 {
23816 memorypool *holeviri, *regionviri;
23817 tetrahedron *tptr, **holetet, **regiontet;
23818 triface searchtet, *holetets, *regiontets;
23819 enum locateresult intersect;
23820 int i;
23821
23822 if (!b->quiet) {
23823 printf("Removing unwanted tetrahedra.\n");
23824 if (b->verbose && (in->numberofholes > 0)) {
23825 printf(" Marking holes for elimination.\n");
23826 }
23827 }
23828
23829
23830 holeviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23831
23832 infecthull(holeviri);
23833
23834 if (in->numberofholes > 0) {
23835
23836 holetets = (triface *) new triface[in->numberofholes];
23837
23838 for (i = 0; i < 3 * in->numberofholes; i += 3) {
23839
23840 if ((in->holelist[i] >= xmin) && (in->holelist[i] <= xmax)
23841 && (in->holelist[i + 1] >= ymin)
23842 && (in->holelist[i + 1] <= ymax)
23843 && (in->holelist[i + 2] >= zmin)
23844 && (in->holelist[i + 2] <= zmax)) {
23845 searchtet.tet = dummytet;
23846
23847 intersect = locate(&in->holelist[i], &searchtet);
23848 if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23849
23850 holetets[i / 3] = searchtet;
23851 }
23852 }
23853 }
23854
23855
23856 for (i = 0; i < in->numberofholes; i++) {
23857 infect(holetets[i]);
23858 holetet = (tetrahedron **) holeviri->alloc();
23859 *holetet = holetets[i].tet;
23860 }
23861
23862 delete [] holetets;
23863 }
23864
23865
23866 plague(holeviri);
23867
23868
23869
23870 if (b->regionattrib) {
23871
23872 tetrahedrons->traversalinit();
23873 tptr = tetrahedrontraverse();
23874 while (tptr != (tetrahedron *) NULL) {
23875 setelemattribute(tptr, in->numberoftetrahedronattributes, 0.0);
23876 tptr = tetrahedrontraverse();
23877 }
23878 }
23879
23880 if (in->numberofregions > 0) {
23881 if (!b->quiet) {
23882 if (b->regionattrib) {
23883 if (b->varvolume) {
23884 printf("Spreading regional attributes and volume constraints.\n");
23885 } else {
23886 printf("Spreading regional attributes.\n");
23887 }
23888 } else {
23889 printf("Spreading regional volume constraints.\n");
23890 }
23891 }
23892
23893 regiontets = (triface *) new triface[in->numberofregions];
23894
23895 for (i = 0; i < in->numberofregions; i++) {
23896 regiontets[i].tet = dummytet;
23897
23898 if ((in->regionlist[5 * i] >= xmin)
23899 && (in->regionlist[5 * i] <= xmax)
23900 && (in->regionlist[5 * i + 1] >= ymin)
23901 && (in->regionlist[5 * i + 1] <= ymax)
23902 && (in->regionlist[5 * i + 2] >= zmin)
23903 && (in->regionlist[5 * i + 2] <= zmax)) {
23904 searchtet.tet = dummytet;
23905
23906 intersect = locate(&in->regionlist[5 * i], &searchtet);
23907 if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23908
23909
23910 regiontets[i] = searchtet;
23911 }
23912 }
23913 }
23914
23915
23916 regionviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23917
23918 for (i = 0; i < in->numberofregions; i++) {
23919 if (regiontets[i].tet != dummytet) {
23920
23921
23922 if (!isdead(&(regiontets[i]))) {
23923
23924 infect(regiontets[i]);
23925 regiontet = (tetrahedron **) regionviri->alloc();
23926 *regiontet = regiontets[i].tet;
23927
23928 regionplague(regionviri, in->regionlist[5 * i + 3],
23929 in->regionlist[5 * i + 4]);
23930
23931 }
23932 }
23933 }
23934
23935 delete [] regiontets;
23936 delete regionviri;
23937 }
23938
23939
23940 removeholetets(holeviri);
23941
23942 nonconvex = 1;
23943
23944 if (b->regionattrib) {
23945 if (b->regionattrib > 1) {
23946
23947 assignregionattribs();
23948 }
23949
23950 in->numberoftetrahedronattributes++;
23951 }
23952
23953
23954 delete holeviri;
23955 }
23956
23957
23958
23959
23960
23961
23962
23963
23964
23966
23967
23968
23969
23970
23971
23972
23973
23974
23975
23977
23978 void tetgenmesh::replacepolygonsubs(list* oldshlist, list* newshlist)
23979 {
23980 face newsh, oldsh, spinsh;
23981 face casingout, casingin;
23982 face checkseg;
23983 point pa, pb;
23984 int i, j, k, l;
23985
23986 for (i = 0; i < newshlist->len(); i++) {
23987
23988 newsh = * (face *)(* newshlist)[i];
23989
23990 for (k = 0; k < 3; k++) {
23991 spivot(newsh, casingout);
23992
23993 if (casingout.sh == dummysh) {
23994
23995 pa = sorg(newsh);
23996 pb = sdest(newsh);
23997 for (j = 0; j < oldshlist->len(); j++) {
23998 oldsh = * (face *)(* oldshlist)[j];
23999 for (l = 0; l < 3; l++) {
24000 if (((sorg(oldsh) == pa) && (sdest(oldsh) == pb)) ||
24001 ((sorg(oldsh) == pb) && (sdest(oldsh) == pa))) break;
24002 senextself(oldsh);
24003 }
24004 if (l < 3) break;
24005 }
24006
24007 if (j < oldshlist->len()) {
24008
24009 spivot(oldsh, casingout);
24010 sspivot(oldsh, checkseg);
24011 if (checkseg.sh != dummysh) {
24012
24013 if (oldsh.sh != casingout.sh) {
24014
24015 spinsh = casingout;
24016 do {
24017 casingin = spinsh;
24018 spivotself(spinsh);
24019 } while (sapex(spinsh) != sapex(oldsh));
24020 assert(casingin.sh != oldsh.sh);
24021
24022 sbond1(casingin, newsh);
24023 sbond1(newsh, casingout);
24024 } else {
24025
24026 sbond(newsh, newsh);
24027 }
24028
24029 ssbond(newsh, checkseg);
24030 } else {
24031
24032 sbond(newsh, casingout);
24033 }
24034
24035
24036 sdissolve(oldsh);
24037 ssdissolve(oldsh);
24038 }
24039 }
24040
24041 senextself(newsh);
24042 }
24043 }
24044 }
24045
24047
24048
24049
24050
24051
24052
24053
24054
24056
24057 void tetgenmesh::orientnewsubs(list* newshlist, face* orientsh, REAL* norm)
24058 {
24059 face *newsh;
24060 point pa, pb, pc;
24061 REAL ref[3], ori, len;
24062 int i;
24063
24064
24065 pa = sorg(*orientsh);
24066 pb = sdest(*orientsh);
24067 pc = sapex(*orientsh);
24068 facenormal(pa, pb, pc, norm, &len);
24069 for (i = 0; i < 3; i++) ref[i] = pa[i] + norm[i];
24070 for (i = 0; i < 3; i++) norm[i] /= len;
24071
24072
24073 for (i = 0; i < newshlist->len(); i++) {
24074 newsh = (face *)(* newshlist)[i];
24075 pa = sorg(*newsh);
24076 pb = sdest(*newsh);
24077 pc = sapex(*newsh);
24078 ori = orient3d(pa, pb, pc, ref);
24079 assert(ori != 0.0);
24080 if (ori > 0.0) {
24081 sesymself(*newsh);
24082 }
24083 }
24084 }
24085
24087
24088
24089
24090
24091
24092
24093
24094
24095
24096
24097
24098
24099
24100
24101
24102
24103
24104
24106
24107 bool tetgenmesh::constrainedflip(triface* flipface, triface* front,
24108 queue* flipque)
24109 {
24110 triface symface, spintet;
24111 face checksh;
24112 point pa, pb, pc, pd, pe;
24113 enum fliptype fc;
24114 REAL sign;
24115 bool doflip;
24116 int ia, ib, ic, id, ie;
24117 int i;
24118
24119
24120 tspivot(*flipface, checksh);
24121 if (checksh.sh != dummysh) return false;
24122
24123 sym(*flipface, symface);
24124 if (symface.tet == dummytet) return false;
24125
24126 adjustedgering(*flipface, CCW);
24127 pa = dest(*flipface);
24128 pb = org(*flipface);
24129 pc = apex(*flipface);
24130 pd = oppo(*flipface);
24131 pe = oppo(symface);
24132
24133 ia = pointmark(pa);
24134 ib = pointmark(pb);
24135 ic = pointmark(pc);
24136 id = pointmark(pd);
24137 ie = pointmark(pe);
24138 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24139 assert(sign != 0.0);
24140
24141
24142
24143 if (sign <= 0.0) {
24144
24145 checksubfaces = 0;
24146 fc = categorizeface(*flipface);
24147 checksubfaces = 1;
24148 if (fc == T23) {
24149 doflip = true;
24150
24151
24152
24153
24154
24155
24156
24157
24158
24159
24160
24161
24162
24163 if (doflip) {
24164 flip23(flipface, flipque);
24165 return true;
24166 }
24167 } else if (fc == T32) {
24168
24169 doflip = true;
24170 spintet = *flipface;
24171 for (i = 0; i < 2; i++) {
24172 fnextself(spintet);
24173 tspivot(spintet, checksh);
24174 if (checksh.sh != dummysh) {
24175 doflip = false; break;
24176 }
24177 }
24178 if (doflip) {
24179 flip32(flipface, flipque);
24180 return true;
24181 }
24182 } else if (fc == T22 || fc == T44) {
24183
24184 doflip = true;
24185 if (fc == T22) {
24186 for (i = 0; i < 2; i++) {
24187 spintet = *flipface;
24188 if (i == 1) {
24189 esymself(spintet);
24190 }
24191 fnextself(spintet);
24192 tspivot(spintet, checksh);
24193 if (checksh.sh != dummysh) {
24194 doflip = false; break;
24195 }
24196 }
24197 } else if (fc == T44) {
24198 spintet = *flipface;
24199 for (i = 0; i < 3; i++) {
24200 fnextself(spintet);
24201 tspivot(spintet, checksh);
24202 if (checksh.sh != dummysh) {
24203 doflip = false; break;
24204 }
24205 }
24206 }
24207 if (doflip) {
24208 flip22(flipface, flipque);
24209 return true;
24210 }
24211 } else if (fc == N32) {
24212
24213 if (front != (triface *) NULL) {
24214
24215 spintet = *flipface;
24216 while (fnextself(spintet)) {
24217 if (apex(spintet) == apex(*flipface)) break;
24218
24219 if (constrainedflip(&spintet, NULL, flipque)) {
24220
24221 return true;
24222 }
24223
24224 findedge(&spintet, org(*flipface), dest(*flipface));
24225 }
24226 }
24227 }
24228 }
24229
24230
24231 if (front != (triface *) NULL) {
24232
24233 pa = org(*front);
24234 pb = dest(*front);
24235 pc = apex(*front);
24236
24237
24238 if (oppo(symface) != pc) {
24239 adjustedgering(symface, CCW);
24240 for (i = 0; i < 3; i++) {
24241 fnext(symface, spintet);
24242
24243 sign = orient3d(org(spintet), dest(spintet), apex(spintet), pc);
24244 if (sign < 0.0) {
24245 if (tritritest(&spintet, pa, pb, pc)) {
24246 if (b->verbose > 2) {
24247 printf(" Next crossface (%d, %d, %d).\n",
24248 pointmark(org(spintet)), pointmark(dest(spintet)),
24249 pointmark(apex(spintet)));
24250 }
24251 return constrainedflip(&spintet, front, flipque);
24252
24253 }
24254 }
24255 enextself(symface);
24256 }
24257 }
24258 }
24259 return false;
24260 }
24261
24263
24264
24265
24266
24267
24268
24270
24271 bool tetgenmesh::recoverfront(triface* front, list* newtetlist, queue* flipque)
24272 {
24273 triface idfront, starttet, spintet;
24274 point pa, pb, pc, pd, ref;
24275 enum locateresult loc;
24276 enum finddirectionresult col;
24277 REAL ori, ori1, ori2, sign;
24278 int hitbdry;
24279 int i, j;
24280
24281
24282 for (i = 0; i < 3; i++) {
24283 pa = org(*front);
24284 pb = dest(*front);
24285
24286 idfront = recenttet;
24287
24288 if (isdead(&idfront)) {
24289
24290 for (j = 0; j < newtetlist->len(); j++) {
24291 recenttet = * (triface *)(* newtetlist)[j];
24292 if (!isdead(&recenttet)) break;
24293 }
24294 assert(j < newtetlist->len());
24295 }
24296 loc = preciselocate(pa, &idfront, (long) newtetlist->len());
24297 if (loc != ONVERTEX) {
24298
24299 for (j = 0; j < newtetlist->len(); j++) {
24300 idfront = * (triface *)(* newtetlist)[j];
24301 if (isdead(&idfront)) continue;
24302 if (findorg(&idfront, pa)) break;
24303 }
24304 assert(j < newtetlist->len());
24305 }
24306 recenttet = idfront;
24307
24308 col = finddirection(&idfront, pb, (long) newtetlist->len());
24309 if (col == BELOWHULL) {
24310
24311 for (j = 0; j < newtetlist->len(); j++) {
24312 idfront = * (triface *)(* newtetlist)[j];
24313 if (isdead(&idfront)) continue;
24314 if (findorg(&idfront, pa)) {
24315 assert(org(idfront) == pa);
24316 if (dest(idfront) == pb) {
24317 col = RIGHTCOLLINEAR; break;
24318 } else if (apex(idfront) == pb) {
24319 col = LEFTCOLLINEAR; break;
24320 } else if (oppo(idfront) == pb) {
24321 col = TOPCOLLINEAR; break;
24322 }
24323 }
24324 }
24325 }
24326 if (col == RIGHTCOLLINEAR) {
24327
24328 } else if (col == LEFTCOLLINEAR) {
24329 enext2self(idfront);
24330 esymself(idfront);
24331 } else if (col == TOPCOLLINEAR) {
24332 fnextself(idfront);
24333 enext2self(idfront);
24334 esymself(idfront);
24335 }
24336 if (dest(idfront) == pb) break;
24337
24338 enextself(*front);
24339 }
24340 if (i == 3) {
24341
24342 return false;
24343 }
24344
24345
24346 pc = apex(*front);
24347 spintet = idfront;
24348 hitbdry = 0;
24349 do {
24350 if (apex(spintet) == pc) {
24351
24352 insertauxsubface(front, &spintet);
24353 return true;
24354 }
24355 if (!fnextself(spintet)) {
24356 hitbdry ++;
24357 if (hitbdry < 2) {
24358 esym(idfront, spintet);
24359 if (!fnextself(spintet)) {
24360 hitbdry ++;
24361 }
24362 }
24363 }
24364 if (apex(spintet) == apex(idfront)) break;
24365 } while (hitbdry < 2);
24366
24367
24368 pd = apex(idfront);
24369 assert(pd != pc);
24370
24371 ori = orient3d(pa, pb, pc, pd);
24372 if (ori < 0.0) {
24373
24374 esym(idfront, starttet);
24375 sign = -1.0;
24376 } else if (ori > 0.0) {
24377
24378 starttet = idfront;
24379 sign = 1.0;
24380 } else {
24381 assert(ori == 0.0);
24382
24383 ref = oppo(idfront);
24384 ori1 = orient3d(pa, pb, ref, pc);
24385 ori2 = orient3d(pa, pb, ref, pd);
24386 assert(ori1 * ori2 != 0.0);
24387 if (ori1 * ori2 > 0) {
24388
24389
24390 ori1 = orient3d(pb, pc, ref, pd);
24391 ori2 = orient3d(pb, pc, ref, pa);
24392 assert(ori1 * ori2 != 0.0);
24393 if (ori1 * ori2 > 0) {
24394
24395 enextself(idfront);
24396 } else {
24397
24398 enext2self(idfront);
24399 }
24400 adjustedgering(idfront, CCW);
24401 fnextself(idfront);
24402 if (b->verbose > 2) {
24403 printf(" Get crossface (%d, %d, %d).\n", pointmark(org(idfront)),
24404 pointmark(dest(idfront)), pointmark(apex(idfront)));
24405 }
24406 if (constrainedflip(&idfront, front, flipque)) {
24407
24408 return recoverfront(front, newtetlist, flipque);
24409 }
24410
24411 return false;
24412 } else {
24413
24414 starttet = idfront;
24415 if (fnextself(starttet)) {
24416
24417 sign = 1.0;
24418 } else {
24419
24420 esym(idfront, starttet);
24421 sign = -1.0;
24422 }
24423 }
24424 }
24425
24426 assert(sign != 0.0);
24427 if (sign == -1) {
24428
24429 pa = org(starttet);
24430 pb = dest(starttet);
24431
24432 sign = -sign;
24433 }
24434
24435
24436 spintet = starttet;
24437 while (fnextself(spintet)) {
24438 pd = apex(spintet);
24439 assert(pd != pc);
24440
24441 ori = orient3d(pa, pb, pc, pd);
24442 if (ori == 0.0) {
24443
24444 ref = oppo(spintet);
24445 ori1 = orient3d(pb, pc, ref, pd);
24446 ori2 = orient3d(pb, pc, ref, pa);
24447 assert(ori1 * ori2 != 0.0);
24448 if (ori1 * ori2 > 0) {
24449
24450 enextself(spintet);
24451 } else {
24452
24453 enext2self(spintet);
24454 }
24455 adjustedgering(spintet, CCW);
24456 fnextself(spintet);
24457 if (b->verbose > 2) {
24458 printf(" Get crossface (%d, %d, %d).\n", pointmark(org(spintet)),
24459 pointmark(dest(spintet)), pointmark(apex(spintet)));
24460 }
24461 if (constrainedflip(&spintet, front, flipque)) {
24462
24463 return recoverfront(front, newtetlist, flipque);
24464 }
24465
24466 return false;
24467 } else if (ori * sign < 0.0) {
24468
24469 adjustedgering(spintet, CCW);
24470 enextself(spintet);
24471 for (i = 0; i < 2; i++) {
24472
24473 fnext(spintet, starttet);
24474 if (tritritest(&starttet, pa, pb, pc)) {
24475 if (b->verbose > 2) {
24476 printf(" Get crossface (%d, %d, %d).\n",
24477 pointmark(org(starttet)), pointmark(dest(starttet)),
24478 pointmark(apex(starttet)));
24479 }
24480 if (constrainedflip(&starttet, front, flipque)) {
24481
24482 return recoverfront(front, newtetlist, flipque);
24483 }
24484 }
24485 enextself(spintet);
24486 }
24487
24488 return false;
24489 }
24490 }
24491
24492 assert(0);
24493 return false;
24494 }
24495
24497
24498
24499
24501
24502 void tetgenmesh::repairflips(queue* flipque)
24503 {
24504 badface *qface;
24505 triface flipface, symface, spintet;
24506 face checksh;
24507 point pa, pb, pc, pd, pe;
24508 enum fliptype fc;
24509 REAL sign;
24510 long flipcount;
24511 bool doflip;
24512 int ia, ib, ic, id, ie;
24513 int i;
24514
24515 if (b->verbose > 1) {
24516 printf(" Repair flip %ld faces.\n", flipque->len());
24517 }
24518 flipcount = flip23s + flip32s + flip22s + flip44s;
24519
24520 while (!flipque->empty()) {
24521 qface = (badface *) flipque->pop();
24522 flipface = qface->tt;
24523
24524 if (isdead(&flipface) || flipface.tet == dummytet ||
24525 (org(flipface) != qface->forg) ||
24526 (dest(flipface) != qface->fdest) ||
24527 (apex(flipface) != qface->fapex) ||
24528 (oppo(flipface) == (point) NULL)) continue;
24529
24530 tspivot(flipface, checksh);
24531 if (checksh.sh != dummysh) continue;
24532
24533 sym(flipface, symface);
24534 if (symface.tet == dummytet) continue;
24535
24536 adjustedgering(flipface, CW);
24537 pa = org(flipface);
24538 pb = dest(flipface);
24539 pc = apex(flipface);
24540 pd = oppo(flipface);
24541 pe = oppo(symface);
24542
24543 ia = pointmark(pa);
24544 ib = pointmark(pb);
24545 ic = pointmark(pc);
24546 id = pointmark(pd);
24547 ie = pointmark(pe);
24548 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24549 assert(sign != 0.0);
24550
24551
24552
24553 if (sign > 0.0) {
24554
24555 checksubfaces = 0;
24556 fc = categorizeface(flipface);
24557 checksubfaces = 1;
24558 if (fc == T23) {
24559 doflip = true;
24560
24561
24562
24563
24564
24565
24566
24567
24568
24569
24570
24571
24572
24573 if (doflip) {
24574 flip23(&flipface, flipque);
24575 }
24576 } else if (fc == T32) {
24577
24578 doflip = true;
24579 spintet = flipface;
24580 for (i = 0; i < 2; i++) {
24581 fnextself(spintet);
24582 tspivot(spintet, checksh);
24583 if (checksh.sh != dummysh) {
24584 doflip = false; break;
24585 }
24586 }
24587 if (doflip) {
24588 flip32(&flipface, flipque);
24589 }
24590 } else if (fc == T22 || fc == T44) {
24591
24592 doflip = true;
24593 if (fc == T22) {
24594 for (i = 0; i < 2; i++) {
24595 spintet = flipface;
24596 if (i == 1) {
24597 esymself(spintet);
24598 }
24599 fnextself(spintet);
24600 tspivot(spintet, checksh);
24601 if (checksh.sh != dummysh) {
24602 doflip = false; break;
24603 }
24604 }
24605 } else if (fc == T44) {
24606 spintet = flipface;
24607 for (i = 0; i < 3; i++) {
24608 fnextself(spintet);
24609 tspivot(spintet, checksh);
24610 if (checksh.sh != dummysh) {
24611 doflip = false; break;
24612 }
24613 }
24614 }
24615 if (doflip) {
24616 flip22(&flipface, flipque);
24617 }
24618 }
24619 }
24620 }
24621 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
24622 if (b->verbose > 1) {
24623 printf(" %ld flips.\n", flipcount);
24624 }
24625 }
24626
24628
24629
24630
24631
24632
24633
24635
24636 bool tetgenmesh::constrainedcavity(triface* oldtet, list* floorlist,
24637 list* ceillist, list* ptlist, list* frontlist, list* misfrontlist,
24638 list* newtetlist, queue* flipque)
24639 {
24640 triface misfront, newtet;
24641 long facenum;
24642 int i;
24643
24644 if (b->verbose > 1) {
24645 printf(" Constrained cavity (%d floors, %d ceilings, %d vertices).\n",
24646 floorlist->len(), ceillist->len(), ptlist->len());
24647 }
24648
24649
24650
24651
24652 initializecavity(floorlist, ceillist, frontlist);
24653
24654 delaunizecavvertices(oldtet, ptlist, NULL, newtetlist, flipque);
24655
24656
24657 if (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
24658
24659 recenttet = * (triface *)(* newtetlist)[0];
24660 assert((recenttet.tet != dummytet) && !isdead(&recenttet));
24661
24662 do {
24663 facenum = misfrontlist->len();
24664 for (i = 0; i < misfrontlist->len(); i++) {
24665
24666 misfront = * (triface *)(* misfrontlist)[i];
24667
24668 adjustedgering(misfront, CW);
24669 if (b->verbose > 1) {
24670 printf(" Recover face (%d, %d, %d).\n", pointmark(org(misfront)),
24671 pointmark(dest(misfront)), pointmark(apex(misfront)));
24672 }
24673 if (recoverfront(&misfront, newtetlist, flipque)) {
24674
24675 frontlist->append(&misfront);
24676 misfrontlist->del(i, 0); i--;
24677 }
24678
24679 repairflips(flipque);
24680 }
24681
24682 if (misfrontlist->len() == 0) break;
24683
24684
24685 } while (misfrontlist->len() < facenum);
24686
24687 retrievenewtets(newtetlist);
24688 }
24689
24690
24691
24692 if (misfrontlist->len() == 0) {
24693
24694
24695
24696 carvecavity(newtetlist, misfrontlist, NULL);
24697
24698
24699 return true;
24700 } else {
24701
24702
24703 detachauxsubfaces(newtetlist);
24704
24705 for (i = 0; i < newtetlist->len(); i++) {
24706 newtet = * (triface *)(* newtetlist)[i];
24707 assert(!isdead(&newtet));
24708 tetrahedrondealloc(newtet.tet);
24709 }
24710 newtetlist->clear();
24711
24712 for (i = 0; i < misfrontlist->len(); i++) {
24713 misfront = * (triface *)(* misfrontlist)[i];
24714 frontlist->append(&misfront);
24715 }
24716 return false;
24717 }
24718 }
24719
24721
24722
24723
24724
24725
24726
24728
24729 void tetgenmesh::expandsteinercavity(point steinpt, REAL eps, list* frontlist,
24730 list* oldtetlist)
24731 {
24732 triface front, symfront, newfront, oldfront;
24733 face frontsh;
24734 point pa, pb, pc;
24735 REAL ori;
24736 bool expflag, newflag;
24737 int i, j;
24738
24739 do {
24740 expflag = false;
24741 for (i = 0; i < frontlist->len(); i++) {
24742
24743 front = * (triface *)(* frontlist)[i];
24744
24745 tspivot(front, frontsh);
24746 if (frontsh.sh == dummysh) {
24747
24748 adjustedgering(front, CW);
24749 pa = org(front);
24750 pb = dest(front);
24751 pc = apex(front);
24752 ori = orient3d(pa, pb, pc, steinpt);
24753 if (ori != 0.0) {
24754 if (iscoplanar(pa, pb, pc, steinpt, ori, eps)) {
24755 ori = 0.0;
24756 }
24757 }
24758 if (ori >= 0.0) {
24759
24760 if (b->verbose > 2) {
24761 printf(" Remove front (%d, %d, %d).\n", pointmark(pa),
24762 pointmark(pb), pointmark(pc));
24763 }
24764 frontlist->del(i, 1);
24765 expflag = true;
24766 break;
24767 }
24768 }
24769 }
24770 if (expflag) {
24771 assert(!infected(front) && (oppo(front) != NULL));
24772
24773 adjustedgering(front, CCW);
24774 for (i = 0; i < 3; i++) {
24775 newflag = true;
24776
24777 fnext(front, symfront);
24778 tspivot(symfront, frontsh);
24779 sym(symfront, newfront);
24780 if (frontsh.sh == dummysh) {
24781 assert(newfront.tet != dummytet);
24782
24783 if (infected(newfront)) {
24784 for (j = 0; j < frontlist->len(); j++) {
24785 oldfront = * (triface *)(* frontlist)[j];
24786 if ((oldfront.tet == symfront.tet) &&
24787 (oldfront.loc == symfront.loc)) {
24788
24789 if (b->verbose > 2) {
24790 printf(" Remove front (%d, %d, %d).\n",
24791 pointmark(org(oldfront)), pointmark(dest(oldfront)),
24792 pointmark(apex(oldfront)));
24793 }
24794 frontlist->del(j, 1);
24795 newflag = false;
24796 break;
24797 }
24798 }
24799 }
24800 } else {
24801
24802 if (newfront.tet == dummytet) {
24803 sesymself(frontsh);
24804
24805 maketetrahedron(&newfront);
24806 setorg(newfront, sorg(frontsh));
24807 setdest(newfront, sdest(frontsh));
24808 setapex(newfront, sapex(frontsh));
24809 setoppo(newfront, (point) NULL);
24810 tsbond(newfront, frontsh);
24811 } else {
24812
24813 assert(!infected(newfront));
24814 }
24815 }
24816 if (newflag) {
24817 if (b->verbose > 2) {
24818 printf(" Add front (%d, %d, %d).\n", pointmark(org(newfront)),
24819 pointmark(dest(newfront)), pointmark(apex(newfront)));
24820 }
24821 frontlist->append(&newfront);
24822 }
24823 enextself(front);
24824 }
24825
24826 infect(front);
24827 oldtetlist->append(&front);
24828 expcavcount++;
24829 }
24830 } while (expflag);
24831 }
24832
24834
24835
24836
24837
24838
24839
24841
24842 bool tetgenmesh::findrelocatepoint(point sp, point np, REAL* n,
24843 list* frontlist, list* oldtetlist)
24844 {
24845 triface front;
24846 point pa, pb, pc;
24847 REAL tp[3], tvol, mvol;
24848 REAL ori, eps;
24849 bool visible;
24850 int i, j, k;
24851
24852 if (b->verbose > 1) {
24853 printf(" Find new location for point %d.\n", pointmark(sp));
24854 }
24855
24856
24857 tvol = mvol = 0.0;
24858 visible = false;
24859
24860 eps = b->epsilon;
24861
24862 for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24863
24864 for (i = 0; i < 3; i++) tp[i] = np[i];
24865
24866 j = 0;
24867 do {
24868 for (i = 0; i < frontlist->len(); i++) {
24869
24870 front = * (triface *)(* frontlist)[i];
24871
24872 adjustedgering(front, CW);
24873 pa = org(front);
24874 pb = dest(front);
24875 pc = apex(front);
24876 ori = orient3d(pa, pb, pc, np);
24877 visible = (ori < 0.0);
24878 if (!visible) {
24879
24880 for (i = 0; i < 3; i++) np[i] = sp[i] + 0.5 * (sp[i] - np[i]);
24881
24882 if ((tp[0] == np[0]) && (tp[1] == np[1]) && (tp[2] == np[2])) {
24883
24884 expandsteinercavity(sp, eps, frontlist, oldtetlist);
24885 eps *= 10.0;
24886 if (eps > b->epsilon * 1000.0) {
24887
24888
24889 return false;
24890 }
24891
24892 for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24893 }
24894 if (j % 2) {
24895
24896 for (i = 0; i < 3; i++) tp[i] = np[i];
24897 }
24898 break;
24899 } else {
24900
24901 if (i == 0) {
24902 mvol = fabs(ori);
24903 } else {
24904 mvol = fabs(ori) < mvol ? fabs(ori) : mvol;
24905 }
24906 }
24907 }
24908 j++;
24909 } while (!visible);
24910
24911 if (b->verbose > 1) {
24912 printf(" %d iterations. minvol = %.12g.\n", j, mvol);
24913 }
24914
24915
24916
24917 k = 0;
24918 do {
24919 j = 0;
24920 do {
24921 if (k == 0) {
24922
24923 for (i = 0; i < 3; i++) tp[i] = sp[i] + 0.9 * (np[i] - sp[i]);
24924 } else {
24925
24926 for (i = 0; i < 3; i++) tp[i] = sp[i] + 1.1 * (np[i] - sp[i]);
24927 }
24928
24929 for (i = 0; i < frontlist->len(); i++) {
24930
24931 front = * (triface *)(* frontlist)[i];
24932
24933 adjustedgering(front, CW);
24934 pa = org(front);
24935 pb = dest(front);
24936 pc = apex(front);
24937 ori = orient3d(pa, pb, pc, tp);
24938 visible = (ori < 0.0);
24939 if (visible) {
24940
24941 if (i == 0) {
24942 tvol = fabs(ori);
24943 } else {
24944 tvol = fabs(ori) < tvol ? fabs(ori) : tvol;
24945 }
24946 } else {
24947
24948 tvol = 0.0;
24949 break;
24950 }
24951 }
24952 if (tvol > mvol) {
24953
24954 for (i = 0; i < 3; i++) np[i] = tp[i];
24955 mvol = tvol;
24956 } else {
24957
24958 break;
24959 }
24960
24961 j++;
24962 } while (true);
24963
24964 if (j > 0) break;
24965
24966 k++;
24967 } while (k < 2);
24968
24969 if (b->verbose > 1) {
24970 printf(" %d adjust iterations. minvol = %.12g.\n", j, mvol);
24971 }
24972 return true;
24973 }
24974
24976
24977
24978
24979
24980
24981
24982
24984
24985 void tetgenmesh::relocatepoint(point steinpt, triface* oldtet, list* frontlist,
24986 list* newtetlist, queue* flipque)
24987 {
24988 triface front, newtet, newface, neightet;
24989 face checksh;
24990 point pa, pb;
24991 REAL attrib, volume;
24992 bool bdflag;
24993 int i, j, k, l;
24994
24995 if (b->verbose > 1) {
24996 printf(" Insert Steiner point (%.12g, %.12g, %.12g) %d.\n",
24997 steinpt[0], steinpt[1], steinpt[2], pointmark(steinpt));
24998 }
24999
25000 newtetlist->clear();
25001
25002
25003 for (i = 0; i < frontlist->len(); i++) {
25004
25005 front = * (triface *)(* frontlist)[i];
25006
25007 adjustedgering(front, CW);
25008 if (b->verbose > 2) {
25009 printf(" Get front (%d, %d, %d).\n", pointmark(org(front)),
25010 pointmark(dest(front)), pointmark(apex(front)));
25011 }
25012 maketetrahedron(&newtet);
25013 newtetlist->append(&newtet);
25014 setorg(newtet, org(front));
25015 setdest(newtet, dest(front));
25016 setapex(newtet, apex(front));
25017 setoppo(newtet, steinpt);
25018 if (oldtet != (triface *) NULL) {
25019 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
25020 attrib = elemattribute(oldtet->tet, j);
25021 setelemattribute(newtet.tet, j, attrib);
25022 }
25023 if (b->varvolume) {
25024 volume = volumebound(oldtet->tet);
25025 setvolumebound(newtet.tet, volume);
25026 }
25027 }
25028
25029 tspivot(front, checksh);
25030 if (oppo(front) == (point) NULL) {
25031 if (checksh.sh != dummysh) {
25032 stdissolve(checksh);
25033 }
25034
25035 tetrahedrondealloc(front.tet);
25036
25037
25038
25039 dummytet[0] = encode(newtet);
25040 } else {
25041
25042 bond(newtet, front);
25043 }
25044 if (checksh.sh != dummysh) {
25045 sesymself(checksh);
25046 tsbond(newtet, checksh);
25047 }
25048 if (flipque != (queue *) NULL) {
25049
25050 enqueueflipface(newtet, flipque);
25051 }
25052
25053 }
25054
25055
25056 for (i = 0; i < newtetlist->len(); i++) {
25057 newtet = * (triface *)(* newtetlist)[i];
25058 newtet.ver = 0;
25059 for (j = 0; j < 3; j++) {
25060 fnext(newtet, newface);
25061 sym(newface, neightet);
25062 if (neightet.tet == dummytet) {
25063
25064 bdflag = false;
25065 pa = org(newface);
25066 pb = dest(newface);
25067 assert(apex(newface) == steinpt);
25068 for (k = i + 1; k < newtetlist->len() && !bdflag; k++) {
25069 neightet = * (triface *)(* newtetlist)[k];
25070 neightet.ver = 0;
25071 for (l = 0; l < 3; l++) {
25072 if ((org(neightet) == pa && dest(neightet) == pb) ||
25073 (org(neightet) == pb && dest(neightet) == pa)) {
25074
25075 fnextself(neightet);
25076 assert(apex(neightet) == steinpt);
25077
25078 bond(newface, neightet);
25079 bdflag = true;
25080 break;
25081 }
25082 enextself(neightet);
25083 }
25084 }
25085 assert(bdflag);
25086 }
25087 enextself(newtet);
25088 }
25089
25090 pa = org(newtet);
25091 setpoint2tet(pa, encode(newtet));
25092 pa = dest(newtet);
25093 setpoint2tet(pa, encode(newtet));
25094 pa = apex(newtet);
25095 setpoint2tet(pa, encode(newtet));
25096 pa = oppo(newtet);
25097 setpoint2tet(pa, encode(newtet));
25098 }
25099
25100 if (flipque != (queue *) NULL) {
25101
25102 flip(flipque, NULL);
25103 }
25104 }
25105
25107
25108
25109
25111
25112 bool tetgenmesh::findcollapseedge(point suppt, point *conpt, list* oldtetlist,
25113 list* ptlist)
25114 {
25115 triface front;
25116 point pt, pa, pb, pc;
25117 REAL *lenarray, ltmp, ori;
25118 bool visflag;
25119 int *idxarray, itmp;
25120 int n, i, j;
25121
25122 if (b->verbose > 2) {
25123 printf(" Search an edge (in %d edges) for collapse %d.\n",
25124 ptlist->len(), pointmark(suppt));
25125 }
25126
25127
25128 n = ptlist->len();
25129 lenarray = new REAL[n];
25130 idxarray = new int[n];
25131
25132 for (i = 0; i < n; i++) {
25133 pt = * (point *)(* ptlist)[i];
25134 lenarray[i] = distance(suppt, pt);
25135 idxarray[i] = i;
25136 }
25137
25138 for (i = 0; i < n - 1; i++) {
25139 for (j = 0; j < n - 1 - i; j++) {
25140 if (lenarray[j + 1] < lenarray[j]) {
25141 ltmp = lenarray[j];
25142 lenarray[j] = lenarray[j + 1];
25143 lenarray[j + 1] = ltmp;
25144 itmp = idxarray[j];
25145 idxarray[j] = idxarray[j + 1];
25146 idxarray[j + 1] = itmp;
25147 }
25148 }
25149 }
25150
25151 for (i = 0; i < n; i++) {
25152 pt = * (point *)(* ptlist)[idxarray[i]];
25153
25154 lenarray[i] = 0.0;
25155 visflag = true;
25156 for (j = 0; j < oldtetlist->len() && visflag; j++) {
25157 front = * (triface *)(* oldtetlist)[j];
25158
25159 adjustedgering(front, CCW);
25160 pa = org(front);
25161 pb = dest(front);
25162 pc = apex(front);
25163
25164 if ((pa != pt) && (pb != pt) && (pc != pt)) {
25165 ori = orient3d(pa, pb, pc, pt);
25166 if (ori != 0.0) {
25167 if (iscoplanar(pa, pb, pc, pt, ori, b->epsilon * 1e+2)) ori = 0.0;
25168 }
25169 visflag = ori < 0.0;
25170 if (visflag) {
25171
25172 if (j == 0) {
25173 lenarray[i] = fabs(ori);
25174 } else {
25175 lenarray[i] = fabs(ori) < lenarray[i] ? fabs(ori) : lenarray[i];
25176 }
25177 } else {
25178
25179 lenarray[i] = 0.0;
25180 }
25181 }
25182 }
25183 if ((b->verbose > 2) && visflag) {
25184 printf(" Got candidate %d vol(%g).\n", pointmark(pt), lenarray[i]);
25185 }
25186 }
25187
25188
25189 ltmp = lenarray[0];
25190 itmp = idxarray[0];
25191 for (i = 1; i < n; i++) {
25192 if (lenarray[i] != 0.0) {
25193 if (lenarray[i] > ltmp) {
25194 ltmp = lenarray[i];
25195 itmp = idxarray[i];
25196 }
25197 }
25198 }
25199
25200 delete [] lenarray;
25201 delete [] idxarray;
25202
25203 if (ltmp == 0.0) {
25204
25205 *conpt = (point) NULL;
25206 return false;
25207 } else {
25208 pt = * (point *)(* ptlist)[itmp];
25209 *conpt = pt;
25210 return true;
25211 }
25212 }
25213
25215
25216
25217
25219
25220 void tetgenmesh::collapseedge(point suppt, point conpt, list* oldtetlist,
25221 list* deadtetlist)
25222 {
25223 triface oldtet, deadtet;
25224 triface adjtet1, adjtet2;
25225 face adjsh;
25226 point pa, pb, pc;
25227 int i, j;
25228
25229 if (b->verbose > 2) {
25230 printf(" Collapse edge (%d,%d).\n", pointmark(suppt), pointmark(conpt));
25231 }
25232
25233
25234 for (i = 0; i < oldtetlist->len(); i++) {
25235 oldtet = * (triface *)(* oldtetlist)[i];
25236 uninfect(oldtet);
25237 pa = org(oldtet);
25238 pb = dest(oldtet);
25239 pc = apex(oldtet);
25240 assert(oppo(oldtet) == suppt);
25241 setoppo(oldtet, conpt);
25242 if ((pa == conpt) || (pb == conpt) || (pc == conpt)) {
25243 deadtetlist->append(&oldtet);
25244 }
25245 }
25246
25247 for (i = 0; i < deadtetlist->len(); i++) {
25248 deadtet = * (triface *)(* deadtetlist)[i];
25249
25250 sym(deadtet, adjtet1);
25251 tspivot(deadtet, adjsh);
25252
25253 adjustedgering(deadtet, CCW);
25254 for (j = 0; j < 3; j++) {
25255 if (apex(deadtet) == conpt) break;
25256 enextself(deadtet);
25257 }
25258 assert(j < 3);
25259
25260 fnext(deadtet, adjtet2);
25261 symself(adjtet2);
25262 assert(adjtet2.tet != dummytet);
25263 if (adjtet1.tet != dummytet) {
25264 bond(adjtet1, adjtet2);
25265 } else {
25266 dissolve(adjtet2);
25267 dummytet[0] = encode(adjtet2);
25268 }
25269 if (adjsh.sh != dummysh) {
25270 tsbond(adjtet2, adjsh);
25271 }
25272
25273 tetrahedrondealloc(deadtet.tet);
25274 }
25275 deadtetlist->clear();
25276 }
25277
25279
25280
25281
25282
25283
25284
25285
25287
25288 void tetgenmesh::deallocfaketets(list* frontlist)
25289 {
25290 triface front, neightet;
25291 face checksh;
25292 bool infectflag;
25293 int i;
25294
25295 for (i = 0; i < frontlist->len(); i++) {
25296
25297 front = * (triface *)(* frontlist)[i];
25298
25299 adjustedgering(front, CW);
25300 sym(front, neightet);
25301 tspivot(front, checksh);
25302 if (oppo(front) == (point) NULL) {
25303 if (b->verbose > 2) {
25304 printf(" Get fake tet (%d, %d, %d).\n", pointmark(org(front)),
25305 pointmark(dest(front)), pointmark(apex(front)));
25306 }
25307 if (neightet.tet != dummytet) {
25308
25309
25310 infectflag = infected(neightet);
25311 dissolve(neightet);
25312 if (infectflag) {
25313 infect(neightet);
25314 }
25315 }
25316 if (checksh.sh != dummysh) {
25317 infectflag = sinfected(checksh);
25318 stdissolve(checksh);
25319 if (infectflag) {
25320 sinfect(checksh);
25321 }
25322 }
25323
25324 tetrahedrondealloc(front.tet);
25325
25326
25327
25328 if (neightet.tet != dummytet) {
25329 dummytet[0] = encode(neightet);
25330 }
25331 }
25332 }
25333 }
25334
25336
25337
25338
25339
25340
25341
25342
25343
25344
25345
25346
25348
25349 void tetgenmesh::restorepolyhedron(list* oldtetlist)
25350 {
25351 triface oldtet, neightet, neineitet;
25352 face checksh;
25353 int i;
25354
25355 for (i = 0; i < oldtetlist->len(); i++) {
25356
25357 oldtet = * (triface *)(* oldtetlist)[i];
25358
25359 for (oldtet.loc = 0; oldtet.loc < 4; oldtet.loc++) {
25360 sym(oldtet, neightet);
25361 tspivot(oldtet, checksh);
25362 if (neightet.tet != dummytet) {
25363 sym(neightet, neineitet);
25364 if (neineitet.tet != oldtet.tet) {
25365
25366 bond(neightet, oldtet);
25367 if (checksh.sh != dummysh) {
25368 tsbond(oldtet, checksh);
25369 }
25370 }
25371 } else {
25372
25373 #ifdef SELF_CHECK
25374 assert(checksh.sh != dummysh);
25375 stpivot(checksh, neineitet);
25376 assert(neineitet.tet != oldtet.tet);
25377 #endif
25378 tsbond(oldtet, checksh);
25379
25380 dummytet[0] = encode(oldtet);
25381 }
25382 }
25383 }
25384 }
25385
25387
25388
25389
25390
25391
25392
25393
25394
25395
25396
25397
25398
25400
25401 bool tetgenmesh::suppressfacetpoint(face* supsh, list* frontlist,
25402 list* misfrontlist, list* ptlist, list* conlist, memorypool* viri,
25403 queue* flipque, bool noreloc, bool optflag)
25404 {
25405 list *oldtetlist[2], *newtetlist[2];
25406 list *oldshlist, *newshlist;
25407 triface oldtet, newtet;
25408 face oldsh, newsh;
25409 point suppt, newpt[2];
25410 point *cons;
25411 REAL norm[3];
25412 bool success;
25413 int shmark;
25414 int i, j;
25415
25416 suppt = sapex(*supsh);
25417 if (b->verbose > 1) {
25418 printf(" Suppress point %d in facet.\n", pointmark(suppt));
25419 }
25420
25421
25422 for (i = 0; i < 2; i++) {
25423 oldtetlist[i] = (list *) NULL;
25424 newtetlist[i] = (list *) NULL;
25425 newpt[i] = (point) NULL;
25426 }
25427 oldshlist = new list(sizeof(face), NULL, 256);
25428 newshlist = new list(sizeof(face), NULL, 256);
25429 success = true;
25430
25431
25432 oldshlist->append(supsh);
25433 formstarpolygon(suppt, oldshlist, ptlist);
25434
25435 for (i = 0; i < oldshlist->len(); i++) {
25436 oldsh = * (face *)(* oldshlist)[i];
25437 cons = (point *) conlist->append(NULL);
25438 cons[0] = sorg(oldsh);
25439 cons[1] = sdest(oldsh);
25440 }
25441
25442 shmark = shellmark(*supsh);
25443 triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25444
25445 retrievenewsubs(newshlist, true);
25446
25447 replacepolygonsubs(oldshlist, newshlist);
25448
25449 ptlist->clear();
25450 conlist->clear();
25451 flipque->clear();
25452 viri->restart();
25453
25454
25455
25456 for (i = 0; i < 2 && success; i++) {
25457 if (i == 1) sesymself(*supsh);
25458
25459 stpivot(*supsh, oldtet);
25460
25461 if (oldtet.tet == dummytet) continue;
25462
25463 oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25464 newtetlist[i] = new list(sizeof(triface), NULL, 256);
25465
25466 assert(!isdead(&oldtet));
25467 oldtetlist[i]->append(&oldtet);
25468 formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25469
25470 for (j = 0; j < oldtetlist[i]->len(); j++) {
25471 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25472 infect(oldtet);
25473 }
25474
25475 orientnewsubs(newshlist, supsh, norm);
25476
25477 success = constrainedcavity(&oldtet, newshlist, oldtetlist[i], ptlist,
25478 frontlist, misfrontlist, newtetlist[i], flipque);
25479
25480 if (!success && !noreloc) {
25481
25482 makepoint(&(newpt[i]));
25483 success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25484 oldtetlist[i]);
25485
25486
25487
25488 if (success) {
25489
25490
25491 relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25492 setpointtype(newpt[i], FREEVOLVERTEX);
25493 relverts++;
25494 } else {
25495
25496 deallocfaketets(frontlist);
25497 pointdealloc(newpt[i]);
25498 newpt[i] = (point) NULL;
25499 assert(newtetlist[i]->len() == 0);
25500 }
25501 }
25502 if (!success && noreloc) {
25503
25504 deallocfaketets(frontlist);
25505 }
25506
25507 ptlist->clear();
25508 frontlist->clear();
25509 misfrontlist->clear();
25510 flipque->clear();
25511 }
25512
25513 if (success) {
25514
25515 setpointtype(suppt, UNUSEDVERTEX);
25516 unuverts++;
25517
25518 for (i = 0; i < oldshlist->len(); i++) {
25519 oldsh = * (face *)(* oldshlist)[i];
25520 if (i == 0) {
25521
25522 stpivot(oldsh, oldtet);
25523 if (oldtet.tet != dummytet) {
25524 sesymself(oldsh);
25525 stpivot(oldsh, oldtet);
25526 }
25527 if (oldtet.tet == dummytet) {
25528
25529 j = oldshlist->len() - newshlist->len();
25530 assert(j > 0);
25531 hullsize -= j;
25532 }
25533 }
25534 shellfacedealloc(subfaces, oldsh.sh);
25535 }
25536
25537 for (i = 0; i < 2; i++) {
25538 if (oldtetlist[i] != (list *) NULL) {
25539
25540 for (j = 0; j < oldtetlist[i]->len(); j++) {
25541 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25542 assert(!isdead(&oldtet));
25543 tetrahedrondealloc(oldtet.tet);
25544 }
25545 }
25546 }
25547 if (optflag) {
25548
25549 for (i = 0; i < 2; i++) {
25550 if (newtetlist[i] != (list *) NULL) {
25551 for (j = 0; j < newtetlist[i]->len(); j++) {
25552 newtet = * (triface *)(* (newtetlist[i]))[j];
25553 if (!isdead(&newtet)) checktet4opt(&newtet, true);
25554 }
25555 }
25556 }
25557 }
25558 } else {
25559
25560 unsupverts++;
25561
25562 replacepolygonsubs(newshlist, oldshlist);
25563
25564 for (i = 0; i < newshlist->len(); i++) {
25565 newsh = * (face *)(* newshlist)[i];
25566 shellfacedealloc(subfaces, newsh.sh);
25567 }
25568
25569 for (i = 0; i < 2; i++) {
25570 if (oldtetlist[i] != (list *) NULL) {
25571
25572 for (j = 0; j < oldtetlist[i]->len(); j++) {
25573 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25574 assert(infected(oldtet));
25575 uninfect(oldtet);
25576 }
25577
25578 if (newtetlist[i]->len() > 0) {
25579
25580 restorepolyhedron(oldtetlist[i]);
25581
25582 for (j = 0; j < newtetlist[i]->len(); j++) {
25583 newtet = * (triface *)(* (newtetlist[i]))[j];
25584
25585 if (!isdead(&newtet)) {
25586 tetrahedrondealloc(newtet.tet);
25587 }
25588 }
25589 }
25590
25591 if (newpt[i] != (point) NULL) {
25592 pointdealloc(newpt[i]);
25593 relverts--;
25594 }
25595 }
25596 }
25597 }
25598
25599
25600 delete oldshlist;
25601 delete newshlist;
25602 for (i = 0; i < 2; i++) {
25603 if (oldtetlist[i] != (list *) NULL) {
25604 delete oldtetlist[i];
25605 delete newtetlist[i];
25606 }
25607 }
25608
25609 return success;
25610 }
25611
25613
25614
25615
25616
25617
25618
25619
25620
25621
25623
25624 bool tetgenmesh::suppresssegpoint(face* supseg, list* spinshlist,
25625 list* newsegshlist, list* frontlist, list* misfrontlist, list* ptlist,
25626 list* conlist, memorypool* viri, queue* flipque, bool noreloc, bool optflag)
25627 {
25628 list **oldtetlist, **newtetlist;
25629 list **oldshlist, **newshlist;
25630 list *pnewshlist, *dnewshlist;
25631 triface oldtet, newtet;
25632 face oldsh, newsh;
25633 face startsh, spinsh, segsh1, segsh2;
25634 face nsupseg, newseg, prevseg, nextseg;
25635 point suppt, *newpt;
25636 point pa, pb, *cons;
25637 REAL pnorm[2][3], norm[3];
25638 bool success;
25639 int shmark;
25640 int n, i, j, k;
25641
25642
25643 assert(supseg->shver < 2);
25644 suppt = sdest(*supseg);
25645
25646 senext(*supseg, nsupseg);
25647 spivotself(nsupseg);
25648 assert(nsupseg.sh != dummysh);
25649 nsupseg.shver = 0;
25650 if (sorg(nsupseg) != suppt) sesymself(nsupseg);
25651 assert(sorg(nsupseg) == suppt);
25652 pa = sorg(*supseg);
25653 pb = sdest(nsupseg);
25654 if (b->verbose > 1) {
25655 printf(" Remove point %d on segment (%d, %d).\n",
25656 pointmark(suppt), pointmark(pa), pointmark(pb));
25657 }
25658
25659
25660 spivot(*supseg, startsh);
25661 spinsh = startsh;
25662 do {
25663
25664 spinshlist->append(&spinsh);
25665
25666 spivotself(spinsh);
25667 } while (spinsh.sh != startsh.sh);
25668 if (spinshlist->len() == 1) {
25669
25670
25671 spinshlist->clear();
25672 unsupverts++;
25673 return false;
25674 }
25675
25676
25677
25678 n = spinshlist->len();
25679 oldtetlist = new list*[n];
25680 newtetlist = new list*[n];
25681 oldshlist = new list*[n];
25682 newshlist = new list*[n];
25683 newpt = new point[n];
25684 for (i = 0; i < n; i++) {
25685 oldtetlist[i] = (list *) NULL;
25686 newtetlist[i] = (list *) NULL;
25687 oldshlist[i] = (list *) NULL;
25688 newshlist[i] = (list *) NULL;
25689 newpt[i] = (point) NULL;
25690 }
25691
25692
25693 makeshellface(subsegs, &newseg);
25694 setsorg(newseg, pa);
25695 setsdest(newseg, pb);
25696
25697 setshellmark(newseg, shellmark(*supseg));
25698 setshelltype(newseg, shelltype(*supseg));
25699 if (b->quality && varconstraint) {
25700
25701 setareabound(newseg, areabound(*supseg));
25702 }
25703
25704 senext2(*supseg, prevseg);
25705 spivotself(prevseg);
25706 if (prevseg.sh != dummysh) {
25707 prevseg.shver = 0;
25708 if (sdest(prevseg) != pa) sesymself(prevseg);
25709 assert(sdest(prevseg) == pa);
25710 senextself(prevseg);
25711 senext2self(newseg);
25712 sbond(newseg, prevseg);
25713 newseg.shver = 0;
25714 }
25715
25716 senext(nsupseg, nextseg);
25717 spivotself(nextseg);
25718 if (nextseg.sh != dummysh) {
25719 nextseg.shver = 0;
25720 if (sorg(nextseg) != pb) sesymself(nextseg);
25721 assert(sorg(nextseg) == pb);
25722 senext2self(nextseg);
25723 senextself(newseg);
25724 sbond(newseg, nextseg);
25725 newseg.shver = 0;
25726 }
25727
25728
25729 for (i = 0; i < spinshlist->len(); i++) {
25730 spinsh = * (face *)(* spinshlist)[i];
25731
25732 oldshlist[i] = new list(sizeof(face), NULL, 256);
25733 newshlist[i] = new list(sizeof(face), NULL, 256);
25734
25735 oldshlist[i]->append(&spinsh);
25736 formstarpolygon(suppt, oldshlist[i], ptlist);
25737
25738 for (j = 0; j < oldshlist[i]->len(); j++) {
25739 oldsh = * (face *)(* (oldshlist[i]))[j];
25740 cons = (point *) conlist->append(NULL);
25741 cons[0] = sorg(oldsh);
25742 cons[1] = sdest(oldsh);
25743 }
25744
25745 cons = (point *) conlist->append(NULL);
25746 cons[0] = pa;
25747 cons[1] = pb;
25748
25749 shmark = shellmark(spinsh);
25750 triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25751
25752 retrievenewsubs(newshlist[i], true);
25753
25754 replacepolygonsubs(oldshlist[i], newshlist[i]);
25755
25756 for (j = 0; j < newshlist[i]->len(); j++) {
25757 segsh1 = * (face *)(* (newshlist[i]))[j];
25758 for (k = 0; k < 3; k++) {
25759 if (((sorg(segsh1) == pa) && (sdest(segsh1) == pb)) ||
25760 ((sorg(segsh1) == pb) && (sdest(segsh1) == pa))) break;
25761 senextself(segsh1);
25762 }
25763 if (k < 3) break;
25764 }
25765 assert(j < newshlist[i]->len());
25766
25767 ssbond(segsh1, newseg);
25768
25769 newsegshlist->append(&segsh1);
25770
25771 ptlist->clear();
25772 conlist->clear();
25773 flipque->clear();
25774 viri->restart();
25775 }
25776
25777 for (i = 0; i < newsegshlist->len(); i++) {
25778 segsh1 = * (face *)(* newsegshlist)[i];
25779 if ((i + 1) == newsegshlist->len()) {
25780 segsh2 = * (face *)(* newsegshlist)[0];
25781 } else {
25782 segsh2 = * (face *)(* newsegshlist)[i + 1];
25783 }
25784 sbond1(segsh1, segsh2);
25785 }
25786
25787
25788 dnewshlist = new list(sizeof(face), NULL, 256);
25789 success = true;
25790
25791
25792 for (i = 0; i < spinshlist->len() && success; i++) {
25793
25794 spinsh = * (face *)(* spinshlist)[i];
25795
25796
25797 if (sorg(spinsh) != pa) sesymself(spinsh);
25798
25799 stpivot(spinsh, oldtet);
25800
25801 if (oldtet.tet == dummytet) continue;
25802
25803 oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25804 newtetlist[i] = new list(sizeof(triface), NULL, 256);
25805
25806 oldtetlist[i]->append(&oldtet);
25807 formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25808
25809 for (j = 0; j < oldtetlist[i]->len(); j++) {
25810 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25811 infect(oldtet);
25812 }
25813
25814 for (k = 0; k < 2; k++) {
25815 if ((i + k) < spinshlist->len()) {
25816 pnewshlist = newshlist[i + k];
25817 segsh1 = * (face *)(* spinshlist)[i + k];
25818 } else {
25819 pnewshlist = newshlist[0];
25820 segsh1 = * (face *)(* spinshlist)[0];
25821 }
25822
25823 if (k == 0) {
25824 if (sorg(segsh1) != pa) sesymself(segsh1);
25825 assert(sorg(segsh1) == pa);
25826 } else {
25827 if (sdest(segsh1) != pa) sesymself(segsh1);
25828 assert(sdest(segsh1) == pa);
25829 }
25830
25831 orientnewsubs(pnewshlist, &segsh1, pnorm[k]);
25832 for (j = 0; j < pnewshlist->len(); j++) {
25833 dnewshlist->append((face *)(* pnewshlist)[j]);
25834 }
25835 }
25836
25837 success = constrainedcavity(&oldtet, dnewshlist, oldtetlist[i], ptlist,
25838 frontlist, misfrontlist, newtetlist[i], flipque);
25839 if (!success && !noreloc) {
25840
25841 makepoint(&(newpt[i]));
25842 for (j = 0; j < 3; j++) norm[j] = 0.5 * (pnorm[0][j] + pnorm[1][j]);
25843 success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25844 oldtetlist[i]);
25845
25846
25847 if (success) {
25848
25849
25850 relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25851 setpointtype(newpt[i], FREEVOLVERTEX);
25852 relverts++;
25853 } else {
25854
25855 deallocfaketets(frontlist);
25856 pointdealloc(newpt[i]);
25857 newpt[i] = (point) NULL;
25858 assert(newtetlist[i]->len() == 0);
25859 }
25860 }
25861 if (!success && noreloc) {
25862
25863 deallocfaketets(frontlist);
25864 }
25865
25866 dnewshlist->clear();
25867 ptlist->clear();
25868 frontlist->clear();
25869 misfrontlist->clear();
25870 flipque->clear();
25871 }
25872
25873 if (success) {
25874
25875 setpointtype(suppt, UNUSEDVERTEX);
25876 unuverts++;
25877
25878 setpoint2sh(pa, sencode(newseg));
25879 setpoint2sh(pb, sencode(newseg));
25880
25881 shellfacedealloc(subsegs, supseg->sh);
25882 shellfacedealloc(subsegs, nsupseg.sh);
25883
25884 for (i = 0; i < spinshlist->len(); i++) {
25885 for (j = 0; j < oldshlist[i]->len(); j++) {
25886 oldsh = * (face *)(* (oldshlist[i]))[j];
25887 if (j == 0) {
25888
25889 stpivot(oldsh, oldtet);
25890 if (oldtet.tet != dummytet) {
25891 sesymself(oldsh);
25892 stpivot(oldsh, oldtet);
25893 }
25894 if (oldtet.tet == dummytet) {
25895
25896 k = oldshlist[i]->len() - newshlist[i]->len();
25897 assert(k > 0);
25898 hullsize -= k;
25899 }
25900 }
25901 shellfacedealloc(subfaces, oldsh.sh);
25902 }
25903 }
25904
25905 for (i = 0; i < spinshlist->len(); i++) {
25906
25907 if (oldtetlist[i] != (list *) NULL) {
25908 for (j = 0; j < oldtetlist[i]->len(); j++) {
25909 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25910 assert(!isdead(&oldtet));
25911 tetrahedrondealloc(oldtet.tet);
25912 }
25913 }
25914 }
25915 if (optflag) {
25916 for (i = 0; i < spinshlist->len(); i++) {
25917
25918 if (newtetlist[i] != (list *) NULL) {
25919 for (j = 0; j < newtetlist[i]->len(); j++) {
25920 newtet = * (triface *)(* (newtetlist[i]))[j];
25921 if (!isdead(&newtet)) checktet4opt(&newtet, true);
25922 }
25923 }
25924 }
25925 }
25926 } else {
25927
25928 unsupverts++;
25929
25930 senext2(*supseg, prevseg);
25931 spivotself(prevseg);
25932 if (prevseg.sh != dummysh) {
25933 prevseg.shver = 0;
25934 if (sdest(prevseg) != pa) sesymself(prevseg);
25935 assert(sdest(prevseg) == pa);
25936 senextself(prevseg);
25937 senext2self(*supseg);
25938 sbond(*supseg, prevseg);
25939 senextself(*supseg);
25940 assert(supseg->shver < 2);
25941 }
25942
25943 senext(nsupseg, nextseg);
25944 spivotself(nextseg);
25945 if (nextseg.sh != dummysh) {
25946 nextseg.shver = 0;
25947 if (sorg(nextseg) != pb) sesymself(nextseg);
25948 assert(sorg(nextseg) == pb);
25949 senext2self(nextseg);
25950 senextself(nsupseg);
25951 sbond(nsupseg, nextseg);
25952
25953 senext2self(nsupseg);
25954 assert(nsupseg.shver < 2);
25955 }
25956
25957 shellfacedealloc(subsegs, newseg.sh);
25958
25959 for (i = 0; i < spinshlist->len(); i++) {
25960 replacepolygonsubs(newshlist[i], oldshlist[i]);
25961
25962 for (j = 0; j < newshlist[i]->len(); j++) {
25963 newsh = * (face *)(* (newshlist[i]))[j];
25964 shellfacedealloc(subfaces, newsh.sh);
25965 }
25966 }
25967
25968 for (i = 0; i < spinshlist->len(); i++) {
25969 if (oldtetlist[i] != (list *) NULL) {
25970
25971 for (j = 0; j < oldtetlist[i]->len(); j++) {
25972 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25973 assert(infected(oldtet));
25974 uninfect(oldtet);
25975 }
25976
25977 if (newtetlist[i]->len() > 0) {
25978
25979 restorepolyhedron(oldtetlist[i]);
25980
25981 for (j = 0; j < newtetlist[i]->len(); j++) {
25982 newtet = * (triface *)(* (newtetlist[i]))[j];
25983
25984 if (!isdead(&newtet)) {
25985 tetrahedrondealloc(newtet.tet);
25986 }
25987 }
25988 }
25989
25990 if (newpt[i] != (point) NULL) {
25991 pointdealloc(newpt[i]);
25992 relverts--;
25993 }
25994 }
25995 }
25996 }
25997
25998
25999 delete dnewshlist;
26000 for (i = 0; i < spinshlist->len(); i++) {
26001 delete oldshlist[i];
26002 delete newshlist[i];
26003 }
26004 delete [] oldshlist;
26005 delete [] newshlist;
26006 for (i = 0; i < spinshlist->len(); i++) {
26007 if (oldtetlist[i] != (list *) NULL) {
26008 delete oldtetlist[i];
26009 delete newtetlist[i];
26010 }
26011 }
26012 delete [] oldtetlist;
26013 delete [] newtetlist;
26014
26015 newsegshlist->clear();
26016 spinshlist->clear();
26017
26018 return success;
26019 }
26020
26022
26023
26024
26025
26026
26027
26028
26029
26030
26032
26033 bool tetgenmesh::suppressvolpoint(triface* suptet, list* frontlist,
26034 list* misfrontlist, list* ptlist, queue* flipque, bool optflag)
26035 {
26036 list *myfrontlist, *mymisfrontlist, *myptlist;
26037 list *oldtetlist, *newtetlist;
26038 list *newshlist;
26039 queue *myflipque;
26040 triface oldtet, newtet;
26041 point suppt, conpt;
26042 bool success;
26043 int j;
26044
26045
26046 oldtetlist = new list(sizeof(triface), NULL, 256);
26047 newtetlist = new list(sizeof(triface), NULL, 256);
26048 newshlist = new list(sizeof(face), NULL, 256);
26049
26050 myfrontlist = mymisfrontlist = myptlist = (list *) NULL;
26051 myflipque = (queue *) NULL;
26052 if (frontlist == (list *) NULL) {
26053 myfrontlist = new list(sizeof(triface), NULL, 256);
26054 frontlist = myfrontlist;
26055 mymisfrontlist = new list(sizeof(triface), NULL, 256);
26056 misfrontlist = mymisfrontlist;
26057 myptlist = new list(sizeof(point *), NULL, 256);
26058 ptlist = myptlist;
26059 myflipque = new queue(sizeof(badface));
26060 flipque = myflipque;
26061 }
26062
26063 suppt = org(*suptet);
26064 oldtet = *suptet;
26065 success = true;
26066
26067 if (b->verbose > 1) {
26068 printf(" Remove point %d in mesh.\n", pointmark(suppt));
26069 }
26070
26071
26072 oldtetlist->append(&oldtet);
26073 formstarpolyhedron(suppt, oldtetlist, ptlist, false);
26074
26075 for (j = 0; j < oldtetlist->len(); j++) {
26076 oldtet = * (triface *)(* oldtetlist)[j];
26077 infect(oldtet);
26078 }
26079
26080 success = constrainedcavity(&oldtet, newshlist, oldtetlist, ptlist,
26081 frontlist, misfrontlist, newtetlist, flipque);
26082 if (!success) {
26083
26084 deallocfaketets(frontlist);
26085
26086 conpt = (point) NULL;
26087 assert(newtetlist->len() == 0);
26088 if (findcollapseedge(suppt, &conpt, oldtetlist, ptlist)) {
26089
26090 collapseedge(suppt, conpt, oldtetlist, newtetlist);
26091
26092 if (optflag) {
26093 assert(newtetlist->len() == 0);
26094 for (j = 0; j < oldtetlist->len(); j++) {
26095 newtet = * (triface *)(* oldtetlist)[j];
26096 newtetlist->append(&newtet);
26097 }
26098 }
26099 oldtetlist->clear();
26100 collapverts++;
26101 success = true;
26102 }
26103 }
26104 if (success) {
26105
26106 setpointtype(suppt, UNUSEDVERTEX);
26107 unuverts++;
26108 suprelverts++;
26109
26110 for (j = 0; j < oldtetlist->len(); j++) {
26111 oldtet = * (triface *)(* oldtetlist)[j];
26112 assert(!isdead(&oldtet));
26113 tetrahedrondealloc(oldtet.tet);
26114 }
26115 if (optflag) {
26116
26117 for (j = 0; j < newtetlist->len(); j++) {
26118 newtet = * (triface *)(* newtetlist)[j];
26119 if (!isdead(&newtet)) checktet4opt(&newtet, true);
26120 }
26121 }
26122 } else {
26123
26124
26125 for (j = 0; j < oldtetlist->len(); j++) {
26126 oldtet = * (triface *)(* oldtetlist)[j];
26127 assert(infected(oldtet));
26128 uninfect(oldtet);
26129 }
26130 }
26131
26132
26133 ptlist->clear();
26134 frontlist->clear();
26135 misfrontlist->clear();
26136 flipque->clear();
26137
26138 if (myfrontlist != (list *) NULL) {
26139 delete myfrontlist;
26140 delete mymisfrontlist;
26141 delete myptlist;
26142 delete myflipque;
26143 }
26144 delete oldtetlist;
26145 delete newtetlist;
26146 delete newshlist;
26147
26148 return success;
26149 }
26150
26152
26153
26154
26155
26156
26157
26158
26159
26160
26161
26162
26163
26164
26165
26167
26168 bool tetgenmesh::smoothpoint(point smthpt, point e1, point e2, list *starlist,
26169 bool invtori, REAL *key)
26170 {
26171 triface starttet;
26172 point pa, pb, pc;
26173 REAL fcent[3], startpt[3], nextpt[3], bestpt[3];
26174 REAL iniTmax, oldTmax, newTmax;
26175 REAL ori, aspT, aspTmax, imprate;
26176 REAL cosd, maxcosd;
26177 bool segflag, randflag;
26178 int numdirs;
26179 int iter, i, j;
26180
26181
26182 segflag = (e1 != (point) NULL);
26183
26184 numdirs = segflag ? 2 : starlist->len();
26185 randflag = numdirs > 10;
26186 if (randflag) {
26187 numdirs = 10;
26188 }
26189
26190 aspTmax = 0.0;
26191
26192 for (i = 0; i < starlist->len(); i++) {
26193 starttet = * (triface *)(* starlist)[i];
26194 adjustedgering(starttet, !invtori ? CCW : CW);
26195 pa = org(starttet);
26196 pb = dest(starttet);
26197 pc = apex(starttet);
26198 aspT = tetaspectratio(pa, pb, pc, smthpt);
26199 if (i == 0) {
26200 aspTmax = aspT;
26201 } else {
26202 aspTmax = aspT > aspTmax ? aspT : aspTmax;
26203 }
26204 }
26205 iniTmax = aspTmax;
26206
26207 if (b->verbose > 1) {
26208 printf(" Smooth %s point %d (%g, %g, %g).\n", segflag ? "seg" : "vol",
26209 pointmark(smthpt), smthpt[0], smthpt[1], smthpt[2]);
26210 printf(" Initial max L/h = %g.\n", iniTmax);
26211 }
26212 for (i = 0; i < 3; i++) {
26213 bestpt[i] = startpt[i] = smthpt[i];
26214 }
26215
26216
26217 newTmax = iniTmax;
26218 iter = 0;
26219 while (true) {
26220
26221 oldTmax = newTmax;
26222 for (i = 0; i < numdirs; i++) {
26223
26224 if (!segflag) {
26225 if (randflag) {
26226
26227 j = (int) randomnation(starlist->len());
26228 } else {
26229 j = i;
26230 }
26231 starttet = * (triface *)(* starlist)[j];
26232 adjustedgering(starttet, !invtori ? CCW : CW);
26233 pa = org(starttet);
26234 pb = dest(starttet);
26235 pc = apex(starttet);
26236 for (j = 0; j < 3; j++) {
26237 fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0;
26238 }
26239 } else {
26240 for (j = 0; j < 3; j++) {
26241 fcent[j] = (i == 0 ? e1[j] : e2[j]);
26242 }
26243 }
26244 for (j = 0; j < 3; j++) {
26245 nextpt[j] = startpt[j] + 0.01 * (fcent[j] - startpt[j]);
26246 }
26247
26248 for (j = 0; j < starlist->len(); j++) {
26249 starttet = * (triface *)(* starlist)[j];
26250 adjustedgering(starttet, !invtori ? CCW : CW);
26251 pa = org(starttet);
26252 pb = dest(starttet);
26253 pc = apex(starttet);
26254 ori = orient3d(pa, pb, pc, nextpt);
26255 if (ori < 0.0) {
26256 aspT = tetaspectratio(pa, pb, pc, nextpt);
26257 if (j == 0) {
26258 aspTmax = aspT;
26259 } else {
26260 aspTmax = aspT > aspTmax ? aspT : aspTmax;
26261 }
26262 } else {
26263
26264 aspTmax = newTmax;
26265 }
26266
26267 if (aspTmax >= newTmax) break;
26268 }
26269 if (aspTmax < newTmax) {
26270
26271 newTmax = aspTmax;
26272 for (j = 0; j < 3; j++) bestpt[j] = nextpt[j];
26273 }
26274 }
26275
26276 imprate = fabs(oldTmax - newTmax) / oldTmax;
26277 if (imprate < 1e-3) break;
26278
26279 for (j = 0; j < 3; j++) startpt[j] = bestpt[j];
26280 iter++;
26281 }
26282
26283 if (iter > 0) {
26284
26285 if (key) {
26286
26287 maxcosd = 0.0;
26288 for (j = 0; j < starlist->len(); j++) {
26289 starttet = * (triface *)(* starlist)[j];
26290 adjustedgering(starttet, !invtori ? CCW : CW);
26291 pa = org(starttet);
26292 pb = dest(starttet);
26293 pc = apex(starttet);
26294 tetalldihedral(pa, pb, pc, startpt, NULL, &cosd, NULL);
26295 if (cosd < *key) {
26296
26297 iter = 0; break;
26298 } else {
26299
26300 maxcosd = maxcosd < cosd ? maxcosd : cosd;
26301 }
26302 }
26303 if (iter > 0) *key = maxcosd;
26304 }
26305 }
26306
26307 if (iter > 0) {
26308 segflag ? smoothsegverts++ : smoothvolverts++;
26309 for (i = 0; i < 3; i++) smthpt[i] = startpt[i];
26310 if (b->verbose > 1) {
26311 printf(" Move to new location (%g, %g, %g).\n", smthpt[0], smthpt[1],
26312 smthpt[2]);
26313 printf(" Final max L/h = %g. (%d iterations)\n", newTmax, iter);
26314 if (key) {
26315 printf(" Max. dihed = %g (degree).\n", acos(*key) / PI * 180.0);
26316 }
26317 }
26318 return true;
26319 } else {
26320 if (b->verbose > 1) {
26321 printf(" Not smoothed.\n");
26322 }
26323 return false;
26324 }
26325 }
26326
26328
26329
26330
26332
26333 void tetgenmesh::removesteiners(bool coarseflag)
26334 {
26335 list *frontlist, *misfrontlist;
26336 list *spinshlist, *newsegshlist;
26337 list *ptlist, *conlist;
26338 memorypool *viri;
26339 queue *flipque;
26340 triface checktet;
26341 face shloop;
26342 face segloop, nextseg;
26343 point pa, neipt;
26344 REAL len;
26345 bool remflag;
26346 int *worklist;
26347 int oldnum, rmstein;
26348 int i, j;
26349
26350 if (!b->quiet) {
26351 if (!coarseflag) {
26352 printf("Removing Steiner points.\n");
26353 } else {
26354 printf("Coarsening mesh.\n");
26355 }
26356 }
26357
26358
26359 frontlist = new list(sizeof(triface), NULL);
26360 misfrontlist = new list(sizeof(triface), NULL);
26361 spinshlist = new list(sizeof(face), NULL);
26362 newsegshlist = new list(sizeof(face), NULL);
26363 ptlist = new list(sizeof(point *), NULL);
26364 conlist = new list(sizeof(point *) * 2, NULL);
26365 flipque = new queue(sizeof(badface));
26366 viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
26367 oldnum = unuverts;
26368 relverts = suprelverts = collapverts = unsupverts;
26369 smoothvolverts = 0;
26370 expcavcount = 0;
26371
26372
26373 do {
26374 rmstein = unuverts;
26375 subfaces->traversalinit();
26376 shloop.sh = shellfacetraverse(subfaces);
26377 while (shloop.sh != (shellface *) NULL) {
26378 remflag = false;
26379
26380 shloop.shver = 0;
26381 for (i = 0; i < 3; i++) {
26382 pa = sapex(shloop);
26383 if (pointtype(pa) == FREESUBVERTEX) {
26384 if (!coarseflag) {
26385
26386 j = pointmark(pa) - in->firstnumber;
26387 if (j >= in->numberofpoints) {
26388 if (b->nobisect == 1) {
26389
26390 stpivot(shloop, checktet);
26391 if (checktet.tet != dummytet) {
26392 sesymself(shloop);
26393 stpivot(shloop, checktet);
26394 }
26395 remflag = (checktet.tet == dummytet);
26396 } else {
26397
26398 remflag = true;
26399 }
26400 }
26401 } else {
26402
26403 if (b->nobisect == 0) {
26404
26405 if (b->metric) {
26406
26407
26408 spinshlist->append(&shloop);
26409 formstarpolygon(pa, spinshlist, ptlist);
26410 len = 0.0;
26411 for (j = 0; j < ptlist->len(); j++) {
26412 neipt = * (point *)(* ptlist)[j];
26413 len += distance(pa, neipt);
26414 }
26415 len /= ptlist->len();
26416
26417 remflag = len < pa[pointmtrindex];
26418 spinshlist->clear();
26419 ptlist->clear();
26420 } else {
26421
26422
26423 remflag = true;
26424 j = pointmark(pa) - in->firstnumber;
26425 if (j < in->numberofpoints) {
26426 remflag = (in->pointmarkerlist[j] == 0);
26427 }
26428 }
26429 }
26430 }
26431 if (remflag) break;
26432 }
26433 senextself(shloop);
26434 }
26435 if (remflag) {
26436 suppressfacetpoint(&shloop, frontlist, misfrontlist, ptlist, conlist,
26437 viri, flipque, coarseflag, false);
26438 }
26439 shloop.sh = shellfacetraverse(subfaces);
26440 }
26441
26442 } while (unuverts > rmstein);
26443
26444 if (coarseflag) {
26445 shellface **segsperverlist;
26446 int *idx2seglist;
26447 face seg1, seg2;
26448 point e1, e2;
26449
26450
26451 makesegmentmap(idx2seglist, segsperverlist);
26452 subsegs->traversalinit();
26453 segloop.sh = shellfacetraverse(subsegs);
26454 while (segloop.sh != (shellface *) NULL) {
26455 for (i = 0; i < 2; i++) {
26456 segloop.shver = i;
26457 senext(segloop, nextseg);
26458 spivotself(nextseg);
26459 if ((nextseg.sh == dummysh) || (nextseg.sh > segloop.sh)) {
26460
26461 pa = sdest(segloop);
26462 j = pointmark(pa) - in->firstnumber;
26463 if (idx2seglist[j + 1] - idx2seglist[j] == 2) {
26464
26465 nextseg.sh = segsperverlist[idx2seglist[j]];
26466 if (nextseg.sh == segloop.sh) {
26467 nextseg.sh = segsperverlist[idx2seglist[j] + 1];
26468 }
26469 nextseg.shver = 0;
26470 if (sorg(nextseg) != pa) sesymself(nextseg);
26471
26472 e1 = sorg(segloop);
26473 e2 = sdest(nextseg);
26474 if (iscollinear(e1, pa, e2, b->epsilon)) {
26475
26476 if (b->verbose > 1) {
26477 printf(" Glue two insegs (%d, %d) at %d.\n", pointmark(e1),
26478 pointmark(e2), pointmark(pa));
26479 }
26480 senext(segloop, seg1);
26481 senext2(nextseg, seg2);
26482 sbond(seg1, seg2);
26483 }
26484 }
26485 }
26486 }
26487 segloop.sh = shellfacetraverse(subsegs);
26488 }
26489 delete [] segsperverlist;
26490 delete [] idx2seglist;
26491 }
26492
26493
26494 do {
26495 rmstein = unuverts;
26496 subsegs->traversalinit();
26497 segloop.sh = shellfacetraverse(subsegs);
26498 while (segloop.sh != (shellface *) NULL) {
26499 remflag = false;
26500
26501
26502
26503 segloop.shver = 0;
26504 senext(segloop, nextseg);
26505 spivotself(nextseg);
26506 if (nextseg.sh != dummysh) {
26507 pa = sdest(segloop);
26508 nextseg.shver = 0;
26509 if (sorg(nextseg) != pa) sesymself(nextseg);
26510 assert(sorg(nextseg) == pa);
26511 if (!coarseflag) {
26512
26513 j = pointmark(pa) - in->firstnumber;
26514 if (j >= in->numberofpoints) {
26515 if (b->nobisect == 1) {
26516
26517 sstpivot(&segloop, &checktet);
26518 assert(checktet.tet != dummytet);
26519 pa = apex(checktet);
26520 do {
26521 if (!fnextself(checktet)) {
26522
26523 remflag = true; break;
26524 }
26525 } while (pa != apex(checktet));
26526 } else {
26527
26528 remflag = true;
26529 }
26530 }
26531 } else {
26532
26533 if (b->nobisect == 0) {
26534 if (b->metric) {
26535
26536 len = 0.0;
26537 neipt = sorg(segloop);
26538 for (j = 0; j < 2; j++) {
26539 len += distance(pa, neipt);
26540
26541
26542
26543
26544
26545 neipt = sdest(nextseg);
26546 }
26547 len /= 2.0;
26548
26549 remflag = len < pa[pointmtrindex];
26550 } else {
26551
26552
26553 remflag = true;
26554 j = pointmark(pa) - in->firstnumber;
26555 if (j < in->numberofpoints) {
26556 remflag = (in->pointmarkerlist[j] == 0);
26557 }
26558 }
26559 }
26560 }
26561 }
26562
26563
26564 if (remflag) {
26565 suppresssegpoint(&segloop, spinshlist, newsegshlist, frontlist,
26566 misfrontlist, ptlist, conlist, viri, flipque, coarseflag, false);
26567 }
26568 segloop.sh = shellfacetraverse(subsegs);
26569 }
26570
26571 } while (unuverts > rmstein);
26572
26573 if ((relverts > 0) || coarseflag) {
26574 worklist = new int[points->items + 1];
26575
26576 do {
26577
26578
26579 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26580 rmstein = unuverts;
26581 tetrahedrons->traversalinit();
26582 checktet.tet = tetrahedrontraverse();
26583 while (checktet.tet != (tetrahedron *) NULL) {
26584 remflag = false;
26585 for (i = 0; i < 4; i++) {
26586 pa = (point) checktet.tet[4 + i];
26587 if (pointtype(pa) == FREEVOLVERTEX) {
26588
26589
26590
26591
26592
26593
26594 if (worklist[pointmark(pa)] < 3) {
26595 worklist[pointmark(pa)]++;
26596 if (!coarseflag) {
26597
26598 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26599 remflag = true;
26600 }
26601 } else {
26602 if (b->metric) {
26603
26604
26605 frontlist->append(&checktet);
26606 formstarpolyhedron(pa, frontlist, ptlist, true);
26607 len = 0.0;
26608 for (j = 0; j < ptlist->len(); j++) {
26609 neipt = * (point *)(* ptlist)[j];
26610 len += distance(pa, neipt);
26611 }
26612 len /= ptlist->len();
26613
26614 remflag = len < pa[pointmtrindex];
26615 frontlist->clear();
26616 ptlist->clear();
26617 } else {
26618
26619
26620 remflag = true;
26621 j = pointmark(pa) - in->firstnumber;
26622 if (j < in->numberofpoints) {
26623 remflag = (in->pointmarkerlist[j] == 0);
26624 }
26625 }
26626 }
26627 if (remflag) break;
26628 }
26629 }
26630 }
26631 if (remflag) {
26632 findorg(&checktet, pa);
26633 assert(org(checktet) == pa);
26634 suppressvolpoint(&checktet, frontlist, misfrontlist, ptlist, flipque,
26635 false);
26636 }
26637 checktet.tet = tetrahedrontraverse();
26638 }
26639
26640 } while (unuverts > rmstein);
26641
26642
26643
26644 if (!coarseflag && (relverts > suprelverts)) {
26645 if (b->verbose) {
26646 printf(" Smoothing relocated points.\n");
26647 }
26648 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26649 tetrahedrons->traversalinit();
26650 checktet.tet = tetrahedrontraverse();
26651 while (checktet.tet != (tetrahedron *) NULL) {
26652 for (i = 0; i < 4; i++) {
26653 pa = (point) checktet.tet[4 + i];
26654 if (pointtype(pa) == FREEVOLVERTEX) {
26655 if (worklist[pointmark(pa)] == 0) {
26656 worklist[pointmark(pa)] = 1;
26657 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26658
26659 findorg(&checktet, pa);
26660 frontlist->append(&checktet);
26661 formstarpolyhedron(pa, frontlist, NULL, false);
26662 smoothpoint(pa, NULL, NULL, frontlist, false, NULL);
26663 frontlist->clear();
26664 }
26665 }
26666 }
26667 }
26668 checktet.tet = tetrahedrontraverse();
26669 }
26670 }
26671 delete [] worklist;
26672 }
26673
26674 if (b->verbose > 0) {
26675 if (!coarseflag) {
26676 printf(" %d points removed from boundary", unuverts - oldnum);
26677 if (expcavcount > 0) {
26678 printf(" (%d cavity corrections)", expcavcount);
26679 }
26680 printf("\n");
26681 if (relverts > 0) {
26682 printf(" %d points relocated (%d suppressed, %d collapsed).\n",
26683 relverts, suprelverts - collapverts, collapverts);
26684 if (smoothvolverts > 0) {
26685 printf(" %d points are smoothed.\n", smoothvolverts);
26686 }
26687 }
26688 if (unsupverts > 0) {
26689 printf(" !! %d points are unsuppressed.\n", unsupverts);
26690 }
26691 } else {
26692 printf(" %d points are removed.\n", unuverts - oldnum);
26693 }
26694 }
26695
26696
26697 delete frontlist;
26698 delete misfrontlist;
26699 delete spinshlist;
26700 delete newsegshlist;
26701 delete ptlist;
26702 delete conlist;
26703 delete flipque;
26704 delete viri;
26705 }
26706
26707
26708
26709
26710
26712
26713
26714
26715
26716
26717
26718
26719
26720
26721
26722
26723
26724
26725
26726
26727
26728
26729
26730
26731
26732
26733
26734
26735
26736
26737
26738
26739
26740
26741
26742
26743
26744
26745
26747
26748 long tetgenmesh::reconstructmesh()
26749 {
26750 tetrahedron **tetsperverlist;
26751 shellface **facesperverlist;
26752 triface tetloop, neightet, neineightet, spintet;
26753 face subloop, neighsh, neineighsh, subseg;
26754 face sface1, sface2;
26755 point *idx2verlist;
26756 point torg, tdest, tapex, toppo;
26757 point norg, ndest, napex;
26758 list *neighshlist, *markerlist;
26759 REAL sign, attrib, volume;
26760 REAL da1, da2;
26761 bool bondflag, insertsegflag;
26762 int *idx2tetlist;
26763 int *idx2facelist;
26764 int *worklist;
26765 int facetidx, marker;
26766 int iorg, idest, iapex, ioppo;
26767 int inorg, indest, inapex;
26768 int index, i, j;
26769
26770 if (!b->quiet) {
26771 printf("Reconstructing mesh.\n");
26772 }
26773
26774
26775 makeindex2pointmap(idx2verlist);
26776
26777
26778 for (i = 0; i < in->numberoftetrahedra; i++) {
26779
26780
26781 maketetrahedron(&tetloop);
26782 index = i * in->numberofcorners;
26783
26784 iorg = in->tetrahedronlist[index] - in->firstnumber;
26785 idest = in->tetrahedronlist[index + 1] - in->firstnumber;
26786 iapex = in->tetrahedronlist[index + 2] - in->firstnumber;
26787 ioppo = in->tetrahedronlist[index + 3] - in->firstnumber;
26788 torg = idx2verlist[iorg];
26789 tdest = idx2verlist[idest];
26790 tapex = idx2verlist[iapex];
26791 toppo = idx2verlist[ioppo];
26792 sign = orient3d(torg, tdest, tapex, toppo);
26793 if (sign > 0.0) {
26794 norg = torg; torg = tdest; tdest = norg;
26795 } else if (sign == 0.0) {
26796 if (!b->quiet) {
26797 printf("Warning: Tet %d is degenerate.\n", i + in->firstnumber);
26798 }
26799 }
26800 setorg(tetloop, torg);
26801 setdest(tetloop, tdest);
26802 setapex(tetloop, tapex);
26803 setoppo(tetloop, toppo);
26804
26805
26806 setpointtype(torg, FREEVOLVERTEX);
26807 setpointtype(tdest, FREEVOLVERTEX);
26808 setpointtype(tapex, FREEVOLVERTEX);
26809 setpointtype(toppo, FREEVOLVERTEX);
26810
26811 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
26812 index = i * in->numberoftetrahedronattributes;
26813 attrib = in->tetrahedronattributelist[index + j];
26814 setelemattribute(tetloop.tet, j, attrib);
26815 }
26816
26817
26818 if (b->varvolume) {
26819 if (in->tetrahedronvolumelist != (REAL *) NULL) {
26820 volume = in->tetrahedronvolumelist[i];
26821 } else {
26822 volume = -1.0;
26823 }
26824 setvolumebound(tetloop.tet, volume);
26825 }
26826 }
26827
26828
26829 hullsize = 0l;
26830
26831 maketetrahedronmap(idx2tetlist, tetsperverlist);
26832
26833 worklist = new int[points->items];
26834 for (i = 0; i < points->items; i++) worklist[i] = 0;
26835
26836
26837 tetrahedrons->traversalinit();
26838 tetloop.tet = tetrahedrontraverse();
26839 while (tetloop.tet != (tetrahedron *) NULL) {
26840
26841 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26842 sym(tetloop, neightet);
26843 if (neightet.tet != dummytet) continue;
26844 torg = org(tetloop);
26845 tdest = dest(tetloop);
26846 tapex = apex(tetloop);
26847 iorg = pointmark(torg) - in->firstnumber;
26848 idest = pointmark(tdest) - in->firstnumber;
26849 iapex = pointmark(tapex) - in->firstnumber;
26850 worklist[iorg] = 1;
26851 worklist[idest] = 1;
26852 worklist[iapex] = 1;
26853 bondflag = false;
26854
26855 for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26856 j++) {
26857 if (tetsperverlist[j] == tetloop.tet) continue;
26858 neightet.tet = tetsperverlist[j];
26859 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26860 sym(neightet, neineightet);
26861 if (neineightet.tet == dummytet) {
26862 norg = org(neightet);
26863 ndest = dest(neightet);
26864 napex = apex(neightet);
26865 inorg = pointmark(norg) - in->firstnumber;
26866 indest = pointmark(ndest) - in->firstnumber;
26867 inapex = pointmark(napex) - in->firstnumber;
26868 if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26869
26870 bond(tetloop, neightet);
26871 bondflag = true;
26872 break;
26873 }
26874 }
26875 }
26876 }
26877 if (!bondflag) {
26878 hullsize++;
26879
26880 dummytet[0] = encode(tetloop);
26881 if ((in->pointmarkerlist != (int *) NULL) && !b->coarse) {
26882
26883 if (in->pointmarkerlist[iorg] == 0) {
26884 in->pointmarkerlist[iorg] = 1;
26885 }
26886 if (in->pointmarkerlist[idest] == 0) {
26887 in->pointmarkerlist[idest] = 1;
26888 }
26889 if (in->pointmarkerlist[iapex] == 0) {
26890 in->pointmarkerlist[iapex] = 1;
26891 }
26892 }
26893 }
26894 worklist[iorg] = 0;
26895 worklist[idest] = 0;
26896 worklist[iapex] = 0;
26897 }
26898 tetloop.tet = tetrahedrontraverse();
26899 }
26900
26901
26902
26903
26904
26905
26906
26907 if (in->trifacelist != (int *) NULL) {
26908
26909 for (i = 0; i < in->numberoftrifaces; i++) {
26910 index = i * 3;
26911 iorg = in->trifacelist[index] - in->firstnumber;
26912 idest = in->trifacelist[index + 1] - in->firstnumber;
26913 iapex = in->trifacelist[index + 2] - in->firstnumber;
26914
26915 worklist[iorg] = 1;
26916 worklist[idest] = 1;
26917 worklist[iapex] = 1;
26918 bondflag = false;
26919
26920 for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26921 j++) {
26922 neightet.tet = tetsperverlist[j];
26923 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26924 norg = org(neightet);
26925 ndest = dest(neightet);
26926 napex = apex(neightet);
26927 inorg = pointmark(norg) - in->firstnumber;
26928 indest = pointmark(ndest) - in->firstnumber;
26929 inapex = pointmark(napex) - in->firstnumber;
26930 if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26931 bondflag = true;
26932 break;
26933 }
26934 }
26935 }
26936 if (bondflag) {
26937
26938 makeshellface(subfaces, &subloop);
26939 torg = idx2verlist[iorg];
26940 tdest = idx2verlist[idest];
26941 tapex = idx2verlist[iapex];
26942 setsorg(subloop, torg);
26943 setsdest(subloop, tdest);
26944 setsapex(subloop, tapex);
26945
26946
26947 setpointtype(torg, FREESUBVERTEX);
26948 setpointtype(tdest, FREESUBVERTEX);
26949 setpointtype(tapex, FREESUBVERTEX);
26950 if (in->trifacemarkerlist != (int *) NULL) {
26951 setshellmark(subloop, in->trifacemarkerlist[i]);
26952 }
26953 adjustedgering(neightet, CCW);
26954 findedge(&subloop, org(neightet), dest(neightet));
26955 tsbond(neightet, subloop);
26956 sym(neightet, neineightet);
26957 if (neineightet.tet != dummytet) {
26958 sesymself(subloop);
26959 tsbond(neineightet, subloop);
26960 }
26961 } else {
26962 if (!b->quiet) {
26963 printf("Warning: Subface %d is discarded.\n", i + in->firstnumber);
26964 }
26965 }
26966 worklist[iorg] = 0;
26967 worklist[idest] = 0;
26968 worklist[iapex] = 0;
26969 }
26970 }
26971
26972
26973 tetrahedrons->traversalinit();
26974 tetloop.tet = tetrahedrontraverse();
26975 while (tetloop.tet != (tetrahedron *) NULL) {
26976
26977 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26978 tspivot(tetloop, subloop);
26979 if (subloop.sh != dummysh) continue;
26980 bondflag = false;
26981 sym(tetloop, neightet);
26982 if (neightet.tet == dummytet) {
26983
26984 bondflag = true;
26985 } else {
26986
26987
26988 if (in->numberoftetrahedronattributes > 0) {
26989 if (elemattribute(neightet.tet,
26990 in->numberoftetrahedronattributes - 1) !=
26991 elemattribute(tetloop.tet,
26992 in->numberoftetrahedronattributes - 1)) {
26993 bondflag = true;
26994 }
26995 }
26996 }
26997 if (bondflag) {
26998 adjustedgering(tetloop, CCW);
26999 makeshellface(subfaces, &subloop);
27000 torg = org(tetloop);
27001 tdest = dest(tetloop);
27002 tapex = apex(tetloop);
27003 setsorg(subloop, torg);
27004 setsdest(subloop, tdest);
27005 setsapex(subloop, tapex);
27006
27007
27008 setpointtype(torg, FREESUBVERTEX);
27009 setpointtype(tdest, FREESUBVERTEX);
27010 setpointtype(tapex, FREESUBVERTEX);
27011 tsbond(tetloop, subloop);
27012 if (neightet.tet != dummytet) {
27013 sesymself(subloop);
27014 tsbond(neightet, subloop);
27015 }
27016 }
27017 }
27018 tetloop.tet = tetrahedrontraverse();
27019 }
27020
27021
27022
27023
27024 neighshlist = new list(sizeof(face), NULL);
27025
27026 makesubfacemap(idx2facelist, facesperverlist);
27027
27028
27029 subfaces->traversalinit();
27030 subloop.sh = shellfacetraverse(subfaces);
27031 while (subloop.sh != (shellface *) NULL) {
27032 for (i = 0; i < 3; i++) {
27033 spivot(subloop, neighsh);
27034 if (neighsh.sh == dummysh) {
27035
27036 torg = sorg(subloop);
27037 tdest = sdest(subloop);
27038 tapex = sapex(subloop);
27039 neighshlist->append(&subloop);
27040 iorg = pointmark(torg) - in->firstnumber;
27041
27042 for (j = idx2facelist[iorg]; j < idx2facelist[iorg + 1]; j++) {
27043 neighsh.sh = facesperverlist[j];
27044 if (neighsh.sh == subloop.sh) continue;
27045 neighsh.shver = 0;
27046 if (isfacehasedge(&neighsh, torg, tdest)) {
27047 findedge(&neighsh, torg, tdest);
27048
27049 if (neighshlist->len() < 2) {
27050 neighshlist->append(&neighsh);
27051 } else {
27052 for (index = 0; index < neighshlist->len() - 1; index++) {
27053 sface1 = * (face *)(* neighshlist)[index];
27054 sface2 = * (face *)(* neighshlist)[index + 1];
27055 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(neighsh));
27056 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
27057 if (da1 < da2) {
27058 break;
27059 }
27060 }
27061 neighshlist->insert(index + 1, &neighsh);
27062 }
27063 }
27064 }
27065
27066 if (neighshlist->len() > 1) {
27067 neighsh = * (face *)(* neighshlist)[0];
27068 for (j = 1; j <= neighshlist->len(); j++) {
27069 if (j < neighshlist->len()) {
27070 neineighsh = * (face *)(* neighshlist)[j];
27071 } else {
27072 neineighsh = * (face *)(* neighshlist)[0];
27073 }
27074 sbond1(neighsh, neineighsh);
27075 neighsh = neineighsh;
27076 }
27077 } else {
27078
27079 sbond(subloop, subloop);
27080 }
27081 neighshlist->clear();
27082 }
27083 senextself(subloop);
27084 }
27085 subloop.sh = shellfacetraverse(subfaces);
27086 }
27087
27088
27089 marker = 1;
27090 subfaces->traversalinit();
27091 subloop.sh = shellfacetraverse(subfaces);
27092 while (subloop.sh != (shellface *) NULL) {
27093 for (i = 0; i < 3; i++) {
27094 sspivot(subloop, subseg);
27095 if (subseg.sh == dummysh) {
27096
27097 torg = sorg(subloop);
27098 tdest = sdest(subloop);
27099 tapex = sapex(subloop);
27100 spivot(subloop, neighsh);
27101 spivot(neighsh, neineighsh);
27102 insertsegflag = false;
27103 if (subloop.sh == neighsh.sh || subloop.sh != neineighsh.sh) {
27104
27105
27106 insertsegflag = true;
27107 } else {
27108
27109 #ifdef SELF_CHECK
27110 assert(subloop.sh != neighsh.sh);
27111 #endif
27112 napex = sapex(neighsh);
27113 sign = orient3d(torg, tdest, tapex, napex);
27114 if (iscoplanar(torg, tdest, tapex, napex, sign, b->epsilon)) {
27115
27116
27117 insertsegflag = (shellmark(subloop) != shellmark(neighsh));
27118 } else {
27119
27120 insertsegflag = true;
27121 }
27122 }
27123 if (insertsegflag) {
27124
27125 makeshellface(subsegs, &subseg);
27126 setsorg(subseg, torg);
27127 setsdest(subseg, tdest);
27128
27129
27130 setpointtype(torg, NACUTEVERTEX);
27131 setpointtype(tdest, NACUTEVERTEX);
27132 setshellmark(subseg, marker);
27133 marker++;
27134
27135 neighsh = subloop;
27136 do {
27137 ssbond(neighsh, subseg);
27138 spivotself(neighsh);
27139 } while (neighsh.sh != subloop.sh);
27140 }
27141 }
27142 senextself(subloop);
27143 }
27144 subloop.sh = shellfacetraverse(subfaces);
27145 }
27146
27147 insegments = subsegs->items;
27148
27149
27150
27151 markerlist = new list((char*)"int");
27152
27153 subfaces->traversalinit();
27154 subloop.sh = shellfacetraverse(subfaces);
27155 while (subloop.sh != (shellface *) NULL) {
27156
27157 if (!sinfected(subloop)) {
27158
27159 marker = shellmark(subloop);
27160 markerlist->append(&marker);
27161 facetidx = markerlist->len();
27162 setshellmark(subloop, facetidx);
27163 sinfect(subloop);
27164 neighshlist->append(&subloop);
27165
27166 for (i = 0; i < neighshlist->len(); i++) {
27167 neighsh = * (face *) (* neighshlist)[i];
27168 for (j = 0; j < 3; j++) {
27169 sspivot(neighsh, subseg);
27170 if (subseg.sh == dummysh) {
27171 spivot(neighsh, neineighsh);
27172 if (!sinfected(neineighsh)) {
27173
27174 #ifdef SELF_CHECK
27175 assert(shellmark(neineighsh) == marker);
27176 #endif
27177 setshellmark(neineighsh, facetidx);
27178 sinfect(neineighsh);
27179 neighshlist->append(&neineighsh);
27180 }
27181 }
27182 senextself(neighsh);
27183 }
27184 }
27185 neighshlist->clear();
27186 }
27187 subloop.sh = shellfacetraverse(subfaces);
27188 }
27189
27190 subfaces->traversalinit();
27191 subloop.sh = shellfacetraverse(subfaces);
27192 while (subloop.sh != (shellface *) NULL) {
27193 #ifdef SELF_CHECK
27194 assert(sinfected(subloop));
27195 #endif
27196 suninfect(subloop);
27197 subloop.sh = shellfacetraverse(subfaces);
27198 }
27199
27200 in->numberoffacets = markerlist->len();
27201 in->facetmarkerlist = new int[in->numberoffacets];
27202 for (i = 0; i < in->numberoffacets; i++) {
27203 marker = * (int *) (* markerlist)[i];
27204 in->facetmarkerlist[i] = marker;
27205 }
27206
27207 facetabovepointarray = new point[in->numberoffacets + 1];
27208 for (i = 0; i < in->numberoffacets + 1; i++) {
27209 facetabovepointarray[i] = (point) NULL;
27210 }
27211
27212
27213 checksubfaces = 1;
27214
27215 nonconvex = 1;
27216
27217
27218 if (checkpbcs) {
27219 tetgenio::pbcgroup *pg;
27220 pbcdata *pd;
27221
27222 createsubpbcgrouptable();
27223
27224 for (i = 0; i < in->numberofpbcgroups; i++) {
27225 pg = &(in->pbcgrouplist[i]);
27226 pd = &(subpbcgrouptable[i]);
27227
27228 for (j = 0; j < 2; j++) {
27229 subfaces->traversalinit();
27230 subloop.sh = shellfacetraverse(subfaces);
27231 while (subloop.sh != (shellface *) NULL) {
27232 facetidx = shellmark(subloop);
27233 marker = in->facetmarkerlist[facetidx - 1];
27234 if (marker == pd->fmark[j]) {
27235 setshellpbcgroup(subloop, i);
27236 pd->ss[j] = subloop;
27237 }
27238 subloop.sh = shellfacetraverse(subfaces);
27239 }
27240 }
27241 if (pg->pointpairlist != (int *) NULL) {
27242
27243 for (j = 0; j < pg->numberofpointpairs; j++) {
27244 iorg = pg->pointpairlist[j * 2] - in->firstnumber;
27245 idest = pg->pointpairlist[j * 2 + 1] - in->firstnumber;
27246 torg = idx2verlist[iorg];
27247 tdest = idx2verlist[idest];
27248 setpoint2pbcpt(torg, tdest);
27249 setpoint2pbcpt(tdest, torg);
27250 }
27251 }
27252 }
27253
27254 createsegpbcgrouptable();
27255 }
27256
27257 delete markerlist;
27258 delete neighshlist;
27259 delete [] worklist;
27260 delete [] idx2tetlist;
27261 delete [] tetsperverlist;
27262 delete [] idx2facelist;
27263 delete [] facesperverlist;
27264 delete [] idx2verlist;
27265
27266 return hullsize;
27267 }
27268
27270
27271
27272
27274
27275 void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
27276 {
27277 queue *flipqueue;
27278 triface searchtet;
27279 face checksh, checkseg;
27280 point newpoint;
27281 enum locateresult loc;
27282 REAL *attr;
27283 bool insertflag;
27284 int covertices, outvertices;
27285 int index;
27286 int i, j;
27287
27288 if (!b->quiet) {
27289 printf("Insert additional points into mesh.\n");
27290 }
27291
27292 flipqueue = new queue(sizeof(badface));
27293 recenttet.tet = dummytet;
27294 covertices = outvertices = 0;
27295
27296 index = 0;
27297 for (i = 0; i < addio->numberofpoints; i++) {
27298
27299 makepoint(&newpoint);
27300 newpoint[0] = addio->pointlist[index++];
27301 newpoint[1] = addio->pointlist[index++];
27302 newpoint[2] = addio->pointlist[index++];
27303
27304 if ((addio->numberofpointattributes > 0) &&
27305 (in->numberofpointattributes > 0)) {
27306 attr = addio->pointattributelist + addio->numberofpointattributes * i;
27307 for (j = 0; j < in->numberofpointattributes; j++) {
27308 if (j < addio->numberofpointattributes) {
27309 newpoint[3 + j] = attr[j];
27310 }
27311 }
27312 }
27313
27314 searchtet = recenttet;
27315 loc = locate(newpoint, &searchtet);
27316 if (loc != ONVERTEX) {
27317 loc = adjustlocate(newpoint, &searchtet, loc, b->epsilon2);
27318 }
27319 if (loc == OUTSIDE) {
27320 loc = hullwalk(newpoint, &searchtet);
27321 if (loc == OUTSIDE) {
27322
27323 tetrahedrons->traversalinit();
27324 searchtet.tet = tetrahedrontraverse();
27325 while (searchtet.tet != (tetrahedron *) NULL) {
27326 loc = adjustlocate(newpoint, &searchtet, OUTSIDE, b->epsilon2);
27327 if (loc != OUTSIDE) break;
27328 searchtet.tet = tetrahedrontraverse();
27329 }
27330 }
27331 }
27332
27333 insertflag = true;
27334 switch (loc) {
27335 case INTETRAHEDRON:
27336 setpointtype(newpoint, FREEVOLVERTEX);
27337 splittetrahedron(newpoint, &searchtet, flipqueue);
27338 break;
27339 case ONFACE:
27340 tspivot(searchtet, checksh);
27341 if (checksh.sh != dummysh) {
27342
27343 if (b->nobisect) {
27344 insertflag = false;
27345 } else {
27346 setpointtype(newpoint, FREESUBVERTEX);
27347 }
27348 } else {
27349 setpointtype(newpoint, FREEVOLVERTEX);
27350 }
27351 if (insertflag) {
27352 splittetface(newpoint, &searchtet, flipqueue);
27353 }
27354 break;
27355 case ONEDGE:
27356 tsspivot(&searchtet, &checkseg);
27357 if (checkseg.sh != dummysh) {
27358 if (b->nobisect) {
27359 insertflag = false;
27360 } else {
27361 setpointtype(newpoint, FREESEGVERTEX);
27362 setpoint2sh(newpoint, sencode(checkseg));
27363 }
27364 } else {
27365 tspivot(searchtet, checksh);
27366 if (checksh.sh != dummysh) {
27367 if (b->nobisect) {
27368 insertflag = false;
27369 } else {
27370 setpointtype(newpoint, FREESUBVERTEX);
27371 }
27372 } else {
27373 setpointtype(newpoint, FREEVOLVERTEX);
27374 }
27375 }
27376 if (insertflag) {
27377 splittetedge(newpoint, &searchtet, flipqueue);
27378 }
27379 break;
27380 case ONVERTEX:
27381 insertflag = false;
27382 covertices++;
27383 break;
27384 case OUTSIDE:
27385 insertflag = false;
27386 outvertices++;
27387 break;
27388 }
27389
27390 recenttet = searchtet;
27391 if (!insertflag) {
27392 pointdealloc(newpoint);
27393 } else {
27394 flip(flipqueue, NULL);
27395 }
27396 }
27397
27398 if (b->verbose) {
27399 if (covertices > 0) {
27400 printf(" %d constrained points already exist.\n", covertices);
27401 }
27402 if (outvertices > 0) {
27403 printf(" %d constrained points lie outside the mesh.\n", outvertices);
27404 }
27405 printf(" %d constrained points have been inserted.\n",
27406 addio->numberofpoints - covertices - outvertices);
27407 }
27408
27409 delete flipqueue;
27410 }
27411
27413
27414
27415
27416
27417
27418
27420
27421 bool tetgenmesh::p1interpolatebgm(point pt, triface* bgmtet, long *scount)
27422 {
27423 point bgmpt[4];
27424 enum locateresult loc;
27425 REAL vol, volpt[4], weights[4];
27426 int i;
27427
27428 loc = bgm->preciselocate(pt, bgmtet, bgm->tetrahedrons->items);
27429 if (loc == OUTSIDE) {
27430 loc = bgm->hullwalk(pt, bgmtet);
27431 if (loc == OUTSIDE) {
27432
27433 if (b->verbose) {
27434 printf("Warning: Global point location.\n");
27435 }
27436 if (scount) (*scount)++;
27437 bgm->tetrahedrons->traversalinit();
27438 bgmtet->tet = bgm->tetrahedrontraverse();
27439 while (bgmtet->tet != (tetrahedron *) NULL) {
27440 loc = bgm->adjustlocate(pt, bgmtet, OUTSIDE, b->epsilon);
27441 if (loc != OUTSIDE) break;
27442 bgmtet->tet = bgm->tetrahedrontraverse();
27443 }
27444 }
27445 }
27446 if (loc != OUTSIDE) {
27447
27448 setpoint2bgmtet(pt, encode(*bgmtet));
27449
27450 for (i = 0; i < 4; i++) bgmpt[i] = (point) bgmtet->tet[4 + i];
27451
27452 vol = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], bgmpt[3]);
27453 volpt[0] = orient3d(pt, bgmpt[1], bgmpt[2], bgmpt[3]);
27454 volpt[1] = orient3d(bgmpt[0], pt, bgmpt[2], bgmpt[3]);
27455 volpt[2] = orient3d(bgmpt[0], bgmpt[1], pt, bgmpt[3]);
27456 volpt[3] = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], pt);
27457 for (i = 0; i < 4; i++) weights[i] = fabs(volpt[i] / vol);
27458
27459 for (i = 0; i < bgm->in->numberofpointmtrs; i++) {
27460 pt[pointmtrindex + i] = weights[0] * bgmpt[0][bgm->pointmtrindex + i]
27461 + weights[1] * bgmpt[1][bgm->pointmtrindex + i]
27462 + weights[2] * bgmpt[2][bgm->pointmtrindex + i]
27463 + weights[3] * bgmpt[3][bgm->pointmtrindex + i];
27464 }
27465 } else {
27466 setpoint2bgmtet(pt, (tetrahedron) NULL);
27467 }
27468 return loc != OUTSIDE;
27469 }
27470
27472
27473
27474
27475
27476
27477
27478
27479
27480
27481
27483
27484 void tetgenmesh::interpolatesizemap()
27485 {
27486 list *adjtetlist;
27487 triface tetloop, neightet, bgmtet;
27488 point searchpt;
27489 long scount;
27490 int *worklist;
27491 int sepcount;
27492 int i;
27493
27494 if (b->verbose) {
27495 printf(" Interpolating size map.\n");
27496 }
27497
27498 worklist = new int[points->items + 1];
27499 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
27500 sepcount = 0;
27501 scount = 0l;
27502
27503 tetrahedrons->traversalinit();
27504 tetloop.tet = tetrahedrontraverse();
27505 while (tetloop.tet != (tetrahedron *) NULL) {
27506 if (!infected(tetloop)) {
27507
27508 adjtetlist = new list(sizeof(triface), NULL, 1024);
27509 infect(tetloop);
27510
27511 for (i = 0; i < 4; i++) {
27512 searchpt = (point) tetloop.tet[4 + i];
27513
27514
27515 worklist[pointmark(searchpt)] = 1;
27516
27517 bgm->decode(point2bgmtet(searchpt), bgmtet);
27518 if (bgm->isdead(&bgmtet)) {
27519 bgmtet = bgm->recenttet;
27520 }
27521 if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27522 bgm->recenttet = bgmtet;
27523 }
27524 }
27525
27526 adjtetlist->append(&tetloop);
27527
27528 for (i = 0; i < adjtetlist->len(); i++) {
27529 tetloop = * (triface *)(* adjtetlist)[i];
27530 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27531 sym(tetloop, neightet);
27532 if ((neightet.tet != dummytet) && !infected(neightet)) {
27533
27534 searchpt = oppo(neightet);
27535 if (worklist[pointmark(searchpt)] == 0) {
27536 worklist[pointmark(searchpt)] = 1;
27537 decode(point2bgmtet(searchpt), bgmtet);
27538 if (bgm->isdead(&bgmtet)) {
27539 bgmtet = bgm->recenttet;
27540 }
27541 if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27542 bgm->recenttet = bgmtet;
27543 }
27544 }
27545 infect(neightet);
27546 adjtetlist->append(&neightet);
27547 }
27548 }
27549 }
27550
27551 sepcount++;
27552 delete adjtetlist;
27553 }
27554 tetloop.tet = tetrahedrontraverse();
27555 }
27556
27557
27558 tetrahedrons->traversalinit();
27559 tetloop.tet = tetrahedrontraverse();
27560 while (tetloop.tet != (tetrahedron *) NULL) {
27561 assert(infected(tetloop));
27562 uninfect(tetloop);
27563 tetloop.tet = tetrahedrontraverse();
27564 }
27565 delete [] worklist;
27566
27567 #ifdef SELF_CHECK
27568 if (b->verbose && scount > 0l) {
27569 printf(" %ld brute-force searches.\n", scount);
27570 }
27571 if (b->verbose && sepcount > 0) {
27572 printf(" %d separate domains.\n", sepcount);
27573 }
27574 #endif
27575 }
27576
27578
27579
27580
27581
27582
27583
27585
27586 void tetgenmesh::duplicatebgmesh()
27587 {
27588 triface tetloop, btetloop;
27589 triface symtet, bsymtet;
27590 face bhullsh, bneighsh;
27591 point *idx2bplist, *tetptbaklist;
27592 point ploop, bploop;
27593 int idx, i;
27594
27595 if (!b->quiet) {
27596 printf("Duplicating background mesh.\n");
27597 }
27598
27599
27600
27601
27602
27603
27604
27605 idx2bplist = new point[points->items + 1];
27606 idx = in->firstnumber;
27607 points->traversalinit();
27608 ploop = pointtraverse();
27609 while (ploop != (point) NULL) {
27610 bgm->makepoint(&bploop);
27611
27612 for (i = 0; i < 3 + in->numberofpointattributes; i++) {
27613 bploop[i] = ploop[i];
27614 }
27615
27616 for (i = 0; i < bgm->sizeoftensor; i++) {
27617 bploop[bgm->pointmtrindex + i] = ploop[pointmtrindex + i];
27618
27619 if (bploop[bgm->pointmtrindex + i] <= 0.0) {
27620 printf("Error: Point %d has non-positive size %g (-m option).\n",
27621 bgm->pointmark(bploop), bploop[bgm->pointmtrindex + i]);
27622 terminatetetgen(1);
27623 }
27624 }
27625
27626 idx2bplist[idx++] = bploop;
27627 ploop = pointtraverse();
27628 }
27629
27630
27631 tetptbaklist = new point[tetrahedrons->items + 1];
27632 idx = in->firstnumber;
27633 tetrahedrons->traversalinit();
27634 tetloop.tet = tetrahedrontraverse();
27635 while (tetloop.tet != (tetrahedron *) NULL) {
27636 bgm->maketetrahedron(&btetloop);
27637
27638 for (i = 0; i < 4; i++) {
27639 ploop = (point) tetloop.tet[4 + i];
27640 bploop = idx2bplist[pointmark(ploop)];
27641 btetloop.tet[4 + i] = (tetrahedron) bploop;
27642 }
27643
27644 tetptbaklist[idx++] = (point) tetloop.tet[4];
27645 tetloop.tet[4] = (tetrahedron) btetloop.tet;
27646 tetloop.tet = tetrahedrontraverse();
27647 }
27648
27649
27650
27651 idx = in->firstnumber;
27652 tetrahedrons->traversalinit();
27653 tetloop.tet = tetrahedrontraverse();
27654 while (tetloop.tet != (tetrahedron *) NULL) {
27655
27656 btetloop.tet = (tetrahedron *) tetloop.tet[4];
27657
27658 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27659 btetloop.loc = tetloop.loc;
27660 sym(tetloop, symtet);
27661 if ((symtet.tet != dummytet) && (symtet.tet > tetloop.tet)) {
27662
27663 bsymtet.tet = (tetrahedron *) symtet.tet[4];
27664 bsymtet.loc = symtet.loc;
27665 bgm->bond(btetloop, bsymtet);
27666 } else if (symtet.tet == dummytet) {
27667
27668 bgm->makeshellface(bgm->subfaces, &bhullsh);
27669 bgm->adjustedgering(btetloop, CCW);
27670 bgm->setsorg(bhullsh, bgm->org(btetloop));
27671 bgm->setsdest(bhullsh, bgm->dest(btetloop));
27672 bgm->setsapex(bhullsh, bgm->apex(btetloop));
27673 bgm->tsbond(btetloop, bhullsh);
27674
27675 bgm->dummytet[0] = bgm->encode(btetloop);
27676 }
27677 }
27678
27679 tetloop.tet[4] = (tetrahedron) tetptbaklist[idx++];
27680
27681 btetloop.loc = 0;
27682 for (i = 0; i < 4; i++) {
27683 ploop = (point) tetloop.tet[4 + i];
27684 setpoint2bgmtet(ploop, bgm->encode(btetloop));
27685 }
27686
27687 tetloop.tet = tetrahedrontraverse();
27688 }
27689
27690
27691 bgm->subfaces->traversalinit();
27692 bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27693 while (bhullsh.sh != (shellface *) NULL) {
27694 bhullsh.shver = 0;
27695 bgm->stpivot(bhullsh, btetloop);
27696 assert(btetloop.tet != bgm->dummytet);
27697 bgm->adjustedgering(btetloop, CCW);
27698 for (i = 0; i < 3; i++) {
27699 bgm->spivot(bhullsh, bneighsh);
27700 if (bneighsh.sh == bgm->dummysh) {
27701
27702 bsymtet = btetloop;
27703 while (bgm->fnextself(bsymtet));
27704 bgm->tspivot(bsymtet, bneighsh);
27705 bgm->findedge(&bneighsh, bgm->sdest(bhullsh), bgm->sorg(bhullsh));
27706 bgm->sbond(bhullsh, bneighsh);
27707 }
27708 bgm->enextself(btetloop);
27709 bgm->senextself(bhullsh);
27710 }
27711 bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27712 }
27713
27714 delete [] tetptbaklist;
27715 delete [] idx2bplist;
27716 }
27717
27718
27719
27720
27721
27723
27724
27725
27726
27727
27728
27729
27730
27731
27732
27733
27734
27735
27736
27737
27739
27740 void tetgenmesh::marksharpsegments(REAL sharpangle)
27741 {
27742 triface adjtet;
27743 face startsh, spinsh, neighsh;
27744 face segloop, prevseg, nextseg;
27745 point eorg, edest;
27746 REAL ang, smallang;
27747 bool issharp;
27748 int sharpsegcount;
27749
27750 if (b->verbose > 0) {
27751 printf(" Marking sharp segments.\n");
27752 }
27753
27754 smallang = sharpangle * PI / 180.;
27755 sharpsegcount = 0;
27756 eorg = edest = (point) NULL;
27757
27758
27759
27760 subsegs->traversalinit();
27761 segloop.sh = shellfacetraverse(subsegs);
27762 while (segloop.sh != (shellface *) NULL) {
27763 segloop.shver = 0;
27764 senext2(segloop, prevseg);
27765 spivotself(prevseg);
27766 if (prevseg.sh == dummysh) {
27767
27768 assert(shelltype(segloop) != SHARP);
27769 issharp = false;
27770 spivot(segloop, startsh);
27771 if (startsh.sh != dummysh) {
27772
27773 eorg = sorg(segloop);
27774 edest = sdest(segloop);
27775 spinsh = startsh;
27776 do {
27777 if (sorg(spinsh) != eorg) {
27778 sesymself(spinsh);
27779 }
27780
27781 stpivot(spinsh, adjtet);
27782 if (adjtet.tet != dummytet) {
27783
27784 spivot(spinsh, neighsh);
27785
27786 if (neighsh.sh != spinsh.sh) {
27787
27788 ang = facedihedral(eorg, edest, sapex(spinsh), sapex(neighsh));
27789
27790 if (!issharp) issharp = (ang < smallang);
27791
27792 minfacetdihed = minfacetdihed < ang ? minfacetdihed : ang;
27793 }
27794 }
27795
27796 spivotself(spinsh);
27797 } while (spinsh.sh != startsh.sh);
27798
27799
27800 spinsh = startsh;
27801 do {
27802 if (sorg(spinsh) != eorg) {
27803 sesymself(spinsh);
27804 }
27805
27806 neighsh = spinsh;
27807
27808
27809
27810
27811 ang = 0.0;
27812 do {
27813 ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27814 senext2self(neighsh);
27815 sspivot(neighsh, nextseg);
27816 if (nextseg.sh != dummysh) break;
27817
27818 spivotself(neighsh);
27819 assert(neighsh.sh != dummysh);
27820 if (sorg(neighsh) != eorg) {
27821 sesymself(neighsh);
27822 }
27823 } while (true);
27824
27825 if (!issharp) issharp = (ang < smallang);
27826
27827 minfaceang = minfaceang < ang ? minfaceang : ang;
27828
27829 spivotself(spinsh);
27830 } while (spinsh.sh != startsh.sh);
27831
27832 }
27833 if (issharp) {
27834 setshelltype(segloop, SHARP);
27835
27836 senext(segloop, nextseg);
27837 spivotself(nextseg);
27838 while (nextseg.sh != dummysh) {
27839 nextseg.shver = 0;
27840 setshelltype(nextseg, SHARP);
27841 senextself(nextseg);
27842 spivotself(nextseg);
27843 }
27844 sharpsegcount++;
27845 }
27846 }
27847 segloop.sh = shellfacetraverse(subsegs);
27848 }
27849
27850
27851
27852
27853 subsegs->traversalinit();
27854 segloop.sh = shellfacetraverse(subsegs);
27855 while (segloop.sh != (shellface *) NULL) {
27856
27857 segloop.shver = 0;
27858 senext(segloop, nextseg);
27859 spivotself(nextseg);
27860
27861 if (nextseg.sh == dummysh) {
27862
27863 issharp = (shelltype(segloop) == SHARP);
27864 spivot(segloop, startsh);
27865 if (startsh.sh != dummysh) {
27866
27867 eorg = sdest(segloop);
27868 spinsh = startsh;
27869 do {
27870 if (sorg(spinsh) != eorg) {
27871 sesymself(spinsh);
27872 }
27873
27874 neighsh = spinsh;
27875 ang = 0.0;
27876 do {
27877 ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27878 senext2self(neighsh);
27879 sspivot(neighsh, nextseg);
27880 if (nextseg.sh != dummysh) break;
27881
27882 spivotself(neighsh);
27883 assert(neighsh.sh != dummysh);
27884 if (sorg(neighsh) != eorg) {
27885 sesymself(neighsh);
27886 }
27887 } while (true);
27888
27889 if (!issharp) issharp = (ang < smallang);
27890
27891 minfaceang = minfaceang < ang ? minfaceang : ang;
27892
27893 spivotself(spinsh);
27894 } while (spinsh.sh != startsh.sh);
27895 }
27896 if (issharp) {
27897 setshelltype(segloop, SHARP);
27898
27899 senext2(segloop, prevseg);
27900 spivotself(prevseg);
27901 while (prevseg.sh != dummysh) {
27902 prevseg.shver = 0;
27903 setshelltype(prevseg, SHARP);
27904 senext2self(prevseg);
27905 spivotself(prevseg);
27906 }
27907 sharpsegcount++;
27908 }
27909 }
27910 segloop.sh = shellfacetraverse(subsegs);
27911 }
27912
27913 if ((b->verbose > 0) && (sharpsegcount > 0)) {
27914 printf(" %d sharp segments.\n", sharpsegcount);
27915 }
27916 }
27917
27919
27920
27921
27922
27923
27924
27925
27926
27927
27928
27929
27930
27931
27932
27933
27934
27935
27937
27938 void tetgenmesh::decidefeaturepointsizes()
27939 {
27940 list *tetlist, *verlist;
27941 shellface **segsperverlist;
27942 triface starttet;
27943 face shloop;
27944 face checkseg, prevseg, nextseg, testseg;
27945 point ploop, adjpt, e1, e2;
27946 REAL lfs_0, len, vol, maxlen, varlen;
27947 bool isfeature;
27948 int *idx2seglist;
27949 int featurecount;
27950 int idx, i, j;
27951
27952 maxlen = 0.0;
27953
27954 if (b->verbose > 0) {
27955 printf(" Deciding feature-point sizes.\n");
27956 }
27957
27958
27959 makesegmentmap(idx2seglist, segsperverlist);
27960
27961 tetlist = new list(sizeof(triface), NULL, 256);
27962 verlist = new list(sizeof(point *), NULL, 256);
27963
27964 if (b->fixedvolume) {
27965
27966
27967 maxlen = pow(6.0 * b->maxvolume, 1.0/3.0);
27968 }
27969
27970 if (!b->refine) {
27971
27972 featurecount = 0;
27973 points->traversalinit();
27974 ploop = pointtraverse();
27975 while (ploop != (point) NULL) {
27976 if (pointtype(ploop) == NACUTEVERTEX) {
27977 if (point2sh(ploop) != (shellface) NULL) {
27978 setpointtype(ploop, FREESEGVERTEX);
27979 featurecount++;
27980 }
27981 }
27982 ploop = pointtraverse();
27983 }
27984 #ifdef SELF_CHECK
27985 if ((b->verbose > 0) && (featurecount > 0)) {
27986 printf(" %d Steiner points correction.\n", featurecount);
27987 }
27988 #endif
27989 }
27990
27991
27992
27993
27994 featurecount = 0;
27995 points->traversalinit();
27996 ploop = pointtraverse();
27997 while (ploop != (point) NULL) {
27998 if (pointtype(ploop) != FREESEGVERTEX) {
27999
28000 isfeature = false;
28001 idx = pointmark(ploop) - in->firstnumber;
28002 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; i++) {
28003 checkseg.sh = segsperverlist[i];
28004 isfeature = (shelltype(checkseg) == SHARP);
28005 }
28006
28007 if (isfeature) {
28008
28009 sstpivot(&checkseg, &starttet);
28010
28011 tetlist->append(&starttet);
28012 formstarpolyhedron(ploop, tetlist, verlist, true);
28013
28014 if (ploop[pointmtrindex] == 0.0) {
28015
28016 lfs_0 = longest;
28017 for (i = 0; i < verlist->len(); i++) {
28018 adjpt = * (point *)(* verlist)[i];
28019 if (pointtype(adjpt) == FREESEGVERTEX) {
28020
28021 sdecode(point2sh(adjpt), checkseg);
28022 assert(checkseg.sh != dummysh);
28023 checkseg.shver = 0;
28024
28025 prevseg = checkseg;
28026 do {
28027 senext2(prevseg, testseg);
28028 spivotself(testseg);
28029 if (testseg.sh == dummysh) break;
28030 prevseg = testseg;
28031 prevseg.shver = 0;
28032 } while (true);
28033
28034 nextseg = checkseg;
28035 do {
28036 senext(nextseg, testseg);
28037 spivotself(testseg);
28038 if (testseg.sh == dummysh) break;
28039 nextseg = testseg;
28040 nextseg.shver = 0;
28041 } while (true);
28042 e1 = sorg(prevseg);
28043 e2 = sdest(nextseg);
28044
28045 if (ploop == e1) {
28046
28047 adjpt = e2;
28048 } else if (ploop == e2) {
28049
28050 adjpt = e1;
28051 }
28052 }
28053 len = distance(ploop, adjpt);
28054 if (lfs_0 > len) lfs_0 = len;
28055 }
28056 ploop[pointmtrindex] = lfs_0;
28057 }
28058 if (b->fixedvolume) {
28059
28060 if (ploop[pointmtrindex] > maxlen) {
28061 ploop[pointmtrindex] = maxlen;
28062 }
28063 }
28064 if (b->varvolume) {
28065
28066 for (i = 0; i < tetlist->len(); i++) {
28067 starttet = * (triface *)(* tetlist)[i];
28068 vol = volumebound(starttet.tet);
28069 if (vol > 0.0) {
28070 varlen = pow(6 * vol, 1.0/3.0);
28071 if (ploop[pointmtrindex] > varlen) {
28072 ploop[pointmtrindex] = varlen;
28073 }
28074 }
28075 }
28076 }
28077
28078 tetlist->clear();
28079 verlist->clear();
28080 featurecount++;
28081 } else {
28082
28083 ploop[pointmtrindex] = 0.0;
28084 }
28085 }
28086 ploop = pointtraverse();
28087 }
28088
28089 if (b->verbose > 0) {
28090 printf(" %d feature points.\n", featurecount);
28091 }
28092
28093 if (!b->refine) {
28094
28095
28096
28097 featurecount = 0;
28098 points->traversalinit();
28099 ploop = pointtraverse();
28100 while (ploop != (point) NULL) {
28101 if (pointtype(ploop) == FREESEGVERTEX) {
28102 if (ploop[pointmtrindex] == 0.0) {
28103 sdecode(point2sh(ploop), checkseg);
28104 assert(checkseg.sh != dummysh);
28105 if (shelltype(checkseg) == SHARP) {
28106 checkseg.shver = 0;
28107
28108 prevseg = checkseg;
28109 do {
28110 senext2(prevseg, testseg);
28111 spivotself(testseg);
28112 if (testseg.sh == dummysh) break;
28113 prevseg = testseg;
28114 prevseg.shver = 0;
28115 } while (true);
28116
28117 nextseg = checkseg;
28118 do {
28119 senext(nextseg, testseg);
28120 spivotself(testseg);
28121 if (testseg.sh == dummysh) break;
28122 nextseg = testseg;
28123 nextseg.shver = 0;
28124 } while (true);
28125 e1 = sorg(prevseg);
28126 e2 = sdest(nextseg);
28127 len = distance(e1, e2);
28128 lfs_0 = distance(e1, ploop);
28129
28130 if (b->nobisect == 0) {
28131 assert(lfs_0 < len);
28132 }
28133 ploop[pointmtrindex] = e1[pointmtrindex]
28134 + (lfs_0 / len) * (e2[pointmtrindex] - e1[pointmtrindex]);
28135 featurecount++;
28136 } else {
28137
28138 ploop[pointmtrindex] = 0.0;
28139 }
28140 }
28141 }
28142 ploop = pointtraverse();
28143 }
28144 if ((b->verbose > 0) && (featurecount > 0)) {
28145 printf(" %d Steiner feature points.\n", featurecount);
28146 }
28147 }
28148
28149 if (varconstraint) {
28150
28151 if (in->facetconstraintlist) {
28152
28153 subfaces->traversalinit();
28154 shloop.sh = shellfacetraverse(subfaces);
28155 while (shloop.sh != (shellface *) NULL) {
28156 varlen = areabound(shloop);
28157 if (varlen > 0.0) {
28158
28159 varlen = sqrt(varlen);
28160 for (j = 0; j < 3; j++) {
28161 ploop = (point) shloop.sh[3 + j];
28162 isfeature = false;
28163 idx = pointmark(ploop) - in->firstnumber;
28164 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28165 i++) {
28166 checkseg.sh = segsperverlist[i];
28167 isfeature = (shelltype(checkseg) == SHARP);
28168 }
28169 if (isfeature) {
28170 assert(ploop[pointmtrindex] > 0.0);
28171 if (ploop[pointmtrindex] > varlen) {
28172 ploop[pointmtrindex] = varlen;
28173 }
28174 }
28175 }
28176 }
28177 shloop.sh = shellfacetraverse(subfaces);
28178 }
28179 }
28180 if (in->segmentconstraintlist) {
28181
28182 subsegs->traversalinit();
28183 shloop.sh = shellfacetraverse(subsegs);
28184 while (shloop.sh != (shellface *) NULL) {
28185 varlen = areabound(shloop);
28186 if (varlen > 0.0) {
28187
28188 for (j = 0; j < 2; j++) {
28189 ploop = (point) shloop.sh[3 + j];
28190 isfeature = false;
28191 idx = pointmark(ploop) - in->firstnumber;
28192 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28193 i++) {
28194 checkseg.sh = segsperverlist[i];
28195 isfeature = (shelltype(checkseg) == SHARP);
28196 }
28197 if (isfeature) {
28198 assert(ploop[pointmtrindex] > 0.0);
28199 if (ploop[pointmtrindex] > varlen) {
28200 ploop[pointmtrindex] = varlen;
28201 }
28202 }
28203 }
28204 }
28205 shloop.sh = shellfacetraverse(subsegs);
28206 }
28207 }
28208 }
28209
28210 delete [] segsperverlist;
28211 delete [] idx2seglist;
28212 delete tetlist;
28213 delete verlist;
28214 }
28215
28217
28218
28219
28221
28222 void tetgenmesh::enqueueencsub(face* testsub, point encpt, int quenumber,
28223 REAL* cent)
28224 {
28225 badface *encsub;
28226 int i;
28227
28228 encsub = (badface *) badsubfaces->alloc();
28229 encsub->ss = *testsub;
28230 encsub->forg = sorg(*testsub);
28231 encsub->fdest = sdest(*testsub);
28232 encsub->fapex = sapex(*testsub);
28233 encsub->foppo = (point) encpt;
28234 for (i = 0; i < 3; i++) encsub->cent[i] = cent[i];
28235 encsub->nextitem = (badface *) NULL;
28236
28237
28238 setshell2badface(encsub->ss, encsub);
28239
28240 *subquetail[quenumber] = encsub;
28241
28242 subquetail[quenumber] = &encsub->nextitem;
28243 if (b->verbose > 2) {
28244 printf(" Queuing subface (%d, %d, %d) [%d].\n", pointmark(encsub->forg),
28245 pointmark(encsub->fdest), pointmark(encsub->fapex), quenumber);
28246 }
28247 }
28248
28250
28251
28252
28254
28255 tetgenmesh::badface* tetgenmesh::dequeueencsub(int* pquenumber)
28256 {
28257 badface *result;
28258 int quenumber;
28259
28260
28261 for (quenumber = 2; quenumber >= 0; quenumber--) {
28262 result = subquefront[quenumber];
28263 if (result != (badface *) NULL) {
28264
28265 subquefront[quenumber] = result->nextitem;
28266
28267 if (subquefront[quenumber] == (badface *) NULL) {
28268 subquetail[quenumber] = &subquefront[quenumber];
28269 }
28270 *pquenumber = quenumber;
28271 return result;
28272 }
28273 }
28274 return (badface *) NULL;
28275 }
28276
28278
28279
28280
28282
28283 void tetgenmesh::enqueuebadtet(triface* testtet, REAL ratio2, REAL* cent)
28284 {
28285 badface *newbadtet;
28286 int queuenumber;
28287 int i;
28288
28289
28290 newbadtet = (badface *) badtetrahedrons->alloc();
28291 newbadtet->tt = *testtet;
28292 newbadtet->key = ratio2;
28293 if (cent != NULL) {
28294 for (i = 0; i < 3; i++) newbadtet->cent[i] = cent[i];
28295 } else {
28296 for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
28297 }
28298 newbadtet->forg = org(*testtet);
28299 newbadtet->fdest = dest(*testtet);
28300 newbadtet->fapex = apex(*testtet);
28301 newbadtet->foppo = oppo(*testtet);
28302 newbadtet->nextitem = (badface *) NULL;
28303
28304 if (ratio2 > b->goodratio) {
28305
28306 queuenumber = (int) (64.0 - 64.0 / ratio2);
28307
28308 if ((queuenumber > 63) || (queuenumber < 0)) {
28309 queuenumber = 63;
28310 }
28311 } else {
28312
28313 queuenumber = 0;
28314 }
28315
28316
28317 if (tetquefront[queuenumber] == (badface *) NULL) {
28318
28319 if (queuenumber > firstnonemptyq) {
28320
28321 nextnonemptyq[queuenumber] = firstnonemptyq;
28322 firstnonemptyq = queuenumber;
28323 } else {
28324
28325 i = queuenumber + 1;
28326 while (tetquefront[i] == (badface *) NULL) {
28327 i++;
28328 }
28329
28330 nextnonemptyq[queuenumber] = nextnonemptyq[i];
28331 nextnonemptyq[i] = queuenumber;
28332 }
28333
28334 tetquefront[queuenumber] = newbadtet;
28335 } else {
28336
28337 tetquetail[queuenumber]->nextitem = newbadtet;
28338 }
28339
28340 tetquetail[queuenumber] = newbadtet;
28341
28342 if (b->verbose > 2) {
28343 printf(" Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
28344 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
28345 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
28346 sqrt(ratio2), queuenumber);
28347 }
28348 }
28349
28351
28352
28353
28355
28356 tetgenmesh::badface* tetgenmesh::topbadtetra()
28357 {
28358
28359
28360 recentq = firstnonemptyq;
28361
28362 if (firstnonemptyq < 0) {
28363 return (badface *) NULL;
28364 } else {
28365
28366 return tetquefront[firstnonemptyq];
28367 }
28368 }
28369
28370 void tetgenmesh::dequeuebadtet()
28371 {
28372 badface *deadbadtet;
28373 int i;
28374
28375
28376 if (recentq >= 0) {
28377
28378 deadbadtet = tetquefront[recentq];
28379
28380 tetquefront[recentq] = deadbadtet->nextitem;
28381
28382 if (deadbadtet == tetquetail[recentq]) {
28383
28384 if (firstnonemptyq == recentq) {
28385
28386 firstnonemptyq = nextnonemptyq[firstnonemptyq];
28387 } else {
28388
28389 i = recentq + 1;
28390 while (tetquefront[i] == (badface *) NULL) {
28391 i++;
28392 }
28393 nextnonemptyq[i] = nextnonemptyq[recentq];
28394 }
28395 }
28396
28397 badfacedealloc(badtetrahedrons, deadbadtet);
28398 }
28399 }
28400
28402
28403
28404
28405
28406
28407
28408
28409
28410
28411
28412
28413
28414
28416
28417 bool tetgenmesh::checkseg4encroach(face* testseg, point testpt, point* prefpt,
28418 bool enqflag)
28419 {
28420 badface *encsubseg;
28421 triface starttet, spintet;
28422 point eorg, edest, eapex, encpt;
28423 REAL cent[3], radius, dist, diff;
28424 REAL maxradius;
28425 bool enq;
28426 int hitbdry;
28427
28428 enq = false;
28429 eorg = sorg(*testseg);
28430 edest = sdest(*testseg);
28431 cent[0] = 0.5 * (eorg[0] + edest[0]);
28432 cent[1] = 0.5 * (eorg[1] + edest[1]);
28433 cent[2] = 0.5 * (eorg[2] + edest[2]);
28434 radius = distance(cent, eorg);
28435
28436 if (varconstraint && (areabound(*testseg) > 0.0)) {
28437 enq = (2.0 * radius) > areabound(*testseg);
28438 }
28439
28440 if (!enq) {
28441 maxradius = 0.0;
28442 if (testpt == (point) NULL) {
28443
28444 sstpivot(testseg, &starttet);
28445 eapex = apex(starttet);
28446 spintet = starttet;
28447 hitbdry = 0;
28448 do {
28449 dist = distance(cent, apex(spintet));
28450 diff = dist - radius;
28451 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28452 if (diff <= 0.0) {
28453
28454 enq = true;
28455 if (prefpt != (point *) NULL) {
28456
28457 encpt = apex(spintet);
28458 circumsphere(eorg, edest, encpt, NULL, NULL, &dist);
28459 if (dist > maxradius) {
28460
28461 *prefpt = encpt;
28462 maxradius = dist;
28463 }
28464 } else {
28465 break;
28466 }
28467 }
28468 if (!fnextself(spintet)) {
28469 hitbdry++;
28470 if (hitbdry < 2) {
28471 esym(starttet, spintet);
28472 if (!fnextself(spintet)) {
28473 hitbdry++;
28474 }
28475 }
28476 }
28477 } while (apex(spintet) != eapex && (hitbdry < 2));
28478 } else {
28479
28480 dist = distance(cent, testpt);
28481 diff = dist - radius;
28482 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28483 enq = (diff <= 0.0);
28484 }
28485 }
28486
28487 if (enq && enqflag) {
28488 if (b->verbose > 2) {
28489 printf(" Queuing encroaching subsegment (%d, %d).\n",
28490 pointmark(eorg), pointmark(edest));
28491 }
28492 encsubseg = (badface *) badsubsegs->alloc();
28493 encsubseg->ss = *testseg;
28494 encsubseg->forg = eorg;
28495 encsubseg->fdest = edest;
28496 encsubseg->foppo = (point) NULL;
28497
28498
28499 setshell2badface(encsubseg->ss, encsubseg);
28500 }
28501
28502 return enq;
28503 }
28504
28506
28507
28508
28509
28510
28511
28512
28513
28514
28515
28517
28518 bool tetgenmesh::checksub4encroach(face* testsub, point testpt, bool enqflag)
28519 {
28520 triface abuttet;
28521 point pa, pb, pc, encpt;
28522 REAL A[4][4], rhs[4], D;
28523 REAL cent[3], area;
28524 REAL radius, dist, diff;
28525 bool enq;
28526 int indx[4];
28527 int quenumber;
28528
28529 enq = false;
28530 radius = 0.0;
28531 encpt = (point) NULL;
28532
28533 pa = sorg(*testsub);
28534 pb = sdest(*testsub);
28535 pc = sapex(*testsub);
28536
28537
28538 A[0][0] = pb[0] - pa[0];
28539 A[0][1] = pb[1] - pa[1];
28540 A[0][2] = pb[2] - pa[2];
28541 A[1][0] = pc[0] - pa[0];
28542 A[1][1] = pc[1] - pa[1];
28543 A[1][2] = pc[2] - pa[2];
28544 cross(A[0], A[1], A[2]);
28545
28546 if (varconstraint && (areabound(*testsub) > 0.0)) {
28547
28548 area = 0.5 * sqrt(dot(A[2], A[2]));
28549 enq = area > areabound(*testsub);
28550 if (enq) {
28551 quenumber = 2;
28552 }
28553 }
28554
28555
28556 rhs[0] = 0.5 * dot(A[0], A[0]);
28557 rhs[1] = 0.5 * dot(A[1], A[1]);
28558 rhs[2] = 0.0;
28559
28560
28561 if (lu_decmp(A, 3, indx, &D, 0)) {
28562 lu_solve(A, 3, indx, rhs, 0);
28563 cent[0] = pa[0] + rhs[0];
28564 cent[1] = pa[1] + rhs[1];
28565 cent[2] = pa[2] + rhs[2];
28566 radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
28567 }
28568
28569 if (!enq) {
28570
28571 if (testpt == (point) NULL) {
28572 stpivot(*testsub, abuttet);
28573 if (abuttet.tet != dummytet) {
28574 dist = distance(cent, oppo(abuttet));
28575 diff = dist - radius;
28576 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28577 enq = (diff <= 0.0);
28578 if (enq) encpt = oppo(abuttet);
28579 }
28580 if (!enq) {
28581 sesymself(*testsub);
28582 stpivot(*testsub, abuttet);
28583 if (abuttet.tet != dummytet) {
28584 dist = distance(cent, oppo(abuttet));
28585 diff = dist - radius;
28586 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28587 enq = (diff <= 0.0);
28588 if (enq) encpt = oppo(abuttet);
28589 }
28590 }
28591 } else {
28592 dist = distance(cent, testpt);
28593 diff = dist - radius;
28594 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28595 enq = (diff <= 0.0);
28596 }
28597 if (enq) {
28598 quenumber = 0;
28599 }
28600 }
28601
28602 if (enq && enqflag) {
28603 enqueueencsub(testsub, encpt, quenumber, cent);
28604 }
28605
28606 return enq;
28607 }
28608
28610
28611
28612
28613
28614
28615
28616
28618
28619 bool tetgenmesh::checktet4badqual(triface* testtet, bool enqflag)
28620 {
28621 point pa, pb, pc, pd, pe1, pe2;
28622 REAL vda[3], vdb[3], vdc[3];
28623 REAL vab[3], vbc[3], vca[3];
28624 REAL N[4][3], A[4][4], rhs[4], D;
28625 REAL elen[6], circumcent[3];
28626 REAL bicent[3], offcent[3];
28627 REAL volume, L, cosd;
28628 REAL radius2, smlen2, ratio2;
28629 REAL dist, sdist, split;
28630 bool enq;
28631 int indx[4];
28632 int sidx, i, j;
28633
28634 pa = (point) testtet->tet[4];
28635 pb = (point) testtet->tet[5];
28636 pc = (point) testtet->tet[6];
28637 pd = (point) testtet->tet[7];
28638
28639
28640
28641 for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
28642 for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
28643 for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
28644
28645 for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
28646 for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i];
28647 for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i];
28648
28649
28650 lu_decmp(A, 3, indx, &D, 0);
28651
28652 volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
28653 if (volume < 0.0) volume = -volume;
28654
28655 rhs[0] = 0.5 * dot(vda, vda);
28656 rhs[1] = 0.5 * dot(vdb, vdb);
28657 rhs[2] = 0.5 * dot(vdc, vdc);
28658 lu_solve(A, 3, indx, rhs, 0);
28659
28660 for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
28661
28662 radius2 = dot(rhs, rhs);
28663
28664 elen[0] = dot(vda, vda);
28665 elen[1] = dot(vdb, vdb);
28666 elen[2] = dot(vdc, vdc);
28667 elen[3] = dot(vab, vab);
28668 elen[4] = dot(vbc, vbc);
28669 elen[5] = dot(vca, vca);
28670 smlen2 = elen[0]; sidx = 0;
28671 for (i = 1; i < 6; i++) {
28672 if (smlen2 > elen[i]) { smlen2 = elen[i]; sidx = i; }
28673 }
28674
28675 ratio2 = radius2 / smlen2;
28676
28677 enq = ratio2 > b->goodratio;
28678 if (!enq) {
28679
28680
28681
28682
28683
28684 for (j = 0; j < 3; j++) {
28685 for (i = 0; i < 3; i++) rhs[i] = 0.0;
28686 rhs[j] = 1.0;
28687 lu_solve(A, 3, indx, rhs, 0);
28688 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
28689 }
28690
28691 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
28692
28693 for (i = 0; i < 4; i++) {
28694 L = sqrt(dot(N[i], N[i]));
28695 if (L > 0.0) {
28696 for (j = 0; j < 3; j++) N[i][j] /= L;
28697 }
28698 }
28699
28700
28701 for (i = 1; i < 4 && !enq; i++) {
28702 cosd = -dot(N[0], N[i]);
28703 enq = cosd > cosmindihed;
28704 }
28705 if (!enq) {
28706 for (i = 2; i < 4 && !enq; i++) {
28707 cosd = -dot(N[1], N[i]);
28708 enq = cosd > cosmindihed;
28709 }
28710 if (!enq) {
28711 cosd = -dot(N[2], N[3]);
28712 enq = cosd > cosmindihed;
28713 }
28714 }
28715
28716 } else if (b->offcenter) {
28717
28718 switch (sidx) {
28719 case 0:
28720 pe1 = pd; pe2 = pa; break;
28721 case 1:
28722 pe1 = pd; pe2 = pb; break;
28723 case 2:
28724 pe1 = pd; pe2 = pc; break;
28725 case 3:
28726 pe1 = pa; pe2 = pb; break;
28727 case 4:
28728 pe1 = pb; pe2 = pc; break;
28729 case 5:
28730 pe1 = pc; pe2 = pa; break;
28731 default:
28732 pe1 = pe2 = (point) NULL;
28733 }
28734
28735 for (i = 0; i < 3; i++) bicent[i] = 0.5 * (pe1[i] + pe2[i]);
28736 dist = distance(bicent, circumcent);
28737
28738
28739 sdist = b->alpha3 * (b->minratio+sqrt(b->goodratio-0.25))* sqrt(smlen2);
28740 split = sdist / dist;
28741 if (split > 1.0) split = 1.0;
28742
28743 for (i = 0; i < 3; i++) {
28744 offcent[i] = bicent[i] + split * (circumcent[i] - bicent[i]);
28745 }
28746 }
28747
28748 if (!enq && (b->varvolume || b->fixedvolume)) {
28749
28750 enq = b->fixedvolume && (volume > b->maxvolume);
28751 if (!enq && b->varvolume) {
28752 enq = (volume > volumebound(testtet->tet)) &&
28753 (volumebound(testtet->tet) > 0.0);
28754 }
28755 }
28756
28757 if (!enq) {
28758
28759 if (b->metric) {
28760
28761 sdist = sqrt(radius2) / b->alpha1;
28762 for (i = 0; i < 4; i++) {
28763 pa = (point) testtet->tet[4 + i];
28764
28765 dist = pa[pointmtrindex];
28766 enq = ((dist < sdist) && (dist > 0.0));
28767 if (enq) break;
28768
28769
28770 }
28771
28772
28773 }
28774 }
28775
28776 if (enq && enqflag) {
28777 if (b->offcenter && (ratio2 > b->goodratio)) {
28778 for (i = 0; i < 3; i++) circumcent[i] = offcent[i];
28779 }
28780 enqueuebadtet(testtet, ratio2, circumcent);
28781 }
28782
28783 return enq;
28784 }
28785
28787
28788
28789
28790
28791
28792
28793
28794
28795
28796
28797
28798
28799
28800
28802
28803 bool tetgenmesh::acceptsegpt(point segpt, point refpt, face* splitseg)
28804 {
28805 point p[2];
28806 REAL L, lfs;
28807 int i, j;
28808
28809 if (b->nobisect == 1) {
28810
28811 triface spintet;
28812 point pc;
28813 sstpivot(splitseg, &spintet);
28814 assert(spintet.tet != dummytet);
28815 pc = apex(spintet);
28816 do {
28817 if (!fnextself(spintet)) {
28818
28819 return false;
28820 }
28821 } while (pc != apex(spintet));
28822 } else if (b->nobisect > 1) {
28823
28824 return false;
28825 }
28826
28827 p[0] = sorg(*splitseg);
28828 p[1] = sdest(*splitseg);
28829 if (varconstraint && (areabound(*splitseg) > 0)) {
28830 lfs = areabound(*splitseg);
28831 L = distance(p[0], p[1]);
28832 if (L > lfs) {
28833 return true;
28834 }
28835 }
28836
28837 j = 0;
28838 for (i = 0; i < 2; i++) {
28839
28840 if (p[i][pointmtrindex] > 0.0) {
28841 lfs = b->alpha2 * p[i][pointmtrindex];
28842 L = distance(p[i], segpt);
28843 if (L < lfs) j++;
28844 }
28845 }
28846 if (j == 0) return true;
28847
28848
28849 if (refpt != (point) NULL) {
28850 cdtenforcesegpts++;
28851 return true;
28852 }
28853
28854
28855 rejsegpts++;
28856 return false;
28857 }
28858
28860
28861
28862
28863
28864
28865
28866
28867
28868
28869
28870
28872
28873 bool tetgenmesh::acceptfacpt(point facpt, list* subceillist, list* verlist)
28874 {
28875 face *testsh;
28876 point p[2], ploop;
28877 REAL L, lfs;
28878 int idx, i, j;
28879
28880 if (b->nobisect == 1) {
28881
28882 triface testtet;
28883 testsh = (face *)(* subceillist)[0];
28884 stpivot(*testsh, testtet);
28885 if (testtet.tet != dummytet) {
28886 sesymself(*testsh);
28887 stpivot(*testsh, testtet);
28888 }
28889 if (testtet.tet == dummytet) return false;
28890 } else if (b->nobisect > 1) {
28891
28892 return false;
28893 }
28894
28895
28896 for (i = 0; i < subceillist->len(); i++) {
28897 testsh = (face *)(* subceillist)[i];
28898 p[0] = sorg(*testsh);
28899 p[1] = sdest(*testsh);
28900 for (j = 0; j < 2; j++) {
28901 idx = pointmark(p[j]);
28902 if (idx >= 0) {
28903 setpointmark(p[j], -idx - 1);
28904 verlist->append(&(p[j]));
28905 }
28906 }
28907 }
28908
28909 j = 0;
28910 for (i = 0; i < verlist->len(); i++) {
28911 ploop = * (point *)(* verlist)[i];
28912
28913 idx = pointmark(ploop);
28914 setpointmark(ploop, -(idx + 1));
28915
28916 if (ploop[pointmtrindex] > 0.0) {
28917 lfs = b->alpha2 * ploop[pointmtrindex];
28918 L = distance(ploop, facpt);
28919 if (L < lfs) j++;
28920 }
28921 }
28922 verlist->clear();
28923
28924 if (j == 0) return true;
28925
28926 rejsubpts++;
28927 return false;
28928 }
28929
28931
28932
28933
28934
28935
28936
28937
28938
28940
28941 bool tetgenmesh::acceptvolpt(point volpt, list* ceillist, list* verlist)
28942 {
28943 triface* testtet;
28944 point p[3], ploop;
28945 REAL L, lfs;
28946 int idx, i, j;
28947
28948
28949 for (i = 0; i < ceillist->len(); i++) {
28950 testtet = (triface *)(* ceillist)[i];
28951 p[0] = org(*testtet);
28952 p[1] = dest(*testtet);
28953 p[2] = apex(*testtet);
28954 for (j = 0; j < 3; j++) {
28955 idx = pointmark(p[j]);
28956 if (idx >= 0) {
28957 setpointmark(p[j], -idx - 1);
28958 verlist->append(&(p[j]));
28959 }
28960 }
28961 }
28962
28963 j = 0;
28964 for (i = 0; i < verlist->len(); i++) {
28965 ploop = * (point *)(* verlist)[i];
28966
28967 idx = pointmark(ploop);
28968 setpointmark(ploop, -(idx + 1));
28969
28970 if (ploop[pointmtrindex] > 0.0) {
28971 lfs = b->alpha2 * ploop[pointmtrindex];
28972 L = distance(ploop, volpt);
28973 if (L < lfs) j++;
28974 }
28975 }
28976 verlist->clear();
28977
28978 if (j == 0) return true;
28979
28980 rejtetpts++;
28981 return false;
28982 }
28983
28985
28986
28987
28989
28990 void tetgenmesh::getsplitpoint(point e1, point e2, point refpt, point newpt)
28991 {
28992 point ei, ej;
28993 REAL split, L, d1, d2, ps, rs;
28994 bool acutea, acuteb;
28995 int i;
28996
28997 if (refpt != (point) NULL) {
28998
28999 acutea = (pointtype(e1) == ACUTEVERTEX);
29000 acuteb = (pointtype(e2) == ACUTEVERTEX);
29001 if (acutea ^ acuteb) {
29002
29003 ei = acutea ? e1 : e2;
29004 ej = acutea ? e2 : e1;
29005 L = distance(ei, ej);
29006
29007 d1 = distance(ei, refpt);
29008 split = d1 / L;
29009 for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29010
29011 d2 = distance(refpt, newpt);
29012 if (d2 > (L - d1)) {
29013
29014 if ((d1 - d2) > (0.5 * d1)) {
29015 split = (d1 - d2) / L;
29016 } else {
29017 split = 0.5 * d1 / L;
29018 }
29019 for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29020 if (b->verbose > 1) {
29021 printf(" Found by rule-3:");
29022 }
29023 r3count++;
29024 } else {
29025 if (b->verbose > 1) {
29026 printf(" Found by rule-2:");
29027 }
29028 r2count++;
29029 }
29030 if (b->verbose > 1) {
29031 printf(" center %d, split = %.12g.\n", pointmark(ei), split);
29032 }
29033
29034 d1 = distance(ei, newpt);
29035 d2 = distance(newpt, refpt);
29036 ps = randgenerator(d2 * b->epsilon2 * 1e+2);
29037 rs = ps / d1;
29038
29039 for (i = 0; i < 3; i++) newpt[i] = ei[i] + (1.0+rs) * (newpt[i] - ei[i]);
29040 } else {
29041
29042 for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29043
29044 d1 = 0.5 * distance(e1, e2);
29045 ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29046 rs = ps / d1;
29047 for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29048 }
29049 } else {
29050
29051 for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29052
29053 d1 = 0.5 * distance(e1, e2);
29054 ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29055 rs = ps / d1;
29056 for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29057 }
29058 }
29059
29061
29062
29063
29064
29065
29066
29067
29068
29070
29071 void tetgenmesh::shepardinterpolate(point newpt, list *verlist)
29072 {
29073 point neipt;
29074 REAL *weights, sumweight;
29075 REAL vec[3];
29076 int i, j;
29077
29078 weights = new REAL[verlist->len()];
29079 sumweight = 0.0;
29080
29081
29082 for (i = 0; i < verlist->len(); i++) {
29083 neipt = * (point *)(* verlist)[i];
29084 for (j = 0; j < 3; j++) vec[j] = neipt[j] - newpt[j];
29085 weights[i] = 1.0 / dot(vec, vec);
29086 sumweight += weights[i];
29087 }
29088
29089 newpt[pointmtrindex] = 0.0;
29090 for (i = 0; i < verlist->len(); i++) {
29091 neipt = * (point *)(* verlist)[i];
29092 newpt[pointmtrindex] += (weights[i] * neipt[pointmtrindex]) / sumweight;
29093 }
29094
29095 delete [] weights;
29096 }
29097
29099
29100
29101
29102
29103
29104
29106
29107 void tetgenmesh::setnewpointsize(point newpt, point e1, point e2)
29108 {
29109 if (b->metric) {
29110
29111 triface bgmtet;
29112
29113 decode(point2bgmtet(e1), bgmtet);
29114 p1interpolatebgm(newpt, &bgmtet, NULL);
29115 } else {
29116 if (e2 != (point) NULL) {
29117
29118 REAL split, l, d;
29119 l = distance(e1, e2);
29120 d = distance(e1, newpt);
29121 split = d / l;
29122 #ifdef SELF_CHECK
29123
29124 assert(e1[pointmtrindex] > 0.0);
29125 assert(e2[pointmtrindex] > 0.0);
29126 #endif
29127 newpt[pointmtrindex] = (1.0 - split) * e1[pointmtrindex]
29128 + split * e2[pointmtrindex];
29129 }
29130 }
29131 }
29132
29134
29135
29136
29138
29139 void tetgenmesh::splitencseg(point newpt, face* splitseg, list* tetlist,
29140 list* sublist, list* verlist, queue* flipque, bool chkencsub, bool chkbadtet,
29141 bool optflag)
29142 {
29143 list *mytetlist;
29144 queue *myflipque;
29145 triface starttet;
29146 face startsh, spinsh, checksh;
29147 int i;
29148
29149 mytetlist = NULL;
29150 myflipque = NULL;
29151
29152 if (optflag) {
29153 mytetlist = new list(sizeof(triface), NULL, 1024);
29154 myflipque = new queue(sizeof(badface));
29155 tetlist = mytetlist;
29156 flipque = myflipque;
29157 }
29158
29159
29160 splitseg->shver = 0;
29161
29162 sstpivot(splitseg, &starttet);
29163 splittetedge(newpt, &starttet, flipque);
29164
29165 flip(flipque, NULL);
29166
29167 if (!optflag) {
29168
29169 for (i = 0; i < 2; i++) {
29170 if (!shell2badface(*splitseg)) {
29171 checkseg4encroach(splitseg, NULL, NULL, true);
29172 }
29173 if (i == 1) break;
29174 senextself(*splitseg);
29175 spivotself(*splitseg);
29176 #ifdef SELF_CHECK
29177 assert(splitseg->sh != (shellface *) NULL);
29178 #endif
29179 splitseg->shver = 0;
29180 }
29181
29182 if (chkencsub) {
29183 spivot(*splitseg, startsh);
29184 spinsh = startsh;
29185 do {
29186 sublist->append(&spinsh);
29187 formstarpolygon(newpt, sublist, verlist);
29188 for (i = 0; i < sublist->len(); i++) {
29189 checksh = * (face *)(* sublist)[i];
29190 if (!shell2badface(checksh)) {
29191 checksub4encroach(&checksh, NULL, true);
29192 }
29193 }
29194 sublist->clear();
29195 if (verlist) verlist->clear();
29196 spivotself(spinsh);
29197 } while (spinsh.sh != startsh.sh);
29198 }
29199 }
29200
29201
29202 sstpivot(splitseg, &starttet);
29203 tetlist->append(&starttet);
29204 formstarpolyhedron(newpt, tetlist, verlist, true);
29205
29206 if (!optflag) {
29207
29208 tallencsegs(newpt, 1, &tetlist);
29209 if (chkencsub) {
29210
29211 tallencsubs(newpt, 1, &tetlist);
29212 }
29213 if (chkbadtet) {
29214
29215 for (i = 0; i < tetlist->len(); i++) {
29216 starttet = * (triface *)(* tetlist)[i];
29217 checktet4badqual(&starttet, true);
29218 }
29219 }
29220 tetlist->clear();
29221 } else {
29222
29223 for (i = 0; i < tetlist->len(); i++) {
29224 starttet = * (triface *)(* tetlist)[i];
29225 checktet4opt(&starttet, true);
29226 }
29227 delete mytetlist;
29228 delete myflipque;
29229 }
29230 }
29231
29233
29234
29235
29236
29237
29238
29239
29240
29241
29242
29244
29245 bool tetgenmesh::tallencsegs(point testpt, int n, list **ceillists)
29246 {
29247 list *ceillist;
29248 triface ceiltet;
29249 face checkseg;
29250 long oldencnum;
29251 int i, j, k;
29252
29253
29254 oldencnum = badsubsegs->items;
29255
29256 if (ceillists != (list **) NULL) {
29257 for (k = 0; k < n; k++) {
29258 ceillist = ceillists[k];
29259
29260 for (i = 0; i < ceillist->len(); i++) {
29261 ceiltet = * (triface *)(* ceillist)[i];
29262 ceiltet.ver = 0;
29263 for (j = 0; j < 3; j++) {
29264 tsspivot(&ceiltet, &checkseg);
29265 if (checkseg.sh != dummysh) {
29266
29267 if (!shell2badface(checkseg)) {
29268 checkseg4encroach(&checkseg, testpt, NULL, true);
29269 }
29270 }
29271 enextself(ceiltet);
29272 }
29273 }
29274 }
29275 } else {
29276
29277 subsegs->traversalinit();
29278 checkseg.sh = shellfacetraverse(subsegs);
29279 while (checkseg.sh != (shellface *) NULL) {
29280
29281 if (!shell2badface(checkseg)) {
29282 checkseg4encroach(&checkseg, testpt, NULL, true);
29283 }
29284 checkseg.sh = shellfacetraverse(subsegs);
29285 }
29286 }
29287
29288 return (badsubsegs->items > oldencnum);
29289 }
29290
29292
29293
29294
29295
29296
29297
29298
29299
29300
29301
29303
29304 bool tetgenmesh::tallencsubs(point testpt, int n, list** ceillists)
29305 {
29306 list *ceillist;
29307 triface ceiltet;
29308 face checksh;
29309 long oldencnum;
29310 int i, k;
29311
29312
29313 oldencnum = badsubfaces->items;
29314
29315 if (ceillists != (list **) NULL) {
29316 for (k = 0; k < n; k++) {
29317 ceillist = ceillists[k];
29318
29319 for (i = 0; i < ceillist->len(); i++) {
29320 ceiltet = * (triface *)(* ceillist)[i];
29321 tspivot(ceiltet, checksh);
29322 if (checksh.sh != dummysh) {
29323
29324 if (!shell2badface(checksh)) {
29325 checksub4encroach(&checksh, testpt, true);
29326 }
29327 }
29328 }
29329 }
29330 } else {
29331
29332 subfaces->traversalinit();
29333 checksh.sh = shellfacetraverse(subfaces);
29334 while (checksh.sh != (shellface *) NULL) {
29335
29336 if (!shell2badface(checksh)) {
29337 checksub4encroach(&checksh, testpt, true);
29338 }
29339 checksh.sh = shellfacetraverse(subfaces);
29340 }
29341 }
29342
29343 return (badsubfaces->items > oldencnum);
29344 }
29345
29347
29348
29349
29351
29352 void tetgenmesh::tallbadtetrahedrons()
29353 {
29354 triface tetloop;
29355
29356 tetrahedrons->traversalinit();
29357 tetloop.tet = tetrahedrontraverse();
29358 while (tetloop.tet != (tetrahedron *) NULL) {
29359 checktet4badqual(&tetloop, true);
29360 tetloop.tet = tetrahedrontraverse();
29361 }
29362 }
29363
29365
29366
29367
29368
29369
29370
29371
29372
29373
29374
29375
29377
29378 void tetgenmesh::repairencsegs(bool chkencsub, bool chkbadtet)
29379 {
29380 list **tetlists, **ceillists;
29381 list **sublists, **subceillists;
29382 list *tetlist, *sublist;
29383 queue *flipque;
29384 badface *encloop;
29385 face splitseg, symsplitseg;
29386 point newpt, sympt, refpt;
29387 point e1, e2;
29388 enum locateresult symloc;
29389 int nmax, n, i, j;
29390
29391 ceillists = NULL;
29392 flipque = NULL;
29393 subceillists = NULL;
29394 sublist = NULL;
29395 sublists = NULL;
29396 tetlist = NULL;
29397 tetlists = NULL;
29398
29399 n = 0;
29400 nmax = 128;
29401 if (!b->fliprepair) {
29402 tetlists = new list*[nmax];
29403 ceillists = new list*[nmax];
29404 sublists = new list*[nmax];
29405 subceillists = new list*[nmax];
29406 } else {
29407 tetlist = new list(sizeof(triface), NULL, 1024);
29408 sublist = new list(sizeof(face), NULL, 256);
29409 flipque = new queue(sizeof(badface));
29410 }
29411
29412
29413
29414 while ((badsubsegs->items > 0) && (steinerleft != 0)) {
29415 badsubsegs->traversalinit();
29416 encloop = badfacetraverse(badsubsegs);
29417 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
29418
29419 splitseg = encloop->ss;
29420
29421 setshell2badface(splitseg, NULL);
29422 if ((sorg(splitseg) == encloop->forg) &&
29423 (sdest(splitseg) == encloop->fdest)) {
29424 if (b->verbose > 1) {
29425 printf(" Get an enc-seg (%d, %d)\n", pointmark(encloop->forg),
29426 pointmark(encloop->fdest));
29427 }
29428 refpt = (point) NULL;
29429 if (b->conformdel) {
29430
29431 checkseg4encroach(&splitseg, NULL, &refpt, false);
29432 }
29433
29434 makepoint(&newpt);
29435 getsplitpoint(encloop->forg, encloop->fdest, refpt, newpt);
29436 setpointtype(newpt, FREESEGVERTEX);
29437 setpoint2sh(newpt, sencode(splitseg));
29438
29439 if (acceptsegpt(newpt, refpt, &splitseg)) {
29440
29441 if (checkpbcs) {
29442
29443 i = shellmark(splitseg) - 1;
29444 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
29445 makepoint(&sympt);
29446 symloc = getsegpbcsympoint(newpt, &splitseg, sympt, &symsplitseg,
29447 segpglist[j]);
29448 if (symloc == ONEDGE) {
29449 if (symsplitseg.sh != splitseg.sh) {
29450
29451 setpointtype(sympt, FREESEGVERTEX);
29452 setpoint2sh(sympt, sencode(symsplitseg));
29453
29454 e1 = sorg(symsplitseg);
29455 if (shelltype(symsplitseg) == SHARP) {
29456 e2 = sdest(symsplitseg);
29457 } else {
29458 e2 = (point) NULL;
29459 }
29460 if (!b->fliprepair) {
29461
29462 formbowatcavity(sympt, &symsplitseg, NULL, &n, &nmax,
29463 sublists, subceillists, tetlists, ceillists);
29464
29465 if (trimbowatcavity(sympt, &symsplitseg, n, sublists,
29466 subceillists, tetlists, ceillists, -1.0)) {
29467 bowatinsertsite(sympt, &symsplitseg, n, sublists,
29468 subceillists, tetlists, ceillists, NULL, flipque,
29469 true, chkencsub, chkbadtet);
29470 setnewpointsize(sympt, e1, e2);
29471 if (steinerleft > 0) steinerleft--;
29472 } else {
29473
29474 pointdealloc(sympt);
29475 }
29476
29477 releasebowatcavity(&symsplitseg, n, sublists, subceillists,
29478 tetlists, ceillists);
29479 } else {
29480 splitencseg(sympt, &symsplitseg, tetlist, sublist, NULL,
29481 flipque, chkencsub, chkbadtet, false);
29482 setnewpointsize(sympt, e1, e2);
29483 if (steinerleft > 0) steinerleft--;
29484 }
29485 } else {
29486
29487
29488 pointdealloc(sympt);
29489 }
29490 } else if (symloc == ONVERTEX) {
29491
29492
29493 pointdealloc(sympt);
29494 } else {
29495
29496
29497 pointdealloc(sympt);
29498 }
29499 }
29500 }
29501
29502 e1 = sorg(splitseg);
29503 if (shelltype(splitseg) == SHARP) {
29504 e2 = sdest(splitseg);
29505 } else {
29506 e2 = (point) NULL;
29507 }
29508 if (!b->fliprepair) {
29509
29510 formbowatcavity(newpt, &splitseg, NULL, &n, &nmax, sublists,
29511 subceillists, tetlists, ceillists);
29512
29513 if (trimbowatcavity(newpt, &splitseg, n, sublists, subceillists,
29514 tetlists, ceillists, -1.0)) {
29515 bowatinsertsite(newpt, &splitseg, n, sublists, subceillists,
29516 tetlists, ceillists, NULL, flipque, true,
29517 chkencsub, chkbadtet);
29518 setnewpointsize(newpt, e1, e2);
29519 if (steinerleft > 0) steinerleft--;
29520 } else {
29521
29522 pointdealloc(newpt);
29523 }
29524
29525 releasebowatcavity(&splitseg, n, sublists, subceillists, tetlists,
29526 ceillists);
29527 } else {
29528 splitencseg(newpt, &splitseg, tetlist, sublist, NULL, flipque,
29529 chkencsub, chkbadtet, false);
29530 setnewpointsize(newpt, e1, e2);
29531 if (steinerleft > 0) steinerleft--;
29532 }
29533 } else {
29534
29535 pointdealloc(newpt);
29536 }
29537 }
29538 badfacedealloc(badsubsegs, encloop);
29539 encloop = badfacetraverse(badsubsegs);
29540 }
29541 }
29542
29543 if (!b->fliprepair) {
29544 delete [] tetlists;
29545 delete [] ceillists;
29546 delete [] sublists;
29547 delete [] subceillists;
29548 } else {
29549 delete tetlist;
29550 delete sublist;
29551 delete flipque;
29552 }
29553 }
29554
29556
29557
29558
29559
29560
29561
29562
29563
29564
29565
29567
29568 void tetgenmesh::repairencsubs(bool chkbadtet)
29569 {
29570 list *tetlists[2], *ceillists[2];
29571 list *sublist, *subceillist;
29572 list *verlist;
29573 badface *encloop;
29574 face splitsub, symsplitsub;
29575 point newpt, sympt, e1;
29576 enum locateresult loc, symloc;
29577 bool reject;
29578 long oldptnum;
29579 int quenumber, n, i;
29580
29581 quenumber = 0;
29582 n = 0;
29583 sublist = (list *) NULL;
29584 subceillist = (list *) NULL;
29585 verlist = new list(sizeof(point *), NULL, 256);
29586
29587
29588
29589 while ((badsubfaces->items > 0) && (steinerleft != 0)) {
29590
29591 encloop = dequeueencsub(&quenumber);
29592 splitsub = encloop->ss;
29593
29594 setshell2badface(splitsub, NULL);
29595
29596 if (!isdead(&splitsub)
29597 && (sorg(splitsub) == encloop->forg)
29598 && (sdest(splitsub) == encloop->fdest)
29599 && (sapex(splitsub) == encloop->fapex)) {
29600 if (b->verbose > 1) {
29601 printf(" Dequeuing ensub (%d, %d, %d) [%d].\n",
29602 pointmark(encloop->forg), pointmark(encloop->fdest),
29603 pointmark(encloop->fapex), quenumber);
29604 }
29605
29606 makepoint(&newpt);
29607 for (i = 0; i < 3; i++) newpt[i] = encloop->cent[i];
29608 setpointtype(newpt, FREESUBVERTEX);
29609 setpoint2sh(newpt, sencode(splitsub));
29610
29611 abovepoint = facetabovepointarray[shellmark(splitsub)];
29612 if (abovepoint == (point) NULL) {
29613 getfacetabovepoint(&splitsub);
29614 }
29615
29616
29617 loc = locatesub(newpt, &splitsub, 1, b->epsilon * 1e+2);
29618 if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29619
29620 formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29621 &subceillist, tetlists, ceillists);
29622
29623 reject = tallencsegs(newpt, 2, ceillists);
29624
29625 if (!reject) {
29626 reject = !acceptfacpt(newpt, subceillist, verlist);
29627 }
29628 if (!reject) {
29629
29630 reject = !trimbowatcavity(newpt, NULL, n, &sublist, &subceillist,
29631 tetlists, ceillists, -1.0);
29632 }
29633 if (!reject) {
29634
29635
29636
29637
29638 reject = !sinfected(encloop->ss);
29639 }
29640 if (!reject) {
29641 if (checkpbcs) {
29642 if (shellpbcgroup(splitsub) >= 0) {
29643
29644 makepoint(&sympt);
29645 symloc = getsubpbcsympoint(newpt,&splitsub,sympt,&symsplitsub);
29646 if (symloc != ONVERTEX) {
29647
29648 releasebowatcavity(NULL, 2, &sublist, &subceillist, tetlists,
29649 ceillists);
29650
29651 formbowatcavity(sympt, NULL, &symsplitsub, &n, NULL, &sublist,
29652 &subceillist, tetlists, ceillists);
29653 reject = tallencsegs(sympt, 2, ceillists);
29654 if (!reject) {
29655 reject = !acceptfacpt(sympt, subceillist, verlist);
29656 }
29657 if (!reject) {
29658 reject = !trimbowatcavity(sympt,NULL,n,&sublist,&subceillist,
29659 tetlists, ceillists, -1.0);
29660 }
29661 if (!reject) {
29662
29663 setpoint2pbcpt(newpt, sympt);
29664 setpoint2pbcpt(sympt, newpt);
29665 setpointtype(sympt, FREESUBVERTEX);
29666 setpoint2sh(sympt, sencode(symsplitsub));
29667
29668 e1 = sorg(symsplitsub);
29669 bowatinsertsite(sympt, NULL, n, &sublist, &subceillist,
29670 tetlists,ceillists,NULL,NULL,false,true,chkbadtet);
29671 setnewpointsize(sympt, e1, NULL);
29672 if (steinerleft > 0) steinerleft--;
29673
29674 releasebowatcavity(NULL, n, &sublist, &subceillist, tetlists,
29675 ceillists);
29676 } else {
29677
29678
29679
29680
29681 pointdealloc(sympt);
29682
29683 }
29684 } else {
29685
29686 pointdealloc(sympt);
29687
29688 reject = true;
29689 }
29690 }
29691 }
29692 }
29693 if (!reject) {
29694
29695 if (checkpbcs) {
29696 if (shellpbcgroup(splitsub) >= 0) {
29697
29698 formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29699 &subceillist, tetlists, ceillists);
29700 trimbowatcavity(newpt, NULL, n, &sublist, &subceillist, tetlists,
29701 ceillists, -1.0);
29702 }
29703 }
29704
29705 e1 = sorg(splitsub);
29706 bowatinsertsite(newpt, NULL, n, &sublist, &subceillist, tetlists,
29707 ceillists, NULL, NULL, true, true, chkbadtet);
29708 setnewpointsize(newpt, e1, NULL);
29709 if (steinerleft > 0) steinerleft--;
29710 } else {
29711
29712
29713
29714
29715
29716
29717 pointdealloc(newpt);
29718 }
29719
29720 releasebowatcavity(NULL,n,&sublist,&subceillist,tetlists,ceillists);
29721 if (reject) {
29722
29723 if (badsubsegs->items > 0) {
29724
29725 oldptnum = points->items;
29726 repairencsegs(true, chkbadtet);
29727 if (points->items > oldptnum) {
29728
29729 splitsub = encloop->ss;
29730 if (!isdead(&splitsub)) {
29731 if (!shell2badface(splitsub)) {
29732 checksub4encroach(&splitsub, NULL, true);
29733 }
29734 }
29735 }
29736 }
29737 }
29738 } else {
29739
29740
29741
29742
29743
29744
29745
29746
29747
29748 if (loc == ONVERTEX) {
29749 printf("Internal error in repairencsubs():\n");
29750 printf(" During repairing encroached subface (%d, %d, %d)\n",
29751 pointmark(encloop->forg), pointmark(encloop->fdest),
29752 pointmark(encloop->fapex));
29753 printf(" New point %d is coincident with an existing vertex %d\n",
29754 pointmark(newpt), pointmark(sorg(splitsub)));
29755 internalerror();
29756 }
29757
29758
29759
29760 pointdealloc(newpt);
29761 }
29762 } else {
29763 if (!isdead(&splitsub)) {
29764
29765 checksub4encroach(&splitsub, NULL, true);
29766 }
29767 }
29768
29769 badfacedealloc(badsubfaces, encloop);
29770 }
29771
29772 delete verlist;
29773 }
29774
29776
29777
29778
29779
29780
29781
29782
29783
29784
29786
29787 void tetgenmesh::repairbadtets()
29788 {
29789 list *tetlist, *ceillist;
29790 list *verlist;
29791 badface *badtet;
29792 triface starttet;
29793 point newpt, e1;
29794 enum locateresult loc;
29795 bool reject;
29796 long oldptnum;
29797 int i;
29798
29799 tetlist = new list(sizeof(triface), NULL, 1024);
29800 ceillist = new list(sizeof(triface), NULL, 1024);
29801 verlist = new list(sizeof(point *), NULL, 256);
29802
29803
29804
29805 while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
29806
29807 badtet = topbadtetra();
29808
29809
29810 if ((badtet != (badface *) NULL) && !isdead(&badtet->tt)
29811 && org(badtet->tt) == badtet->forg
29812 && dest(badtet->tt) == badtet->fdest
29813 && apex(badtet->tt) == badtet->fapex
29814 && oppo(badtet->tt) == badtet->foppo) {
29815 if (b->verbose > 1) {
29816 printf(" Dequeuing btet (%d, %d, %d, %d).\n",
29817 pointmark(badtet->forg), pointmark(badtet->fdest),
29818 pointmark(badtet->fapex), pointmark(badtet->foppo));
29819 }
29820
29821 makepoint(&newpt);
29822 for (i = 0; i < 3; i++) newpt[i] = badtet->cent[i];
29823 setpointtype(newpt, FREEVOLVERTEX);
29824
29825 starttet = badtet->tt;
29826 loc = preciselocate(newpt, &starttet, tetrahedrons->items);
29827 if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29828
29829 infect(starttet);
29830 tetlist->append(&starttet);
29831 formbowatcavityquad(newpt, tetlist, ceillist);
29832
29833 reject = tallencsegs(newpt, 1, &ceillist);
29834 if (!reject) {
29835
29836 reject = tallencsubs(newpt, 1, &ceillist);
29837 }
29838
29839
29840 if (!reject) {
29841 reject = !acceptvolpt(newpt, ceillist, verlist);
29842 }
29843 if (!reject) {
29844 reject = !trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist,
29845 &ceillist, -1.0);
29846 }
29847 if (!reject) {
29848
29849
29850
29851
29852 reject = !infected(badtet->tt);
29853 if (reject) outbowatcircumcount++;
29854 }
29855 if (!reject) {
29856
29857 e1 = org(starttet);
29858
29859 bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist,
29860 NULL, NULL, false, false, true);
29861 setnewpointsize(newpt, e1, NULL);
29862 if (steinerleft > 0) steinerleft--;
29863 } else {
29864
29865
29866
29867
29868
29869
29870 pointdealloc(newpt);
29871
29872 for (i = 0; i < tetlist->len(); i++) {
29873 starttet = * (triface *)(* tetlist)[i];
29874 uninfect(starttet);
29875 }
29876 }
29877 tetlist->clear();
29878 ceillist->clear();
29879
29880 if (reject) {
29881 oldptnum = points->items;
29882 if (badsubsegs->items > 0) {
29883 repairencsegs(true, true);
29884 }
29885 if (badsubfaces->items > 0) {
29886 repairencsubs(true);
29887 }
29888 if (points->items > oldptnum) {
29889
29890
29891 starttet = badtet->tt;
29892 if (!isdead(&starttet)) {
29893 checktet4badqual(&starttet, true);
29894 }
29895 }
29896 }
29897 } else {
29898
29899
29900
29901
29902
29903
29904
29905
29906
29907 if (loc == ONVERTEX) {
29908 printf("Internal error in repairbadtets():\n");
29909 printf(" During repairing bad tet (%d, %d, %d, %d)\n",
29910 pointmark(badtet->forg), pointmark(badtet->fdest),
29911 pointmark(badtet->fapex), pointmark(badtet->foppo));
29912 printf(" New point %d is coincident with an existing vertex %d\n",
29913 pointmark(newpt), pointmark(org(starttet)));
29914 internalerror();
29915 }
29916
29917
29918
29919
29920 pointdealloc(newpt);
29921 }
29922 }
29923
29924 dequeuebadtet();
29925 }
29926
29927 delete tetlist;
29928 delete ceillist;
29929 delete verlist;
29930 }
29931
29933
29934
29935
29937
29938 void tetgenmesh::enforcequality()
29939 {
29940 long total, vertcount;
29941 int i;
29942
29943 if (!b->quiet) {
29944 printf("Adding Steiner points to enforce quality.\n");
29945 }
29946
29947 total = vertcount = 0l;
29948 if (b->conformdel) {
29949 r2count = r3count = 0l;
29950 }
29951
29952
29953 if (b->conformdel && b->refine) {
29954 markacutevertices(65.0);
29955 }
29956
29957 if (!b->metric) {
29958
29959 marksharpsegments(65.0);
29960
29961 decidefeaturepointsizes();
29962 }
29963
29964
29965 badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29966
29967 tallencsegs(NULL, 0, NULL);
29968 if (b->verbose && badsubsegs->items > 0) {
29969 printf(" Splitting encroached subsegments.\n");
29970 }
29971 vertcount = points->items;
29972
29973 repairencsegs(false, false);
29974 if (b->verbose > 0) {
29975 printf(" %ld split points.\n", points->items - vertcount);
29976 }
29977 total += points->items - vertcount;
29978
29979
29980 badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29981
29982 for (i = 0; i < 3; i++) subquefront[i] = (badface *) NULL;
29983 for (i = 0; i < 3; i++) subquetail[i] = &subquefront[i];
29984
29985 tallencsubs(NULL, 0, NULL);
29986 if (b->verbose && badsubfaces->items > 0) {
29987 printf(" Splitting encroached subfaces.\n");
29988 }
29989 vertcount = points->items;
29990
29991 repairencsubs(false);
29992 if (b->verbose > 0) {
29993 printf(" %ld split points.\n", points->items - vertcount);
29994 }
29995 total += points->items - vertcount;
29996
29997
29998
29999
30000 if ((b->minratio > 0.0) || b->varvolume || b->fixedvolume) {
30001
30002 badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30003
30004 for (i = 0; i < 64; i++) tetquefront[i] = (badface *) NULL;
30005 firstnonemptyq = -1;
30006 recentq = -1;
30007
30008 cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30009 cosmindihed = cos(b->mindihedral * PI / 180.0);
30010 tallbadtetrahedrons();
30011 if (b->verbose && badtetrahedrons->items > 0) {
30012 printf(" Splitting bad tetrahedra.\n");
30013 }
30014 vertcount = points->items;
30015 repairbadtets();
30016 if (b->verbose > 0) {
30017 printf(" %ld refinement points.\n", points->items - vertcount);
30018 }
30019 total += points->items - vertcount;
30020 delete badtetrahedrons;
30021 }
30022
30023 if (b->verbose > 0) {
30024 printf(" Totally added %ld points.\n", total);
30025 }
30026
30027 delete badsubfaces;
30028 delete badsubsegs;
30029 }
30030
30031
30032
30033
30034
30035
30036
30037
30038
30039 void tetgenmesh::dumpbadtets()
30040 {
30041 FILE *fout;
30042 badface *remtet;
30043
30044
30045 printf(" Writing bad tets to file bad-dump.lua.\n");
30046 fout = fopen("bad-dump.lua", "w");
30047 fprintf(fout, "-- %ld remaining bad tets (> %g degree).\n",
30048 badtetrahedrons->items, b->maxdihedral);
30049 badtetrahedrons->traversalinit();
30050 remtet = badfacetraverse(badtetrahedrons);
30051 while (remtet != (badface *) NULL) {
30052 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30053 dest(remtet->tt) == remtet->fdest &&
30054 apex(remtet->tt) == remtet->fapex &&
30055 oppo(remtet->tt) == remtet->foppo) {
30056 fprintf(fout, "p:draw_tet(%d, %d, %d, %d) -- %g\n",
30057 pointmark(remtet->forg), pointmark(remtet->fdest),
30058 pointmark(remtet->fapex), pointmark(remtet->foppo),
30059 acos(remtet->key) * 180.0 / PI);
30060 }
30061 remtet = badfacetraverse(badtetrahedrons);
30062 }
30063 fclose(fout);
30064 }
30065
30067
30068
30069
30070
30071
30072
30073
30074
30075
30077
30078 bool tetgenmesh::checktet4ill(triface* testtet, bool enqflag)
30079 {
30080 badface *newbadtet;
30081 triface checktet;
30082 face checksh1, checksh2;
30083 face checkseg;
30084 bool illflag;
30085 int i;
30086
30087 illflag = false;
30088 for (testtet->loc = 0; testtet->loc < 4; testtet->loc++) {
30089 tspivot(*testtet, checksh1);
30090 if (checksh1.sh != dummysh) {
30091 testtet->ver = 0;
30092 findedge(&checksh1, org(*testtet), dest(*testtet));
30093 for (i = 0; i < 3; i++) {
30094 fnext(*testtet, checktet);
30095 tspivot(checktet, checksh2);
30096 if (checksh2.sh != dummysh) {
30097
30098 sspivot(checksh1, checkseg);
30099 if (checkseg.sh == dummysh) {
30100
30101
30102 enextfnextself(*testtet);
30103 enextself(*testtet);
30104 illflag = true;
30105 break;
30106 }
30107 }
30108 enextself(*testtet);
30109 senextself(checksh1);
30110 }
30111 }
30112 if (illflag) break;
30113 }
30114
30115 if (illflag && enqflag) {
30116
30117 newbadtet = (badface *) badtetrahedrons->alloc();
30118 newbadtet->tt = *testtet;
30119 newbadtet->key = -1.0;
30120 for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
30121 newbadtet->forg = org(*testtet);
30122 newbadtet->fdest = dest(*testtet);
30123 newbadtet->fapex = apex(*testtet);
30124 newbadtet->foppo = oppo(*testtet);
30125 newbadtet->nextitem = (badface *) NULL;
30126 if (b->verbose > 2) {
30127 printf(" Queueing illtet: (%d, %d, %d, %d).\n",
30128 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30129 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo));
30130 }
30131 }
30132
30133 return illflag;
30134 }
30135
30137
30138
30139
30140
30141
30142
30143
30144
30145
30146
30147
30148
30149
30150
30151
30153
30154 bool tetgenmesh::checktet4opt(triface* testtet, bool enqflag)
30155 {
30156 badface *newbadtet;
30157 point pa, pb, pc, pd;
30158 REAL N[4][3], len;
30159 REAL cosd;
30160 bool enq;
30161 int i, j;
30162
30163 cosd = 0.0;
30164 enq = false;
30165 pa = (point) testtet->tet[4];
30166 pb = (point) testtet->tet[5];
30167 pc = (point) testtet->tet[6];
30168 pd = (point) testtet->tet[7];
30169
30170 tetallnormal(pa, pb, pc, pd, N, NULL);
30171
30172 for (i = 0; i < 4; i++) {
30173 len = sqrt(dot(N[i], N[i]));
30174 if (len != 0.0) {
30175 for (j = 0; j < 3; j++) N[i][j] /= len;
30176 }
30177 }
30178
30179 for (i = 0; i < 6; i++) {
30180
30181 testtet->loc = 0;
30182 testtet->ver = 0;
30183 switch (i) {
30184 case 0:
30185 cosd = -dot(N[2], N[3]);
30186 break;
30187 case 1:
30188 enextfnextself(*testtet);
30189 enextself(*testtet);
30190 cosd = -dot(N[0], N[1]);
30191 break;
30192 case 2:
30193 enextfnextself(*testtet);
30194 enext2self(*testtet);
30195 cosd = -dot(N[0], N[2]);
30196 break;
30197 case 3:
30198 enextself(*testtet);
30199 cosd = -dot(N[0], N[3]);
30200 break;
30201 case 4:
30202 enext2fnextself(*testtet);
30203 enextself(*testtet);
30204 cosd = -dot(N[1], N[2]);
30205 break;
30206 case 5:
30207 enext2self(*testtet);
30208 cosd = -dot(N[1], N[3]);
30209 break;
30210 }
30211 if (cosd < cosmaxdihed) {
30212
30213 if (enqflag) {
30214
30215 newbadtet = (badface *) badtetrahedrons->alloc();
30216 newbadtet->tt = *testtet;
30217 newbadtet->key = cosd;
30218 for (j = 0; j < 3; j++) newbadtet->cent[j] = 0.0;
30219 newbadtet->forg = org(*testtet);
30220 newbadtet->fdest = dest(*testtet);
30221 newbadtet->fapex = apex(*testtet);
30222 newbadtet->foppo = oppo(*testtet);
30223 newbadtet->nextitem = (badface *) NULL;
30224 if (b->verbose > 2) {
30225 printf(" Queueing tet: (%d, %d, %d, %d), dihed %g (degree).\n",
30226 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30227 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
30228 acos(cosd) * 180.0 / PI);
30229 }
30230 }
30231 enq = true;
30232 }
30233 }
30234
30235 return enq;
30236 }
30237
30239
30240
30241
30242
30243
30244
30245
30246
30247
30248
30249
30250
30251
30252
30253
30254
30255
30256
30257
30258
30260
30261 bool tetgenmesh::removeedge(badface* remedge, bool optflag)
30262 {
30263 triface abcd, badc;
30264 triface baccasing, abdcasing;
30265 triface abtetlist[11];
30266 triface bftetlist[11];
30267 triface newtetlist[33];
30268 face checksh;
30269 enum fliptype fty;
30270 REAL key;
30271 bool remflag, subflag;
30272 int n, n1, m, i, j;
30273
30274
30275
30276 abcd = remedge->tt;
30277 adjustedgering(abcd, CCW);
30278 i = 0;
30279 do {
30280 sym(abcd, baccasing);
30281
30282 if (baccasing.tet == dummytet) {
30283 fnext(abcd, badc);
30284 sym(badc, abdcasing);
30285 if (abdcasing.tet == dummytet) {
30286
30287 if (removetetbypeeloff(&abcd)) {
30288 if (b->verbose > 1) {
30289 printf(" Stripped tet from the mesh.\n");
30290 }
30291 optcount[0]++;
30292 return true;
30293 }
30294 }
30295 }
30296
30297 enext2fnextself(abcd);
30298 enext2self(abcd);
30299 esymself(abcd);
30300 i++;
30301 } while (i < 2);
30302
30303
30304 subflag = false;
30305 abcd = remedge->tt;
30306 adjustedgering(abcd, CW);
30307 n = 0;
30308 abtetlist[n] = abcd;
30309 do {
30310
30311 if (n == 10) break;
30312
30313 tspivot(abtetlist[n], checksh);
30314 if (checksh.sh != dummysh) {
30315
30316
30317 subflag = true; break;
30318 }
30319
30320 fnext(abtetlist[n], abtetlist[n + 1]);
30321 n++;
30322 } while (apex(abtetlist[n]) != apex(abcd));
30323
30324 remflag = false;
30325 key = remedge->key;
30326
30327 if (subflag && optflag) {
30328 abcd = remedge->tt;
30329 adjustedgering(abcd, CCW);
30330
30331 for (j = 0; j < 2; j++) {
30332 if (j == 0) {
30333 enext2fnext(abcd, abtetlist[0]);
30334 } else {
30335 enextfnext(abcd, abtetlist[0]);
30336 }
30337 fty = categorizeface(abtetlist[0]);
30338 if (fty == T23) {
30339
30340 sym(abtetlist[0], abtetlist[1]);
30341 assert(abtetlist[1].tet != dummytet);
30342 n = 2;
30343 m = 3;
30344 remflag = removefacebyflip23(&key, abtetlist, newtetlist, NULL);
30345 } else if (fty == T22) {
30346
30347 n = 2;
30348 newtetlist[0] = abtetlist[0];
30349 adjustedgering(newtetlist[0], CW);
30350 fnext(newtetlist[0], newtetlist[1]);
30351 assert(newtetlist[1].tet != dummytet);
30352
30353 if (fnext(newtetlist[1], newtetlist[2])) {
30354 fnext(newtetlist[2], newtetlist[3]);
30355 assert(newtetlist[3].tet != dummytet);
30356 n = 4;
30357 }
30358 m = n;
30359 remflag = removeedgebyflip22(&key, n, newtetlist, NULL);
30360 }
30361
30362 if (remflag) {
30363 if (b->verbose > 1) {
30364 printf(" Done flip %d-to-%d. Qual: %g -> %g.\n", n, m,
30365 acos(remedge->key) / PI * 180.0, acos(key) / PI * 180.0);
30366 }
30367
30368 if (m == 3) {
30369 for (i = 0; i < n; i++) {
30370 tetrahedrondealloc(abtetlist[i].tet);
30371 }
30372 }
30373 for (i = 0; i < m; i++) {
30374 checktet4opt(&(newtetlist[i]), true);
30375 }
30376 optcount[1]++;
30377 return true;
30378 }
30379 }
30380
30381 return false;
30382 }
30383
30384
30385 if (n == 3) {
30386
30387 remflag = removeedgebyflip32(&key, abtetlist, newtetlist, NULL);
30388 } else if ((n == 4) || (n == 5) || (n == 6)) {
30389
30390 remflag = removeedgebytranNM(&key,n,abtetlist,newtetlist,NULL,NULL,NULL);
30391 } else {
30392 if (b->verbose > 1) {
30393 printf(" !! Unhandled case: n = %d.\n", n);
30394 }
30395 }
30396 if (remflag) {
30397 optcount[n]++;
30398
30399 for (i = 0; i < n; i++) {
30400 tetrahedrondealloc(abtetlist[i].tet);
30401 }
30402 m = (n - 2) * 2;
30403 if (b->verbose > 1) {
30404 printf(" Done flip %d-to-%d. ", n, m);
30405 if (optflag) {
30406 printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30407 acos(key) / PI * 180.0);
30408 }
30409 printf("\n");
30410 }
30411 }
30412
30413 if (!remflag && (key == remedge->key) && (n < 7)) {
30414
30415 n1 = 0;
30416 remflag = removeedgebycombNM(&key, n, abtetlist, &n1, bftetlist,
30417 newtetlist, NULL);
30418 if (remflag) {
30419 optcount[9]++;
30420
30421 for (i = 0; i < n; i++) {
30422 tetrahedrondealloc(abtetlist[i].tet);
30423 }
30424 for (i = 0; i < n1; i++) {
30425 if (!isdead(&(bftetlist[i]))) {
30426 tetrahedrondealloc(bftetlist[i].tet);
30427 }
30428 }
30429 m = ((n1 - 2) * 2 - 1) + (n - 3) * 2;
30430 if (b->verbose > 1) {
30431 printf(" Done flip %d-to-%d (n-1=%d, n1=%d). ", n+n1-2, m, n-1,n1);
30432 if (optflag) {
30433 printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30434 acos(key) / PI * 180.0);
30435 }
30436 printf("\n");
30437 }
30438 }
30439 }
30440
30441 if (remflag) {
30442
30443 for (i = 0; i < m; i++) {
30444 if (optflag) {
30445 checktet4opt(&(newtetlist[i]), true);
30446 } else {
30447 checktet4ill(&(newtetlist[i]), true);
30448 }
30449 }
30450 }
30451
30452 return remflag;
30453 }
30454
30456
30457
30458
30459
30460
30461
30463
30464 bool tetgenmesh::smoothsliver(badface* remedge, list *starlist)
30465 {
30466 triface checktet;
30467 point smthpt;
30468 bool smthed;
30469 int idx, i, j;
30470
30471
30472 smthed = false;
30473 for (i = 0; i < 4 && !smthed; i++) {
30474 smthpt = (point) remedge->tt.tet[4 + i];
30475
30476 if (pointtype(smthpt) == FREEVOLVERTEX) {
30477
30478 idx = pointmark(smthpt) - in->firstnumber;
30479 if (!(idx < in->numberofpoints)) {
30480
30481 starlist->append(&(remedge->tt.tet));
30482 formstarpolyhedron(smthpt, starlist, NULL, false);
30483 smthed = smoothpoint(smthpt,NULL,NULL,starlist,false,&remedge->key);
30484
30485 if (smthed) {
30486 for (j = 0; j < starlist->len(); j++) {
30487 checktet = * (triface *)(* starlist)[j];
30488 checktet4opt(&checktet, true);
30489 }
30490 }
30491 starlist->clear();
30492 }
30493 }
30494 }
30495
30496
30497
30498
30499
30500
30501
30502
30503
30504
30505
30506
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 return smthed;
30536 }
30537
30539
30540
30541
30542
30543
30544
30546
30547 bool tetgenmesh::splitsliver(badface *remedge, list *tetlist, list *ceillist)
30548 {
30549 triface starttet;
30550 face checkseg;
30551 point newpt, pt[4];
30552 bool remflag;
30553 int i;
30554
30555 starttet = remedge->tt;
30556
30557
30558 adjustedgering(starttet, CCW);
30559 enextfnextself(starttet);
30560 enextself(starttet);
30561 tsspivot(&starttet, &checkseg);
30562 if (b->nobisect == 0) {
30563 if (checkseg.sh != dummysh) {
30564
30565
30566 checkseg.shver = 0;
30567 pt[0] = sorg(checkseg);
30568 pt[1] = sdest(checkseg);
30569 makepoint(&newpt);
30570 getsplitpoint(pt[0], pt[1], NULL, newpt);
30571 setpointtype(newpt, FREESEGVERTEX);
30572 setpoint2sh(newpt, sencode(checkseg));
30573
30574 sstpivot(&checkseg, &starttet);
30575 splittetedge(newpt, &starttet, NULL);
30576
30577 sstpivot(&checkseg, &starttet);
30578 ceillist->append(&starttet);
30579 formstarpolyhedron(newpt, ceillist, NULL, true);
30580 setnewpointsize(newpt, pt[0], NULL);
30581 if (steinerleft > 0) steinerleft--;
30582
30583 smoothpoint(newpt, pt[0], pt[1], ceillist, false, NULL);
30584
30585 for (i = 0; i < ceillist->len(); i++) {
30586 starttet = * (triface *)(* ceillist)[i];
30587 checktet4opt(&starttet, true);
30588 }
30589 ceillist->clear();
30590 return true;
30591 }
30592 }
30593
30594
30595 for (i = 0; i < 4; i++) {
30596 pt[i] = (point) starttet.tet[4 + i];
30597 }
30598
30599 makepoint(&newpt);
30600 for (i = 0; i < 3; i++) {
30601 newpt[i] = 0.25 * (pt[0][i] + pt[1][i] + pt[2][i] + pt[3][i]);
30602 }
30603 setpointtype(newpt, FREEVOLVERTEX);
30604
30605
30606 remflag = false;
30607 infect(starttet);
30608 tetlist->append(&starttet);
30609 formbowatcavityquad(newpt, tetlist, ceillist);
30610 if (trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, -1.0)) {
30611
30612 if (smoothpoint( newpt, NULL, NULL, ceillist, false, &remedge->key)) {
30613
30614 bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, NULL,
30615 NULL, false, false, false);
30616 setnewpointsize(newpt, pt[0], NULL);
30617 if (steinerleft > 0) steinerleft--;
30618
30619 for (i = 0; i < ceillist->len(); i++) {
30620 starttet = * (triface *)(* ceillist)[i];
30621 checktet4opt(&starttet, true);
30622 }
30623 remflag = true;
30624 }
30625 }
30626
30627 if (!remflag) {
30628
30629 pointdealloc(newpt);
30630
30631 for (i = 0; i < tetlist->len(); i++) {
30632 starttet = * (triface *)(* tetlist)[i];
30633 uninfect(starttet);
30634 }
30635 }
30636 tetlist->clear();
30637 ceillist->clear();
30638
30639 return remflag;
30640 }
30641
30643
30644
30645
30647
30648 void tetgenmesh::tallslivers(bool optflag)
30649 {
30650 triface tetloop;
30651
30652 tetrahedrons->traversalinit();
30653 tetloop.tet = tetrahedrontraverse();
30654 while (tetloop.tet != (tetrahedron *) NULL) {
30655 if (optflag) {
30656 checktet4opt(&tetloop, true);
30657 } else {
30658 checktet4ill(&tetloop, true);
30659 }
30660 tetloop.tet = tetrahedrontraverse();
30661 }
30662 }
30663
30665
30666
30667
30668
30669
30670
30671
30672
30673
30674
30675
30677
30678 void tetgenmesh::optimizemesh(bool optflag)
30679 {
30680 list *splittetlist, *tetlist, *ceillist;
30681 badface *remtet, *lastentry;
30682
30683 REAL objdihed, curdihed;
30684 long oldnum;
30685 int iter, i;
30686
30687 objdihed = 0.0;
30688
30689 if (!b->quiet) {
30690 if (optflag) {
30691 printf("Optimizing mesh.\n");
30692 } else {
30693 printf("Repairing mesh.\n");
30694 }
30695 }
30696
30697 #ifdef SELF_CHECK
30698 if (optflag && (b->verbose)) {
30699 printf(" level = %d.\n", b->optlevel);
30700 }
30701 #endif
30702
30703
30704 badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30705 if (optflag) {
30706 cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30707 cosmindihed = cos(b->mindihedral * PI / 180.0);
30708
30709
30710
30711 objdihed = b->maxdihedral + 5.0;
30712 if (objdihed < 170.0) objdihed = 170.0;
30713 objdihed = objdihed / 180.0 * PI;
30714 }
30715
30716 tallslivers(optflag);
30717
30718 optcount[0] = 0l;
30719 optcount[1] = 0l;
30720 optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l;
30721 optcount[9] = 0l;
30722
30723
30724 lastentry = (badface *) NULL;
30725
30726 while (badtetrahedrons->items > 0) {
30727 badtetrahedrons->traversalinit();
30728 remtet = badfacetraverse(badtetrahedrons);
30729 while (remtet != (badface *) NULL) {
30730
30731
30732 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30733 dest(remtet->tt) == remtet->fdest &&
30734 apex(remtet->tt) == remtet->fapex &&
30735 oppo(remtet->tt) == remtet->foppo) {
30736 if (b->verbose > 1) {
30737 printf(" Repair tet (%d, %d, %d, %d) %g (degree).\n",
30738 pointmark(remtet->forg), pointmark(remtet->fdest),
30739 pointmark(remtet->fapex), pointmark(remtet->foppo),
30740 acos(remtet->key) / PI * 180.0);
30741 }
30742 if (!removeedge(remtet, optflag)) {
30743
30744 if (lastentry != (badface *) NULL) {
30745 if (remtet == lastentry) break;
30746 } else {
30747
30748 lastentry = remtet;
30749 }
30750 } else {
30751
30752 lastentry = (badface *) NULL;
30753
30754 badfacedealloc(badtetrahedrons, remtet);
30755 }
30756 } else {
30757
30758 badfacedealloc(badtetrahedrons, remtet);
30759 }
30760 remtet = badfacetraverse(badtetrahedrons);
30761 }
30762
30763 if (remtet != (badface *) NULL) break;
30764 }
30765
30766 if (b->verbose) {
30767 if (optcount[0] > 0l) {
30768 printf(" %ld tets are peeled off.\n", optcount[0]);
30769 }
30770 if (optcount[1] > 0l) {
30771 printf(" %ld faces are flipped.\n", optcount[1]);
30772 }
30773 if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30774 optcount[9] > 0l) {
30775 printf(" %ld edges are flipped.\n", optcount[3] + optcount[4] +
30776 optcount[5] + optcount[6] + optcount[9]);
30777 }
30778
30779
30780
30781 }
30782
30783 if ((badtetrahedrons->items > 0l) && optflag && (b->optlevel > 2)) {
30784 splittetlist = new list(sizeof(badface), NULL, 256);
30785 tetlist = new list(sizeof(triface), NULL, 256);
30786 ceillist = new list(sizeof(triface), NULL, 256);
30787 oldnum = points->items;
30788 smoothsegverts = smoothvolverts = 0;
30789 optcount[1] = 0l;
30790 optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l;
30791 optcount[9] = 0l;
30792 iter = 0;
30793
30794 do {
30795
30796 badtetrahedrons->traversalinit();
30797 remtet = badfacetraverse(badtetrahedrons);
30798 while (remtet != (badface *) NULL) {
30799 splittetlist->append(remtet);
30800
30801 badfacedealloc(badtetrahedrons, remtet);
30802 remtet = badfacetraverse(badtetrahedrons);
30803 }
30804 for (i = 0; i < splittetlist->len(); i++) {
30805 remtet = (badface *)(* splittetlist)[i];
30806
30807
30808 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30809 dest(remtet->tt) == remtet->fdest &&
30810 apex(remtet->tt) == remtet->fapex &&
30811 oppo(remtet->tt) == remtet->foppo) {
30812
30813 curdihed = facedihedral(remtet->forg, remtet->fdest, remtet->fapex,
30814 remtet->foppo);
30815
30816 if (curdihed > PI) curdihed = 2 * PI - curdihed;
30817
30818 if (curdihed > objdihed) {
30819 remtet->key = cos(curdihed);
30820 if (b->verbose > 1) {
30821 printf(" Get sliver (%d, %d, %d, %d) %g (degree).\n",
30822 pointmark(remtet->forg), pointmark(remtet->fdest),
30823 pointmark(remtet->fapex), pointmark(remtet->foppo),
30824 acos(remtet->key) / PI * 180.0);
30825 }
30826 if (!removeedge(remtet, optflag)) {
30827 if (!smoothsliver(remtet, tetlist)) {
30828 splitsliver(remtet, tetlist, ceillist);
30829 }
30830 }
30831 }
30832 }
30833 }
30834 iter++;
30835 } while ((badtetrahedrons->items > 0l) && (iter < b->optpasses));
30836
30837 if (b->verbose) {
30838 printf(" %d passes.\n", iter);
30839 if ((points->items - oldnum) > 0l) {
30840 printf(" %ld points are inserted (%d on segment).\n",
30841 points->items - oldnum, smoothsegverts);
30842 }
30843 if (optcount[1] > 0l) {
30844 printf(" %ld faces are flipped.\n", optcount[1]);
30845 }
30846 if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30847 optcount[9] > 0l) {
30848 printf(" %ld edges are flipped.\n", optcount[3] + optcount[4] +
30849 optcount[5] + optcount[6] + optcount[9]);
30850 }
30851
30852
30853
30854 }
30855 delete tetlist;
30856 delete ceillist;
30857 delete splittetlist;
30858 }
30859
30860 delete badtetrahedrons;
30861 badtetrahedrons = (memorypool *) NULL;
30862 }
30863
30864
30865
30866
30867
30868
30869
30870
30871
30873
30874
30875
30876
30877
30878
30879
30880
30882
30883 void tetgenmesh::transfernodes()
30884 {
30885 point pointloop;
30886 REAL x, y, z;
30887 int coordindex;
30888 int attribindex;
30889 int mtrindex;
30890 int i, j;
30891
30892
30893 coordindex = 0;
30894 attribindex = 0;
30895 mtrindex = 0;
30896 for (i = 0; i < in->numberofpoints; i++) {
30897 makepoint(&pointloop);
30898
30899 x = pointloop[0] = in->pointlist[coordindex++];
30900 y = pointloop[1] = in->pointlist[coordindex++];
30901 z = pointloop[2] = in->pointlist[coordindex++];
30902
30903 for (j = 0; j < in->numberofpointattributes; j++) {
30904 pointloop[3 + j] = in->pointattributelist[attribindex++];
30905 }
30906
30907 for (j = 0; j < in->numberofpointmtrs; j++) {
30908 pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
30909 }
30910
30911 if (i == 0) {
30912 xmin = xmax = x;
30913 ymin = ymax = y;
30914 zmin = zmax = z;
30915 } else {
30916 xmin = (x < xmin) ? x : xmin;
30917 xmax = (x > xmax) ? x : xmax;
30918 ymin = (y < ymin) ? y : ymin;
30919 ymax = (y > ymax) ? y : ymax;
30920 zmin = (z < zmin) ? z : zmin;
30921 zmax = (z > zmax) ? z : zmax;
30922 }
30923 }
30924
30925 x = xmax - xmin;
30926 y = ymax - ymin;
30927 z = zmax - zmin;
30928 longest = sqrt(x * x + y * y + z * z);
30929 if (longest == 0.0) {
30930 printf("Error: The point set is trivial.\n");
30931 terminatetetgen(1);
30932 }
30933
30934 lengthlimit = longest * b->epsilon * 1e+2;
30935 }
30936
30938
30939
30940
30941
30942
30943
30944
30945
30946
30948
30949 void tetgenmesh::jettisonnodes()
30950 {
30951 point pointloop;
30952 bool jetflag;
30953 int oldidx, newidx;
30954 int remcount;
30955
30956 if (!b->quiet) {
30957 printf("Jettisoning redundants points.\n");
30958 }
30959
30960 points->traversalinit();
30961 pointloop = pointtraverse();
30962 oldidx = newidx = 0;
30963 remcount = 0;
30964 while (pointloop != (point) NULL) {
30965 jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) ||
30966 (pointtype(pointloop) == UNUSEDVERTEX);
30967 if (jetflag) {
30968
30969 pointdealloc(pointloop);
30970 remcount++;
30971 } else {
30972
30973 setpointmark(pointloop, newidx + in->firstnumber);
30974 if (in->pointmarkerlist != (int *) NULL) {
30975 if (oldidx < in->numberofpoints) {
30976
30977 in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
30978 }
30979 }
30980 newidx++;
30981 }
30982 oldidx++;
30983 if (oldidx == in->numberofpoints) {
30984
30985 in->numberofpoints -= remcount;
30986
30987 jettisoninverts = remcount;
30988 }
30989 pointloop = pointtraverse();
30990 }
30991 if (b->verbose) {
30992 printf(" %d duplicated vertices have been removed.\n", dupverts);
30993 printf(" %d unused vertices have been removed.\n", unuverts);
30994 }
30995 dupverts = 0;
30996 unuverts = 0;
30997
30998
30999
31000
31001 points->deaditemstack = (void *) NULL;
31002 }
31003
31005
31006
31007
31008
31009
31010
31011
31013
31014 void tetgenmesh::highorder()
31015 {
31016 triface tetloop, worktet;
31017 triface spintet, adjtet;
31018 point torg, tdest, tapex;
31019 point *extralist, *adjextralist;
31020 point newpoint;
31021 int hitbdry, ptmark;
31022 int i, j;
31023
31024 if (!b->quiet) {
31025 printf("Adding vertices for second-order tetrahedra.\n");
31026 }
31027
31028
31029 highordertable = new point[tetrahedrons->items * 6];
31030 if (highordertable == (point *) NULL) {
31031 printf("Error: Out of memory.\n");
31032 terminatetetgen(1);
31033 }
31034
31035
31036
31037
31038
31039
31040 points->deaditemstack = (void *) NULL;
31041
31042
31043
31044 i = 0;
31045 tetrahedrons->traversalinit();
31046 tetloop.tet = tetrahedrontraverse();
31047 while (tetloop.tet != (tetrahedron *) NULL) {
31048 tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
31049 for (j = 0; j < 6; j++) {
31050 highordertable[i + j] = (point) NULL;
31051 }
31052 i += 6;
31053 tetloop.tet = tetrahedrontraverse();
31054 }
31055
31056
31057
31058
31059
31060
31061 tetrahedrons->traversalinit();
31062 tetloop.tet = tetrahedrontraverse();
31063 while (tetloop.tet != (tetrahedron *) NULL) {
31064
31065 extralist = (point *) tetloop.tet[highorderindex];
31066 worktet.tet = tetloop.tet;
31067 for (i = 0; i < 6; i++) {
31068 if (extralist[i] == (point) NULL) {
31069
31070 worktet.loc = edge2locver[i][0];
31071 worktet.ver = edge2locver[i][1];
31072
31073 torg = org(worktet);
31074 tdest = dest(worktet);
31075
31076 newpoint = (point) points->alloc();
31077
31078 for (j = 0; j < 3 + in->numberofpointattributes; j++) {
31079 newpoint[j] = 0.5 * (torg[j] + tdest[j]);
31080 }
31081 ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
31082 setpointmark(newpoint, ptmark);
31083
31084 extralist[i] = newpoint;
31085
31086
31087 tapex = apex(worktet);
31088 spintet = worktet;
31089 hitbdry = 0;
31090 while (hitbdry < 2) {
31091 if (fnextself(spintet)) {
31092
31093 adjextralist = (point *) spintet.tet[highorderindex];
31094
31095 j = locver2edge[spintet.loc][spintet.ver];
31096
31097
31098 if (adjextralist[j] == (point) NULL) {
31099 adjextralist[j] = newpoint;
31100 }
31101 if (apex(spintet) == tapex) {
31102 break;
31103 }
31104 } else {
31105 hitbdry++;
31106 if (hitbdry < 2) {
31107 esym(worktet, spintet);
31108 }
31109 }
31110 }
31111 }
31112 }
31113 tetloop.tet = tetrahedrontraverse();
31114 }
31115 }
31116
31118
31119
31120
31121
31122
31123
31125
31126 void tetgenmesh::outnodes(tetgenio* out)
31127 {
31128 FILE *outfile;
31129 char outnodefilename[FILENAMESIZE];
31130 shellface subptr;
31131 triface adjtet;
31132 face subloop;
31133 point pointloop;
31134 point *extralist, ep[3];
31135 int nextras, bmark, shmark, marker;
31136 int coordindex, attribindex;
31137 int pointnumber, firstindex;
31138 int index, i;
31139
31140 if (out == (tetgenio *) NULL) {
31141 strcpy(outnodefilename, b->outfilename);
31142 strcat(outnodefilename, ".node");
31143 }
31144
31145 if (!b->quiet) {
31146 if (out == (tetgenio *) NULL) {
31147 printf("Writing %s.\n", outnodefilename);
31148 } else {
31149 printf("Writing nodes.\n");
31150 }
31151 }
31152
31153 nextras = in->numberofpointattributes;
31154 bmark = !b->nobound && in->pointmarkerlist;
31155
31156
31157 outfile = (FILE *) NULL;
31158 marker = coordindex = 0;
31159
31160 if (out == (tetgenio *) NULL) {
31161 outfile = fopen(outnodefilename, "w");
31162 if (outfile == (FILE *) NULL) {
31163 printf("File I/O Error: Cannot create file %s.\n", outnodefilename);
31164 terminatetetgen(1);
31165 }
31166
31167
31168 fprintf(outfile, "%ld %d %d %d\n", points->items, 3, nextras, bmark);
31169 } else {
31170
31171 out->pointlist = new REAL[points->items * 3];
31172 if (out->pointlist == (REAL *) NULL) {
31173 printf("Error: Out of memory.\n");
31174 terminatetetgen(1);
31175 }
31176
31177 if (nextras > 0) {
31178 out->pointattributelist = new REAL[points->items * nextras];
31179 if (out->pointattributelist == (REAL *) NULL) {
31180 printf("Error: Out of memory.\n");
31181 terminatetetgen(1);
31182 }
31183 }
31184
31185 if (bmark) {
31186 out->pointmarkerlist = new int[points->items];
31187 if (out->pointmarkerlist == (int *) NULL) {
31188 printf("Error: Out of memory.\n");
31189 terminatetetgen(1);
31190 }
31191 }
31192 out->numberofpoints = points->items;
31193 out->numberofpointattributes = nextras;
31194 coordindex = 0;
31195 attribindex = 0;
31196 }
31197
31198 if (bmark && (b->plc || b->refine)) {
31199
31200 points->traversalinit();
31201 pointloop = pointtraverse();
31202 while (pointloop != (point) NULL) {
31203 setpoint2tet(pointloop, (tetrahedron) NULL);
31204 pointloop = pointtraverse();
31205 }
31206
31207
31208 subfaces->traversalinit();
31209 subloop.sh = shellfacetraverse(subfaces);
31210 while (subloop.sh != (shellface *) NULL) {
31211 subloop.shver = 0;
31212
31213 for (i = 0; i < 3; i++) {
31214 pointloop = (point) subloop.sh[3 + i];
31215 setpoint2tet(pointloop, (tetrahedron) sencode(subloop));
31216 }
31217 if (b->order == 2) {
31218
31219 stpivot(subloop, adjtet);
31220 if (adjtet.tet == dummytet) {
31221 sesymself(subloop);
31222 stpivot(subloop, adjtet);
31223 }
31224 assert(adjtet.tet != dummytet);
31225 extralist = (point *) adjtet.tet[highorderindex];
31226 switch (adjtet.loc) {
31227 case 0:
31228 ep[0] = extralist[0];
31229 ep[1] = extralist[1];
31230 ep[2] = extralist[2];
31231 break;
31232 case 1:
31233 ep[0] = extralist[0];
31234 ep[1] = extralist[4];
31235 ep[2] = extralist[3];
31236 break;
31237 case 2:
31238 ep[0] = extralist[1];
31239 ep[1] = extralist[5];
31240 ep[2] = extralist[4];
31241 break;
31242 case 3:
31243 ep[0] = extralist[2];
31244 ep[1] = extralist[3];
31245 ep[2] = extralist[5];
31246 break;
31247 default: break;
31248 }
31249 for (i = 0; i < 3; i++) {
31250 setpoint2tet(ep[i], (tetrahedron) sencode(subloop));
31251 }
31252 }
31253 subloop.sh = shellfacetraverse(subfaces);
31254 }
31255 }
31256
31257
31258 firstindex = b->zeroindex ? 0 : in->firstnumber;
31259
31260 points->traversalinit();
31261 pointloop = pointtraverse();
31262 pointnumber = firstindex;
31263 index = 0;
31264 while (pointloop != (point) NULL) {
31265 if (bmark) {
31266
31267 marker = 0;
31268
31269 if (index < in->numberofpoints) {
31270
31271 marker = in->pointmarkerlist[index];
31272 }
31273
31274 if ((marker == 0) && (b->plc || b->refine)) {
31275 subptr = (shellface) point2tet(pointloop);
31276 if (subptr != (shellface) NULL) {
31277
31278 marker = 1;
31279 if (in->facetmarkerlist != (int *) NULL) {
31280
31281 sdecode(subptr, subloop);
31282 shmark = shellmark(subloop);
31283 marker = in->facetmarkerlist[shmark - 1];
31284 }
31285 }
31286 }
31287 }
31288 if (out == (tetgenio *) NULL) {
31289
31290 fprintf(outfile, "%4d %.17g %.17g %.17g", pointnumber,
31291 pointloop[0], pointloop[1], pointloop[2]);
31292 for (i = 0; i < nextras; i++) {
31293
31294 fprintf(outfile, " %.17g", pointloop[3 + i]);
31295 }
31296 if (bmark) {
31297
31298 fprintf(outfile, " %d", marker);
31299 }
31300 fprintf(outfile, "\n");
31301 } else {
31302
31303 out->pointlist[coordindex++] = pointloop[0];
31304 out->pointlist[coordindex++] = pointloop[1];
31305 out->pointlist[coordindex++] = pointloop[2];
31306
31307 for (i = 0; i < nextras; i++) {
31308
31309 out->pointattributelist[attribindex++] = pointloop[3 + i];
31310 }
31311 if (bmark) {
31312
31313 out->pointmarkerlist[index] = marker;
31314 }
31315 }
31316 pointloop = pointtraverse();
31317 pointnumber++;
31318 index++;
31319 }
31320
31321 if (out == (tetgenio *) NULL) {
31322 fprintf(outfile, "# Generated by %s\n", b->commandline);
31323 fclose(outfile);
31324 }
31325 }
31326
31328
31329
31330
31332
31333 void tetgenmesh::outmetrics(tetgenio* out)
31334 {
31335 FILE *outfile;
31336 char outmtrfilename[FILENAMESIZE];
31337 list *tetlist, *ptlist;
31338 triface tetloop;
31339 point ptloop, neipt;
31340 REAL lave, len;
31341 int mtrindex;
31342 int i;
31343
31344 lave = 0.0;
31345
31346 if (out == (tetgenio *) NULL) {
31347 strcpy(outmtrfilename, b->outfilename);
31348 strcat(outmtrfilename, ".mtr");
31349 }
31350
31351 if (!b->quiet) {
31352 if (out == (tetgenio *) NULL) {
31353 printf("Writing %s.\n", outmtrfilename);
31354 } else {
31355 printf("Writing metrics.\n");
31356 }
31357 }
31358
31359
31360 outfile = (FILE *) NULL;
31361 mtrindex = 0;
31362
31363 if (out == (tetgenio *) NULL) {
31364 outfile = fopen(outmtrfilename, "w");
31365 if (outfile == (FILE *) NULL) {
31366 printf("File I/O Error: Cannot create file %s.\n", outmtrfilename);
31367 terminatetetgen(1);
31368 }
31369
31370
31371 fprintf(outfile, "%ld %d\n", points->items, 1);
31372 } else {
31373
31374
31375 out->pointmtrlist = new REAL[points->items];
31376 if (out->pointmtrlist == (REAL *) NULL) {
31377 printf("Error: Out of memory.\n");
31378 terminatetetgen(1);
31379 }
31380 out->numberofpointmtrs = 1;
31381 mtrindex = 0;
31382 }
31383
31384
31385 points->traversalinit();
31386 ptloop = pointtraverse();
31387 while (ptloop != (point) NULL) {
31388 setpoint2tet(ptloop, (tetrahedron) NULL);
31389 ptloop = pointtraverse();
31390 }
31391
31392 tetrahedrons->traversalinit();
31393 tetloop.tet = tetrahedrontraverse();
31394 while (tetloop.tet != (tetrahedron *) NULL) {
31395 for (i = 0; i < 4; i++) {
31396 ptloop = (point) tetloop.tet[4 + i];
31397 setpoint2tet(ptloop, encode(tetloop));
31398 }
31399 tetloop.tet = tetrahedrontraverse();
31400 }
31401
31402 tetlist = new list(sizeof(triface), NULL, 256);
31403 ptlist = new list(sizeof(point *), NULL, 256);
31404
31405 points->traversalinit();
31406 ptloop = pointtraverse();
31407 while (ptloop != (point) NULL) {
31408 decode(point2tet(ptloop), tetloop);
31409 if (!isdead(&tetloop)) {
31410
31411 tetlist->append(&tetloop);
31412 formstarpolyhedron(ptloop, tetlist, ptlist, true);
31413
31414
31415 lave = 0.0;
31416 for (i = 0; i < ptlist->len(); i++) {
31417 neipt = * (point *)(* ptlist)[i];
31418 len = distance(ptloop, neipt);
31419
31420
31421 lave += len;
31422 }
31423 lave /= ptlist->len();
31424 }
31425 if (out == (tetgenio *) NULL) {
31426
31427
31428
31429 if (ptlist->len() > 0) {
31430
31431 fprintf(outfile, "%-16.8e ", lave);
31432 } else {
31433 fprintf(outfile, "0.0 ");
31434 }
31435 fprintf(outfile, "\n");
31436 } else {
31437
31438
31439
31440 if (ptlist->len() > 0) {
31441
31442
31443 out->pointmtrlist[mtrindex++] = lave;
31444 } else {
31445
31446
31447 out->pointmtrlist[mtrindex++] = 0.0;
31448 }
31449 }
31450 tetlist->clear();
31451 ptlist->clear();
31452 ptloop = pointtraverse();
31453 }
31454
31455 delete tetlist;
31456 delete ptlist;
31457
31458 if (out == (tetgenio *) NULL) {
31459 fprintf(outfile, "# Generated by %s\n", b->commandline);
31460 fclose(outfile);
31461 }
31462 }
31463
31465
31466
31467
31468
31470
31471 void tetgenmesh::outelements(tetgenio* out)
31472 {
31473 FILE *outfile;
31474 char outelefilename[FILENAMESIZE];
31475 tetrahedron* tptr;
31476 int *tlist;
31477 REAL *talist;
31478 int firstindex, shift;
31479 int pointindex;
31480 int attribindex;
31481 point p1, p2, p3, p4;
31482 point *extralist;
31483 int elementnumber;
31484 int eextras;
31485 int i;
31486
31487 if (out == (tetgenio *) NULL) {
31488 strcpy(outelefilename, b->outfilename);
31489 strcat(outelefilename, ".ele");
31490 }
31491
31492 if (!b->quiet) {
31493 if (out == (tetgenio *) NULL) {
31494 printf("Writing %s.\n", outelefilename);
31495 } else {
31496 printf("Writing elements.\n");
31497 }
31498 }
31499
31500
31501 outfile = (FILE *) NULL;
31502 tlist = (int *) NULL;
31503 talist = (double *) NULL;
31504 pointindex = attribindex = 0;
31505
31506 eextras = in->numberoftetrahedronattributes;
31507 if (out == (tetgenio *) NULL) {
31508 outfile = fopen(outelefilename, "w");
31509 if (outfile == (FILE *) NULL) {
31510 printf("File I/O Error: Cannot create file %s.\n", outelefilename);
31511 terminatetetgen(1);
31512 }
31513
31514 fprintf(outfile, "%ld %d %d\n", tetrahedrons->items,
31515 b->order == 1 ? 4 : 10, eextras);
31516 } else {
31517
31518 out->tetrahedronlist = new int[tetrahedrons->items *
31519 (b->order == 1 ? 4 : 10)];
31520 if (out->tetrahedronlist == (int *) NULL) {
31521 printf("Error: Out of memory.\n");
31522 terminatetetgen(1);
31523 }
31524
31525 if (eextras > 0) {
31526 out->tetrahedronattributelist = new REAL[tetrahedrons->items * eextras];
31527 if (out->tetrahedronattributelist == (REAL *) NULL) {
31528 printf("Error: Out of memory.\n");
31529 terminatetetgen(1);
31530 }
31531 }
31532 out->numberoftetrahedra = tetrahedrons->items;
31533 out->numberofcorners = b->order == 1 ? 4 : 10;
31534 out->numberoftetrahedronattributes = eextras;
31535 tlist = out->tetrahedronlist;
31536 talist = out->tetrahedronattributelist;
31537 pointindex = 0;
31538 attribindex = 0;
31539 }
31540
31541
31542 firstindex = b->zeroindex ? 0 : in->firstnumber;
31543 shift = 0;
31544 if ((in->firstnumber == 1) && (firstindex == 0)) {
31545 shift = 1;
31546 }
31547
31548 tetrahedrons->traversalinit();
31549 tptr = tetrahedrontraverse();
31550 elementnumber = firstindex;
31551 while (tptr != (tetrahedron *) NULL) {
31552 p1 = (point) tptr[4];
31553 p2 = (point) tptr[5];
31554 p3 = (point) tptr[6];
31555 p4 = (point) tptr[7];
31556 if (out == (tetgenio *) NULL) {
31557
31558 fprintf(outfile, "%5d %5d %5d %5d %5d", elementnumber,
31559 pointmark(p1) - shift, pointmark(p2) - shift,
31560 pointmark(p3) - shift, pointmark(p4) - shift);
31561 if (b->order == 2) {
31562 extralist = (point *) tptr[highorderindex];
31563
31564 fprintf(outfile, " %5d %5d %5d %5d %5d %5d",
31565 pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
31566 pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
31567 pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
31568 }
31569 for (i = 0; i < eextras; i++) {
31570 fprintf(outfile, " %.17g", elemattribute(tptr, i));
31571 }
31572 fprintf(outfile, "\n");
31573 } else {
31574 tlist[pointindex++] = pointmark(p1) - shift;
31575 tlist[pointindex++] = pointmark(p2) - shift;
31576 tlist[pointindex++] = pointmark(p3) - shift;
31577 tlist[pointindex++] = pointmark(p4) - shift;
31578 if (b->order == 2) {
31579 extralist = (point *) tptr[highorderindex];
31580 tlist[pointindex++] = pointmark(extralist[0]) - shift;
31581 tlist[pointindex++] = pointmark(extralist[1]) - shift;
31582 tlist[pointindex++] = pointmark(extralist[2]) - shift;
31583 tlist[pointindex++] = pointmark(extralist[3]) - shift;
31584 tlist[pointindex++] = pointmark(extralist[4]) - shift;
31585 tlist[pointindex++] = pointmark(extralist[5]) - shift;
31586 }
31587 for (i = 0; i < eextras; i++) {
31588 talist[attribindex++] = elemattribute(tptr, i);
31589 }
31590 }
31591 if (b->neighout) {
31592
31593 * (int *) (tptr + elemmarkerindex) = elementnumber;
31594 }
31595 tptr = tetrahedrontraverse();
31596 elementnumber++;
31597 }
31598 if (b->neighout) {
31599
31600 * (int *) (dummytet + elemmarkerindex) = -1;
31601 }
31602
31603 if (out == (tetgenio *) NULL) {
31604 fprintf(outfile, "# Generated by %s\n", b->commandline);
31605 fclose(outfile);
31606 }
31607 }
31608
31610
31611
31612
31613
31614
31615
31617
31618 void tetgenmesh::outfaces(tetgenio* out)
31619 {
31620 FILE *outfile;
31621 char facefilename[FILENAMESIZE];
31622 int *elist;
31623 int *emlist;
31624 int neigh1, neigh2;
31625 int index;
31626 triface tface, tsymface;
31627 face checkmark;
31628 point torg, tdest, tapex;
31629 long faces;
31630 int bmark, faceid, marker;
31631 int firstindex, shift;
31632 int facenumber;
31633
31634 neigh1 = 0;
31635 neigh2 = 0;
31636
31637 if (out == (tetgenio *) NULL) {
31638 strcpy(facefilename, b->outfilename);
31639 strcat(facefilename, ".face");
31640 }
31641
31642 if (!b->quiet) {
31643 if (out == (tetgenio *) NULL) {
31644 printf("Writing %s.\n", facefilename);
31645 } else {
31646 printf("Writing faces.\n");
31647 }
31648 }
31649
31650
31651 outfile = (FILE *) NULL;
31652 elist = (int *) NULL;
31653 emlist = (int *) NULL;
31654 index = marker = 0;
31655
31656 faces = (4l * tetrahedrons->items + hullsize) / 2l;
31657 bmark = !b->nobound && in->facetmarkerlist;
31658
31659 if (out == (tetgenio *) NULL) {
31660 outfile = fopen(facefilename, "w");
31661 if (outfile == (FILE *) NULL) {
31662 printf("File I/O Error: Cannot create file %s.\n", facefilename);
31663 terminatetetgen(1);
31664 }
31665 fprintf(outfile, "%ld %d\n", faces, bmark);
31666 } else {
31667
31668 out->trifacelist = new int[faces * 3];
31669 if (out->trifacelist == (int *) NULL) {
31670 printf("Error: Out of memory.\n");
31671 terminatetetgen(1);
31672 }
31673
31674 if (bmark) {
31675 out->trifacemarkerlist = new int[faces];
31676 if (out->trifacemarkerlist == (int *) NULL) {
31677 printf("Error: Out of memory.\n");
31678 terminatetetgen(1);
31679 }
31680 }
31681 if (b->neighout > 1) {
31682
31683 out->adjtetlist = new int[subfaces->items * 2];
31684 if (out->adjtetlist == (int *) NULL) {
31685 printf("Error: Out of memory.\n");
31686 terminatetetgen(1);
31687 }
31688 }
31689 out->numberoftrifaces = faces;
31690 elist = out->trifacelist;
31691 emlist = out->trifacemarkerlist;
31692 index = 0;
31693 }
31694
31695
31696 firstindex = b->zeroindex ? 0 : in->firstnumber;
31697 shift = 0;
31698 if ((in->firstnumber == 1) && (firstindex == 0)) {
31699 shift = 1;
31700 }
31701
31702 tetrahedrons->traversalinit();
31703 tface.tet = tetrahedrontraverse();
31704 facenumber = firstindex;
31705
31706
31707
31708
31709
31710
31711 while (tface.tet != (tetrahedron *) NULL) {
31712 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31713 sym(tface, tsymface);
31714 if ((tsymface.tet == dummytet) || (tface.tet < tsymface.tet)) {
31715 torg = org(tface);
31716 tdest = dest(tface);
31717 tapex = apex(tface);
31718 if (bmark) {
31719
31720
31721 if (b->useshelles) {
31722
31723 tspivot(tface, checkmark);
31724 if (checkmark.sh == dummysh) {
31725 marker = 0;
31726 } else {
31727 faceid = shellmark(checkmark) - 1;
31728 marker = in->facetmarkerlist[faceid];
31729 }
31730 } else {
31731
31732 marker = tsymface.tet != dummytet ? 1 : 0;
31733 }
31734 }
31735 if (b->neighout > 1) {
31736
31737 neigh1 = * (int *)(tface.tet + elemmarkerindex);
31738 if (tsymface.tet != dummytet) {
31739 neigh2 = * (int *)(tsymface.tet + elemmarkerindex);
31740 } else {
31741 neigh2 = -1;
31742 }
31743 }
31744 if (out == (tetgenio *) NULL) {
31745
31746 fprintf(outfile, "%5d %4d %4d %4d", facenumber,
31747 pointmark(torg) - shift, pointmark(tdest) - shift,
31748 pointmark(tapex) - shift);
31749 if (bmark) {
31750
31751 fprintf(outfile, " %d", marker);
31752 }
31753 if (b->neighout > 1) {
31754 fprintf(outfile, " %5d %5d", neigh1, neigh2);
31755 }
31756 fprintf(outfile, "\n");
31757 } else {
31758
31759 elist[index++] = pointmark(torg) - shift;
31760 elist[index++] = pointmark(tdest) - shift;
31761 elist[index++] = pointmark(tapex) - shift;
31762 if (bmark) {
31763 emlist[facenumber - in->firstnumber] = marker;
31764 }
31765 if (b->neighout > 1) {
31766 out->adjtetlist[(facenumber - in->firstnumber) * 2] = neigh1;
31767 out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
31768 }
31769 }
31770 facenumber++;
31771 }
31772 }
31773 tface.tet = tetrahedrontraverse();
31774 }
31775
31776 if (out == (tetgenio *) NULL) {
31777 fprintf(outfile, "# Generated by %s\n", b->commandline);
31778 fclose(outfile);
31779 }
31780 }
31781
31783
31784
31785
31786
31787
31788
31789
31790
31792
31793 void tetgenmesh::outhullfaces(tetgenio* out)
31794 {
31795 FILE *outfile;
31796 char facefilename[FILENAMESIZE];
31797 int *elist;
31798 int index;
31799 triface tface, tsymface;
31800 face checkmark;
31801 point torg, tdest, tapex;
31802 int firstindex, shift;
31803 int facenumber;
31804
31805 if (out == (tetgenio *) NULL) {
31806 strcpy(facefilename, b->outfilename);
31807 strcat(facefilename, ".face");
31808 }
31809
31810 if (!b->quiet) {
31811 if (out == (tetgenio *) NULL) {
31812 printf("Writing %s.\n", facefilename);
31813 } else {
31814 printf("Writing faces.\n");
31815 }
31816 }
31817
31818
31819 outfile = (FILE *) NULL;
31820 elist = (int *) NULL;
31821 index = 0;
31822
31823 if (out == (tetgenio *) NULL) {
31824 outfile = fopen(facefilename, "w");
31825 if (outfile == (FILE *) NULL) {
31826 printf("File I/O Error: Cannot create file %s.\n", facefilename);
31827 terminatetetgen(1);
31828 }
31829 fprintf(outfile, "%ld 0\n", hullsize);
31830 } else {
31831
31832 out->trifacelist = new int[hullsize * 3];
31833 if (out->trifacelist == (int *) NULL) {
31834 printf("Error: Out of memory.\n");
31835 terminatetetgen(1);
31836 }
31837 out->numberoftrifaces = hullsize;
31838 elist = out->trifacelist;
31839 index = 0;
31840 }
31841
31842
31843 firstindex = b->zeroindex ? 0 : in->firstnumber;
31844 shift = 0;
31845 if ((in->firstnumber == 1) && (firstindex == 0)) {
31846 shift = 1;
31847 }
31848
31849 tetrahedrons->traversalinit();
31850 tface.tet = tetrahedrontraverse();
31851 facenumber = firstindex;
31852
31853
31854
31855 while (tface.tet != (tetrahedron *) NULL) {
31856 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31857 sym(tface, tsymface);
31858 if (tsymface.tet == dummytet) {
31859 torg = org(tface);
31860 tdest = dest(tface);
31861 tapex = apex(tface);
31862 if (out == (tetgenio *) NULL) {
31863
31864 fprintf(outfile, "%5d %4d %4d %4d", facenumber,
31865 pointmark(torg) - shift, pointmark(tdest) - shift,
31866 pointmark(tapex) - shift);
31867 fprintf(outfile, "\n");
31868 } else {
31869
31870 elist[index++] = pointmark(torg) - shift;
31871 elist[index++] = pointmark(tdest) - shift;
31872 elist[index++] = pointmark(tapex) - shift;
31873 }
31874 facenumber++;
31875 }
31876 }
31877 tface.tet = tetrahedrontraverse();
31878 }
31879
31880 if (out == (tetgenio *) NULL) {
31881 fprintf(outfile, "# Generated by %s\n", b->commandline);
31882 fclose(outfile);
31883 }
31884 }
31885
31887
31888
31889
31890
31891
31892
31893
31894
31896
31897 void tetgenmesh::outsubfaces(tetgenio* out)
31898 {
31899 FILE *outfile;
31900 char facefilename[FILENAMESIZE];
31901 int *elist;
31902 int *emlist;
31903 int index, index1, index2;
31904 triface abuttingtet;
31905 face faceloop;
31906 point torg, tdest, tapex;
31907 int bmark, faceid, marker;
31908 int firstindex, shift;
31909 int neigh1, neigh2;
31910 int facenumber;
31911
31912 if (out == (tetgenio *) NULL) {
31913 strcpy(facefilename, b->outfilename);
31914 strcat(facefilename, ".face");
31915 }
31916
31917 if (!b->quiet) {
31918 if (out == (tetgenio *) NULL) {
31919 printf("Writing %s.\n", facefilename);
31920 } else {
31921 printf("Writing faces.\n");
31922 }
31923 }
31924
31925
31926 outfile = (FILE *) NULL;
31927 elist = (int *) NULL;
31928 emlist = (int *) NULL;
31929 index = index1 = index2 = 0;
31930 faceid = marker = 0;
31931 neigh1 = neigh2 = 0;
31932
31933 bmark = !b->nobound && in->facetmarkerlist;
31934
31935 if (out == (tetgenio *) NULL) {
31936 outfile = fopen(facefilename, "w");
31937 if (outfile == (FILE *) NULL) {
31938 printf("File I/O Error: Cannot create file %s.\n", facefilename);
31939 terminatetetgen(1);
31940 }
31941
31942 fprintf(outfile, "%ld %d\n", subfaces->items, bmark);
31943 } else {
31944
31945 out->trifacelist = new int[subfaces->items * 3];
31946 if (out->trifacelist == (int *) NULL) {
31947 printf("Error: Out of memory.\n");
31948 terminatetetgen(1);
31949 }
31950 if (bmark) {
31951
31952 out->trifacemarkerlist = new int[subfaces->items];
31953 if (out->trifacemarkerlist == (int *) NULL) {
31954 printf("Error: Out of memory.\n");
31955 terminatetetgen(1);
31956 }
31957 }
31958 if (b->neighout > 1) {
31959
31960 out->adjtetlist = new int[subfaces->items * 2];
31961 if (out->adjtetlist == (int *) NULL) {
31962 printf("Error: Out of memory.\n");
31963 terminatetetgen(1);
31964 }
31965 }
31966 out->numberoftrifaces = subfaces->items;
31967 elist = out->trifacelist;
31968 emlist = out->trifacemarkerlist;
31969 }
31970
31971
31972 firstindex = b->zeroindex ? 0 : in->firstnumber;
31973 shift = 0;
31974 if ((in->firstnumber == 1) && (firstindex == 0)) {
31975 shift = 1;
31976 }
31977
31978 subfaces->traversalinit();
31979 faceloop.sh = shellfacetraverse(subfaces);
31980 facenumber = firstindex;
31981 while (faceloop.sh != (shellface *) NULL) {
31982 stpivot(faceloop, abuttingtet);
31983 if (abuttingtet.tet == dummytet) {
31984 sesymself(faceloop);
31985 stpivot(faceloop, abuttingtet);
31986 }
31987 if (abuttingtet.tet != dummytet) {
31988
31989
31990
31991 adjustedgering(abuttingtet, CCW);
31992 torg = org(abuttingtet);
31993 tdest = dest(abuttingtet);
31994 tapex = apex(abuttingtet);
31995 } else {
31996
31997 torg = sorg(faceloop);
31998 tdest = sdest(faceloop);
31999 tapex = sapex(faceloop);
32000 }
32001 if (bmark) {
32002 faceid = shellmark(faceloop) - 1;
32003 marker = in->facetmarkerlist[faceid];
32004 }
32005 if (b->neighout > 1) {
32006
32007 neigh1 = -1;
32008 stpivot(faceloop, abuttingtet);
32009 if (abuttingtet.tet != dummytet) {
32010 neigh1 = * (int *)(abuttingtet.tet + elemmarkerindex);
32011 }
32012 neigh2 = -1;
32013 sesymself(faceloop);
32014 stpivot(faceloop, abuttingtet);
32015 if (abuttingtet.tet != dummytet) {
32016 neigh2 = * (int *)(abuttingtet.tet + elemmarkerindex);
32017 }
32018 }
32019 if (out == (tetgenio *) NULL) {
32020 fprintf(outfile, "%5d %4d %4d %4d", facenumber,
32021 pointmark(torg) - shift, pointmark(tdest) - shift,
32022 pointmark(tapex) - shift);
32023 if (bmark) {
32024 fprintf(outfile, " %d", marker);
32025 }
32026 if (b->neighout > 1) {
32027 fprintf(outfile, " %5d %5d", neigh1, neigh2);
32028 }
32029 fprintf(outfile, "\n");
32030 } else {
32031
32032 elist[index++] = pointmark(torg) - shift;
32033 elist[index++] = pointmark(tdest) - shift;
32034 elist[index++] = pointmark(tapex) - shift;
32035 if (bmark) {
32036 emlist[index1++] = marker;
32037 }
32038 if (b->neighout > 1) {
32039 out->adjtetlist[index2++] = neigh1;
32040 out->adjtetlist[index2++] = neigh2;
32041 }
32042 }
32043 facenumber++;
32044 faceloop.sh = shellfacetraverse(subfaces);
32045 }
32046
32047 if (out == (tetgenio *) NULL) {
32048 fprintf(outfile, "# Generated by %s\n", b->commandline);
32049 fclose(outfile);
32050 }
32051 }
32052
32054
32055
32056
32058
32059 void tetgenmesh::outedges(tetgenio* out)
32060 {
32061 FILE *outfile;
32062 char edgefilename[FILENAMESIZE];
32063 int *elist, *emlist;
32064 int index, index1;
32065 triface tetloop, worktet, spintet;
32066 face checksh;
32067 point torg, tdest;
32068 long faces, edges;
32069 int firstindex, shift;
32070 int edgenumber, faceid, marker;
32071 int hitbdry, i;
32072
32073 if (out == (tetgenio *) NULL) {
32074 strcpy(edgefilename, b->outfilename);
32075 strcat(edgefilename, ".edge");
32076 }
32077
32078 if (!b->quiet) {
32079 if (out == (tetgenio *) NULL) {
32080 printf("Writing %s.\n", edgefilename);
32081 } else {
32082 printf("Writing edges.\n");
32083 }
32084 }
32085
32086
32087 outfile = (FILE *) NULL;
32088 elist = (int *) NULL;
32089 emlist = (int *) NULL;
32090 index = index1 = 0;
32091 faceid = marker = 0;
32092
32093
32094 faces = (4l * tetrahedrons->items + hullsize) / 2l;
32095 edges = points->items + faces - tetrahedrons->items - 1l;
32096
32097 if (out == (tetgenio *) NULL) {
32098 outfile = fopen(edgefilename, "w");
32099 if (outfile == (FILE *) NULL) {
32100 printf("File I/O Error: Cannot create file %s.\n", edgefilename);
32101 terminatetetgen(1);
32102 }
32103
32104 fprintf(outfile, "%ld %d\n", edges, !b->nobound);
32105 } else {
32106
32107 out->edgelist = new int[edges * 2];
32108 if (out->edgelist == (int *) NULL) {
32109 printf("Error: Out of memory.\n");
32110 terminatetetgen(1);
32111 }
32112 if (!b->nobound) {
32113 out->edgemarkerlist = new int[edges];
32114 }
32115 out->numberofedges = edges;
32116 elist = out->edgelist;
32117 emlist = out->edgemarkerlist;
32118 }
32119
32120
32121 firstindex = b->zeroindex ? 0 : in->firstnumber;
32122 shift = 0;
32123 if ((in->firstnumber == 1) && (firstindex == 0)) {
32124 shift = 1;
32125 }
32126
32127 tetrahedrons->traversalinit();
32128 tetloop.tet = tetrahedrontraverse();
32129 edgenumber = firstindex;
32130 while (tetloop.tet != (tetrahedron *) NULL) {
32131
32132
32133
32134 worktet.tet = tetloop.tet;
32135 for (i = 0; i < 6; i++) {
32136 worktet.loc = edge2locver[i][0];
32137 worktet.ver = edge2locver[i][1];
32138 adjustedgering(worktet, CW);
32139 spintet = worktet;
32140 hitbdry = 0;
32141 while (hitbdry < 2) {
32142 if (fnextself(spintet)) {
32143 if (apex(spintet) == apex(worktet)) break;
32144 if (spintet.tet < worktet.tet) break;
32145 } else {
32146 hitbdry++;
32147 if (hitbdry < 2) {
32148 esym(worktet, spintet);
32149 fnextself(spintet);
32150 }
32151 }
32152 }
32153
32154 if (spintet.tet >= worktet.tet) {
32155 torg = org(worktet);
32156 tdest = dest(worktet);
32157 if (out == (tetgenio *) NULL) {
32158 fprintf(outfile, "%5d %4d %4d", edgenumber,
32159 pointmark(torg) - shift, pointmark(tdest) - shift);
32160 } else {
32161
32162 elist[index++] = pointmark(torg) - shift;
32163 elist[index++] = pointmark(tdest) - shift;
32164 }
32165 if (!b->nobound) {
32166 if (hitbdry > 0) {
32167
32168
32169
32170 if ((b->plc || b->refine) && in->facetmarkerlist) {
32171 tspivot(spintet, checksh);
32172 faceid = shellmark(checksh) - 1;
32173 marker = in->facetmarkerlist[faceid];
32174 } else {
32175 marker = 1;
32176 }
32177 } else {
32178 marker = 0;
32179 }
32180 if (out == (tetgenio *) NULL) {
32181 fprintf(outfile, " %d", marker);
32182 } else {
32183 emlist[index1++] = marker;
32184 }
32185 }
32186 if (out == (tetgenio *) NULL) {
32187 fprintf(outfile, "\n");
32188 }
32189 edgenumber++;
32190 }
32191 }
32192 tetloop.tet = tetrahedrontraverse();
32193 }
32194
32195 if (out == (tetgenio *) NULL) {
32196 fprintf(outfile, "# Generated by %s\n", b->commandline);
32197 fclose(outfile);
32198 }
32199 }
32200
32202
32203
32204
32206
32207 void tetgenmesh::outsubsegments(tetgenio* out)
32208 {
32209 FILE *outfile;
32210 char edgefilename[FILENAMESIZE];
32211 int *elist;
32212 int index;
32213 face edgeloop;
32214 point torg, tdest;
32215 int firstindex, shift;
32216 int edgenumber;
32217
32218 if (out == (tetgenio *) NULL) {
32219 strcpy(edgefilename, b->outfilename);
32220 strcat(edgefilename, ".edge");
32221 }
32222
32223 if (!b->quiet) {
32224 if (out == (tetgenio *) NULL) {
32225 printf("Writing %s.\n", edgefilename);
32226 } else {
32227 printf("Writing edges.\n");
32228 }
32229 }
32230
32231
32232 outfile = (FILE *) NULL;
32233 elist = (int *) NULL;
32234 index = 0;
32235
32236 if (out == (tetgenio *) NULL) {
32237 outfile = fopen(edgefilename, "w");
32238 if (outfile == (FILE *) NULL) {
32239 printf("File I/O Error: Cannot create file %s.\n", edgefilename);
32240 terminatetetgen(1);
32241 }
32242
32243 fprintf(outfile, "%ld\n", subsegs->items);
32244 } else {
32245
32246 out->edgelist = new int[subsegs->items * 2];
32247 if (out->edgelist == (int *) NULL) {
32248 printf("Error: Out of memory.\n");
32249 terminatetetgen(1);
32250 }
32251 out->numberofedges = subsegs->items;
32252 elist = out->edgelist;
32253 }
32254
32255
32256 firstindex = b->zeroindex ? 0 : in->firstnumber;
32257 shift = 0;
32258 if ((in->firstnumber == 1) && (firstindex == 0)) {
32259 shift = 1;
32260 }
32261
32262 subsegs->traversalinit();
32263 edgeloop.sh = shellfacetraverse(subsegs);
32264 edgenumber = firstindex;
32265 while (edgeloop.sh != (shellface *) NULL) {
32266 torg = sorg(edgeloop);
32267 tdest = sdest(edgeloop);
32268 if (out == (tetgenio *) NULL) {
32269 fprintf(outfile, "%5d %4d %4d\n", edgenumber,
32270 pointmark(torg) - shift, pointmark(tdest) - shift);
32271 } else {
32272
32273 elist[index++] = pointmark(torg) - shift;
32274 elist[index++] = pointmark(tdest) - shift;
32275 }
32276 edgenumber++;
32277 edgeloop.sh = shellfacetraverse(subsegs);
32278 }
32279
32280 if (out == (tetgenio *) NULL) {
32281 fprintf(outfile, "# Generated by %s\n", b->commandline);
32282 fclose(outfile);
32283 }
32284 }
32285
32287
32288
32289
32291
32292 void tetgenmesh::outneighbors(tetgenio* out)
32293 {
32294 FILE *outfile;
32295 char neighborfilename[FILENAMESIZE];
32296 int *nlist;
32297 int index;
32298 triface tetloop, tetsym;
32299 int neighbor1, neighbor2, neighbor3, neighbor4;
32300 int firstindex;
32301 int elementnumber;
32302
32303 if (out == (tetgenio *) NULL) {
32304 strcpy(neighborfilename, b->outfilename);
32305 strcat(neighborfilename, ".neigh");
32306 }
32307
32308 if (!b->quiet) {
32309 if (out == (tetgenio *) NULL) {
32310 printf("Writing %s.\n", neighborfilename);
32311 } else {
32312 printf("Writing neighbors.\n");
32313 }
32314 }
32315
32316
32317 outfile = (FILE *) NULL;
32318 nlist = (int *) NULL;
32319 index = 0;
32320
32321 if (out == (tetgenio *) NULL) {
32322 outfile = fopen(neighborfilename, "w");
32323 if (outfile == (FILE *) NULL) {
32324 printf("File I/O Error: Cannot create file %s.\n", neighborfilename);
32325 terminatetetgen(1);
32326 }
32327
32328 fprintf(outfile, "%ld %d\n", tetrahedrons->items, 4);
32329 } else {
32330
32331 out->neighborlist = new int[tetrahedrons->items * 4];
32332 if (out->neighborlist == (int *) NULL) {
32333 printf("Error: Out of memory.\n");
32334 terminatetetgen(1);
32335 }
32336 nlist = out->neighborlist;
32337 }
32338
32339
32340 firstindex = b->zeroindex ? 0 : in->firstnumber;
32341
32342 tetrahedrons->traversalinit();
32343 tetloop.tet = tetrahedrontraverse();
32344 elementnumber = firstindex;
32345 while (tetloop.tet != (tetrahedron *) NULL) {
32346 tetloop.loc = 2;
32347 sym(tetloop, tetsym);
32348 neighbor1 = * (int *) (tetsym.tet + elemmarkerindex);
32349 tetloop.loc = 3;
32350 sym(tetloop, tetsym);
32351 neighbor2 = * (int *) (tetsym.tet + elemmarkerindex);
32352 tetloop.loc = 1;
32353 sym(tetloop, tetsym);
32354 neighbor3 = * (int *) (tetsym.tet + elemmarkerindex);
32355 tetloop.loc = 0;
32356 sym(tetloop, tetsym);
32357 neighbor4 = * (int *) (tetsym.tet + elemmarkerindex);
32358 if (out == (tetgenio *) NULL) {
32359
32360 fprintf(outfile, "%4d %4d %4d %4d %4d\n", elementnumber,
32361 neighbor1, neighbor2, neighbor3, neighbor4);
32362 } else {
32363 nlist[index++] = neighbor1;
32364 nlist[index++] = neighbor2;
32365 nlist[index++] = neighbor3;
32366 nlist[index++] = neighbor4;
32367 }
32368 tetloop.tet = tetrahedrontraverse();
32369 elementnumber++;
32370 }
32371
32372 if (out == (tetgenio *) NULL) {
32373 fprintf(outfile, "# Generated by %s\n", b->commandline);
32374 fclose(outfile);
32375 }
32376 }
32377
32379
32380
32381
32382
32383
32384
32385
32386
32387
32388
32389
32390
32391
32392
32393
32395
32396 void tetgenmesh::outvoronoi(tetgenio* out)
32397 {
32398 FILE *outfile;
32399 char outfilename[FILENAMESIZE];
32400 tetgenio::voroedge *vedge;
32401 tetgenio::vorofacet *vfacet;
32402 list *tetlist, *ptlist;
32403 triface tetloop, worktet, spintet;
32404 point pt[4], ptloop, neipt;
32405 REAL ccent[3], infvec[3], vec1[3], vec2[3], L;
32406 long faces, edges;
32407 int *tetfaceindexarray, *tetedgeindexarray;
32408 int arraysize, *vertarray;
32409 int vpointcount, vedgecount, vfacecount, tcount;
32410 int index, shift;
32411 int end1, end2;
32412 int hitbdry, i, j, k;
32413
32414 vedge = NULL;
32415 vertarray = NULL;
32416 vfacet = NULL;
32417 k = 0;
32418
32419
32420 if (out == (tetgenio *) NULL) {
32421 strcpy(outfilename, b->outfilename);
32422 strcat(outfilename, ".v.node");
32423 }
32424
32425 if (!b->quiet) {
32426 if (out == (tetgenio *) NULL) {
32427 printf("Writing %s.\n", outfilename);
32428 } else {
32429 printf("Writing Voronoi vertices.\n");
32430 }
32431 }
32432
32433
32434 shift = (b->zeroindex ? 0 : in->firstnumber);
32435
32436 faces = (4l * tetrahedrons->items + hullsize) / 2l;
32437
32438 edges = points->items + faces - tetrahedrons->items - 1;
32439 outfile = (FILE *) NULL;
32440
32441 if (out == (tetgenio *) NULL) {
32442 outfile = fopen(outfilename, "w");
32443 if (outfile == (FILE *) NULL) {
32444 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32445 terminatetetgen(1);
32446 }
32447
32448 fprintf(outfile, "%ld 3 0 0\n", tetrahedrons->items);
32449 } else {
32450
32451 out->numberofvpoints = (int) tetrahedrons->items;
32452 out->vpointlist = new REAL[out->numberofvpoints * 3];
32453 if (out->vpointlist == (REAL *) NULL) {
32454 printf("Error: Out of memory.\n");
32455 terminatetetgen(1);
32456 }
32457 }
32458
32459
32460
32461
32462 tetrahedrons->traversalinit();
32463 tetloop.tet = tetrahedrontraverse();
32464 vpointcount = 0;
32465 index = 0;
32466 while (tetloop.tet != (tetrahedron *) NULL) {
32467
32468 for (i = 0; i < 4; i++) {
32469 pt[i] = (point) tetloop.tet[4 + i];
32470 setpoint2tet(pt[i], encode(tetloop));
32471 }
32472 circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
32473 if (out == (tetgenio *) NULL) {
32474 fprintf(outfile, "%4d %16.8e %16.8e %16.8e\n", vpointcount + shift,
32475 ccent[0], ccent[1], ccent[2]);
32476 } else {
32477 out->vpointlist[index++] = ccent[0];
32478 out->vpointlist[index++] = ccent[1];
32479 out->vpointlist[index++] = ccent[2];
32480 }
32481
32482 * (int *) (tetloop.tet + elemmarkerindex) = vpointcount;
32483 vpointcount++;
32484 tetloop.tet = tetrahedrontraverse();
32485 }
32486
32487 * (int *) (dummytet + elemmarkerindex) = -1;
32488
32489 if (out == (tetgenio *) NULL) {
32490 fprintf(outfile, "# Generated by %s\n", b->commandline);
32491 fclose(outfile);
32492 }
32493
32494
32495 if (out == (tetgenio *) NULL) {
32496 strcpy(outfilename, b->outfilename);
32497 strcat(outfilename, ".v.edge");
32498 }
32499
32500 if (!b->quiet) {
32501 if (out == (tetgenio *) NULL) {
32502 printf("Writing %s.\n", outfilename);
32503 } else {
32504 printf("Writing Voronoi edges.\n");
32505 }
32506 }
32507
32508 if (out == (tetgenio *) NULL) {
32509 outfile = fopen(outfilename, "w");
32510 if (outfile == (FILE *) NULL) {
32511 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32512 terminatetetgen(1);
32513 }
32514
32515 fprintf(outfile, "%ld 0\n", faces);
32516 } else {
32517
32518 out->numberofedges = (int) faces;
32519 out->vedgelist = new tetgenio::voroedge[out->numberofvedges];
32520 }
32521
32522
32523
32524
32525
32526
32527 tetfaceindexarray = new int[tetrahedrons->items * 4];
32528 tetrahedrons->traversalinit();
32529 tetloop.tet = tetrahedrontraverse();
32530 vedgecount = 0;
32531 index = 0;
32532 while (tetloop.tet != (tetrahedron *) NULL) {
32533
32534
32535
32536 end1 = * (int *) (tetloop.tet + elemmarkerindex);
32537 for (i = 0; i < 4; i++) {
32538 decode(tetloop.tet[i], worktet);
32539 if ((worktet.tet == dummytet) || (tetloop.tet < worktet.tet)) {
32540 if (out == (tetgenio *) NULL) {
32541 fprintf(outfile, "%4d %4d", vedgecount + shift, end1 + shift);
32542 } else {
32543 vedge = &(out->vedgelist[index++]);
32544 vedge->v1 = end1 + shift;
32545 }
32546 end2 = * (int *) (worktet.tet + elemmarkerindex);
32547
32548 if (end2 == -1) {
32549
32550 worktet.tet = tetloop.tet;
32551 worktet.loc = i;
32552 worktet.ver = 1;
32553 pt[0] = org(worktet);
32554 pt[1] = dest(worktet);
32555 pt[2] = apex(worktet);
32556 for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j];
32557 for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j];
32558 cross(vec1, vec2, infvec);
32559
32560 L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1]
32561 + infvec[2] * infvec[2]);
32562 if (L > 0) for (j = 0; j < 3; j++) infvec[j] /= L;
32563 if (out == (tetgenio *) NULL) {
32564 fprintf(outfile, " -1");
32565 fprintf(outfile, " %g %g %g\n", infvec[0], infvec[1], infvec[2]);
32566 } else {
32567 vedge->v2 = -1;
32568 vedge->vnormal[0] = infvec[0];
32569 vedge->vnormal[1] = infvec[1];
32570 vedge->vnormal[2] = infvec[2];
32571 }
32572 } else {
32573 if (out == (tetgenio *) NULL) {
32574 fprintf(outfile, " %4d\n", end2 + shift);
32575 } else {
32576 vedge->v2 = end2 + shift;
32577 vedge->vnormal[0] = 0.0;
32578 vedge->vnormal[1] = 0.0;
32579 vedge->vnormal[2] = 0.0;
32580 }
32581 }
32582
32583 tetfaceindexarray[end1 * 4 + i] = vedgecount;
32584 if (end2 != -1) {
32585 tetfaceindexarray[end2 * 4 + worktet.loc] = vedgecount;
32586 }
32587 vedgecount++;
32588 }
32589 }
32590 tetloop.tet = tetrahedrontraverse();
32591 }
32592
32593 if (out == (tetgenio *) NULL) {
32594 fprintf(outfile, "# Generated by %s\n", b->commandline);
32595 fclose(outfile);
32596 }
32597
32598
32599 if (out == (tetgenio *) NULL) {
32600 strcpy(outfilename, b->outfilename);
32601 strcat(outfilename, ".v.face");
32602 }
32603
32604 if (!b->quiet) {
32605 if (out == (tetgenio *) NULL) {
32606 printf("Writing %s.\n", outfilename);
32607 } else {
32608 printf("Writing Voronoi faces.\n");
32609 }
32610 }
32611
32612 if (out == (tetgenio *) NULL) {
32613 outfile = fopen(outfilename, "w");
32614 if (outfile == (FILE *) NULL) {
32615 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32616 terminatetetgen(1);
32617 }
32618
32619 fprintf(outfile, "%ld 0\n", edges);
32620 } else {
32621 out->numberofvfacets = edges;
32622 out->vfacetlist = new tetgenio::vorofacet[out->numberofvfacets];
32623 if (out->vfacetlist == (tetgenio::vorofacet *) NULL) {
32624 printf("Error: Out of memory.\n");
32625 terminatetetgen(1);
32626 }
32627 }
32628
32629
32630
32631
32632
32633
32634 tetedgeindexarray = new int[tetrahedrons->items * 6];
32635 tetrahedrons->traversalinit();
32636 tetloop.tet = tetrahedrontraverse();
32637 vfacecount = 0;
32638 while (tetloop.tet != (tetrahedron *) NULL) {
32639
32640
32641
32642 worktet = tetloop;
32643 for (i = 0; i < 6; i++) {
32644 worktet.loc = edge2locver[i][0];
32645 worktet.ver = edge2locver[i][1];
32646
32647 tcount = 1;
32648 adjustedgering(worktet, CW);
32649 spintet = worktet;
32650 hitbdry = 0;
32651 while (hitbdry < 2) {
32652 if (fnextself(spintet)) {
32653 if (apex(spintet) == apex(worktet)) break;
32654 if (spintet.tet < worktet.tet) break;
32655 tcount++;
32656 } else {
32657 hitbdry++;
32658 if (hitbdry < 2) {
32659 esym(worktet, spintet);
32660 fnextself(spintet);
32661 }
32662 }
32663 }
32664
32665 if (spintet.tet >= worktet.tet) {
32666
32667 pt[0] = org(worktet);
32668 pt[1] = dest(worktet);
32669 end1 = pointmark(pt[0]) - in->firstnumber;
32670 end2 = pointmark(pt[1]) - in->firstnumber;
32671 if (out == (tetgenio *) NULL) {
32672 fprintf(outfile, "%4d %4d %4d %-2d ", vfacecount + shift,
32673 end1 + shift, end2 + shift, tcount + (hitbdry > 0));
32674 } else {
32675 vfacet = &(out->vfacetlist[vfacecount]);
32676 vfacet->c1 = end1 + shift;
32677 vfacet->c2 = end2 + shift;
32678 vfacet->elist = new int[tcount + (hitbdry > 0) + 1];
32679 vfacet->elist[0] = tcount + (hitbdry > 0);
32680 index = 1;
32681 }
32682
32683 if (hitbdry > 0) {
32684
32685 vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32686 vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32687 if (out == (tetgenio *) NULL) {
32688 fprintf(outfile, " %d", vedgecount + shift);
32689 } else {
32690 vfacet->elist[index++] = vedgecount + shift;
32691 }
32692
32693 tetedgeindexarray[vpointcount * 6 +
32694 locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32695 esymself(spintet);
32696 fnextself(spintet);
32697 }
32698
32699 for (j = 0; j < tcount; j++) {
32700 vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32701 vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32702 if (out == (tetgenio *) NULL) {
32703 fprintf(outfile, " %d", vedgecount + shift);
32704 } else {
32705 vfacet->elist[index++] = vedgecount + shift;
32706 }
32707
32708 tetedgeindexarray[vpointcount * 6 +
32709 locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32710 fnextself(spintet);
32711 }
32712 if (out == (tetgenio *) NULL) {
32713 fprintf(outfile, "\n");
32714 }
32715 vfacecount++;
32716 }
32717 }
32718 tetloop.tet = tetrahedrontraverse();
32719 }
32720
32721 if (out == (tetgenio *) NULL) {
32722 fprintf(outfile, "# Generated by %s\n", b->commandline);
32723 fclose(outfile);
32724 }
32725
32726
32727 if (out == (tetgenio *) NULL) {
32728 strcpy(outfilename, b->outfilename);
32729 strcat(outfilename, ".v.cell");
32730 }
32731
32732 if (!b->quiet) {
32733 if (out == (tetgenio *) NULL) {
32734 printf("Writing %s.\n", outfilename);
32735 } else {
32736 printf("Writing Voronoi cells.\n");
32737 }
32738 }
32739
32740 if (out == (tetgenio *) NULL) {
32741 outfile = fopen(outfilename, "w");
32742 if (outfile == (FILE *) NULL) {
32743 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32744 terminatetetgen(1);
32745 }
32746
32747 fprintf(outfile, "%ld\n", points->items);
32748 } else {
32749 out->numberofvcells = points->items;
32750 out->vcelllist = new int*[out->numberofvcells];
32751 if (out->vcelllist == (int **) NULL) {
32752 printf("Error: Out of memory.\n");
32753 terminatetetgen(1);
32754 }
32755 }
32756
32757
32758 tetlist = new list(sizeof(triface), NULL, 256);
32759 ptlist = new list(sizeof(point *), NULL, 256);
32760 points->traversalinit();
32761 ptloop = pointtraverse();
32762 vpointcount = 0;
32763 while (ptloop != (point) NULL) {
32764 decode(point2tet(ptloop), tetloop);
32765
32766 if (!isdead(&tetloop)) {
32767
32768 tetlist->append(&tetloop);
32769 formstarpolyhedron(ptloop, tetlist, ptlist, true);
32770 tcount = ptlist->len();
32771 if (out == (tetgenio *) NULL) {
32772 fprintf(outfile, "%4d %-2d ", vpointcount + shift, tcount);
32773 } else {
32774 arraysize = tcount;
32775 vertarray = out->vcelllist[vpointcount];
32776 vertarray = new int[arraysize + 1];
32777 vertarray[0] = arraysize;
32778 index = 1;
32779 }
32780
32781 for (i = 0; i < ptlist->len(); i++) {
32782 neipt = * (point *)(* ptlist)[i];
32783
32784 for (j = 0; j < tetlist->len(); j++) {
32785 tetloop = * (triface *)(* tetlist)[j];
32786 for (k = 0; k < 6; k++) {
32787 tetloop.loc = edge2locver[k][0];
32788 tetloop.ver = edge2locver[k][1];
32789 if (org(tetloop) == ptloop) {
32790 if (dest(tetloop) == neipt) break;
32791 } else if (org(tetloop) == neipt) {
32792 if (dest(tetloop) == ptloop) break;
32793 }
32794 }
32795 if (k < 6) break;
32796 }
32797 assert(j < tetlist->len());
32798
32799 end1 = * (int *) (tetloop.tet + elemmarkerindex);
32800 vfacecount = tetedgeindexarray[end1 * 6 + k];
32801 if (out == (tetgenio *) NULL) {
32802 fprintf(outfile, " %d", vfacecount + shift);
32803 } else {
32804 vertarray[index++] = vfacecount + shift;
32805 }
32806 }
32807 if (out == (tetgenio *) NULL) {
32808 fprintf(outfile, "\n");
32809 }
32810 vpointcount++;
32811 }
32812 tetlist->clear();
32813 ptlist->clear();
32814 ptloop = pointtraverse();
32815 }
32816 delete tetlist;
32817 delete ptlist;
32818 delete [] tetfaceindexarray;
32819 delete [] tetedgeindexarray;
32820
32821 if (out == (tetgenio *) NULL) {
32822 fprintf(outfile, "# Generated by %s\n", b->commandline);
32823 fclose(outfile);
32824 }
32825 }
32826
32828
32829
32830
32832
32833 void tetgenmesh::outpbcnodes(tetgenio* out)
32834 {
32835 FILE *outfile;
32836 char pbcfilename[FILENAMESIZE];
32837 list *ptpairlist;
32838 tetgenio::pbcgroup *pgi, *pgo;
32839 pbcdata *pd;
32840 face faceloop;
32841 face checkseg, symseg;
32842 point *ptpair, pa, pb;
32843 enum locateresult loc;
32844 REAL sympt[3], d1, d2;
32845 int *worklist;
32846 int firstindex, shift;
32847 int index, idx;
32848 int i, j, k, l;
32849
32850 if (out == (tetgenio *) NULL) {
32851 strcpy(pbcfilename, b->outfilename);
32852 strcat(pbcfilename, ".pbc");
32853 }
32854
32855 if (!b->quiet) {
32856 if (out == (tetgenio *) NULL) {
32857 printf("Writing %s.\n", pbcfilename);
32858 } else {
32859 printf("Writing pbc nodes.\n");
32860 }
32861 }
32862
32863
32864 outfile = (FILE *) NULL;
32865 pgo = (tetgenio::pbcgroup *) NULL;
32866 index = 0;
32867
32868 if (out == (tetgenio *) NULL) {
32869 outfile = fopen(pbcfilename, "w");
32870 if (outfile == (FILE *) NULL) {
32871 printf("File I/O Error: Cannot create file %s.\n", pbcfilename);
32872 terminatetetgen(1);
32873 }
32874
32875 fprintf(outfile, "# number of PBCs.\n");
32876 fprintf(outfile, "%d\n\n", in->numberofpbcgroups);
32877 } else {
32878 out->numberofpbcgroups = in->numberofpbcgroups;
32879
32880 out->pbcgrouplist = new tetgenio::pbcgroup[in->numberofpbcgroups];
32881
32882 if (out->pbcgrouplist == (tetgenio::pbcgroup *) NULL) {
32883 printf("Error: Out of memory.\n");
32884 terminatetetgen(1);
32885 }
32886 }
32887
32888 ptpairlist = new list(2 * sizeof(point *), NULL, 256);
32889 worklist = new int[points->items + 1];
32890 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
32891
32892
32893 firstindex = b->zeroindex ? 0 : in->firstnumber;
32894 shift = 0;
32895 if ((in->firstnumber == 1) && (firstindex == 0)) {
32896 shift = 1;
32897 }
32898
32899 for (i = 0; i < in->numberofpbcgroups; i++) {
32900
32901 pgi = &(in->pbcgrouplist[i]);
32902 if (out == (tetgenio *) NULL) {
32903 fprintf(outfile, "# PBC %d\n", in->firstnumber + i);
32904
32905 fprintf(outfile, "%d %d\n", pgi->fmark1, pgi->fmark2);
32906
32907 fprintf(outfile, "[\n");
32908 for (j = 0; j < 4; j++) {
32909 fprintf(outfile, " %.12g %.12g %.12g %.12g\n", pgi->transmat[j][0],
32910 pgi->transmat[j][1], pgi->transmat[j][2], pgi->transmat[j][3]);
32911 }
32912 fprintf(outfile, "]\n");
32913 } else {
32914 pgo = &(out->pbcgrouplist[i]);
32915
32916 pgo->fmark1 = pgi->fmark1;
32917 pgo->fmark2 = pgi->fmark2;
32918 for (j = 0; j < 4; j++) {
32919 for (k = 0; k < 4; k++) pgo->transmat[j][k] = pgi->transmat[j][k];
32920 }
32921 }
32922
32923
32924 subfaces->traversalinit();
32925 faceloop.sh = shellfacetraverse(subfaces);
32926 while (faceloop.sh != (shellface *) NULL) {
32927 if (shellpbcgroup(faceloop) == i) {
32928
32929 idx = shellmark(faceloop) - 1;
32930 if (in->facetmarkerlist[idx] == pgi->fmark1) {
32931
32932 for (j = 0; j < 3; j++) {
32933 sspivot(faceloop, checkseg);
32934
32935 for (k = 0; k < 2; k++) {
32936 if (k == 0) pa = sorg(faceloop);
32937 else pa = sdest(faceloop);
32938 if (worklist[pointmark(pa)] == 0) {
32939 pb = (point) NULL;
32940 if (checkseg.sh != dummysh) {
32941
32942
32943 idx = shellmark(checkseg) - 1;
32944 for (l = idx2segpglist[idx]; l < idx2segpglist[idx + 1];
32945 l++) {
32946 pd = (pbcdata *)(* segpbcgrouptable)[segpglist[l]];
32947 if (((pd->fmark[0] == pgi->fmark1) &&
32948 (pd->fmark[1] == pgi->fmark2)) ||
32949 ((pd->fmark[0] == pgi->fmark2) &&
32950 (pd->fmark[1] == pgi->fmark1))) break;
32951 }
32952 #ifdef SELF_CHECK
32953 assert(l < idx2segpglist[idx + 1]);
32954 #endif
32955 loc = getsegpbcsympoint(pa, &checkseg, sympt, &symseg,
32956 segpglist[l]);
32957 if (loc != ONVERTEX) {
32958
32959
32960
32961 d1 = distance(sympt, sorg(symseg));
32962 d2 = distance(sympt, sdest(symseg));
32963 if (d1 > d2) sesymself(symseg);
32964 }
32965 pb = sorg(symseg);
32966 } else {
32967
32968 if (pointtype(pa) == FREESUBVERTEX) {
32969 pb = point2pbcpt(pa);
32970 }
32971 }
32972 if (pb != (point) NULL) {
32973
32974 ptpair = (point *) ptpairlist->append(NULL);
32975 ptpair[0] = pa;
32976 ptpair[1] = pb;
32977
32978 worklist[pointmark(pa)] = 1;
32979 }
32980 }
32981 }
32982
32983 senextself(faceloop);
32984 }
32985 }
32986 }
32987 faceloop.sh = shellfacetraverse(subfaces);
32988 }
32989
32990
32991 if (out == (tetgenio *) NULL) {
32992 fprintf(outfile, "%d\n", ptpairlist->len());
32993 } else {
32994 pgo->numberofpointpairs = ptpairlist->len();
32995 pgo->pointpairlist = new int[pgo->numberofpointpairs * 2];
32996 index = 0;
32997 }
32998 for (j = 0; j < ptpairlist->len(); j++) {
32999 ptpair = (point *)(* ptpairlist)[j];
33000 pa = ptpair[0];
33001 pb = ptpair[1];
33002 if (out == (tetgenio *) NULL) {
33003 fprintf(outfile, " %4d %4d\n", pointmark(pa) - shift,
33004 pointmark(pb) - shift);
33005 } else {
33006 pgo->pointpairlist[index++] = pointmark(pa) - shift;
33007 pgo->pointpairlist[index++] = pointmark(pb) - shift;
33008 }
33009
33010 worklist[pointmark(pa)] = 0;
33011 }
33012 if (out == (tetgenio *) NULL) {
33013 fprintf(outfile, "\n");
33014 }
33015 ptpairlist->clear();
33016 }
33017
33018 delete [] worklist;
33019 delete ptpairlist;
33020
33021 if (out == (tetgenio *) NULL) {
33022 fprintf(outfile, "# Generated by %s\n", b->commandline);
33023 fclose(outfile);
33024 }
33025 }
33026
33028
33029
33030
33031
33032
33033
33034
33035
33037
33038 void tetgenmesh::outsmesh(char* smfilename)
33039 {
33040 FILE *outfile;
33041 char nodfilename[FILENAMESIZE];
33042 char smefilename[FILENAMESIZE];
33043 face faceloop;
33044 point p1, p2, p3;
33045 int firstindex, shift;
33046 int bmark;
33047 int faceid, marker;
33048 int i;
33049
33050 if (smfilename != (char *) NULL && smfilename[0] != '\0') {
33051 strcpy(smefilename, smfilename);
33052 } else if (b->outfilename[0] != '\0') {
33053 strcpy(smefilename, b->outfilename);
33054 } else {
33055 strcpy(smefilename, "unnamed");
33056 }
33057 strcpy(nodfilename, smefilename);
33058 strcat(smefilename, ".smesh");
33059 strcat(nodfilename, ".node");
33060
33061 if (!b->quiet) {
33062 printf("Writing %s.\n", smefilename);
33063 }
33064 outfile = fopen(smefilename, "w");
33065 if (outfile == (FILE *) NULL) {
33066 printf("File I/O Error: Cannot create file %s.\n", smefilename);
33067 return;
33068 }
33069
33070
33071 firstindex = b->zeroindex ? 0 : in->firstnumber;
33072 shift = 0;
33073 if ((in->firstnumber == 1) && (firstindex == 0)) {
33074 shift = 1;
33075 }
33076
33077 fprintf(outfile, "# %s. TetGen's input file.\n", smefilename);
33078 fprintf(outfile, "\n# part 1: node list.\n");
33079 fprintf(outfile, "0 3 0 0 # nodes are found in %s.\n", nodfilename);
33080
33081 marker = 0;
33082 bmark = !b->nobound && in->facetmarkerlist;
33083
33084 fprintf(outfile, "\n# part 2: facet list.\n");
33085
33086 fprintf(outfile, "%ld %d\n", subfaces->items, bmark);
33087
33088 subfaces->traversalinit();
33089 faceloop.sh = shellfacetraverse(subfaces);
33090 while (faceloop.sh != (shellface *) NULL) {
33091 p1 = sorg(faceloop);
33092 p2 = sdest(faceloop);
33093 p3 = sapex(faceloop);
33094 if (bmark) {
33095 faceid = shellmark(faceloop) - 1;
33096 if (faceid >= 0) {
33097 marker = in->facetmarkerlist[faceid];
33098 } else {
33099 marker = 0;
33100 }
33101 }
33102 fprintf(outfile, "3 %4d %4d %4d", pointmark(p1) - shift,
33103 pointmark(p2) - shift, pointmark(p3) - shift);
33104 if (bmark) {
33105 fprintf(outfile, " %d", marker);
33106 }
33107 fprintf(outfile, "\n");
33108 faceloop.sh = shellfacetraverse(subfaces);
33109 }
33110
33111
33112 fprintf(outfile, "\n# part 3: hole list.\n");
33113 fprintf(outfile, "%d\n", in->numberofholes);
33114 for (i = 0; i < in->numberofholes; i++) {
33115 fprintf(outfile, "%d %g %g %g\n", i + in->firstnumber,
33116 in->holelist[i * 3], in->holelist[i * 3 + 1],
33117 in->holelist[i * 3 + 2]);
33118 }
33119
33120
33121 fprintf(outfile, "\n# part 4: region list.\n");
33122 fprintf(outfile, "%d\n", in->numberofregions);
33123 for (i = 0; i < in->numberofregions; i++) {
33124 fprintf(outfile, "%d %g %g %g %d %g\n", i + in->firstnumber,
33125 in->regionlist[i * 5], in->regionlist[i * 5 + 1],
33126 in->regionlist[i * 5 + 2], (int) in->regionlist[i * 5 + 3],
33127 in->regionlist[i * 5 + 4]);
33128 }
33129
33130 fprintf(outfile, "# Generated by %s\n", b->commandline);
33131 fclose(outfile);
33132 }
33133
33135
33136
33137
33138
33139
33140
33141
33142
33144
33145 void tetgenmesh::outmesh2medit(char* mfilename)
33146 {
33147 FILE *outfile;
33148 char mefilename[FILENAMESIZE];
33149 tetrahedron* tetptr;
33150 triface tface, tsymface;
33151 face segloop, checkmark;
33152 point ptloop, p1, p2, p3, p4;
33153 long faces;
33154 int pointnumber;
33155 int i;
33156
33157 if (mfilename != (char *) NULL && mfilename[0] != '\0') {
33158 strcpy(mefilename, mfilename);
33159 } else if (b->outfilename[0] != '\0') {
33160 strcpy(mefilename, b->outfilename);
33161 } else {
33162 strcpy(mefilename, "unnamed");
33163 }
33164 strcat(mefilename, ".mesh");
33165
33166 if (!b->quiet) {
33167 printf("Writing %s.\n", mefilename);
33168 }
33169 outfile = fopen(mefilename, "w");
33170 if (outfile == (FILE *) NULL) {
33171 printf("File I/O Error: Cannot create file %s.\n", mefilename);
33172 return;
33173 }
33174
33175 fprintf(outfile, "MeshVersionFormatted 1\n");
33176 fprintf(outfile, "\n");
33177 fprintf(outfile, "Dimension\n");
33178 fprintf(outfile, "3\n");
33179 fprintf(outfile, "\n");
33180
33181 fprintf(outfile, "\n# Set of mesh vertices\n");
33182 fprintf(outfile, "Vertices\n");
33183 fprintf(outfile, "%ld\n", points->items);
33184
33185 points->traversalinit();
33186 ptloop = pointtraverse();
33187 pointnumber = 1;
33188 while (ptloop != (point) NULL) {
33189
33190 fprintf(outfile, "%.17g %.17g %.17g", ptloop[0], ptloop[1], ptloop[2]);
33191 if (in->numberofpointattributes > 0) {
33192
33193 fprintf(outfile, " %.17g\n", ptloop[3]);
33194 } else {
33195 fprintf(outfile, " 0\n");
33196 }
33197 setpointmark(ptloop, pointnumber);
33198 ptloop = pointtraverse();
33199 pointnumber++;
33200 }
33201
33202
33203 faces = (4l * tetrahedrons->items + hullsize) / 2l;
33204
33205 fprintf(outfile, "\n# Set of Triangles\n");
33206 fprintf(outfile, "Triangles\n");
33207 fprintf(outfile, "%ld\n", faces);
33208
33209 tetrahedrons->traversalinit();
33210 tface.tet = tetrahedrontraverse();
33211
33212
33213
33214
33215
33216
33217 while (tface.tet != (tetrahedron *) NULL) {
33218 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33219 sym(tface, tsymface);
33220 if (tface.tet < tsymface.tet || tsymface.tet == dummytet) {
33221 p1 = org (tface);
33222 p2 = dest(tface);
33223 p3 = apex(tface);
33224 fprintf(outfile, "%5d %5d %5d",
33225 pointmark(p1), pointmark(p2), pointmark(p3));
33226 fprintf(outfile, " 0\n");
33227 }
33228 }
33229 tface.tet = tetrahedrontraverse();
33230 }
33231
33232 fprintf(outfile, "\n# Set of Tetrahedra\n");
33233 fprintf(outfile, "Tetrahedra\n");
33234 fprintf(outfile, "%ld\n", tetrahedrons->items);
33235
33236 tetrahedrons->traversalinit();
33237 tetptr = tetrahedrontraverse();
33238 while (tetptr != (tetrahedron *) NULL) {
33239 p1 = (point) tetptr[4];
33240 p2 = (point) tetptr[5];
33241 p3 = (point) tetptr[6];
33242 p4 = (point) tetptr[7];
33243 fprintf(outfile, "%5d %5d %5d %5d",
33244 pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33245 if (in->numberoftetrahedronattributes > 0) {
33246 fprintf(outfile, " %.17g", elemattribute(tetptr, 0));
33247 } else {
33248 fprintf(outfile, " 0");
33249 }
33250 fprintf(outfile, "\n");
33251 tetptr = tetrahedrontraverse();
33252 }
33253
33254 fprintf(outfile, "\nCorners\n");
33255 fprintf(outfile, "%d\n", in->numberofpoints);
33256
33257 for (i = 0; i < in->numberofpoints; i++) {
33258 fprintf(outfile, "%4d\n", i + 1);
33259 }
33260
33261 if (b->useshelles) {
33262 fprintf(outfile, "\nEdges\n");
33263 fprintf(outfile, "%ld\n", subsegs->items);
33264
33265 subsegs->traversalinit();
33266 segloop.sh = shellfacetraverse(subsegs);
33267 while (segloop.sh != (shellface *) NULL) {
33268 p1 = sorg(segloop);
33269 p2 = sdest(segloop);
33270 fprintf(outfile, "%5d %5d", pointmark(p1), pointmark(p2));
33271 fprintf(outfile, " 0\n");
33272 segloop.sh = shellfacetraverse(subsegs);
33273 }
33274 }
33275
33276 fprintf(outfile, "\nEnd\n");
33277 fclose(outfile);
33278 }
33279
33281
33282
33283
33284
33285
33286
33287
33288
33289
33291
33292 void tetgenmesh::outmesh2gid(char* gfilename)
33293 {
33294 FILE *outfile;
33295 char gidfilename[FILENAMESIZE];
33296 tetrahedron* tetptr;
33297 triface tface, tsymface;
33298 face sface;
33299 point ptloop, p1, p2, p3, p4;
33300 int pointnumber;
33301 int elementnumber;
33302
33303 if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33304 strcpy(gidfilename, gfilename);
33305 } else if (b->outfilename[0] != '\0') {
33306 strcpy(gidfilename, b->outfilename);
33307 } else {
33308 strcpy(gidfilename, "unnamed");
33309 }
33310 strcat(gidfilename, ".ele.msh");
33311
33312 if (!b->quiet) {
33313 printf("Writing %s.\n", gidfilename);
33314 }
33315 outfile = fopen(gidfilename, "w");
33316 if (outfile == (FILE *) NULL) {
33317 printf("File I/O Error: Cannot create file %s.\n", gidfilename);
33318 return;
33319 }
33320
33321 fprintf(outfile, "mesh dimension = 3 elemtype tetrahedron nnode = 4\n");
33322 fprintf(outfile, "coordinates\n");
33323
33324 points->traversalinit();
33325 ptloop = pointtraverse();
33326 pointnumber = 1;
33327 while (ptloop != (point) NULL) {
33328
33329 fprintf(outfile, "%4d %.17g %.17g %.17g", pointnumber,
33330 ptloop[0], ptloop[1], ptloop[2]);
33331 if (in->numberofpointattributes > 0) {
33332
33333 fprintf(outfile, " %.17g", ptloop[3]);
33334 }
33335 fprintf(outfile, "\n");
33336 setpointmark(ptloop, pointnumber);
33337 ptloop = pointtraverse();
33338 pointnumber++;
33339 }
33340
33341 fprintf(outfile, "end coordinates\n");
33342 fprintf(outfile, "elements\n");
33343
33344 tetrahedrons->traversalinit();
33345 tetptr = tetrahedrontraverse();
33346 elementnumber = 1;
33347 while (tetptr != (tetrahedron *) NULL) {
33348 p1 = (point) tetptr[4];
33349 p2 = (point) tetptr[5];
33350 p3 = (point) tetptr[6];
33351 p4 = (point) tetptr[7];
33352 fprintf(outfile, "%5d %5d %5d %5d %5d", elementnumber,
33353 pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33354 if (in->numberoftetrahedronattributes > 0) {
33355 fprintf(outfile, " %.17g", elemattribute(tetptr, 0));
33356 }
33357 fprintf(outfile, "\n");
33358 tetptr = tetrahedrontraverse();
33359 elementnumber++;
33360 }
33361
33362 fprintf(outfile, "end elements\n");
33363 fclose(outfile);
33364
33365 if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33366 strcpy(gidfilename, gfilename);
33367 } else if (b->outfilename[0] != '\0') {
33368 strcpy(gidfilename, b->outfilename);
33369 } else {
33370 strcpy(gidfilename, "unnamed");
33371 }
33372 strcat(gidfilename, ".face.msh");
33373
33374 if (!b->quiet) {
33375 printf("Writing %s.\n", gidfilename);
33376 }
33377 outfile = fopen(gidfilename, "w");
33378 if (outfile == (FILE *) NULL) {
33379 printf("File I/O Error: Cannot create file %s.\n", gidfilename);
33380 return;
33381 }
33382
33383 fprintf(outfile, "mesh dimension = 3 elemtype triangle nnode = 3\n");
33384 fprintf(outfile, "coordinates\n");
33385
33386 points->traversalinit();
33387 ptloop = pointtraverse();
33388 pointnumber = 1;
33389 while (ptloop != (point) NULL) {
33390
33391 fprintf(outfile, "%4d %.17g %.17g %.17g", pointnumber,
33392 ptloop[0], ptloop[1], ptloop[2]);
33393 if (in->numberofpointattributes > 0) {
33394
33395 fprintf(outfile, " %.17g", ptloop[3]);
33396 }
33397 fprintf(outfile, "\n");
33398 setpointmark(ptloop, pointnumber);
33399 ptloop = pointtraverse();
33400 pointnumber++;
33401 }
33402
33403 fprintf(outfile, "end coordinates\n");
33404 fprintf(outfile, "elements\n");
33405
33406 tetrahedrons->traversalinit();
33407 tface.tet = tetrahedrontraverse();
33408 elementnumber = 1;
33409 while (tface.tet != (tetrahedron *) NULL) {
33410 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33411 sym(tface, tsymface);
33412 if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33413 p1 = org(tface);
33414 p2 = dest(tface);
33415 p3 = apex(tface);
33416 if (tsymface.tet == dummytet) {
33417
33418 fprintf(outfile, "%5d %d %d %d\n", elementnumber,
33419 pointmark(p1), pointmark(p2), pointmark(p3));
33420 elementnumber++;
33421 } else if (b->useshelles) {
33422
33423 tspivot(tface, sface);
33424 if (sface.sh != dummysh) {
33425 fprintf(outfile, "%5d %d %d %d\n", elementnumber,
33426 pointmark(p1), pointmark(p2), pointmark(p3));
33427 elementnumber++;
33428 }
33429 }
33430 }
33431 }
33432 tface.tet = tetrahedrontraverse();
33433 }
33434
33435 fprintf(outfile, "end elements\n");
33436 fclose(outfile);
33437 }
33438
33440
33441
33442
33443
33444
33445
33447
33448 void tetgenmesh::outmesh2off(char* ofilename)
33449 {
33450 FILE *outfile;
33451 char offfilename[FILENAMESIZE];
33452 triface tface, tsymface;
33453 point ptloop, p1, p2, p3;
33454 long faces;
33455 int shift;
33456
33457 if (ofilename != (char *) NULL && ofilename[0] != '\0') {
33458 strcpy(offfilename, ofilename);
33459 } else if (b->outfilename[0] != '\0') {
33460 strcpy(offfilename, b->outfilename);
33461 } else {
33462 strcpy(offfilename, "unnamed");
33463 }
33464 strcat(offfilename, ".off");
33465
33466 if (!b->quiet) {
33467 printf("Writing %s.\n", offfilename);
33468 }
33469 outfile = fopen(offfilename, "w");
33470 if (outfile == (FILE *) NULL) {
33471 printf("File I/O Error: Cannot create file %s.\n", offfilename);
33472 return;
33473 }
33474
33475
33476 faces = (4l * tetrahedrons->items + hullsize) / 2l;
33477
33478
33479 fprintf(outfile, "OFF\n%ld %ld %ld\n", points->items, faces, hullsize);
33480
33481
33482 points->traversalinit();
33483 ptloop = pointtraverse();
33484 while (ptloop != (point) NULL) {
33485 fprintf(outfile, " %.17g %.17g %.17g\n",ptloop[0], ptloop[1], ptloop[2]);
33486 ptloop = pointtraverse();
33487 }
33488
33489
33490 shift = in->firstnumber == 1 ? 1 : 0;
33491
33492 tetrahedrons->traversalinit();
33493 tface.tet = tetrahedrontraverse();
33494
33495
33496
33497
33498
33499
33500 while (tface.tet != (tetrahedron *) NULL) {
33501 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33502 sym(tface, tsymface);
33503 if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33504 p1 = org(tface);
33505 p2 = dest(tface);
33506 p3 = apex(tface);
33507
33508 fprintf(outfile, "3 %4d %4d %4d\n", pointmark(p1) - shift,
33509 pointmark(p2) - shift, pointmark(p3) - shift);
33510 }
33511 }
33512 tface.tet = tetrahedrontraverse();
33513 }
33514
33515 fprintf(outfile, "# Generated by %s\n", b->commandline);
33516 fclose(outfile);
33517 }
33518
33519
33520
33521
33522
33523
33524
33525
33526
33528
33529
33530
33532
33533 void tetgenmesh::internalerror()
33534 {
33535 printf(" Please report this bug to sihang@mail.berlios.de. Include the\n");
33536 printf(" message above, your input data set, and the exact command\n");
33537 printf(" line you used to run this program, thank you.\n");
33538 terminatetetgen(2);
33539 }
33540
33542
33543
33544
33546
33547 void tetgenmesh::checkmesh()
33548 {
33549 triface tetraloop;
33550 triface oppotet, oppooppotet;
33551 point tetorg, tetdest, tetapex, tetoppo;
33552 REAL oritest;
33553 int horrors;
33554
33555 if (!b->quiet) {
33556 printf(" Checking consistency of mesh...\n");
33557 }
33558
33559 horrors = 0;
33560
33561 tetrahedrons->traversalinit();
33562 tetraloop.tet = tetrahedrontraverse();
33563 while (tetraloop.tet != (tetrahedron *) NULL) {
33564
33565 for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33566 tetorg = org(tetraloop);
33567 tetdest = dest(tetraloop);
33568 tetapex = apex(tetraloop);
33569 tetoppo = oppo(tetraloop);
33570 if (tetraloop.loc == 0) {
33571 oritest = orient3d(tetorg, tetdest, tetapex, tetoppo);
33572 if (oritest >= 0.0) {
33573 printf(" !! !! %s ", oritest > 0.0 ? "Inverted" : "Degenerated");
33574 printtet(&tetraloop);
33575 printf(" orient3d = %.17g.\n", oritest);
33576 horrors++;
33577 }
33578 }
33579
33580 sym(tetraloop, oppotet);
33581 if (oppotet.tet != dummytet) {
33582
33583 sym(oppotet, oppooppotet);
33584 if ((tetraloop.tet != oppooppotet.tet)
33585 || (tetraloop.loc != oppooppotet.loc)) {
33586 printf(" !! !! Asymmetric tetra-tetra bond:\n");
33587 if (tetraloop.tet == oppooppotet.tet) {
33588 printf(" (Right tetrahedron, wrong orientation)\n");
33589 }
33590 printf(" First ");
33591 printtet(&tetraloop);
33592 printf(" Second (nonreciprocating) ");
33593 printtet(&oppotet);
33594 horrors++;
33595 }
33596 }
33597 }
33598 tetraloop.tet = tetrahedrontraverse();
33599 }
33600 if (horrors == 0) {
33601 if (!b->quiet) {
33602 printf(" In my studied opinion, the mesh appears to be consistent.\n");
33603 }
33604 } else if (horrors == 1) {
33605 printf(" !! !! !! !! Precisely one festering wound discovered.\n");
33606 } else {
33607 printf(" !! !! !! !! %d abominations witnessed.\n", horrors);
33608 }
33609 }
33610
33612
33613
33614
33616
33617 void tetgenmesh::checkshells()
33618 {
33619 triface oppotet, oppooppotet, testtet;
33620 face shloop, segloop, spin;
33621 face testsh, testseg, testshsh;
33622 point shorg, shdest, segorg, segdest;
33623 REAL checksign;
33624 bool same;
33625 int horrors;
33626 int i;
33627
33628 if (!b->quiet) {
33629 printf(" Checking consistency of the mesh boundary...\n");
33630 }
33631 horrors = 0;
33632
33633
33634 subfaces->traversalinit();
33635 shloop.sh = shellfacetraverse(subfaces);
33636 while (shloop.sh != (shellface *) NULL) {
33637
33638 shloop.shver = 0;
33639 stpivot(shloop, oppotet);
33640 if (oppotet.tet != dummytet) {
33641 tspivot(oppotet, testsh);
33642 if (testsh.sh != shloop.sh) {
33643 printf(" !! !! Wrong tetra-subface connection.\n");
33644 printf(" Tetra: ");
33645 printtet(&oppotet);
33646 printf(" Subface: ");
33647 printsh(&shloop);
33648 horrors++;
33649 }
33650 if (oppo(oppotet) != (point) NULL) {
33651 adjustedgering(oppotet, CCW);
33652 checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33653 oppo(oppotet));
33654 if (checksign >= 0.0) {
33655 printf(" !! !! Wrong subface orientation.\n");
33656 printf(" Subface: ");
33657 printsh(&shloop);
33658 horrors++;
33659 }
33660 }
33661 }
33662 sesymself(shloop);
33663 stpivot(shloop, oppooppotet);
33664 if (oppooppotet.tet != dummytet) {
33665 tspivot(oppooppotet, testsh);
33666 if (testsh.sh != shloop.sh) {
33667 printf(" !! !! Wrong tetra-subface connection.\n");
33668 printf(" Tetra: ");
33669 printtet(&oppooppotet);
33670 printf(" Subface: ");
33671 printsh(&shloop);
33672 horrors++;
33673 }
33674 if (oppotet.tet != dummytet) {
33675 sym(oppotet, testtet);
33676 if (testtet.tet != oppooppotet.tet) {
33677 printf(" !! !! Wrong tetra-subface-tetra connection.\n");
33678 printf(" Tetra 1: ");
33679 printtet(&oppotet);
33680 printf(" Subface: ");
33681 printsh(&shloop);
33682 printf(" Tetra 2: ");
33683 printtet(&oppooppotet);
33684 horrors++;
33685 }
33686 }
33687 if (oppo(oppooppotet) != (point) NULL) {
33688 adjustedgering(oppooppotet, CCW);
33689 checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33690 oppo(oppooppotet));
33691 if (checksign >= 0.0) {
33692 printf(" !! !! Wrong subface orientation.\n");
33693 printf(" Subface: ");
33694 printsh(&shloop);
33695 horrors++;
33696 }
33697 }
33698 }
33699
33700 shloop.shver = 0;
33701 for (i = 0; i < 3; i++) {
33702 shorg = sorg(shloop);
33703 shdest = sdest(shloop);
33704 sspivot(shloop, testseg);
33705 if (testseg.sh != dummysh) {
33706 segorg = sorg(testseg);
33707 segdest = sdest(testseg);
33708 same = ((shorg == segorg) && (shdest == segdest))
33709 || ((shorg == segdest) && (shdest == segorg));
33710 if (!same) {
33711 printf(" !! !! Wrong subface-subsegment connection.\n");
33712 printf(" Subface: ");
33713 printsh(&shloop);
33714 printf(" Subsegment: ");
33715 printsh(&testseg);
33716 horrors++;
33717 }
33718 }
33719 spivot(shloop, testsh);
33720 if (testsh.sh != dummysh) {
33721 segorg = sorg(testsh);
33722 segdest = sdest(testsh);
33723 same = ((shorg == segorg) && (shdest == segdest))
33724 || ((shorg == segdest) && (shdest == segorg));
33725 if (!same) {
33726 printf(" !! !! Wrong subface-subface connection.\n");
33727 printf(" Subface 1: ");
33728 printsh(&shloop);
33729 printf(" Subface 2: ");
33730 printsh(&testsh);
33731 horrors++;
33732 }
33733 spivot(testsh, testshsh);
33734 shorg = sorg(testshsh);
33735 shdest = sdest(testshsh);
33736 same = ((shorg == segorg) && (shdest == segdest))
33737 || ((shorg == segdest) && (shdest == segorg));
33738 if (!same) {
33739 printf(" !! !! Wrong subface-subface connection.\n");
33740 printf(" Subface 1: ");
33741 printsh(&testsh);
33742 printf(" Subface 2: ");
33743 printsh(&testshsh);
33744 horrors++;
33745 }
33746 if (testseg.sh == dummysh) {
33747 if (testshsh.sh != shloop.sh) {
33748 printf(" !! !! Wrong subface-subface connection.\n");
33749 printf(" Subface 1: ");
33750 printsh(&shloop);
33751 printf(" Subface 2: ");
33752 printsh(&testsh);
33753 horrors++;
33754 }
33755 }
33756 }
33757 senextself(shloop);
33758 }
33759 shloop.sh = shellfacetraverse(subfaces);
33760 }
33761
33762
33763 subsegs->traversalinit();
33764 segloop.sh = shellfacetraverse(subsegs);
33765 while (segloop.sh != (shellface *) NULL) {
33766 segorg = sorg(segloop);
33767 segdest = sdest(segloop);
33768 spivot(segloop, testsh);
33769 if (testsh.sh == dummysh) {
33770 printf(" !! !! Wrong subsegment-subface connection.\n");
33771 printf(" Subsegment: ");
33772 printsh(&segloop);
33773 horrors++;
33774 segloop.sh = shellfacetraverse(subsegs);
33775 continue;
33776 }
33777 shorg = sorg(testsh);
33778 shdest = sdest(testsh);
33779 same = ((shorg == segorg) && (shdest == segdest))
33780 || ((shorg == segdest) && (shdest == segorg));
33781 if (!same) {
33782 printf(" !! !! Wrong subsegment-subface connection.\n");
33783 printf(" Subsegment : ");
33784 printsh(&segloop);
33785 printf(" Subface : ");
33786 printsh(&testsh);
33787 horrors++;
33788 segloop.sh = shellfacetraverse(subsegs);
33789 continue;
33790 }
33791
33792 spin = testsh;
33793 i = 0;
33794 do {
33795 spivotself(spin);
33796 shorg = sorg(spin);
33797 shdest = sdest(spin);
33798 same = ((shorg == segorg) && (shdest == segdest))
33799 || ((shorg == segdest) && (shdest == segorg));
33800 if (!same) {
33801 printf(" !! !! Wrong subsegment-subface connection.\n");
33802 printf(" Subsegment : ");
33803 printsh(&segloop);
33804 printf(" Subface : ");
33805 printsh(&testsh);
33806 horrors++;
33807 break;
33808 }
33809 i++;
33810 } while (spin.sh != testsh.sh && i < 1000);
33811 if (i >= 1000) {
33812 printf(" !! !! Wrong subsegment-subface connection.\n");
33813 printf(" Subsegment : ");
33814 printsh(&segloop);
33815 horrors++;
33816 }
33817 segloop.sh = shellfacetraverse(subsegs);
33818 }
33819 if (horrors == 0) {
33820 if (!b->quiet) {
33821 printf(" Mesh boundaries connected correctly.\n");
33822 }
33823 } else {
33824 printf(" !! !! !! !! %d boundary connection viewed with horror.\n",
33825 horrors);
33826 return;
33827 }
33828 }
33829
33831
33832
33833
33834
33835
33837
33838 void tetgenmesh::checkdelaunay(REAL eps, queue* flipqueue)
33839 {
33840 triface tetraloop;
33841 triface oppotet;
33842 face opposhelle;
33843 point tetorg, tetdest, tetapex, tetoppo;
33844 point oppooppo;
33845 enum fliptype fc;
33846 REAL sign;
33847 int shouldbedelaunay;
33848 int horrors;
33849
33850 if (!b->quiet) {
33851 printf(" Checking Delaunay property of the mesh...\n");
33852 }
33853 horrors = 0;
33854
33855 tetrahedrons->traversalinit();
33856 tetraloop.tet = tetrahedrontraverse();
33857 while (tetraloop.tet != (tetrahedron *) NULL) {
33858
33859 for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33860 tetorg = org(tetraloop);
33861 tetdest = dest(tetraloop);
33862 tetapex = apex(tetraloop);
33863 tetoppo = oppo(tetraloop);
33864 sym(tetraloop, oppotet);
33865 oppooppo = oppo(oppotet);
33866
33867
33868 shouldbedelaunay = (oppotet.tet != dummytet)
33869 && (tetoppo != (point) NULL)
33870 && (oppooppo != (point) NULL)
33871 && (tetraloop.tet < oppotet.tet);
33872 if (checksubfaces && shouldbedelaunay) {
33873
33874
33875 tspivot(tetraloop, opposhelle);
33876 if (opposhelle.sh != dummysh){
33877 shouldbedelaunay = 0;
33878 }
33879 }
33880 if (shouldbedelaunay) {
33881 sign = insphere(tetdest, tetorg, tetapex, tetoppo, oppooppo);
33882 if ((sign > 0.0) && (eps > 0.0)) {
33883 if (iscospheric(tetdest, tetorg, tetapex, tetoppo, oppooppo, sign,
33884 eps)) sign = 0.0;
33885 }
33886 if (sign > 0.0) {
33887 if (flipqueue) {
33888 enqueueflipface(tetraloop, flipqueue);
33889 } else {
33890 printf(" !! Non-locally Delaunay face (%d, %d, %d) ",
33891 pointmark(tetorg), pointmark(tetdest), pointmark(tetapex));
33892 fc = categorizeface(tetraloop);
33893 switch (fc) {
33894 case T23: printf("\"T23\""); break;
33895 case T32: printf("\"T32\""); break;
33896 case T22: printf("\"T22\""); break;
33897 case T44: printf("\"T44\""); break;
33898 case N32: printf("\"N32\""); break;
33899 case N40: printf("\"N40\""); break;
33900 case FORBIDDENFACE:printf("\"FORBIDDENFACE\""); break;
33901 case FORBIDDENEDGE:printf("\"FORBIDDENEDGE\""); break;
33902 }
33903 printf("\n");
33904 }
33905 horrors++;
33906 }
33907 }
33908 }
33909 tetraloop.tet = tetrahedrontraverse();
33910 }
33911 if (flipqueue == (queue *) NULL) {
33912 if (horrors == 0) {
33913 if (!b->quiet) {
33914 printf(" The mesh is %s.\n",
33915 checksubfaces ? "constrained Delaunay" : "Delaunay");
33916 }
33917 } else {
33918 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
33919 }
33920 }
33921 }
33922
33924
33925
33926
33928
33929 void tetgenmesh::checkconforming()
33930 {
33931 face segloop, shloop;
33932 int encsubsegs, encsubfaces;
33933
33934 if (!b->quiet) {
33935 printf(" Checking conforming Delaunay property of mesh...\n");
33936 }
33937 encsubsegs = encsubfaces = 0;
33938
33939 subsegs->traversalinit();
33940 segloop.sh = shellfacetraverse(subsegs);
33941 while (segloop.sh != (shellface *) NULL) {
33942 if (checkseg4encroach(&segloop, NULL, NULL, false)) {
33943 printf(" !! !! Non-conforming subsegment: (%d, %d)\n",
33944 pointmark(sorg(segloop)), pointmark(sdest(segloop)));
33945 encsubsegs++;
33946 }
33947 segloop.sh = shellfacetraverse(subsegs);
33948 }
33949
33950 subfaces->traversalinit();
33951 shloop.sh = shellfacetraverse(subfaces);
33952 while (shloop.sh != (shellface *) NULL) {
33953 if (checksub4encroach(&shloop, NULL, false)) {
33954 printf(" !! !! Non-conforming subface: (%d, %d, %d)\n",
33955 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
33956 pointmark(sapex(shloop)));
33957 encsubfaces++;
33958 }
33959 shloop.sh = shellfacetraverse(subfaces);
33960 }
33961 if (encsubsegs == 0 && encsubfaces == 0) {
33962 if (!b->quiet) {
33963 printf(" The mesh is conforming Delaunay.\n");
33964 }
33965 } else {
33966 if (encsubsegs > 0) {
33967 printf(" !! !! %d subsegments are non-conforming.\n", encsubsegs);
33968 }
33969 if (encsubfaces > 0) {
33970 printf(" !! !! %d subfaces are non-conforming.\n", encsubfaces);
33971 }
33972 }
33973 }
33974
33976
33977
33978
33980
33981 #ifdef SELF_CHECK
33982
33983 void tetgenmesh::algorithmicstatistics()
33984 {
33985
33986
33987
33988
33989
33990
33991
33992
33993
33994
33995
33996
33997
33998
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 #endif // #ifdef SELF_CHECK
34024
34026
34027
34028
34030
34031 void tetgenmesh::qualitystatistics()
34032 {
34033 triface tetloop, neightet;
34034 point p[4];
34035 char sbuf[128];
34036 REAL radiusratiotable[12];
34037 REAL aspectratiotable[12];
34038 REAL A[4][4], rhs[4], D;
34039 REAL V[6][3], N[4][3], H[4];
34040 REAL edgelength[6], alldihed[6], faceangle[3];
34041 REAL shortest, longest;
34042 REAL smallestvolume, biggestvolume;
34043 REAL smallestdiangle, biggestdiangle;
34044 REAL smallestfaangle, biggestfaangle;
34045 REAL tetvol, minaltitude;
34046 REAL cirradius, minheightinv;
34047 REAL shortlen, longlen;
34048 REAL tetaspect, tetradius;
34049 REAL smalldiangle, bigdiangle;
34050 REAL smallfaangle, bigfaangle;
34051 int radiustable[12];
34052 int aspecttable[16];
34053 int dihedangletable[18];
34054 int faceangletable[18];
34055 int indx[4];
34056 int radiusindex;
34057 int aspectindex;
34058 int tendegree;
34059 int i, j;
34060
34061 smallfaangle = 0.0;
34062 bigfaangle = 0.0;
34063
34064 printf("Mesh quality statistics:\n\n");
34065
34066
34067 shortlen = longlen = 0.0;
34068 smalldiangle = bigdiangle = 0.0;
34069
34070 radiusratiotable[0] = 0.707; radiusratiotable[1] = 1.0;
34071 radiusratiotable[2] = 1.1; radiusratiotable[3] = 1.2;
34072 radiusratiotable[4] = 1.4; radiusratiotable[5] = 1.6;
34073 radiusratiotable[6] = 1.8; radiusratiotable[7] = 2.0;
34074 radiusratiotable[8] = 2.5; radiusratiotable[9] = 3.0;
34075 radiusratiotable[10] = 10.0; radiusratiotable[11] = 0.0;
34076
34077 aspectratiotable[0] = 1.5; aspectratiotable[1] = 2.0;
34078 aspectratiotable[2] = 2.5; aspectratiotable[3] = 3.0;
34079 aspectratiotable[4] = 4.0; aspectratiotable[5] = 6.0;
34080 aspectratiotable[6] = 10.0; aspectratiotable[7] = 15.0;
34081 aspectratiotable[8] = 25.0; aspectratiotable[9] = 50.0;
34082 aspectratiotable[10] = 100.0; aspectratiotable[11] = 0.0;
34083
34084 for (i = 0; i < 12; i++) radiustable[i] = 0;
34085 for (i = 0; i < 12; i++) aspecttable[i] = 0;
34086 for (i = 0; i < 18; i++) dihedangletable[i] = 0;
34087 for (i = 0; i < 18; i++) faceangletable[i] = 0;
34088
34089 minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
34090 minaltitude = minaltitude * minaltitude;
34091 shortest = minaltitude;
34092 longest = 0.0;
34093 smallestvolume = minaltitude;
34094 biggestvolume = 0.0;
34095 smallestdiangle = smallestfaangle = 180.0;
34096 biggestdiangle = biggestfaangle = 0.0;
34097
34098
34099 tetrahedrons->traversalinit();
34100 tetloop.tet = tetrahedrontraverse();
34101 while (tetloop.tet != (tetrahedron *) NULL) {
34102
34103
34104 for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i];
34105
34106 for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i];
34107 for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i];
34108 for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i];
34109 for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i];
34110 for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i];
34111 for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i];
34112
34113 for (j = 0; j < 3; j++) {
34114 for (i = 0; i < 3; i++) A[j][i] = V[j][i];
34115 }
34116
34117 lu_decmp(A, 3, indx, &D, 0);
34118
34119 tetvol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
34120
34121 for (j = 0; j < 3; j++) {
34122 for (i = 0; i < 3; i++) rhs[i] = 0.0;
34123 rhs[j] = 1.0;
34124 lu_solve(A, 3, indx, rhs, 0);
34125 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
34126 }
34127
34128 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
34129
34130 for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]);
34131 lu_solve(A, 3, indx, rhs, 0);
34132 cirradius = sqrt(dot(rhs, rhs));
34133
34134 for (i = 0; i < 4; i++) {
34135
34136 H[i] = sqrt(dot(N[i], N[i]));
34137 for (j = 0; j < 3; j++) N[i][j] /= H[i];
34138 }
34139
34140
34141
34142 minheightinv = H[0];
34143 for (i = 1; i < 3; i++) {
34144 if (H[i] > minheightinv) minheightinv = H[i];
34145 }
34146
34147 for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
34148
34149 j = 0;
34150 for (i = 1; i < 4; i++) {
34151 alldihed[j] = -dot(N[0], N[i]);
34152 if (alldihed[j] < -1.0) alldihed[j] = -1;
34153 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34154 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34155 j++;
34156 }
34157 for (i = 2; i < 4; i++) {
34158 alldihed[j] = -dot(N[1], N[i]);
34159 if (alldihed[j] < -1.0) alldihed[j] = -1;
34160 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34161 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34162 j++;
34163 }
34164 alldihed[j] = -dot(N[2], N[3]);
34165 if (alldihed[j] < -1.0) alldihed[j] = -1;
34166 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34167 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34168
34169
34170 for (i = 0; i < 6; i++) {
34171 if (i == 0) {
34172 shortlen = longlen = edgelength[i];
34173 } else {
34174 shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen;
34175 longlen = edgelength[i] > longlen ? edgelength[i] : longlen;
34176 }
34177 if (edgelength[i] > longest) {
34178 longest = edgelength[i];
34179 }
34180 if (edgelength[i] < shortest) {
34181 shortest = edgelength[i];
34182 }
34183 }
34184
34185
34186 if (tetvol < smallestvolume) {
34187 smallestvolume = tetvol;
34188 }
34189 if (tetvol > biggestvolume) {
34190 biggestvolume = tetvol;
34191 }
34192
34193
34194 for (i = 0; i < 6; i++) {
34195 if (i == 0) {
34196 smalldiangle = bigdiangle = alldihed[i];
34197 } else {
34198 smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle;
34199 bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle;
34200 }
34201 if (alldihed[i] < smallestdiangle) {
34202 smallestdiangle = alldihed[i];
34203 }
34204 if (alldihed[i] > biggestdiangle) {
34205 biggestdiangle = alldihed[i];
34206 }
34207 }
34208
34209 if (smalldiangle < 5.0) {
34210 tendegree = 0;
34211 } else if (smalldiangle >= 5.0 && smalldiangle < 10.0) {
34212 tendegree = 1;
34213 } else if (smalldiangle >= 80.0 && smalldiangle < 110.0) {
34214 tendegree = 9;
34215 } else {
34216 tendegree = (int) (smalldiangle / 10.);
34217 if (smalldiangle < 80.0) {
34218 tendegree++;
34219 } else {
34220 tendegree--;
34221 }
34222 }
34223 dihedangletable[tendegree]++;
34224 if (bigdiangle >= 80.0 && bigdiangle < 110.0) {
34225 tendegree = 9;
34226 } else if (bigdiangle >= 170.0 && bigdiangle < 175.0) {
34227 tendegree = 16;
34228 } else if (bigdiangle >= 175.0) {
34229 tendegree = 17;
34230 } else {
34231 tendegree = (int) (bigdiangle / 10.);
34232 if (bigdiangle < 80.0) {
34233 tendegree++;
34234 } else {
34235 tendegree--;
34236 }
34237 }
34238 dihedangletable[tendegree]++;
34239
34240
34241 tetloop.ver = 0;
34242 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
34243 sym(tetloop, neightet);
34244
34245 if ((neightet.tet == dummytet) || (tetloop.tet < neightet.tet)) {
34246 p[0] = org(tetloop);
34247 p[1] = dest(tetloop);
34248 p[2] = apex(tetloop);
34249 faceangle[0] = interiorangle(p[0], p[1], p[2], NULL);
34250 faceangle[1] = interiorangle(p[1], p[2], p[0], NULL);
34251 faceangle[2] = PI - (faceangle[0] + faceangle[1]);
34252
34253 for (i = 0; i < 3; i++) {
34254 faceangle[i] = (faceangle[i] * 180.0) / PI;
34255 }
34256
34257 for (i = 0; i < 3; i++) {
34258 if (i == 0) {
34259 smallfaangle = bigfaangle = faceangle[i];
34260 } else {
34261 smallfaangle = faceangle[i] < smallfaangle ?
34262 faceangle[i] : smallfaangle;
34263 bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle;
34264 }
34265 if (faceangle[i] < smallestfaangle) {
34266 smallestfaangle = faceangle[i];
34267 }
34268 if (faceangle[i] > biggestfaangle) {
34269 biggestfaangle = faceangle[i];
34270 }
34271 }
34272 tendegree = (int) (smallfaangle / 10.);
34273 faceangletable[tendegree]++;
34274 tendegree = (int) (bigfaangle / 10.);
34275 faceangletable[tendegree]++;
34276 }
34277 }
34278
34279
34280 tetradius = cirradius / sqrt(shortlen);
34281
34282 tetaspect = sqrt(longlen) * minheightinv;
34283 aspectindex = 0;
34284 while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) {
34285 aspectindex++;
34286 }
34287 aspecttable[aspectindex]++;
34288 radiusindex = 0;
34289 while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) {
34290 radiusindex++;
34291 }
34292 radiustable[radiusindex]++;
34293
34294 tetloop.tet = tetrahedrontraverse();
34295 }
34296
34297 shortest = sqrt(shortest);
34298 longest = sqrt(longest);
34299 minaltitude = sqrt(minaltitude);
34300
34301 printf(" Smallest volume: %16.5g | Largest volume: %16.5g\n",
34302 smallestvolume, biggestvolume);
34303 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n",
34304 shortest, longest);
34305 sprintf(sbuf, "%.17g", biggestfaangle);
34306 if (strlen(sbuf) > 8) {
34307 sbuf[8] = '\0';
34308 }
34309 printf(" Smallest facangle: %14.5g | Largest facangle: %s\n",
34310 smallestfaangle, sbuf);
34311 sprintf(sbuf, "%.17g", biggestdiangle);
34312 if (strlen(sbuf) > 8) {
34313 sbuf[8] = '\0';
34314 }
34315 printf(" Smallest dihedral: %14.5g | Largest dihedral: %s\n\n",
34316 smallestdiangle, sbuf);
34317
34318
34319
34320
34321
34322
34323
34324
34325
34326
34327
34328
34329
34330
34331
34332
34333
34334
34335
34336
34337 printf(" Aspect ratio histogram:\n");
34338 printf(" < %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
34339 aspectratiotable[0], aspecttable[0], aspectratiotable[5],
34340 aspectratiotable[6], aspecttable[6]);
34341 for (i = 1; i < 5; i++) {
34342 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
34343 aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i],
34344 aspectratiotable[i + 5], aspectratiotable[i + 6],
34345 aspecttable[i + 6]);
34346 }
34347 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
34348 aspectratiotable[4], aspectratiotable[5], aspecttable[5],
34349 aspectratiotable[10], aspecttable[11]);
34350 printf(" (A tetrahedron's aspect ratio is its longest edge length");
34351 printf(" divided by its\n");
34352 printf(" smallest side height)\n\n");
34353
34354 printf(" Face angle histogram:\n");
34355 for (i = 0; i < 9; i++) {
34356 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
34357 i * 10, i * 10 + 10, faceangletable[i],
34358 i * 10 + 90, i * 10 + 100, faceangletable[i + 9]);
34359 }
34360 if (minfaceang != PI) {
34361 printf(" Minimum input face angle is %g (degree).\n",
34362 minfaceang / PI * 180.0);
34363 }
34364 printf("\n");
34365
34366 printf(" Dihedral angle histogram:\n");
34367
34368 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34369 0, 5, dihedangletable[0], 80, 110, dihedangletable[9]);
34370 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34371 5, 10, dihedangletable[1], 110, 120, dihedangletable[10]);
34372
34373 for (i = 2; i < 7; i++) {
34374 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34375 (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i],
34376 (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]);
34377 }
34378
34379 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34380 60, 70, dihedangletable[7], 170, 175, dihedangletable[16]);
34381 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34382 70, 80, dihedangletable[8], 175, 180, dihedangletable[17]);
34383 if (minfacetdihed != PI) {
34384 printf(" Minimum input facet dihedral angle is %g (degree).\n",
34385 minfacetdihed / PI * 180.0);
34386 }
34387 printf("\n");
34388 }
34389
34391
34392
34393
34395
34396 void tetgenmesh::statistics()
34397 {
34398 printf("\nStatistics:\n\n");
34399 printf(" Input points: %d\n", in->numberofpoints + jettisoninverts);
34400 if (b->refine) {
34401 printf(" Input tetrahedra: %d\n", in->numberoftetrahedra);
34402 }
34403 if (b->plc) {
34404 printf(" Input facets: %d\n", in->numberoffacets);
34405 printf(" Input segments: %ld\n", insegments);
34406 printf(" Input holes: %d\n", in->numberofholes);
34407 printf(" Input regions: %d\n", in->numberofregions);
34408 }
34409
34410 printf("\n Mesh points: %ld\n", points->items);
34411 printf(" Mesh tetrahedra: %ld\n", tetrahedrons->items);
34412 if (b->plc || b->refine) {
34413 printf(" Mesh triangles: %ld\n", (4l*tetrahedrons->items+hullsize)/2l);
34414 }
34415 if (b->plc || b->refine) {
34416 printf(" Mesh subfaces: %ld\n", subfaces->items);
34417 printf(" Mesh subsegments: %ld\n\n", subsegs->items);
34418 } else {
34419 printf(" Convex hull triangles: %ld\n\n", hullsize);
34420 }
34421 if (b->verbose > 0) {
34422 qualitystatistics();
34423 unsigned long totalmeshbytes;
34424 printf("Memory allocation statistics:\n\n");
34425 printf(" Maximum number of vertices: %ld\n", points->maxitems);
34426 totalmeshbytes = points->maxitems * points->itembytes;
34427 printf(" Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems);
34428 totalmeshbytes += tetrahedrons->maxitems * tetrahedrons->itembytes;
34429 if (subfaces != (memorypool *) NULL) {
34430 printf(" Maximum number of subfaces: %ld\n", subfaces->maxitems);
34431 totalmeshbytes += subfaces->maxitems * subfaces->itembytes;
34432 }
34433 if (subsegs != (memorypool *) NULL) {
34434 printf(" Maximum number of segments: %ld\n", subsegs->maxitems);
34435 totalmeshbytes += subsegs->maxitems * subsegs->itembytes;
34436 }
34437 printf(" Approximate heap memory used by the mesh (K bytes): %g\n\n",
34438 (double) totalmeshbytes / 1024.0);
34439 #ifdef SELF_CHECK
34440 algorithmicstatistics();
34441 #endif
34442 }
34443 }
34444
34445
34446
34447
34448
34449
34450
34451
34452
34454
34455
34456
34458
34459 tetgenmesh::~tetgenmesh()
34460 {
34461 bgm = (tetgenmesh *) NULL;
34462 in = (tetgenio *) NULL;
34463 b = (tetgenbehavior *) NULL;
34464
34465 if (tetrahedrons != (memorypool *) NULL) {
34466 delete tetrahedrons;
34467 }
34468 if (subfaces != (memorypool *) NULL) {
34469 delete subfaces;
34470 }
34471 if (subsegs != (memorypool *) NULL) {
34472 delete subsegs;
34473 }
34474 if (points != (memorypool *) NULL) {
34475 delete points;
34476 }
34477 if (dummytetbase != (tetrahedron *) NULL) {
34478 delete [] dummytetbase;
34479 }
34480 if (dummyshbase != (shellface *) NULL) {
34481 delete [] dummyshbase;
34482 }
34483 if (facetabovepointarray != (point *) NULL) {
34484 delete [] facetabovepointarray;
34485 }
34486 if (highordertable != (point *) NULL) {
34487 delete [] highordertable;
34488 }
34489 if (subpbcgrouptable != (pbcdata *) NULL) {
34490 delete [] subpbcgrouptable;
34491 }
34492 if (segpbcgrouptable != (list *) NULL) {
34493 delete segpbcgrouptable;
34494 delete [] idx2segpglist;
34495 delete [] segpglist;
34496 }
34497 }
34498
34500
34501
34502
34504
34505 tetgenmesh::tetgenmesh()
34506 {
34507 bgm = (tetgenmesh *) NULL;
34508 in = (tetgenio *) NULL;
34509 b = (tetgenbehavior *) NULL;
34510
34511 tetrahedrons = (memorypool *) NULL;
34512 subfaces = (memorypool *) NULL;
34513 subsegs = (memorypool *) NULL;
34514 points = (memorypool *) NULL;
34515 badsubsegs = (memorypool *) NULL;
34516 badsubfaces = (memorypool *) NULL;
34517 badtetrahedrons = (memorypool *) NULL;
34518 flipstackers = (memorypool *) NULL;
34519
34520 dummytet = (tetrahedron *) NULL;
34521 dummytetbase = (tetrahedron *) NULL;
34522 dummysh = (shellface *) NULL;
34523 dummyshbase = (shellface *) NULL;
34524
34525 facetabovepointarray = (point *) NULL;
34526 abovepoint = (point) NULL;
34527 highordertable = (point *) NULL;
34528 subpbcgrouptable = (pbcdata *) NULL;
34529 segpbcgrouptable = (list *) NULL;
34530 idx2segpglist = (int *) NULL;
34531 segpglist = (int *) NULL;
34532
34533 xmax = xmin = ymax = ymin = zmax = zmin = 0.0;
34534 longest = 0.0;
34535 hullsize = 0l;
34536 insegments = 0l;
34537 pointmtrindex = 0;
34538 pointmarkindex = 0;
34539 point2simindex = 0;
34540 point2pbcptindex = 0;
34541 highorderindex = 0;
34542 elemattribindex = 0;
34543 volumeboundindex = 0;
34544 shmarkindex = 0;
34545 areaboundindex = 0;
34546 checksubfaces = 0;
34547 checksubsegs = 0;
34548 checkpbcs = 0;
34549 varconstraint = 0;
34550 nonconvex = 0;
34551 dupverts = 0;
34552 unuverts = 0;
34553 relverts = 0;
34554 suprelverts = 0;
34555 collapverts = 0;
34556 unsupverts = 0;
34557 jettisoninverts = 0;
34558 symbolic = 1;
34559 samples = 0l;
34560 randomseed = 1l;
34561 macheps = 0.0;
34562 minfaceang = minfacetdihed = PI;
34563 maxcavfaces = maxcavverts = 0;
34564 expcavcount = 0;
34565 abovecount = 0l;
34566 bowatvolcount = bowatsubcount = bowatsegcount = 0l;
34567 updvolcount = updsubcount = updsegcount = 0l;
34568 repairflipcount = 0l;
34569 outbowatcircumcount = 0l;
34570 failvolcount = failsubcount = failsegcount = 0l;
34571 r1count = r2count = r3count = 0l;
34572 cdtenforcesegpts = 0l;
34573 rejsegpts = rejsubpts = rejtetpts = 0l;
34574 flip23s = flip32s = flip22s = flip44s = 0l;
34575 tloctime = tfliptime = 0.0;
34576 }
34577
34578
34579
34580
34581
34582
34583
34584
34585
34587
34588
34589
34590
34591
34592
34593
34594
34595
34596
34597
34598
34599
34600
34601
34602
34603
34604
34605
34606
34607
34609
34610 void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
34611 tetgenio *addin, tetgenio *bgmin)
34612 {
34613 tetgenmesh m;
34614
34615 clock_t tv[14];
34616
34617 tv[0] = clock();
34618
34619 m.b = b;
34620 m.in = in;
34621 m.macheps = exactinit();
34622 m.steinerleft = b->steiner;
34623 if (b->metric) {
34624 m.bgm = new tetgenmesh();
34625 m.bgm->b = b;
34626 m.bgm->in = bgmin;
34627 m.bgm->macheps = exactinit();
34628 }
34629 m.initializepools();
34630 m.transfernodes();
34631
34632 tv[1] = clock();
34633
34634 if (b->refine) {
34635 m.reconstructmesh();
34636 } else {
34637 m.delaunizevertices();
34638 }
34639
34640 tv[2] = clock();
34641
34642 if (!b->quiet) {
34643 if (b->refine) {
34644 printf("Mesh reconstruction seconds:");
34645 } else {
34646 printf("Delaunay seconds:");
34647 }
34648 printf(" %g\n", (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
34649 }
34650
34651 if (b->metric) {
34652 if (bgmin != (tetgenio *) NULL) {
34653 m.bgm->initializepools();
34654 m.bgm->transfernodes();
34655 m.bgm->reconstructmesh();
34656 } else {
34657 m.bgm->in = in;
34658 m.bgm->initializepools();
34659 m.duplicatebgmesh();
34660 }
34661 }
34662
34663 tv[3] = clock();
34664
34665 if (!b->quiet) {
34666 if (b->metric) {
34667 printf("Background mesh reconstruct seconds: %g\n",
34668 (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
34669 }
34670 }
34671
34672 if (b->useshelles && !b->refine) {
34673 m.meshsurface();
34674 if (b->diagnose != 1) {
34675 m.markacutevertices(89.0);
34676 m.incrperturbvertices(b->epsilon);
34677 m.delaunizesegments();
34678 if (m.checkpbcs) {
34679 long oldnum;
34680 do {
34681 oldnum = m.points->items;
34682 m.incrperturbvertices(b->epsilon);
34683 if (m.points->items > oldnum) {
34684 oldnum = m.points->items;
34685 m.delaunizesegments();
34686 }
34687 } while (oldnum < m.points->items);
34688 }
34689 m.constrainedfacets();
34690 } else {
34691 m.detectinterfaces();
34692 }
34693 }
34694
34695 tv[4] = clock();
34696
34697 if (!b->quiet) {
34698 if (b->useshelles && !b->refine) {
34699 if (b->diagnose != 1) {
34700 printf("Segment and facet ");
34701 } else {
34702 printf("Intersection ");
34703 }
34704 printf("seconds: %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
34705 }
34706 }
34707
34708 if (b->plc && !(b->diagnose == 1)) {
34709 m.carveholes();
34710 }
34711
34712 tv[5] = clock();
34713
34714 if (!b->quiet) {
34715 if (b->plc && !(b->diagnose == 1)) {
34716 printf("Hole seconds: %g\n", (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
34717 }
34718 }
34719
34720 if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34721 m.optimizemesh(false);
34722 }
34723
34724 tv[6] = clock();
34725
34726 if (!b->quiet) {
34727 if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34728 printf("Repair seconds: %g\n", (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
34729 }
34730 }
34731
34732 if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34733 m.removesteiners(false);
34734 }
34735
34736 tv[7] = clock();
34737
34738 if (!b->quiet) {
34739 if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34740 printf("Steiner removal seconds: %g\n",
34741 (tv[7] - tv[6]) / (REAL) CLOCKS_PER_SEC);
34742 }
34743 }
34744
34745 if (b->insertaddpoints && (addin != (tetgenio *) NULL)) {
34746 if (addin->numberofpoints > 0) {
34747 m.insertconstrainedpoints(addin);
34748 }
34749 }
34750
34751 tv[8] = clock();
34752
34753 if (!b->quiet) {
34754 if ((b->plc || b->refine) && (b->insertaddpoints)) {
34755 printf("Constrained points seconds: %g\n",
34756 (tv[8] - tv[7]) / (REAL) CLOCKS_PER_SEC);
34757 }
34758 }
34759
34760 if (b->metric) {
34761 m.interpolatesizemap();
34762 }
34763
34764 tv[9] = clock();
34765
34766 if (!b->quiet) {
34767 if (b->metric) {
34768 printf("Size interpolating seconds: %g\n",
34769 (tv[9] - tv[8]) / (REAL) CLOCKS_PER_SEC);
34770 }
34771 }
34772
34773 if (b->coarse) {
34774 m.removesteiners(true);
34775 }
34776
34777 tv[10] = clock();
34778
34779 if (!b->quiet) {
34780 if (b->coarse) {
34781 printf("Mesh coarsening seconds: %g\n",
34782 (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
34783 }
34784 }
34785
34786 if (b->quality) {
34787 m.enforcequality();
34788 }
34789
34790 tv[11] = clock();
34791
34792 if (!b->quiet) {
34793 if (b->quality) {
34794 printf("Quality seconds: %g\n",
34795 (tv[11] - tv[10]) / (REAL) CLOCKS_PER_SEC);
34796 }
34797 }
34798
34799 if (b->quality && (b->optlevel > 0)) {
34800 m.optimizemesh(true);
34801 }
34802
34803 tv[12] = clock();
34804
34805 if (!b->quiet) {
34806 if (b->quality && (b->optlevel > 0)) {
34807 printf("Optimize seconds: %g\n",
34808 (tv[12] - tv[11]) / (REAL) CLOCKS_PER_SEC);
34809 }
34810 }
34811
34812 if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0)
34813 || (b->refine && (in->numberofcorners == 10)))) {
34814 m.jettisonnodes();
34815 }
34816
34817 if (b->order > 1) {
34818 m.highorder();
34819 }
34820
34821 if (!b->quiet) {
34822 printf("\n");
34823 }
34824
34825 if (out != (tetgenio *) NULL) {
34826 out->firstnumber = in->firstnumber;
34827 out->mesh_dim = in->mesh_dim;
34828 }
34829
34830 if (b->nonodewritten || b->noiterationnum) {
34831 if (!b->quiet) {
34832 printf("NOT writing a .node file.\n");
34833 }
34834 } else {
34835 if (b->diagnose == 1) {
34836 if (m.subfaces->items > 0l) {
34837 m.outnodes(out);
34838 }
34839 } else {
34840 m.outnodes(out);
34841 if (b->quality || b->metric) {
34842
34843 }
34844 }
34845 }
34846
34847 if (b->noelewritten) {
34848 if (!b->quiet) {
34849 printf("NOT writing an .ele file.\n");
34850 }
34851 } else {
34852 if (!(b->diagnose == 1)) {
34853 if (m.tetrahedrons->items > 0l) {
34854 m.outelements(out);
34855 }
34856 }
34857 }
34858
34859 if (b->nofacewritten) {
34860 if (!b->quiet) {
34861 printf("NOT writing an .face file.\n");
34862 }
34863 } else {
34864 if (b->facesout) {
34865 if (m.tetrahedrons->items > 0l) {
34866 m.outfaces(out);
34867 }
34868 } else {
34869 if (b->diagnose == 1) {
34870 if (m.subfaces->items > 0l) {
34871 m.outsubfaces(out);
34872 }
34873 } else if (b->plc || b->refine) {
34874 if (m.subfaces->items > 0l) {
34875 m.outsubfaces(out);
34876 }
34877 } else {
34878 if (m.tetrahedrons->items > 0l) {
34879 m.outhullfaces(out);
34880 }
34881 }
34882 }
34883 }
34884
34885 if (m.checkpbcs) {
34886 m.outpbcnodes(out);
34887 }
34888
34889 if (b->edgesout) {
34890 if (b->edgesout > 1) {
34891 m.outedges(out);
34892 } else {
34893 m.outsubsegments(out);
34894 }
34895 }
34896
34897 if (!out && b->plc &&
34898 ((b->object == tetgenbehavior::OFF) ||
34899 (b->object == tetgenbehavior::PLY) ||
34900 (b->object == tetgenbehavior::STL))) {
34901 m.outsmesh(b->outfilename);
34902 }
34903
34904 if (!out && b->meditview) {
34905 m.outmesh2medit(b->outfilename);
34906 }
34907
34908 if (!out && b->gidview) {
34909 m.outmesh2gid(b->outfilename);
34910 }
34911
34912 if (!out && b->geomview) {
34913 m.outmesh2off(b->outfilename);
34914 }
34915
34916 if (b->neighout) {
34917 m.outneighbors(out);
34918 }
34919
34920 if (b->voroout) {
34921 m.outvoronoi(out);
34922 }
34923
34924 tv[13] = clock();
34925
34926 if (!b->quiet) {
34927 printf("\nOutput seconds: %g\n",
34928 (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
34929 printf("Total running seconds: %g\n",
34930 (tv[13] - tv[0]) / (REAL) CLOCKS_PER_SEC);
34931 }
34932
34933 if (b->docheck) {
34934 m.checkmesh();
34935 if (m.checksubfaces) {
34936 m.checkshells();
34937 }
34938 if (b->docheck > 1) {
34939 m.checkdelaunay(0.0, NULL);
34940 if (b->docheck > 2) {
34941 if (b->quality || b->refine) {
34942 m.checkconforming();
34943 }
34944 }
34945 }
34946 }
34947
34948 if (!b->quiet) {
34949 m.statistics();
34950 }
34951
34952 if (b->metric) {
34953 delete m.bgm;
34954 }
34955 }
34956
34957 #ifndef TETLIBRARY
34958
34960
34961
34962
34964
34965 int main(int argc, char *argv[])
34966
34967 #else // with TETLIBRARY
34968
34970
34971
34972
34974
34975 void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
34976 tetgenio *addin, tetgenio *bgmin)
34977
34978 #endif // not TETLIBRARY
34979
34980 {
34981 tetgenbehavior b;
34982
34983 #ifndef TETLIBRARY
34984
34985 tetgenio in, addin, bgmin;
34986
34987 if (!b.parse_commandline(argc, argv)) {
34988 terminatetetgen(1);
34989 }
34990 if (b.refine) {
34991 if (!in.load_tetmesh(b.infilename)) {
34992 terminatetetgen(1);
34993 }
34994 } else {
34995 if (!in.load_plc(b.infilename, (int) b.object)) {
34996 terminatetetgen(1);
34997 }
34998 }
34999 if (b.insertaddpoints) {
35000 if (!addin.load_node(b.addinfilename)) {
35001 addin.numberofpoints = 0l;
35002 }
35003 }
35004 if (b.metric) {
35005 if (!bgmin.load_tetmesh(b.bgmeshfilename)) {
35006 bgmin.numberoftetrahedra = 0l;
35007 }
35008 }
35009
35010 if (bgmin.numberoftetrahedra > 0l) {
35011 tetrahedralize(&b, &in, NULL, &addin, &bgmin);
35012 } else {
35013 tetrahedralize(&b, &in, NULL, &addin, NULL);
35014 }
35015
35016 return 0;
35017
35018 #else // with TETLIBRARY
35019
35020 if (!b.parse_commandline(switches)) {
35021 terminatetetgen(1);
35022 }
35023 tetrahedralize(&b, in, out, addin, bgmin);
35024
35025 #endif // not TETLIBRARY
35026 }
35027
35028 }
35029
35030 #ifndef TETLIBRARY
35031
35032
35033 int main(int argc, char *argv[])
35034 {
35035 tetgen::main(argc, argv);
35036 }
35037 #endif // not TETLIBRARY