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, pe, pf;
10597 int mirrorflag, i;
10598
10599 adjustedgering(*flipface, CCW);
10600 fnext(*flipface, abce);
10601 esymself(abce);
10602 adjustedgering(*flipface, CW);
10603 fnext(*flipface, bade);
10604 #ifdef SELF_CHECK
10605 assert(bade.tet != dummytet);
10606 #endif
10607 esymself(bade);
10608 pa = org(abce);
10609 pb = dest(abce);
10610 pc = apex(abce);
10611 pd = apex(bade);
10612 pe = oppo(bade);
10613 #ifdef SELF_CHECK
10614 assert(oppo(abce) == pe);
10615 #endif
10616 sym(abce, bacf);
10617 mirrorflag = bacf.tet != dummytet;
10618 if (mirrorflag) {
10619
10620 bacf.ver = 0;
10621 for (i = 0; (i < 3) && (org(bacf) != pb); i++) {
10622 enextself(bacf);
10623 }
10624 sym(bade, abdf);
10625 #ifdef SELF_CHECK
10626 assert(abdf.tet != dummytet);
10627 #endif
10628
10629 abdf.ver = 0;
10630 for (i = 0; (i < 3) && (org(abdf) != pa); i++) {
10631 enextself(abdf);
10632 }
10633 pf = oppo(bacf);
10634 #ifdef SELF_CHECK
10635 assert(oppo(abdf) == pf);
10636 #endif
10637 }
10638
10639 if (b->verbose > 2) {
10640 printf(" Do %s on edge (%d, %d).\n", mirrorflag ? "T44" : "T22",
10641 pointmark(pa), pointmark(pb));
10642 }
10643 mirrorflag ? flip44s++ : flip22s++;
10644
10645
10646 enextfnext(abce, oldbce);
10647 enext2fnext(abce, oldcae);
10648 enextfnext(bade, oldade);
10649 enext2fnext(bade, olddbe);
10650 sym(oldbce, bcecasing);
10651 sym(oldcae, caecasing);
10652 sym(oldade, adecasing);
10653 sym(olddbe, dbecasing);
10654 if (checksubfaces) {
10655 tspivot(oldbce, bcesh);
10656 tspivot(oldcae, caesh);
10657 tspivot(oldade, adesh);
10658 tspivot(olddbe, dbesh);
10659 tspivot(abce, abc);
10660 tspivot(bade, bad);
10661 } else if (checksubsegs) {
10662
10663 enext(bade, worktet);
10664 tsspivot1(worktet, adseg);
10665 enext2(bade, worktet);
10666 tsspivot1(worktet, dbseg);
10667 enext(abce, worktet);
10668 tsspivot1(worktet, bcseg);
10669 enext2(abce, worktet);
10670 tsspivot1(worktet, caseg);
10671
10672 fnext(bade, worktet);
10673 enextself(worktet);
10674 tsspivot1(worktet, aeseg);
10675 enextfnext(bade, worktet);
10676 enextself(worktet);
10677 tsspivot1(worktet, deseg);
10678 enext2fnext(bade, worktet);
10679 enextself(worktet);
10680 tsspivot1(worktet, beseg);
10681 enextfnext(abce, worktet);
10682 enextself(worktet);
10683 tsspivot1(worktet, ceseg);
10684 }
10685 if (mirrorflag) {
10686 enextfnext(bacf, oldacf);
10687 enext2fnext(bacf, oldcbf);
10688 enextfnext(abdf, oldbdf);
10689 enext2fnext(abdf, olddaf);
10690 sym(oldacf, acfcasing);
10691 sym(oldcbf, cbfcasing);
10692 sym(oldbdf, bdfcasing);
10693 sym(olddaf, dafcasing);
10694 if (checksubfaces) {
10695 tspivot(oldacf, acfsh);
10696 tspivot(oldcbf, cbfsh);
10697 tspivot(oldbdf, bdfsh);
10698 tspivot(olddaf, dafsh);
10699 } else if (checksubsegs) {
10700
10701 fnext(abdf, worktet);
10702 enext2self(worktet);
10703 tsspivot1(worktet, afseg);
10704 enext2fnext(abdf, worktet);
10705 enext2self(worktet);
10706 tsspivot1(worktet, dfseg);
10707 enextfnext(abdf, worktet);
10708 enext2self(worktet);
10709 tsspivot1(worktet, bfseg);
10710 enextfnext(bacf, worktet);
10711 enextself(worktet);
10712 tsspivot1(worktet, cfseg);
10713 }
10714 }
10715
10716
10717 bond(oldbce, caecasing);
10718 bond(oldcae, adecasing);
10719 bond(oldade, dbecasing);
10720 bond(olddbe, bcecasing);
10721 if (checksubfaces) {
10722
10723 if (caesh.sh == dummysh) {
10724 tsdissolve(oldbce);
10725 } else {
10726 tsbond(oldbce, caesh);
10727 }
10728 if (adesh.sh == dummysh) {
10729 tsdissolve(oldcae);
10730 } else {
10731 tsbond(oldcae, adesh);
10732 }
10733 if (dbesh.sh == dummysh) {
10734 tsdissolve(oldade);
10735 } else {
10736 tsbond(oldade, dbesh);
10737 }
10738 if (bcesh.sh == dummysh) {
10739 tsdissolve(olddbe);
10740 } else {
10741 tsbond(olddbe, bcesh);
10742 }
10743 } else if (checksubsegs) {
10744
10745 enext(abce, worktet);
10746 if (caseg.sh == dummysh) {
10747 tssdissolve1(worktet);
10748 } else {
10749 tssbond1(worktet, caseg);
10750 }
10751 enext2(abce, worktet);
10752 if (adseg.sh == dummysh) {
10753 tssdissolve1(worktet);
10754 } else {
10755 tssbond1(worktet, adseg);
10756 }
10757 fnext(abce, worktet);
10758 enextself(worktet);
10759 if (ceseg.sh == dummysh) {
10760 tssdissolve1(worktet);
10761 } else {
10762 tssbond1(worktet, ceseg);
10763 }
10764 enextfnext(abce, worktet);
10765 enextself(worktet);
10766 if (aeseg.sh == dummysh) {
10767 tssdissolve1(worktet);
10768 } else {
10769 tssbond1(worktet, aeseg);
10770 }
10771 enext2fnext(abce, worktet);
10772 enextself(worktet);
10773 if (deseg.sh == dummysh) {
10774 tssdissolve1(worktet);
10775 } else {
10776 tssbond1(worktet, deseg);
10777 }
10778
10779 enext(bade, worktet);
10780 if (dbseg.sh == dummysh) {
10781 tssdissolve1(worktet);
10782 } else {
10783 tssbond1(worktet, dbseg);
10784 }
10785 enext2(bade, worktet);
10786 if (bcseg.sh == dummysh) {
10787 tssdissolve1(worktet);
10788 } else {
10789 tssbond1(worktet, bcseg);
10790 }
10791 fnext(bade, worktet);
10792 enextself(worktet);
10793 if (deseg.sh == dummysh) {
10794 tssdissolve1(worktet);
10795 } else {
10796 tssbond1(worktet, deseg);
10797 }
10798 enextfnext(bade, worktet);
10799 enextself(worktet);
10800 if (beseg.sh == dummysh) {
10801 tssdissolve1(worktet);
10802 } else {
10803 tssbond1(worktet, beseg);
10804 }
10805 enext2fnext(bade, worktet);
10806 enextself(worktet);
10807 if (ceseg.sh == dummysh) {
10808 tssdissolve1(worktet);
10809 } else {
10810 tssbond1(worktet, ceseg);
10811 }
10812 }
10813 if (mirrorflag) {
10814
10815 bond(oldcbf, acfcasing);
10816 bond(oldacf, dafcasing);
10817 bond(olddaf, bdfcasing);
10818 bond(oldbdf, cbfcasing);
10819 if (checksubfaces) {
10820
10821 if (acfsh.sh == dummysh) {
10822 tsdissolve(oldcbf);
10823 } else {
10824 tsbond(oldcbf, acfsh);
10825 }
10826 if (dafsh.sh == dummysh) {
10827 tsdissolve(oldacf);
10828 } else {
10829 tsbond(oldacf, dafsh);
10830 }
10831 if (bdfsh.sh == dummysh) {
10832 tsdissolve(olddaf);
10833 } else {
10834 tsbond(olddaf, bdfsh);
10835 }
10836 if (cbfsh.sh == dummysh) {
10837 tsdissolve(oldbdf);
10838 } else {
10839 tsbond(oldbdf, cbfsh);
10840 }
10841 } else if (checksubsegs) {
10842
10843 enext2(bacf, worktet);
10844 if (caseg.sh == dummysh) {
10845 tssdissolve1(worktet);
10846 } else {
10847 tssbond1(worktet, caseg);
10848 }
10849 enext(bacf, worktet);
10850 if (adseg.sh == dummysh) {
10851 tssdissolve1(worktet);
10852 } else {
10853 tssbond1(worktet, adseg);
10854 }
10855 fnext(bacf, worktet);
10856 enext2self(worktet);
10857 if (cfseg.sh == dummysh) {
10858 tssdissolve1(worktet);
10859 } else {
10860 tssbond1(worktet, cfseg);
10861 }
10862 enext2fnext(bacf, worktet);
10863 enext2self(worktet);
10864 if (afseg.sh == dummysh) {
10865 tssdissolve1(worktet);
10866 } else {
10867 tssbond1(worktet, afseg);
10868 }
10869 enextfnext(bacf, worktet);
10870 enext2self(worktet);
10871 if (dfseg.sh == dummysh) {
10872 tssdissolve1(worktet);
10873 } else {
10874 tssbond1(worktet, dfseg);
10875 }
10876
10877 enext2(abdf, worktet);
10878 if (dbseg.sh == dummysh) {
10879 tssdissolve1(worktet);
10880 } else {
10881 tssbond1(worktet, dbseg);
10882 }
10883 enext(abdf, worktet);
10884 if (bcseg.sh == dummysh) {
10885 tssdissolve1(worktet);
10886 } else {
10887 tssbond1(worktet, bcseg);
10888 }
10889 fnext(abdf, worktet);
10890 enext2self(worktet);
10891 if (dfseg.sh == dummysh) {
10892 tssdissolve1(worktet);
10893 } else {
10894 tssbond1(worktet, dfseg);
10895 }
10896 enext2fnext(abdf, worktet);
10897 enext2self(worktet);
10898 if (bfseg.sh == dummysh) {
10899 tssdissolve1(worktet);
10900 } else {
10901 tssbond1(worktet, bfseg);
10902 }
10903 enextfnext(abdf, worktet);
10904 enext2self(worktet);
10905 if (cfseg.sh == dummysh) {
10906 tssdissolve1(worktet);
10907 } else {
10908 tssbond1(worktet, cfseg);
10909 }
10910 }
10911 }
10912
10913
10914 setorg(abce, pd);
10915 setdest(abce, pc);
10916 setapex(abce, pa);
10917 setorg(bade, pc);
10918 setdest(bade, pd);
10919 setapex(bade, pb);
10920 if (mirrorflag) {
10921 setorg(bacf, pc);
10922 setdest(bacf, pd);
10923 setapex(bacf, pa);
10924 setorg(abdf, pd);
10925 setdest(abdf, pc);
10926 setapex(abdf, pb);
10927 }
10928
10929
10930 if (checksubfaces && abc.sh != dummysh) {
10931 #ifdef SELF_CHECK
10932 assert(bad.sh != dummysh);
10933 #endif
10934
10935
10936 findedge(&abc, pa, pb);
10937
10938 flip22sub(&abc, NULL);
10939 }
10940
10941 if (b->verbose > 3) {
10942 printf(" Updating abce ");
10943 printtet(&abce);
10944 printf(" Updating bade ");
10945 printtet(&bade);
10946 if (mirrorflag) {
10947 printf(" Updating bacf ");
10948 printtet(&bacf);
10949 printf(" Updating abdf ");
10950 printtet(&abdf);
10951 }
10952 }
10953
10954 if (flipqueue != (queue *) NULL) {
10955 enextfnext(abce, bcecasing);
10956 enqueueflipface(bcecasing, flipqueue);
10957 enext2fnext(abce, caecasing);
10958 enqueueflipface(caecasing, flipqueue);
10959 enextfnext(bade, adecasing);
10960 enqueueflipface(adecasing, flipqueue);
10961 enext2fnext(bade, dbecasing);
10962 enqueueflipface(dbecasing, flipqueue);
10963 if (mirrorflag) {
10964 enextfnext(bacf, acfcasing);
10965 enqueueflipface(acfcasing, flipqueue);
10966 enext2fnext(bacf, cbfcasing);
10967 enqueueflipface(cbfcasing, flipqueue);
10968 enextfnext(abdf, bdfcasing);
10969 enqueueflipface(bdfcasing, flipqueue);
10970 enext2fnext(abdf, dafcasing);
10971 enqueueflipface(dafcasing, flipqueue);
10972 }
10973
10974
10975
10976
10977
10978 enqueueflipface(abce, flipqueue);
10979 enqueueflipface(bade, flipqueue);
10980 }
10981
10982
10983 recenttet = abce;
10984 }
10985
10987
10988
10989
10990
10991
10992
10993
10994
10995
10996
10997
10998
10999
11000
11001
11002
11003
11004
11005
11006
11007
11008
11009
11010
11012
11013 void tetgenmesh::flip22sub(face* flipedge, queue* flipqueue)
11014 {
11015 face abc, bad;
11016 face oldbc, oldca, oldad, olddb;
11017 face bccasin, bccasout, cacasin, cacasout;
11018 face adcasin, adcasout, dbcasin, dbcasout;
11019 face bc, ca, ad, db;
11020 face spinsh;
11021 point pa, pb, pc, pd;
11022
11023 abc = *flipedge;
11024 spivot(abc, bad);
11025 if (sorg(bad) != sdest(abc)) {
11026 sesymself(bad);
11027 }
11028 pa = sorg(abc);
11029 pb = sdest(abc);
11030 pc = sapex(abc);
11031 pd = sapex(bad);
11032
11033 if (b->verbose > 2) {
11034 printf(" Flip sub edge (%d, %d).\n", pointmark(pa), pointmark(pb));
11035 }
11036
11037
11038 senext(abc, oldbc);
11039 senext2(abc, oldca);
11040 senext(bad, oldad);
11041 senext2(bad, olddb);
11042
11043
11044
11045 spivot(oldbc, bccasout);
11046 sspivot(oldbc, bc);
11047 if (bc.sh != dummysh) {
11048
11049 if (bccasout.sh != dummysh) {
11050 if (oldbc.sh != bccasout.sh) {
11051
11052 spinsh = bccasout;
11053 do {
11054 bccasin = spinsh;
11055 spivotself(spinsh);
11056 } while (spinsh.sh != oldbc.sh);
11057 } else {
11058 bccasout.sh = dummysh;
11059 }
11060 }
11061 ssdissolve(oldbc);
11062 }
11063 spivot(oldca, cacasout);
11064 sspivot(oldca, ca);
11065 if (ca.sh != dummysh) {
11066
11067 if (cacasout.sh != dummysh) {
11068 if (oldca.sh != cacasout.sh) {
11069
11070 spinsh = cacasout;
11071 do {
11072 cacasin = spinsh;
11073 spivotself(spinsh);
11074 } while (spinsh.sh != oldca.sh);
11075 } else {
11076 cacasout.sh = dummysh;
11077 }
11078 }
11079 ssdissolve(oldca);
11080 }
11081 spivot(oldad, adcasout);
11082 sspivot(oldad, ad);
11083 if (ad.sh != dummysh) {
11084
11085 if (adcasout.sh != dummysh) {
11086 if (oldad.sh != adcasout.sh) {
11087
11088 spinsh = adcasout;
11089 do {
11090 adcasin = spinsh;
11091 spivotself(spinsh);
11092 } while (spinsh.sh != oldad.sh);
11093 } else {
11094 adcasout.sh = dummysh;
11095 }
11096 }
11097 ssdissolve(oldad);
11098 }
11099 spivot(olddb, dbcasout);
11100 sspivot(olddb, db);
11101 if (db.sh != dummysh) {
11102
11103 if (dbcasout.sh != dummysh) {
11104 if (olddb.sh != dbcasout.sh) {
11105
11106 spinsh = dbcasout;
11107 do {
11108 dbcasin = spinsh;
11109 spivotself(spinsh);
11110 } while (spinsh.sh != olddb.sh);
11111 } else {
11112 dbcasout.sh = dummysh;
11113 }
11114 }
11115 ssdissolve(olddb);
11116 }
11117
11118
11119 if (ca.sh != dummysh) {
11120 if (cacasout.sh != dummysh) {
11121 sbond1(cacasin, oldbc);
11122 sbond1(oldbc, cacasout);
11123 } else {
11124
11125 sbond(oldbc, oldbc);
11126
11127 dummysh[0] = sencode(oldbc);
11128 }
11129 ssbond(oldbc, ca);
11130 } else {
11131 sbond(oldbc, cacasout);
11132 }
11133 if (ad.sh != dummysh) {
11134 if (adcasout.sh != dummysh) {
11135 sbond1(adcasin, oldca);
11136 sbond1(oldca, adcasout);
11137 } else {
11138
11139 sbond(oldca, oldca);
11140
11141 dummysh[0] = sencode(oldca);
11142 }
11143 ssbond(oldca, ad);
11144 } else {
11145 sbond(oldca, adcasout);
11146 }
11147 if (db.sh != dummysh) {
11148 if (dbcasout.sh != dummysh) {
11149 sbond1(dbcasin, oldad);
11150 sbond1(oldad, dbcasout);
11151 } else {
11152
11153 sbond(oldad, oldad);
11154
11155 dummysh[0] = sencode(oldad);
11156 }
11157 ssbond(oldad, db);
11158 } else {
11159 sbond(oldad, dbcasout);
11160 }
11161 if (bc.sh != dummysh) {
11162 if (bccasout.sh != dummysh) {
11163 sbond1(bccasin, olddb);
11164 sbond1(olddb, bccasout);
11165 } else {
11166
11167 sbond(olddb, olddb);
11168
11169 dummysh[0] = sencode(olddb);
11170 }
11171 ssbond(olddb, bc);
11172 } else {
11173 sbond(olddb, bccasout);
11174 }
11175
11176
11177 setsorg(abc, pd);
11178 setsdest(abc, pc);
11179 setsapex(abc, pa);
11180 setsorg(bad, pc);
11181 setsdest(bad, pd);
11182 setsapex(bad, pb);
11183
11184 if (flipqueue != (queue *) NULL) {
11185 enqueueflipedge(bccasout, flipqueue);
11186 enqueueflipedge(cacasout, flipqueue);
11187 enqueueflipedge(adcasout, flipqueue);
11188 enqueueflipedge(dbcasout, flipqueue);
11189 }
11190 }
11191
11193
11194
11195
11196
11197
11198
11199
11200
11201
11202
11203
11204
11205
11206
11208
11209 long tetgenmesh::flip(queue* flipqueue, badface **plastflip)
11210 {
11211 badface *qface, *newflip;
11212 triface flipface, symface;
11213 point pa, pb, pc, pd, pe;
11214 enum fliptype fc;
11215 REAL sign, bakepsilon;
11216 long flipcount, maxfaces;
11217 int epscount, fcount;
11218 int ia, ib, ic, id, ie;
11219
11220 if (b->verbose > 1) {
11221 printf(" Do flipface queue: %ld faces.\n", flipqueue->len());
11222 }
11223
11224 flipcount = flip23s + flip32s + flip22s + flip44s;
11225 if (checksubfaces) {
11226 maxfaces = (4l * tetrahedrons->items + hullsize) / 2l;
11227 fcount = 0;
11228 }
11229
11230 if (plastflip != (badface **) NULL) {
11231
11232 flipstackers->restart();
11233 *plastflip = (badface *) NULL;
11234 }
11235
11236
11237 while (!flipqueue->empty()) {
11238 qface = (badface *) flipqueue->pop();
11239 flipface = qface->tt;
11240 if (isdead(&flipface)) continue;
11241 sym(flipface, symface);
11242
11243 if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11244
11245 adjustedgering(flipface, CW);
11246 pa = org(flipface);
11247 pb = dest(flipface);
11248 pc = apex(flipface);
11249 pd = oppo(flipface);
11250 pe = oppo(symface);
11251 if (symbolic) {
11252 ia = pointmark(pa);
11253 ib = pointmark(pb);
11254 ic = pointmark(pc);
11255 id = pointmark(pd);
11256 ie = pointmark(pe);
11257 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
11258 assert(sign != 0.0);
11259 } else {
11260 sign = insphere(pa, pb, pc, pd, pe);
11261 }
11262 } else {
11263 sign = -1.0;
11264 }
11265 if (sign > 0.0) {
11266
11267 if (checksubfaces) {
11268 fcount++;
11269 bakepsilon = b->epsilon;
11270 epscount = 0;
11271 while (epscount < 32) {
11272 fc = categorizeface(flipface);
11273 if (fc == N40) {
11274 b->epsilon *= 1e-1;
11275 epscount++;
11276 continue;
11277 }
11278 break;
11279 }
11280 b->epsilon = bakepsilon;
11281 if (epscount >= 32) {
11282 if (b->verbose > 0) {
11283 printf("Warning: Can't flip a degenerate tetrahedron.\n");
11284 }
11285 fc = N40;
11286 }
11287 } else {
11288 fc = categorizeface(flipface);
11289 #ifdef SELF_CHECK
11290 assert(fc != N40);
11291 #endif
11292 }
11293 switch (fc) {
11294
11295 case T44:
11296 case T22:
11297 flip22(&flipface, flipqueue);
11298 break;
11299 case T23:
11300 flip23(&flipface, flipqueue);
11301 break;
11302 case T32:
11303 flip32(&flipface, flipqueue);
11304 break;
11305
11306 case N32:
11307 break;
11308 case FORBIDDENFACE:
11309 break;
11310 case FORBIDDENEDGE:
11311 break;
11312
11313 case N40:
11314
11315 break;
11316 }
11317 if (plastflip != (badface **) NULL) {
11318 if ((fc == T44) || (fc == T22) || (fc == T23) || (fc == T32)) {
11319
11320 newflip = (badface *) flipstackers->alloc();
11321 newflip->tt = flipface;
11322 newflip->key = (REAL) fc;
11323 newflip->forg = org(flipface);
11324 newflip->fdest = dest(flipface);
11325 newflip->fapex = apex(flipface);
11326 newflip->previtem = *plastflip;
11327 *plastflip = newflip;
11328 }
11329 }
11330 }
11331 }
11332
11333 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11334 if (b->verbose > 1) {
11335 printf(" %ld flips.\n", flipcount);
11336 }
11337
11338 return flipcount;
11339 }
11340
11342
11343
11344
11346
11347 long tetgenmesh::lawson(list *misseglist, queue* flipqueue)
11348 {
11349 badface *qface, *misseg;
11350 triface flipface, symface;
11351 triface starttet, spintet;
11352 face checksh, checkseg;
11353 point pa, pb, pc, pd, pe;
11354 point swappt;
11355 REAL sign, ori;
11356 long flipcount;
11357 int ia, ib, ic, id, ie;
11358 int hitbdry, i;
11359
11360 if (b->verbose > 1) {
11361 printf(" Do flipface queue: %ld faces.\n", flipqueue->len());
11362 }
11363 flipcount = flip23s + flip32s + flip22s + flip44s;
11364
11365
11366
11367
11368 while (!flipqueue->empty()) {
11369 qface = (badface *) flipqueue->pop();
11370 flipface = qface->tt;
11371
11372 if (!isdead(&flipface)) {
11373 sym(flipface, symface);
11374
11375 if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11376 flipface.ver = 0;
11377 pa = org(flipface);
11378 pb = dest(flipface);
11379 pc = apex(flipface);
11380 pd = oppo(flipface);
11381 pe = oppo(symface);
11382 if (symbolic) {
11383 ia = pointmark(pa);
11384 ib = pointmark(pb);
11385 ic = pointmark(pc);
11386 id = pointmark(pd);
11387 ie = pointmark(pe);
11388 sign = insphere_sos(pb, pa, pc, pd, pe, ib, ia, ic, id, ie);
11389 } else {
11390 sign = insphere(pb, pa, pc, pd, pe);
11391 }
11392 if (sign > 0.0) {
11393 for (i = 0; i < 3; i++) {
11394 ori = orient3d(pa, pb, pd, pe);
11395 if (ori > 0.0) {
11396
11397 swappt = pa;
11398 pa = pb;
11399 pb = pc;
11400 pc = swappt;
11401 enextself(flipface);
11402 } else {
11403 break;
11404 }
11405 }
11406 if (ori > 0.0) {
11407
11408 if (checksubfaces) {
11409 tspivot(flipface, checksh);
11410 if (checksh.sh != dummysh) {
11411
11412 continue;
11413 }
11414 }
11415 flip23(&flipface, flipqueue);
11416 } else if (ori < 0.0) {
11417
11418 fnext(flipface, symface);
11419 symself(symface);
11420 if (oppo(symface) == pe) {
11421
11422 if (checksubfaces) {
11423 tsspivot(&flipface, &checkseg);
11424 if (checkseg.sh != dummysh) {
11425
11426 continue;
11427 }
11428 } else if (checksubsegs) {
11429 tsspivot1(flipface, checkseg);
11430 if (checkseg.sh != dummysh) {
11431 if (b->verbose > 2) {
11432 printf(" Queuing missing segment (%d, %d).\n",
11433 pointmark(org(flipface)), pointmark(dest(flipface)));
11434 }
11435 misseg = (badface *) misseglist->append(NULL);
11436 misseg->ss = checkseg;
11437 misseg->forg = sorg(checkseg);
11438 misseg->fdest = sdest(checkseg);
11439
11440 starttet = flipface;
11441 adjustedgering(starttet, CCW);
11442 fnextself(starttet);
11443 spintet = starttet;
11444 hitbdry = 0;
11445 do {
11446 tssdissolve1(spintet);
11447 if (!fnextself(spintet)) {
11448 hitbdry++;
11449 if (hitbdry < 2) {
11450 esym(starttet, spintet);
11451 if (!fnextself(spintet)) {
11452 hitbdry++;
11453 }
11454 }
11455 }
11456 } while ((apex(spintet) != apex(starttet)) && (hitbdry < 2));
11457 }
11458 }
11459 flip32(&flipface, flipqueue);
11460 }
11461 } else {
11462
11463 fnext(flipface, symface);
11464 if (fnextself(symface)) {
11465
11466 fnextself(symface);
11467 if (apex(symface) == pe) {
11468 if (checksubfaces) {
11469 tsspivot(&flipface, &checkseg);
11470 if (checkseg.sh != dummysh) {
11471
11472 continue;
11473 }
11474 } else if (checksubsegs) {
11475 tsspivot1(flipface, checkseg);
11476 if (checkseg.sh != dummysh) {
11477 if (b->verbose > 2) {
11478 printf(" Queuing missing segment (%d, %d).\n",
11479 pointmark(org(flipface)), pointmark(dest(flipface)));
11480 }
11481 misseg = (badface *) misseglist->append(NULL);
11482 misseg->ss = checkseg;
11483 misseg->forg = sorg(checkseg);
11484 misseg->fdest = sdest(checkseg);
11485
11486 starttet = flipface;
11487 adjustedgering(starttet, CCW);
11488 fnextself(starttet);
11489 spintet = starttet;
11490 hitbdry = 0;
11491 do {
11492 tssdissolve1(spintet);
11493 if (!fnextself(spintet)) {
11494 hitbdry++;
11495 if (hitbdry < 2) {
11496 esym(starttet, spintet);
11497 if (!fnextself(spintet)) {
11498 hitbdry++;
11499 }
11500 }
11501 }
11502 } while ((apex(spintet) != apex(starttet)) &&
11503 (hitbdry < 2));
11504 }
11505 }
11506 flip22(&flipface, flipqueue);
11507 }
11508 } else {
11509
11510 esym(flipface, symface);
11511 fnextself(symface);
11512 symself(symface);
11513 if (symface.tet == dummytet) {
11514 if (checksubfaces) {
11515 tsspivot(&flipface, &checkseg);
11516 if (checkseg.sh != dummysh) {
11517
11518 continue;
11519 }
11520 } else if (checksubsegs) {
11521 tsspivot1(flipface, checkseg);
11522 if (checkseg.sh != dummysh) {
11523 if (b->verbose > 2) {
11524 printf(" Queuing missing segment (%d, %d).\n",
11525 pointmark(org(flipface)), pointmark(dest(flipface)));
11526 }
11527 misseg = (badface *) misseglist->append(NULL);
11528 misseg->ss = checkseg;
11529 misseg->forg = sorg(checkseg);
11530 misseg->fdest = sdest(checkseg);
11531
11532 starttet = flipface;
11533 adjustedgering(starttet, CCW);
11534 fnextself(starttet);
11535 spintet = starttet;
11536 hitbdry = 0;
11537 do {
11538 tssdissolve1(spintet);
11539 if (!fnextself(spintet)) {
11540 hitbdry++;
11541 if (hitbdry < 2) {
11542 esym(starttet, spintet);
11543 if (!fnextself(spintet)) {
11544 hitbdry++;
11545 }
11546 }
11547 }
11548 } while ((apex(spintet) != apex(starttet)) &&
11549 (hitbdry < 2));
11550 }
11551 }
11552 flip22(&flipface, flipqueue);
11553 }
11554 }
11555 }
11556 }
11557 }
11558 }
11559 }
11560
11561 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11562 if (b->verbose > 1) {
11563 printf(" %ld flips.\n", flipcount);
11564 }
11565 return flipcount;
11566 }
11567
11569
11570
11571
11572
11573
11574
11575
11577
11578 void tetgenmesh::undoflip(badface *lastflip)
11579 {
11580 enum fliptype fc;
11581
11582 while (lastflip != (badface *) NULL) {
11583
11584 findface(&lastflip->tt, lastflip->forg, lastflip->fdest, lastflip->fapex);
11585 fc = (enum fliptype) (int) lastflip->key;
11586 switch (fc) {
11587 case T23:
11588
11589 flip32(&lastflip->tt, NULL);
11590 break;
11591 case T32:
11592
11593 flip23(&lastflip->tt, NULL);
11594 break;
11595 case T22:
11596 case T44:
11597
11598 flip22(&lastflip->tt, NULL);
11599 break;
11600 default:
11601 break;
11602 }
11603
11604 lastflip = lastflip->previtem;
11605 }
11606 }
11607
11609
11610
11611
11612
11613
11614
11615
11617
11618 long tetgenmesh::flipsub(queue* flipqueue)
11619 {
11620 badface *qedge;
11621 face flipedge, symedge;
11622 face checkseg;
11623 point pa, pb, pc, pd;
11624 REAL vab[3], vac[3], vad[3];
11625 REAL dot1, dot2, lac, lad;
11626 REAL sign, ori;
11627 int edgeflips;
11628 int i;
11629
11630 if (b->verbose > 1) {
11631 printf(" Start do edge queue: %ld edges.\n", flipqueue->len());
11632 }
11633
11634 edgeflips = 0;
11635
11636 while (!flipqueue->empty()) {
11637 qedge = (badface *) flipqueue->pop();
11638 flipedge = qedge->ss;
11639 if (flipedge.sh == dummysh) continue;
11640 if ((sorg(flipedge) != qedge->forg) ||
11641 (sdest(flipedge) != qedge->fdest)) continue;
11642 sspivot(flipedge, checkseg);
11643 if (checkseg.sh != dummysh) continue;
11644 spivot(flipedge, symedge);
11645 if (symedge.sh == dummysh) continue;
11646 pa = sorg(flipedge);
11647 pb = sdest(flipedge);
11648 pc = sapex(flipedge);
11649 pd = sapex(symedge);
11650
11651
11652 for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
11653 for (i = 0; i < 3; i++) vac[i] = pc[i] - pa[i];
11654 for (i = 0; i < 3; i++) vad[i] = pd[i] - pa[i];
11655 dot1 = dot(vac, vab);
11656 dot2 = dot(vad, vab);
11657 dot1 *= dot1;
11658 dot2 *= dot2;
11659 lac = dot(vac, vac);
11660 lad = dot(vad, vad);
11661 if (lad * dot1 <= lac * dot2) {
11662
11663 abovepoint = facetabovepointarray[shellmark(flipedge)];
11664 if (abovepoint == (point) NULL) {
11665 getfacetabovepoint(&flipedge);
11666 }
11667 sign = insphere(pa, pb, pc, abovepoint, pd);
11668 ori = orient3d(pa, pb, pc, abovepoint);
11669 } else {
11670
11671 abovepoint = facetabovepointarray[shellmark(symedge)];
11672 if (abovepoint == (point) NULL) {
11673 getfacetabovepoint(&symedge);
11674 }
11675 sign = insphere(pa, pb, pd, abovepoint, pc);
11676 ori = orient3d(pa, pb, pd, abovepoint);
11677 }
11678
11679 sign = ori > 0.0 ? sign : -sign;
11680 if (sign > 0.0) {
11681
11682 flip22sub(&flipedge, flipqueue);
11683 edgeflips++;
11684 }
11685 }
11686
11687 if (b->verbose > 1) {
11688 printf(" Total %d flips.\n", edgeflips);
11689 }
11690
11691 return edgeflips;
11692 }
11693
11695
11696
11697
11698
11699
11700
11701
11702
11703
11704
11705
11706
11707
11709
11710 bool tetgenmesh::removetetbypeeloff(triface *striptet)
11711 {
11712 triface abcd, badc;
11713 triface dcacasing, cdbcasing;
11714 face abc, bad;
11715 face abseg;
11716 REAL ang;
11717
11718 abcd = *striptet;
11719 adjustedgering(abcd, CCW);
11720
11721 enextfnext(abcd, cdbcasing);
11722 enext2fnext(abcd, dcacasing);
11723 symself(cdbcasing);
11724 symself(dcacasing);
11725
11726
11727 if ((cdbcasing.tet == dummytet) || (dcacasing.tet == dummytet)) {
11728
11729 return false;
11730 }
11731
11732
11733 if (checksubfaces) {
11734
11735 fnext(abcd, badc);
11736 esymself(badc);
11737 tspivot(abcd, abc);
11738 tspivot(badc, bad);
11739 if (abc.sh != dummysh) {
11740 assert(bad.sh != dummysh);
11741 findedge(&abc, org(abcd), dest(abcd));
11742 findedge(&bad, org(badc), dest(badc));
11743
11744 sspivot(abc, abseg);
11745 if (abseg.sh != dummysh) {
11746
11747 if ((b->optlevel > 3) && (b->nobisect == 0)) {
11748
11749
11750
11751 ang = facedihedral(org(abcd), dest(abcd), apex(abcd), oppo(abcd));
11752 ang = ang * 180.0 / PI;
11753 if ((ang + 9.0) > b->maxdihedral) {
11754 if (b->verbose > 1) {
11755 printf(" Remove a segment during peeling.\n");
11756 }
11757 face prevseg, nextseg;
11758
11759 ssdissolve(abc);
11760 ssdissolve(bad);
11761 abseg.shver = 0;
11762 senext(abseg, nextseg);
11763 spivotself(nextseg);
11764 if (nextseg.sh != dummysh) {
11765 ssdissolve(nextseg);
11766 }
11767 senext2(abseg, prevseg);
11768 spivotself(prevseg);
11769 if (prevseg.sh != dummysh) {
11770 ssdissolve(prevseg);
11771 }
11772 shellfacedealloc(subsegs, abseg.sh);
11773 optcount[1]++;
11774 } else {
11775 return false;
11776 }
11777 } else {
11778 return false;
11779 }
11780 }
11781
11782 flip22sub(&abc, NULL);
11783
11784 tsbond(cdbcasing, bad);
11785 tsbond(dcacasing, abc);
11786 }
11787 }
11788
11789
11790 dissolve(cdbcasing);
11791 dissolve(dcacasing);
11792
11793 tetrahedrondealloc(abcd.tet);
11794 return true;
11795 }
11796
11798
11799
11800
11801
11802
11803
11804
11805
11806
11807
11808
11809
11810
11812
11813 bool tetgenmesh::removeedgebyflip22(REAL *key, int n, triface *abtetlist,
11814 queue *flipque)
11815 {
11816 point pa, pb, pc, pd, pe, pf;
11817 REAL cosmaxd, d1, d2, d3;
11818 bool doflip;
11819
11820 cosmaxd = 0.0;
11821 pf = apex(abtetlist[2]);
11822 doflip = true;
11823 adjustedgering(abtetlist[0], CW);
11824 pa = org(abtetlist[0]);
11825 pb = dest(abtetlist[0]);
11826 pe = apex(abtetlist[0]);
11827 pc = oppo(abtetlist[0]);
11828 pd = apex(abtetlist[1]);
11829 if (n == 4) {
11830 pf = apex(abtetlist[2]);
11831 }
11832 if (key && (*key > -1.0)) {
11833 tetalldihedral(pc, pd, pe, pa, NULL, &d1, NULL);
11834 tetalldihedral(pd, pc, pe, pb, NULL, &d2, NULL);
11835 cosmaxd = d1 < d2 ? d1 : d2;
11836 if (n == 4) {
11837 tetalldihedral(pd, pc, pf, pa, NULL, &d1, NULL);
11838 tetalldihedral(pc, pd, pf, pb, NULL, &d2, NULL);
11839 d3 = d1 < d2 ? d1 : d2;
11840 cosmaxd = cosmaxd < d3 ? cosmaxd : d3;
11841 }
11842 doflip = (*key < cosmaxd);
11843 }
11844
11845 if (doflip) {
11846 flip22(&abtetlist[0], NULL);
11847
11848 if (key) *key = cosmaxd;
11849 }
11850
11851 return doflip;
11852 }
11853
11855
11856
11857
11858
11859
11860
11861
11862
11863
11864
11865
11866
11867
11868
11869
11870
11872
11873 bool tetgenmesh::removefacebyflip23(REAL *key, triface *abctetlist,
11874 triface *newtetlist, queue *flipque)
11875 {
11876 triface edab, edbc, edca;
11877 triface newfront, oldfront, adjfront;
11878 face checksh;
11879 point pa, pb, pc, pd, pe;
11880 REAL ori, cosmaxd, d1, d2, d3;
11881 REAL attrib, volume;
11882 bool doflip;
11883 int i;
11884
11885 cosmaxd = 0.0;
11886
11887 adjustedgering(abctetlist[0], CCW);
11888 pa = org(abctetlist[0]);
11889 pb = dest(abctetlist[0]);
11890 pc = apex(abctetlist[0]);
11891 pd = oppo(abctetlist[0]);
11892 pe = oppo(abctetlist[1]);
11893
11894
11895 ori = orient3d(pe, pd, pa, pb);
11896 if (ori < 0.0) {
11897 ori = orient3d(pe, pd, pb, pc);
11898 if (ori < 0.0) {
11899 ori = orient3d(pe, pd, pc, pa);
11900 }
11901 }
11902 doflip = (ori < 0.0);
11903 if (doflip && (key != (REAL *) NULL)) {
11904 if (*key > -1.0) {
11905
11906 tetalldihedral(pe, pd, pa, pb, NULL, &d1, NULL);
11907 tetalldihedral(pe, pd, pb, pc, NULL, &d2, NULL);
11908 tetalldihedral(pe, pd, pc, pa, NULL, &d3, NULL);
11909 cosmaxd = d1 < d2 ? d1 : d2;
11910 cosmaxd = cosmaxd < d3 ? cosmaxd : d3;
11911 doflip = (*key < cosmaxd);
11912 }
11913 }
11914
11915 if (doflip) {
11916
11917 flip23s++;
11918
11919 maketetrahedron(&edab);
11920 setorg(edab, pe);
11921 setdest(edab, pd);
11922 setapex(edab, pa);
11923 setoppo(edab, pb);
11924 maketetrahedron(&edbc);
11925 setorg(edbc, pe);
11926 setdest(edbc, pd);
11927 setapex(edbc, pb);
11928 setoppo(edbc, pc);
11929 maketetrahedron(&edca);
11930 setorg(edca, pe);
11931 setdest(edca, pd);
11932 setapex(edca, pc);
11933 setoppo(edca, pa);
11934
11935 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
11936 attrib = elemattribute(abctetlist[0].tet, i);
11937 setelemattribute(edab.tet, i, attrib);
11938 setelemattribute(edbc.tet, i, attrib);
11939 setelemattribute(edca.tet, i, attrib);
11940 }
11941
11942 if (b->varvolume && !b->refine) {
11943 volume = volumebound(abctetlist[0].tet);
11944 setvolumebound(edab.tet, volume);
11945 setvolumebound(edbc.tet, volume);
11946 setvolumebound(edca.tet, volume);
11947 }
11948
11949 newtetlist[0] = edab;
11950 newtetlist[1] = edbc;
11951 newtetlist[2] = edca;
11952
11953 for (i = 0; i < 3; i++) {
11954 fnext(newtetlist[i], newfront);
11955 bond(newfront, newtetlist[(i + 1) % 3]);
11956 }
11957
11958 for (i = 0; i < 3; i++) {
11959 fnext(abctetlist[0], oldfront);
11960 sym(oldfront, adjfront);
11961 enextfnext(newtetlist[i], newfront);
11962 bond(newfront, adjfront);
11963 if (checksubfaces) {
11964 tspivot(oldfront, checksh);
11965 if (checksh.sh != dummysh) {
11966 tsbond(newfront, checksh);
11967 }
11968 }
11969 if (flipque != (queue *) NULL) {
11970 enqueueflipface(newfront, flipque);
11971 }
11972 enextself(abctetlist[0]);
11973 }
11974 findedge(&(abctetlist[1]), pb, pa);
11975 for (i = 0; i < 3; i++) {
11976 fnext(abctetlist[1], oldfront);
11977 sym(oldfront, adjfront);
11978 enext2fnext(newtetlist[i], newfront);
11979 bond(newfront, adjfront);
11980 if (checksubfaces) {
11981 tspivot(oldfront, checksh);
11982 if (checksh.sh != dummysh) {
11983 tsbond(newfront, checksh);
11984 }
11985 }
11986 if (flipque != (queue *) NULL) {
11987 enqueueflipface(newfront, flipque);
11988 }
11989 enext2self(abctetlist[1]);
11990 }
11991
11992
11993
11994
11995
11996 if (key != (REAL *) NULL) *key = cosmaxd;
11997 return true;
11998 }
11999
12000 return false;
12001 }
12002
12004
12005
12006
12007
12008
12009
12010
12011
12012
12013
12014
12015
12016
12017
12018
12019
12020
12021
12022
12024
12025 bool tetgenmesh::removeedgebyflip32(REAL *key, triface *abtetlist,
12026 triface *newtetlist, queue *flipque)
12027 {
12028 triface dcea, cdeb;
12029 triface newfront, oldfront, adjfront;
12030 face checksh;
12031 point pa, pb, pc, pd, pe;
12032 REAL ori, cosmaxd, d1, d2;
12033 REAL attrib, volume;
12034 bool doflip;
12035 int i;
12036
12037 pa = org(abtetlist[0]);
12038 pb = dest(abtetlist[0]);
12039 pc = apex(abtetlist[0]);
12040 pd = apex(abtetlist[1]);
12041 pe = apex(abtetlist[2]);
12042
12043 ori = orient3d(pd, pc, pe, pa);
12044 if (ori < 0.0) {
12045 ori = orient3d(pc, pd, pe, pb);
12046 }
12047 doflip = (ori < 0.0);
12048
12049
12050 if (doflip && (key != (REAL *) NULL)) {
12051 if (*key > -1.0) {
12052
12053 tetalldihedral(pd, pc, pe, pa, NULL, &d1, NULL);
12054 tetalldihedral(pc, pd, pe, pb, NULL, &d2, NULL);
12055 cosmaxd = d1 < d2 ? d1 : d2;
12056 doflip = (*key < cosmaxd);
12057
12058 *key = cosmaxd;
12059 }
12060 }
12061
12062 if (doflip) {
12063
12064 maketetrahedron(&dcea);
12065 setorg(dcea, pd);
12066 setdest(dcea, pc);
12067 setapex(dcea, pe);
12068 setoppo(dcea, pa);
12069 maketetrahedron(&cdeb);
12070 setorg(cdeb, pc);
12071 setdest(cdeb, pd);
12072 setapex(cdeb, pe);
12073 setoppo(cdeb, pb);
12074
12075 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12076 attrib = elemattribute(abtetlist[0].tet, i);
12077 setelemattribute(dcea.tet, i, attrib);
12078 setelemattribute(cdeb.tet, i, attrib);
12079 }
12080
12081 if (b->varvolume && !b->refine) {
12082 volume = volumebound(abtetlist[0].tet);
12083 setvolumebound(dcea.tet, volume);
12084 setvolumebound(cdeb.tet, volume);
12085 }
12086
12087 newtetlist[0] = dcea;
12088 newtetlist[1] = cdeb;
12089
12090 bond(dcea, cdeb);
12091
12092 for (i = 0; i < 3; i++) {
12093 fnext(dcea, newfront);
12094 esym(abtetlist[(i + 1) % 3], oldfront);
12095 enextfnextself(oldfront);
12096
12097 sym(oldfront, adjfront);
12098 bond(newfront, adjfront);
12099 if (checksubfaces) {
12100 tspivot(oldfront, checksh);
12101 if (checksh.sh != dummysh) {
12102 tsbond(newfront, checksh);
12103 }
12104 }
12105 if (flipque != (queue *) NULL) {
12106 enqueueflipface(newfront, flipque);
12107 }
12108 enext2self(dcea);
12109 }
12110 for (i = 0; i < 3; i++) {
12111 fnext(cdeb, newfront);
12112 esym(abtetlist[(i + 1) % 3], oldfront);
12113 enext2fnextself(oldfront);
12114
12115 sym(oldfront, adjfront);
12116 bond(newfront, adjfront);
12117 if (checksubfaces) {
12118 tspivot(oldfront, checksh);
12119 if (checksh.sh != dummysh) {
12120 tsbond(newfront, checksh);
12121 }
12122 }
12123 if (flipque != (queue *) NULL) {
12124 enqueueflipface(newfront, flipque);
12125 }
12126 enextself(cdeb);
12127 }
12128
12129
12130
12131
12132 return true;
12133 }
12134
12135 return false;
12136 }
12137
12139
12140
12141
12142
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
12178
12179 bool tetgenmesh::removeedgebytranNM(REAL *key, int n, triface *abtetlist,
12180 triface *newtetlist, point e1, point e2, queue *flipque)
12181 {
12182 triface tmpabtetlist[9];
12183 triface newfront, oldfront, adjfront;
12184 face checksh;
12185 point pa, pb, p[10];
12186 REAL ori, cosmaxd, d1, d2;
12187 REAL tmpkey;
12188 REAL attrib, volume;
12189 bool doflip, copflag, success;
12190 int i, j, k;
12191
12192 cosmaxd = 0.0;
12193
12194 assert(n <= 10);
12195
12196 pa = org(abtetlist[0]);
12197 pb = dest(abtetlist[0]);
12198
12199
12200
12201
12202 for (i = 0; i < n; i++) {
12203
12204 for (j = 0; j < n; j++) {
12205 p[j] = apex(abtetlist[(i + j) % n]);
12206 }
12207
12208 if ((e1 != (point) NULL) && (e2 != (point) NULL)) {
12209
12210 if (!(((p[1] == e1) && (p[n - 1] == e2)) ||
12211 ((p[1] == e2) && (p[n - 1] == e1)))) continue;
12212 }
12213
12214
12215
12216
12217
12218
12219 ori = orient3d(pa, pb, p[1], p[n - 1]);
12220 copflag = (ori == 0.0);
12221 if (ori >= 0.0) {
12222
12223 ori = orient3d(pb, p[0], p[1], p[n - 1]);
12224 if (ori > 0.0) {
12225 ori = orient3d(p[0], pa, p[1], p[n - 1]);
12226 }
12227 }
12228
12229 if (ori > 0.0) {
12230
12231 copflag ? flip44s++ : flip23s++;
12232 doflip = true;
12233 if (key != (REAL *) NULL) {
12234 if (*key > -1.0) {
12235
12236
12237
12238 tetalldihedral(p[n - 1], p[1], p[0], pa, NULL, &d1, NULL);
12239 tetalldihedral(p[1], p[n - 1], p[0], pb, NULL, &d2, NULL);
12240 cosmaxd = d1 < d2 ? d1 : d2;
12241 doflip = *key < cosmaxd;
12242 }
12243 }
12244 if (doflip) {
12245 tmpkey = key != NULL ? *key : -1.0;
12246
12247 maketetrahedron(&(newtetlist[0]));
12248 setorg(newtetlist[0], p[n - 1]);
12249 setdest(newtetlist[0], p[1]);
12250 setapex(newtetlist[0], p[0]);
12251 setoppo(newtetlist[0], pa);
12252 maketetrahedron(&(newtetlist[1]));
12253 setorg(newtetlist[1], p[1]);
12254 setdest(newtetlist[1], p[n - 1]);
12255 setapex(newtetlist[1], p[0]);
12256 setoppo(newtetlist[1], pb);
12257
12258 maketetrahedron(&(tmpabtetlist[0]));
12259 setorg(tmpabtetlist[0], pa);
12260 setdest(tmpabtetlist[0], pb);
12261 setapex(tmpabtetlist[0], p[n - 1]);
12262 setoppo(tmpabtetlist[0], p[1]);
12263 for (j = 1; j < n - 1; j++) {
12264 maketetrahedron(&(tmpabtetlist[j]));
12265 setorg(tmpabtetlist[j], pa);
12266 setdest(tmpabtetlist[j], pb);
12267 setapex(tmpabtetlist[j], p[j]);
12268 setoppo(tmpabtetlist[j], p[j + 1]);
12269 }
12270
12271 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12272 attrib = elemattribute(abtetlist[0].tet, j);
12273 setelemattribute(newtetlist[0].tet, j, attrib);
12274 setelemattribute(newtetlist[1].tet, j, attrib);
12275 for (k = 0; k < n - 1; k++) {
12276 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12277 }
12278 }
12279
12280 if (b->varvolume && !b->refine) {
12281 volume = volumebound(abtetlist[0].tet);
12282 setvolumebound(newtetlist[0].tet, volume);
12283 setvolumebound(newtetlist[1].tet, volume);
12284 for (k = 0; k < n - 1; k++) {
12285 setvolumebound(tmpabtetlist[k].tet, volume);
12286 }
12287 }
12288
12289 bond(newtetlist[0], newtetlist[1]);
12290 fnext(newtetlist[0], newfront);
12291 enext2fnext(tmpabtetlist[0], adjfront);
12292 bond(newfront, adjfront);
12293 fnext(newtetlist[1], newfront);
12294 enextfnext(tmpabtetlist[0], adjfront);
12295 bond(newfront, adjfront);
12296
12297 for (j = 0; j < n - 1; j++) {
12298 fnext(tmpabtetlist[j], newfront);
12299 bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]);
12300 }
12301
12302
12303
12304
12305
12306
12307 for (j = 0; j < n; j++) {
12308
12309 oldfront = abtetlist[(i + j) % n];
12310 esymself(oldfront);
12311 enextfnextself(oldfront);
12312
12313 sym(oldfront, adjfront);
12314
12315 if (j == 0) {
12316 enext2fnext(newtetlist[0], newfront);
12317 } else if (j == 1) {
12318 enextfnext(newtetlist[0], newfront);
12319 } else {
12320 enext2fnext(tmpabtetlist[j - 1], newfront);
12321 }
12322 bond(newfront, adjfront);
12323 if (checksubfaces) {
12324 tspivot(oldfront, checksh);
12325 if (checksh.sh != dummysh) {
12326 tsbond(newfront, checksh);
12327 }
12328 }
12329 if (flipque != (queue *) NULL) {
12330
12331 if (j < 2) enqueueflipface(newfront, flipque);
12332 }
12333 }
12334 for (j = 0; j < n; j++) {
12335
12336 oldfront = abtetlist[(i + j) % n];
12337 esymself(oldfront);
12338 enext2fnextself(oldfront);
12339
12340 sym(oldfront, adjfront);
12341
12342 if (j == 0) {
12343 enextfnext(newtetlist[1], newfront);
12344 } else if (j == 1) {
12345 enext2fnext(newtetlist[1], newfront);
12346 } else {
12347 enextfnext(tmpabtetlist[j - 1], newfront);
12348 }
12349 bond(newfront, adjfront);
12350 if (checksubfaces) {
12351 tspivot(oldfront, checksh);
12352 if (checksh.sh != dummysh) {
12353 tsbond(newfront, checksh);
12354 }
12355 }
12356 if (flipque != (queue *) NULL) {
12357
12358 if (j < 2) enqueueflipface(newfront, flipque);
12359 }
12360 }
12361
12362
12363 for (j = 0; j < n - 1; j++) {
12364 fnextself(tmpabtetlist[j]);
12365 }
12366 if (n > 4) {
12367 success = removeedgebytranNM(&tmpkey, n-1, tmpabtetlist,
12368 &(newtetlist[2]), NULL, NULL, flipque);
12369 } else {
12370 success = removeedgebyflip32(&tmpkey, tmpabtetlist,
12371 &(newtetlist[2]), flipque);
12372 }
12373
12374 for (j = 0; j < n - 1; j++) {
12375 tetrahedrondealloc(tmpabtetlist[j].tet);
12376 }
12377 if (success) {
12378
12379
12380
12381
12382
12383
12384 if (key != (REAL *) NULL) {
12385 *key = (tmpkey < cosmaxd ? tmpkey : cosmaxd);
12386 }
12387 return true;
12388 } else {
12389
12390 for (j = 0; j < n; j++) {
12391 oldfront = abtetlist[(i + j) % n];
12392 esymself(oldfront);
12393 enextfnextself(oldfront);
12394 sym(oldfront, adjfront);
12395 bond(oldfront, adjfront);
12396 if (checksubfaces) {
12397 tspivot(oldfront, checksh);
12398 if (checksh.sh != dummysh) {
12399 tsbond(oldfront, checksh);
12400 }
12401 }
12402 }
12403 for (j = 0; j < n; j++) {
12404 oldfront = abtetlist[(i + j) % n];
12405 esymself(oldfront);
12406 enext2fnextself(oldfront);
12407 sym(oldfront, adjfront);
12408 bond(oldfront, adjfront);
12409 if (checksubfaces) {
12410 tspivot(oldfront, checksh);
12411 if (checksh.sh != dummysh) {
12412 tsbond(oldfront, checksh);
12413 }
12414 }
12415 }
12416
12417 tetrahedrondealloc(newtetlist[0].tet);
12418 tetrahedrondealloc(newtetlist[1].tet);
12419
12420
12421 if (key && (tmpkey < *key)) {
12422 *key = tmpkey;
12423 return false;
12424 }
12425 }
12426 }
12427 }
12428 }
12429
12430 return false;
12431 }
12432
12434
12435
12436
12437
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
12474
12475 bool tetgenmesh::removeedgebycombNM(REAL *key, int n, triface *abtetlist,
12476 int *n1, triface *bftetlist, triface *newtetlist, queue *flipque)
12477 {
12478 triface tmpabtetlist[11];
12479 triface newfront, oldfront, adjfront;
12480 face checksh;
12481 point pa, pb, p[10];
12482 REAL ori, tmpkey, tmpkey2;
12483 REAL attrib, volume;
12484 bool doflip, success;
12485 int twice, count;
12486 int i, j, k, m;
12487
12488
12489 assert(n <= 10);
12490
12491
12492
12493 twice = 0;
12494 do {
12495
12496 pa = org(abtetlist[0]);
12497 pb = dest(abtetlist[0]);
12498
12499 for (i = 0; i < n; i++) {
12500
12501 for (j = 0; j < n; j++) {
12502 p[j] = apex(abtetlist[(i + j) % n]);
12503 }
12504
12505 ori = orient3d(pb, p[0], p[1], p[n - 1]);
12506 if ((ori > 0) && (key != (REAL *) NULL)) {
12507
12508
12509
12510 tetalldihedral(pb, p[0], p[n - 1], p[1], NULL, &tmpkey, NULL);
12511 if (tmpkey < *key) ori = 0.0;
12512 }
12513 if (ori <= 0.0) {
12514
12515 bftetlist[0] = abtetlist[i];
12516 enextself(bftetlist[0]);
12517 adjustedgering(bftetlist[0], CW);
12518 assert(apex(bftetlist[0]) == pa);
12519
12520 doflip = true;
12521 *n1 = 0;
12522 do {
12523
12524 if (*n1 == 10) break;
12525 if (checksubfaces) {
12526
12527 tspivot(bftetlist[*n1], checksh);
12528 if (checksh.sh != dummysh) {
12529 doflip = false; break;
12530 }
12531 }
12532
12533 fnext(bftetlist[*n1], bftetlist[(*n1) + 1]);
12534 (*n1)++;
12535 } while (apex(bftetlist[*n1]) != pa);
12536
12537 if (doflip) {
12538 success = false;
12539 tmpkey = -1.0;
12540 if (key != (REAL *) NULL) tmpkey = *key;
12541 m = 0;
12542 if (*n1 == 3) {
12543
12544 success = removeedgebyflip32(&tmpkey,bftetlist,newtetlist,flipque);
12545 m = 2;
12546 } else if ((*n1 > 3) && (*n1 < 7)) {
12547
12548 success = removeedgebytranNM(&tmpkey, *n1, bftetlist, newtetlist,
12549 p[1], p[n - 1], flipque);
12550
12551 m = ((*n1) - 2) * 2;
12552 } else {
12553 if (b->verbose > 1) {
12554 printf(" !! Unhandled case: n1 = %d.\n", *n1);
12555 }
12556 }
12557 if (success) {
12558
12559
12560
12561
12562
12563 setpointmark(pa, -pointmark(pa) - 1);
12564 setpointmark(pb, -pointmark(pb) - 1);
12565 assert(m > 0);
12566 for (j = 0; j < m; j++) {
12567 tmpabtetlist[0] = newtetlist[j];
12568
12569 count = 0;
12570 for (k = 0; k < 4; k++) {
12571 if (pointmark((point)(tmpabtetlist[0].tet[4+k])) < 0) count++;
12572 }
12573 if (count == 2) {
12574
12575 for (tmpabtetlist[0].loc = 0; tmpabtetlist[0].loc < 4;
12576 tmpabtetlist[0].loc++) {
12577 if ((oppo(tmpabtetlist[0]) != pa) &&
12578 (oppo(tmpabtetlist[0]) != pb)) break;
12579 }
12580
12581 assert(tmpabtetlist[0].loc < 4);
12582 findedge(&(tmpabtetlist[0]), pa, pb);
12583 break;
12584 }
12585 }
12586 assert(j < m);
12587
12588 newtetlist[j] = newtetlist[m - 1];
12589 setpointmark(pa, -(pointmark(pa) + 1));
12590 setpointmark(pb, -(pointmark(pb) + 1));
12591
12592 adjustedgering(tmpabtetlist[0], CCW);
12593 if (org(tmpabtetlist[0]) != pa) {
12594 fnextself(tmpabtetlist[0]);
12595 esymself(tmpabtetlist[0]);
12596 }
12597 #ifdef SELF_CHECK
12598
12599 assert(org(tmpabtetlist[0]) == pa);
12600 assert(dest(tmpabtetlist[0]) == pb);
12601 assert(apex(tmpabtetlist[0]) == p[n - 1]);
12602 assert(oppo(tmpabtetlist[0]) == p[1]);
12603 #endif // SELF_CHECK
12604
12605 for (j = 1; j < n - 1; j++) {
12606 maketetrahedron(&(tmpabtetlist[j]));
12607 setorg(tmpabtetlist[j], pa);
12608 setdest(tmpabtetlist[j], pb);
12609 setapex(tmpabtetlist[j], p[j]);
12610 setoppo(tmpabtetlist[j], p[j + 1]);
12611 }
12612
12613 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12614 attrib = elemattribute(abtetlist[0].tet, j);
12615 for (k = 0; k < n - 1; k++) {
12616 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12617 }
12618 }
12619
12620 if (b->varvolume && !b->refine) {
12621 volume = volumebound(abtetlist[0].tet);
12622 for (k = 0; k < n - 1; k++) {
12623 setvolumebound(tmpabtetlist[k].tet, volume);
12624 }
12625 }
12626
12627 for (j = 0; j < n - 1; j++) {
12628 fnext(tmpabtetlist[j], newfront);
12629 bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]);
12630 }
12631
12632
12633
12634
12635
12636
12637 for (j = 2; j < n; j++) {
12638
12639 oldfront = abtetlist[(i + j) % n];
12640 esymself(oldfront);
12641 enextfnextself(oldfront);
12642
12643 sym(oldfront, adjfront);
12644
12645
12646 enext2fnext(tmpabtetlist[j - 1], newfront);
12647 bond(newfront, adjfront);
12648 if (checksubfaces) {
12649 tspivot(oldfront, checksh);
12650 if (checksh.sh != dummysh) {
12651 tsbond(newfront, checksh);
12652 }
12653 }
12654 }
12655 for (j = 2; j < n; j++) {
12656
12657 oldfront = abtetlist[(i + j) % n];
12658 esymself(oldfront);
12659 enext2fnextself(oldfront);
12660
12661 sym(oldfront, adjfront);
12662
12663
12664 enextfnext(tmpabtetlist[j - 1], newfront);
12665 bond(newfront, adjfront);
12666 if (checksubfaces) {
12667 tspivot(oldfront, checksh);
12668 if (checksh.sh != dummysh) {
12669 tsbond(newfront, checksh);
12670 }
12671 }
12672 }
12673
12674
12675 for (j = 0; j < n - 1; j++) {
12676 fnextself(tmpabtetlist[j]);
12677 }
12678 tmpkey2 = -1;
12679 if (key) tmpkey2 = *key;
12680 if ((n - 1) == 3) {
12681 success = removeedgebyflip32(&tmpkey2, tmpabtetlist,
12682 &(newtetlist[m - 1]), flipque);
12683 } else {
12684 success = removeedgebytranNM(&tmpkey2, n - 1, tmpabtetlist,
12685 &(newtetlist[m - 1]), NULL, NULL, flipque);
12686 }
12687
12688 for (j = 0; j < n - 1; j++) {
12689 tetrahedrondealloc(tmpabtetlist[j].tet);
12690 }
12691 if (success) {
12692
12693
12694
12695
12696
12697
12698 if (key != (REAL *) NULL) {
12699 *key = tmpkey2 < tmpkey ? tmpkey2 : tmpkey;
12700 }
12701 return true;
12702 } else {
12703
12704 for (j = 0; j < n; j++) {
12705 oldfront = abtetlist[(i + j) % n];
12706 esymself(oldfront);
12707 enextfnextself(oldfront);
12708 sym(oldfront, adjfront);
12709 bond(oldfront, adjfront);
12710 if (checksubfaces) {
12711 tspivot(oldfront, checksh);
12712 if (checksh.sh != dummysh) {
12713 tsbond(oldfront, checksh);
12714 }
12715 }
12716 }
12717 for (j = 0; j < n; j++) {
12718 oldfront = abtetlist[(i + j) % n];
12719 esymself(oldfront);
12720 enext2fnextself(oldfront);
12721 sym(oldfront, adjfront);
12722 bond(oldfront, adjfront);
12723 if (checksubfaces) {
12724 tspivot(oldfront, checksh);
12725 if (checksh.sh != dummysh) {
12726 tsbond(oldfront, checksh);
12727 }
12728 }
12729 }
12730
12731 for (j = 0; j < *n1; j++) {
12732 oldfront = bftetlist[j];
12733 esymself(oldfront);
12734 enextfnextself(oldfront);
12735 sym(oldfront, adjfront);
12736 bond(oldfront, adjfront);
12737 if (checksubfaces) {
12738 tspivot(oldfront, checksh);
12739 if (checksh.sh != dummysh) {
12740 tsbond(oldfront, checksh);
12741 }
12742 }
12743 }
12744 for (j = 0; j < *n1; j++) {
12745 oldfront = bftetlist[j];
12746 esymself(oldfront);
12747 enext2fnextself(oldfront);
12748 sym(oldfront, adjfront);
12749 bond(oldfront, adjfront);
12750 if (checksubfaces) {
12751 tspivot(oldfront, checksh);
12752 if (checksh.sh != dummysh) {
12753 tsbond(oldfront, checksh);
12754 }
12755 }
12756 }
12757
12758
12759 for (j = 0; j < m - 1; j++) {
12760 tetrahedrondealloc(newtetlist[j].tet);
12761 }
12762 }
12763 }
12764 }
12765 }
12766 }
12767
12768 for (i = 0; i < n; i++) newtetlist[i] = abtetlist[i];
12769 for (i = 0; i < n; i++) {
12770 oldfront = newtetlist[n - i - 1];
12771 esymself(oldfront);
12772 fnextself(oldfront);
12773 abtetlist[i] = oldfront;
12774 }
12775 twice++;
12776 } while (twice < 2);
12777
12778 return false;
12779 }
12780
12782
12783
12784
12785
12786
12787
12788
12789
12790
12791
12792
12793
12794
12796
12797 void tetgenmesh::splittetrahedron(point newpoint, triface* splittet,
12798 queue* flipqueue)
12799 {
12800 triface oldabd, oldbcd, oldcad;
12801 triface abdcasing, bcdcasing, cadcasing;
12802 face abdsh, bcdsh, cadsh;
12803 triface abcv, badv, cbdv, acdv;
12804 triface worktet;
12805 face abseg, bcseg, caseg;
12806 face adseg, bdseg, cdseg;
12807 point pa, pb, pc, pd;
12808 REAL attrib, volume;
12809 int i;
12810
12811 abcv = *splittet;
12812 abcv.ver = 0;
12813
12814 pa = org(abcv);
12815 pb = dest(abcv);
12816 pc = apex(abcv);
12817 pd = oppo(abcv);
12818
12819 if (b->verbose > 1) {
12820 printf(" Inserting point %d in tetrahedron (%d, %d, %d, %d).\n",
12821 pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc),
12822 pointmark(pd));
12823 }
12824
12825 fnext(abcv, oldabd);
12826 enextfnext(abcv, oldbcd);
12827 enext2fnext(abcv, oldcad);
12828 sym(oldabd, abdcasing);
12829 sym(oldbcd, bcdcasing);
12830 sym(oldcad, cadcasing);
12831 maketetrahedron(&badv);
12832 maketetrahedron(&cbdv);
12833 maketetrahedron(&acdv);
12834
12835
12836 setorg (badv, pb);
12837 setdest(badv, pa);
12838 setapex(badv, pd);
12839 setoppo(badv, newpoint);
12840
12841 setorg (cbdv, pc);
12842 setdest(cbdv, pb);
12843 setapex(cbdv, pd);
12844 setoppo(cbdv, newpoint);
12845
12846 setorg (acdv, pa);
12847 setdest(acdv, pc);
12848 setapex(acdv, pd);
12849 setoppo(acdv, newpoint);
12850
12851 setoppo(abcv, newpoint);
12852
12853
12854 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12855 attrib = elemattribute(abcv.tet, i);
12856 setelemattribute(badv.tet, i, attrib);
12857 setelemattribute(cbdv.tet, i, attrib);
12858 setelemattribute(acdv.tet, i, attrib);
12859 }
12860
12861 if (b->varvolume) {
12862 volume = volumebound(abcv.tet);
12863 setvolumebound(badv.tet, volume);
12864 setvolumebound(cbdv.tet, volume);
12865 setvolumebound(acdv.tet, volume);
12866 }
12867
12868
12869 bond(badv, abdcasing);
12870 bond(cbdv, bcdcasing);
12871 bond(acdv, cadcasing);
12872
12873 if (checksubfaces) {
12874 tspivot(oldabd, abdsh);
12875 if (abdsh.sh != dummysh) {
12876 tsdissolve(oldabd);
12877 tsbond(badv, abdsh);
12878 }
12879 tspivot(oldbcd, bcdsh);
12880 if (bcdsh.sh != dummysh) {
12881 tsdissolve(oldbcd);
12882 tsbond(cbdv, bcdsh);
12883 }
12884 tspivot(oldcad, cadsh);
12885 if (cadsh.sh != dummysh) {
12886 tsdissolve(oldcad);
12887 tsbond(acdv, cadsh);
12888 }
12889 } else if (checksubsegs) {
12890 tsspivot1(abcv, abseg);
12891 if (abseg.sh != dummysh) {
12892 tssbond1(badv, abseg);
12893 }
12894 enext(abcv, worktet);
12895 tsspivot1(worktet, bcseg);
12896 if (bcseg.sh != dummysh) {
12897 tssbond1(cbdv, bcseg);
12898 }
12899 enext2(abcv, worktet);
12900 tsspivot1(worktet, caseg);
12901 if (caseg.sh != dummysh) {
12902 tssbond1(acdv, caseg);
12903 }
12904 fnext(abcv, worktet);
12905 enext2self(worktet);
12906 tsspivot1(worktet, adseg);
12907 if (adseg.sh != dummysh) {
12908 tssdissolve1(worktet);
12909 enext(badv, worktet);
12910 tssbond1(worktet, adseg);
12911 enext2(acdv, worktet);
12912 tssbond1(worktet, adseg);
12913 }
12914 enextfnext(abcv, worktet);
12915 enext2self(worktet);
12916 tsspivot1(worktet, bdseg);
12917 if (bdseg.sh != dummysh) {
12918 tssdissolve1(worktet);
12919 enext(cbdv, worktet);
12920 tssbond1(worktet, bdseg);
12921 enext2(badv, worktet);
12922 tssbond1(worktet, bdseg);
12923 }
12924 enext2fnext(abcv, worktet);
12925 enext2self(worktet);
12926 tsspivot1(worktet, cdseg);
12927 if (cdseg.sh != dummysh) {
12928 tssdissolve1(worktet);
12929 enext(acdv, worktet);
12930 tssbond1(worktet, cdseg);
12931 enext2(cbdv, worktet);
12932 tssbond1(worktet, cdseg);
12933 }
12934 }
12935 badv.loc = 3;
12936 cbdv.loc = 2;
12937 bond(badv, cbdv);
12938 cbdv.loc = 3;
12939 acdv.loc = 2;
12940 bond(cbdv, acdv);
12941 acdv.loc = 3;
12942 badv.loc = 2;
12943 bond(acdv, badv);
12944 badv.loc = 1;
12945 bond(badv, oldabd);
12946 cbdv.loc = 1;
12947 bond(cbdv, oldbcd);
12948 acdv.loc = 1;
12949 bond(acdv, oldcad);
12950
12951 badv.loc = 0;
12952 cbdv.loc = 0;
12953 acdv.loc = 0;
12954 if (b->verbose > 3) {
12955 printf(" Updating abcv ");
12956 printtet(&abcv);
12957 printf(" Creating badv ");
12958 printtet(&badv);
12959 printf(" Creating cbdv ");
12960 printtet(&cbdv);
12961 printf(" Creating acdv ");
12962 printtet(&acdv);
12963 }
12964
12965 if (flipqueue != (queue *) NULL) {
12966 enqueueflipface(abcv, flipqueue);
12967 enqueueflipface(badv, flipqueue);
12968 enqueueflipface(cbdv, flipqueue);
12969 enqueueflipface(acdv, flipqueue);
12970 }
12971
12972
12973 recenttet = abcv;
12974
12975 *splittet = abcv;
12976 }
12977
12979
12980
12981
12982
12983
12984
12985
12986
12987
12988
12989
12990
12992
12993 void tetgenmesh::unsplittetrahedron(triface* splittet)
12994 {
12995 triface abcv, badv, cbdv, acdv;
12996 triface oldabv, oldbcv, oldcav;
12997 triface badcasing, cbdcasing, acdcasing;
12998 face badsh, cbdsh, acdsh;
12999
13000 abcv = *splittet;
13001 adjustedgering(abcv, CCW);
13002 fnext(abcv, oldabv);
13003 fnext(oldabv, badv);
13004 esymself(badv);
13005 enextfnext(abcv, oldbcv);
13006 fnext(oldbcv, cbdv);
13007 esymself(cbdv);
13008 enext2fnext(abcv, oldcav);
13009 fnext(oldcav, acdv);
13010 esymself(acdv);
13011
13012 if (b->verbose > 1) {
13013 printf(" Removing point %d in tetrahedron (%d, %d, %d, %d).\n",
13014 pointmark(oppo(abcv)), pointmark(org(abcv)), pointmark(dest(abcv)),
13015 pointmark(apex(abcv)), pointmark(apex(badv)));
13016 }
13017
13018 sym(badv, badcasing);
13019 tspivot(badv, badsh);
13020 sym(cbdv, cbdcasing);
13021 tspivot(cbdv, cbdsh);
13022 sym(acdv, acdcasing);
13023 tspivot(acdv, acdsh);
13024
13025
13026 setoppo(abcv, apex(badv));
13027 bond(oldabv, badcasing);
13028 if (badsh.sh != dummysh) {
13029 tsbond(oldabv, badsh);
13030 }
13031 bond(oldbcv, cbdcasing);
13032 if (cbdsh.sh != dummysh) {
13033 tsbond(oldbcv, cbdsh);
13034 }
13035 bond(oldcav, acdcasing);
13036 if (acdsh.sh != dummysh) {
13037 tsbond(oldcav, acdsh);
13038 }
13039
13040
13041 tetrahedrondealloc(badv.tet);
13042 tetrahedrondealloc(cbdv.tet);
13043 tetrahedrondealloc(acdv.tet);
13044 }
13045
13047
13048
13049
13050
13051
13052
13053
13054
13055
13056
13057
13058
13059
13060
13061
13062
13063
13064
13066
13067 void tetgenmesh::splittetface(point newpoint, triface* splittet,
13068 queue* flipqueue)
13069 {
13070 triface abcd, bace;
13071 triface oldbcd, oldcad, oldace, oldcbe;
13072 triface bcdcasing, cadcasing, acecasing, cbecasing;
13073 face abcsh, bcdsh, cadsh, acesh, cbesh;
13074 triface abvd, bcvd, cavd, bave, cbve, acve;
13075 triface worktet;
13076 face bcseg, caseg;
13077 face adseg, bdseg, cdseg;
13078 face aeseg, beseg, ceseg;
13079 point pa, pb, pc, pd, pe;
13080 REAL attrib, volume;
13081 bool mirrorflag;
13082 int i;
13083
13084 abcd = *splittet;
13085
13086 adjustedgering(abcd, CCW);
13087 pa = org(abcd);
13088 pb = dest(abcd);
13089 pc = apex(abcd);
13090 pd = oppo(abcd);
13091 pe = (point) NULL;
13092
13093 mirrorflag = issymexist(&abcd);
13094 if (mirrorflag) {
13095
13096 sym(abcd, bace);
13097 findedge(&bace, dest(abcd), org(abcd));
13098 pe = oppo(bace);
13099 }
13100 if (checksubfaces) {
13101
13102 tspivot(abcd, abcsh);
13103 if (abcsh.sh != dummysh) {
13104
13105 findedge(&abcsh, org(abcd), dest(abcd));
13106 }
13107 }
13108
13109 if (b->verbose > 1) {
13110 printf(" Inserting point %d on face (%d, %d, %d).\n", pointmark(newpoint),
13111 pointmark(pa), pointmark(pb), pointmark(pc));
13112 }
13113
13114
13115 enextfnext(abcd, oldbcd);
13116 enext2fnext(abcd, oldcad);
13117 sym(oldbcd, bcdcasing);
13118 sym(oldcad, cadcasing);
13119
13120 maketetrahedron(&bcvd);
13121 maketetrahedron(&cavd);
13122 if (mirrorflag) {
13123
13124 enextfnext(bace, oldace);
13125 enext2fnext(bace, oldcbe);
13126 sym(oldace, acecasing);
13127 sym(oldcbe, cbecasing);
13128
13129 maketetrahedron(&acve);
13130 maketetrahedron(&cbve);
13131 } else {
13132
13133 hullsize += 2;
13134 }
13135
13136
13137 abvd = abcd;
13138 setapex(abvd, newpoint);
13139 setorg (bcvd, pb);
13140 setdest(bcvd, pc);
13141 setapex(bcvd, newpoint);
13142 setoppo(bcvd, pd);
13143 setorg (cavd, pc);
13144 setdest(cavd, pa);
13145 setapex(cavd, newpoint);
13146 setoppo(cavd, pd);
13147
13148 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13149 attrib = elemattribute(abvd.tet, i);
13150 setelemattribute(bcvd.tet, i, attrib);
13151 setelemattribute(cavd.tet, i, attrib);
13152 }
13153 if (b->varvolume) {
13154
13155 volume = volumebound(abvd.tet);
13156 setvolumebound(bcvd.tet, volume);
13157 setvolumebound(cavd.tet, volume);
13158 }
13159 if (mirrorflag) {
13160 bave = bace;
13161 setapex(bave, newpoint);
13162 setorg (acve, pa);
13163 setdest(acve, pc);
13164 setapex(acve, newpoint);
13165 setoppo(acve, pe);
13166 setorg (cbve, pc);
13167 setdest(cbve, pb);
13168 setapex(cbve, newpoint);
13169 setoppo(cbve, pe);
13170
13171 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13172 attrib = elemattribute(bave.tet, i);
13173 setelemattribute(acve.tet, i, attrib);
13174 setelemattribute(cbve.tet, i, attrib);
13175 }
13176 if (b->varvolume) {
13177
13178 volume = volumebound(bave.tet);
13179 setvolumebound(acve.tet, volume);
13180 setvolumebound(cbve.tet, volume);
13181 }
13182 }
13183
13184
13185 bcvd.loc = 1;
13186 bond(bcvd, bcdcasing);
13187 cavd.loc = 1;
13188 bond(cavd, cadcasing);
13189 bcvd.loc = 3;
13190 bond(bcvd, oldbcd);
13191 cavd.loc = 2;
13192 bond(cavd, oldcad);
13193 bcvd.loc = 2;
13194 cavd.loc = 3;
13195 bond(bcvd, cavd);
13196 if (mirrorflag) {
13197 acve.loc = 1;
13198 bond(acve, acecasing);
13199 cbve.loc = 1;
13200 bond(cbve, cbecasing);
13201 acve.loc = 3;
13202 bond(acve, oldace);
13203 cbve.loc = 2;
13204 bond(cbve, oldcbe);
13205 acve.loc = 2;
13206 cbve.loc = 3;
13207 bond(acve, cbve);
13208
13209 bcvd.loc = 0;
13210 cbve.loc = 0;
13211 bond(bcvd, cbve);
13212 cavd.loc = 0;
13213 acve.loc = 0;
13214 bond(cavd, acve);
13215 }
13216
13217
13218 if (checksubfaces) {
13219 tspivot(oldbcd, bcdsh);
13220 if (bcdsh.sh != dummysh) {
13221 tsdissolve(oldbcd);
13222 bcvd.loc = 1;
13223 tsbond(bcvd, bcdsh);
13224 }
13225 tspivot(oldcad, cadsh);
13226 if (cadsh.sh != dummysh) {
13227 tsdissolve(oldcad);
13228 cavd.loc = 1;
13229 tsbond(cavd, cadsh);
13230 }
13231 if (mirrorflag) {
13232 tspivot(oldace, acesh);
13233 if (acesh.sh != dummysh) {
13234 tsdissolve(oldace);
13235 acve.loc = 1;
13236 tsbond(acve, acesh);
13237 }
13238 tspivot(oldcbe, cbesh);
13239 if (cbesh.sh != dummysh) {
13240 tsdissolve(oldcbe);
13241 cbve.loc = 1;
13242 tsbond(cbve, cbesh);
13243 }
13244 }
13245
13246 if (abcsh.sh != dummysh) {
13247
13248 splitsubface(newpoint, &abcsh, (queue *) NULL);
13249 }
13250 } else if (checksubsegs) {
13251
13252 bcvd.loc = bcvd.ver = 0;
13253 cavd.loc = cavd.ver = 0;
13254 if (mirrorflag) {
13255
13256 cbve.loc = cbve.ver = 0;
13257 acve.loc = acve.ver = 0;
13258 }
13259 enext(abvd, worktet);
13260 tsspivot1(worktet, bcseg);
13261 if (bcseg.sh != dummysh) {
13262 tssdissolve1(worktet);
13263 tssbond1(bcvd, bcseg);
13264 if (mirrorflag) {
13265 enext2(bave, worktet);
13266 tssdissolve1(worktet);
13267 tssbond1(cbve, bcseg);
13268 }
13269 }
13270 enext2(abvd, worktet);
13271 tsspivot1(worktet, caseg);
13272 if (caseg.sh != dummysh) {
13273 tssdissolve1(worktet);
13274 tssbond1(cavd, caseg);
13275 if (mirrorflag) {
13276 enext(bave, worktet);
13277 tssdissolve1(worktet);
13278 tssbond1(acve, caseg);
13279 }
13280 }
13281 fnext(abvd, worktet);
13282 enext2self(worktet);
13283 tsspivot1(worktet, adseg);
13284 if (adseg.sh != dummysh) {
13285 fnext(cavd, worktet);
13286 enextself(worktet);
13287 tssbond1(worktet, adseg);
13288 }
13289 fnext(abvd, worktet);
13290 enextself(worktet);
13291 tsspivot1(worktet, bdseg);
13292 if (bdseg.sh != dummysh) {
13293 fnext(bcvd, worktet);
13294 enext2self(worktet);
13295 tssbond1(worktet, bdseg);
13296 }
13297 enextfnext(abvd, worktet);
13298 enextself(worktet);
13299 tsspivot1(worktet, cdseg);
13300 if (cdseg.sh != dummysh) {
13301 tssdissolve1(worktet);
13302 fnext(bcvd, worktet);
13303 enextself(worktet);
13304 tssbond1(worktet, cdseg);
13305 fnext(cavd, worktet);
13306 enext2self(worktet);
13307 tssbond1(worktet, cdseg);
13308 }
13309 if (mirrorflag) {
13310 fnext(bave, worktet);
13311 enextself(worktet);
13312 tsspivot1(worktet, aeseg);
13313 if (aeseg.sh != dummysh) {
13314 fnext(acve, worktet);
13315 enext2self(worktet);
13316 tssbond1(worktet, aeseg);
13317 }
13318 fnext(bave, worktet);
13319 enext2self(worktet);
13320 tsspivot1(worktet, beseg);
13321 if (beseg.sh != dummysh) {
13322 fnext(cbve, worktet);
13323 enextself(worktet);
13324 tssbond1(worktet, beseg);
13325 }
13326 enextfnext(bave, worktet);
13327 enextself(worktet);
13328 tsspivot1(worktet, ceseg);
13329 if (ceseg.sh != dummysh) {
13330 tssdissolve1(worktet);
13331 fnext(cbve, worktet);
13332 enext2self(worktet);
13333 tssbond1(worktet, ceseg);
13334 fnext(acve, worktet);
13335 enextself(worktet);
13336 tssbond1(worktet, ceseg);
13337 }
13338 }
13339 }
13340
13341
13342 recenttet = abvd;
13343
13344 *splittet = abvd;
13345
13346 bcvd.loc = 0;
13347 cavd.loc = 0;
13348 if (mirrorflag) {
13349 cbve.loc = 0;
13350 acve.loc = 0;
13351 }
13352 if (b->verbose > 3) {
13353 printf(" Updating abvd ");
13354 printtet(&abvd);
13355 printf(" Creating bcvd ");
13356 printtet(&bcvd);
13357 printf(" Creating cavd ");
13358 printtet(&cavd);
13359 if (mirrorflag) {
13360 printf(" Updating bave ");
13361 printtet(&bave);
13362 printf(" Creating cbve ");
13363 printtet(&cbve);
13364 printf(" Creating acve ");
13365 printtet(&acve);
13366 }
13367 }
13368
13369 if (flipqueue != (queue *) NULL) {
13370 fnextself(abvd);
13371 enqueueflipface(abvd, flipqueue);
13372 fnextself(bcvd);
13373 enqueueflipface(bcvd, flipqueue);
13374 fnextself(cavd);
13375 enqueueflipface(cavd, flipqueue);
13376 if (mirrorflag) {
13377 fnextself(bave);
13378 enqueueflipface(bave, flipqueue);
13379 fnextself(cbve);
13380 enqueueflipface(cbve, flipqueue);
13381 fnextself(acve);
13382 enqueueflipface(acve, flipqueue);
13383 }
13384 }
13385 }
13386
13388
13389
13390
13391
13392
13393
13394
13395
13396
13397
13398
13399
13400
13401
13402
13403
13405
13406 void tetgenmesh::unsplittetface(triface* splittet)
13407 {
13408 triface abvd, bcvd, cavd, bave, cbve, acve;
13409 triface oldbvd, oldvad, oldvbe, oldave;
13410 triface bcdcasing, cadcasing, cbecasing, acecasing;
13411 face bcdsh, cadsh, cbesh, acesh;
13412 face abvsh;
13413 bool mirrorflag;
13414
13415 abvd = *splittet;
13416 adjustedgering(abvd, CCW);
13417 enextfnext(abvd, oldbvd);
13418 fnext(oldbvd, bcvd);
13419 esymself(bcvd);
13420 enextself(bcvd);
13421 enext2fnext(abvd, oldvad);
13422 fnext(oldvad, cavd);
13423 esymself(cavd);
13424 enext2self(cavd);
13425
13426 sym(abvd, bave);
13427 mirrorflag = bave.tet != dummytet;
13428 if (mirrorflag) {
13429 findedge(&bave, dest(abvd), org(abvd));
13430 enextfnext(bave, oldave);
13431 fnext(oldave, acve);
13432 esymself(acve);
13433 enextself(acve);
13434 enext2fnext(bave, oldvbe);
13435 fnext(oldvbe, cbve);
13436 esymself(cbve);
13437 enext2self(cbve);
13438 } else {
13439
13440 hullsize -= 2;
13441 }
13442
13443 tspivot(abvd, abvsh);
13444 if (abvsh.sh != dummysh) {
13445
13446 findedge(&abvsh, org(abvd), dest(abvd));
13447 }
13448
13449 if (b->verbose > 1) {
13450 printf(" Removing point %d on face (%d, %d, %d).\n",
13451 pointmark(apex(abvd)), pointmark(org(abvd)), pointmark(dest(abvd)),
13452 pointmark(dest(bcvd)));
13453 }
13454
13455 fnextself(bcvd);
13456 sym(bcvd, bcdcasing);
13457 tspivot(bcvd, bcdsh);
13458 fnextself(cavd);
13459 sym(cavd, cadcasing);
13460 tspivot(cavd, cadsh);
13461 if (mirrorflag) {
13462 fnextself(acve);
13463 sym(acve, acecasing);
13464 tspivot(acve, acesh);
13465 fnextself(cbve);
13466 sym(cbve, cbecasing);
13467 tspivot(cbve, cbesh);
13468 }
13469
13470
13471 setapex(abvd, dest(bcvd));
13472 bond(oldbvd, bcdcasing);
13473 if (bcdsh.sh != dummysh) {
13474 tsbond(oldbvd, bcdsh);
13475 }
13476 bond(oldvad, cadcasing);
13477 if (cadsh.sh != dummysh) {
13478 tsbond(oldvad, cadsh);
13479 }
13480 if (mirrorflag) {
13481
13482 setapex(bave, dest(acve));
13483 bond(oldave, acecasing);
13484 if (acesh.sh != dummysh) {
13485 tsbond(oldave, acesh);
13486 }
13487 bond(oldvbe, cbecasing);
13488 if (cbesh.sh != dummysh) {
13489 tsbond(oldvbe, cbesh);
13490 }
13491 }
13492
13493
13494 if (abvsh.sh != dummysh) {
13495 unsplitsubface(&abvsh);
13496 }
13497
13498
13499 tetrahedrondealloc(bcvd.tet);
13500 tetrahedrondealloc(cavd.tet);
13501 if (mirrorflag) {
13502 tetrahedrondealloc(acve.tet);
13503 tetrahedrondealloc(cbve.tet);
13504 }
13505 }
13506
13508
13509
13510
13511
13512
13513
13514
13515
13516
13517
13518
13519
13520
13521
13522
13523
13524
13525
13526
13527
13528
13530
13531 void tetgenmesh::splitsubface(point newpoint, face* splitface,
13532 queue* flipqueue)
13533 {
13534 triface abvd, bcvd, cavd, bave, cbve, acve;
13535 face abc, oldbc, oldca, bc, ca, spinsh;
13536 face bccasin, bccasout, cacasin, cacasout;
13537 face abv, bcv, cav;
13538 point pa, pb, pc;
13539
13540 abc = *splitface;
13541
13542 adjustedgering(abc, CCW);
13543 pa = sorg(abc);
13544 pb = sdest(abc);
13545 pc = sapex(abc);
13546
13547 if (b->verbose > 1) {
13548 printf(" Inserting point %d on subface (%d, %d, %d).\n",
13549 pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc));
13550 }
13551
13552
13553
13554 senext(abc, oldbc);
13555 senext2(abc, oldca);
13556 spivot(oldbc, bccasout);
13557 sspivot(oldbc, bc);
13558 if (bc.sh != dummysh) {
13559 if (oldbc.sh != bccasout.sh) {
13560
13561 spinsh = bccasout;
13562 do {
13563 bccasin = spinsh;
13564 spivotself(spinsh);
13565 } while (spinsh.sh != oldbc.sh);
13566 } else {
13567 bccasout.sh = dummysh;
13568 }
13569 ssdissolve(oldbc);
13570 }
13571 spivot(oldca, cacasout);
13572 sspivot(oldca, ca);
13573 if (ca.sh != dummysh) {
13574 if (oldca.sh != cacasout.sh) {
13575
13576 spinsh = cacasout;
13577 do {
13578 cacasin = spinsh;
13579 spivotself(spinsh);
13580 } while (spinsh.sh != oldca.sh);
13581 } else {
13582 cacasout.sh = dummysh;
13583 }
13584 ssdissolve(oldca);
13585 }
13586
13587 makeshellface(subfaces, &bcv);
13588 makeshellface(subfaces, &cav);
13589
13590
13591 abv = abc;
13592 setsapex(abv, newpoint);
13593 setsorg(bcv, pb);
13594 setsdest(bcv, pc);
13595 setsapex(bcv, newpoint);
13596 setsorg(cav, pc);
13597 setsdest(cav, pa);
13598 setsapex(cav, newpoint);
13599 if (b->quality && varconstraint) {
13600
13601 setareabound(bcv, areabound(abv));
13602 setareabound(cav, areabound(abv));
13603 }
13604
13605 setshellmark(bcv, shellmark(abv));
13606 setshellmark(cav, shellmark(abv));
13607
13608 setshelltype(bcv, shelltype(abv));
13609 setshelltype(cav, shelltype(abv));
13610 if (checkpbcs) {
13611
13612 setshellpbcgroup(bcv, shellpbcgroup(abv));
13613 setshellpbcgroup(cav, shellpbcgroup(abv));
13614 }
13615
13616 if (bc.sh != dummysh) {
13617 if (bccasout.sh != dummysh) {
13618 sbond1(bccasin, bcv);
13619 sbond1(bcv, bccasout);
13620 } else {
13621
13622 sbond(bcv, bcv);
13623 }
13624 ssbond(bcv, bc);
13625 } else {
13626 sbond(bcv, bccasout);
13627 }
13628 if (ca.sh != dummysh) {
13629 if (cacasout.sh != dummysh) {
13630 sbond1(cacasin, cav);
13631 sbond1(cav, cacasout);
13632 } else {
13633
13634 sbond(cav, cav);
13635 }
13636 ssbond(cav, ca);
13637 } else {
13638 sbond(cav, cacasout);
13639 }
13640 senext2self(bcv);
13641 sbond(bcv, oldbc);
13642 senextself(cav);
13643 sbond(cav, oldca);
13644 senext2self(bcv);
13645 senextself(cav);
13646 sbond(bcv, cav);
13647
13648
13649 stpivot(abv, abvd);
13650 if (abvd.tet != dummytet) {
13651
13652 findedge(&abvd, sorg(abv), sdest(abv));
13653 enextfnext(abvd, bcvd);
13654 #ifdef SELF_CHECK
13655 assert(bcvd.tet != dummytet);
13656 #endif
13657 fnextself(bcvd);
13658 enext2fnext(abvd, cavd);
13659 #ifdef SELF_CHECK
13660 assert(cavd.tet != dummytet);
13661 #endif
13662 fnextself(cavd);
13663
13664 tsbond(bcvd, bcv);
13665 tsbond(cavd, cav);
13666 }
13667
13668 sesymself(abv);
13669 stpivot(abv, bave);
13670 if (bave.tet != dummytet) {
13671 sesymself(bcv);
13672 sesymself(cav);
13673
13674 findedge(&bave, sorg(abv), sdest(abv));
13675 enextfnext(bave, acve);
13676 #ifdef SELF_CHECK
13677 assert(acve.tet != dummytet);
13678 #endif
13679 fnextself(acve);
13680 enext2fnext(bave, cbve);
13681 #ifdef SELF_CHECK
13682 assert(cbve.tet != dummytet);
13683 #endif
13684 fnextself(cbve);
13685
13686 tsbond(acve, cav);
13687 tsbond(cbve, bcv);
13688 }
13689
13690 bcv.shver = 0;
13691 cav.shver = 0;
13692 if (b->verbose > 3) {
13693 printf(" Updating abv ");
13694 printsh(&abv);
13695 printf(" Creating bcv ");
13696 printsh(&bcv);
13697 printf(" Creating cav ");
13698 printsh(&cav);
13699 }
13700
13701 if (flipqueue != (queue *) NULL) {
13702 enqueueflipedge(abv, flipqueue);
13703 enqueueflipedge(bcv, flipqueue);
13704 enqueueflipedge(cav, flipqueue);
13705 }
13706
13707
13708 *splitface = abv;
13709 }
13710
13712
13713
13714
13715
13716
13717
13718
13719
13720
13721
13722
13723
13725
13726 void tetgenmesh::unsplitsubface(face* splitsh)
13727 {
13728 face abv, bcv, cav;
13729 face oldbv, oldva, bc, ca, spinsh;
13730 face bccasin, bccasout, cacasin, cacasout;
13731
13732 abv = *splitsh;
13733 senext(abv, oldbv);
13734 spivot(oldbv, bcv);
13735 if (sorg(bcv) != sdest(oldbv)) {
13736 sesymself(bcv);
13737 }
13738 senextself(bcv);
13739 senext2(abv, oldva);
13740 spivot(oldva, cav);
13741 if (sorg(cav) != sdest(oldva)) {
13742 sesymself(cav);
13743 }
13744 senext2self(cav);
13745
13746 if (b->verbose > 1) {
13747 printf(" Removing point %d on subface (%d, %d, %d).\n",
13748 pointmark(sapex(abv)), pointmark(sorg(abv)), pointmark(sdest(abv)),
13749 pointmark(sdest(bcv)));
13750 }
13751
13752 spivot(bcv, bccasout);
13753 sspivot(bcv, bc);
13754 if (bc.sh != dummysh) {
13755 if (bcv.sh != bccasout.sh) {
13756
13757 spinsh = bccasout;
13758 do {
13759 bccasin = spinsh;
13760 spivotself(spinsh);
13761 } while (spinsh.sh != bcv.sh);
13762 } else {
13763 bccasout.sh = dummysh;
13764 }
13765 }
13766 spivot(cav, cacasout);
13767 sspivot(cav, ca);
13768 if (ca.sh != dummysh) {
13769 if (cav.sh != cacasout.sh) {
13770
13771 spinsh = cacasout;
13772 do {
13773 cacasin = spinsh;
13774 spivotself(spinsh);
13775 } while (spinsh.sh != cav.sh);
13776 } else {
13777 cacasout.sh = dummysh;
13778 }
13779 }
13780
13781
13782 setsapex(abv, sdest(bcv));
13783 if (bc.sh != dummysh) {
13784 if (bccasout.sh != dummysh) {
13785 sbond1(bccasin, oldbv);
13786 sbond1(oldbv, bccasout);
13787 } else {
13788
13789 sbond(oldbv, oldbv);
13790 }
13791 ssbond(oldbv, bc);
13792 } else {
13793 sbond(oldbv, bccasout);
13794 }
13795 if (ca.sh != dummysh) {
13796 if (cacasout.sh != dummysh) {
13797 sbond1(cacasin, oldva);
13798 sbond1(oldva, cacasout);
13799 } else {
13800
13801 sbond(oldva, oldva);
13802 }
13803 ssbond(oldva, ca);
13804 } else {
13805 sbond(oldva, cacasout);
13806 }
13807
13808
13809 shellfacedealloc(subfaces, bcv.sh);
13810 shellfacedealloc(subfaces, cav.sh);
13811 }
13812
13814
13815
13816
13817
13818
13819
13820
13821
13822
13823
13824
13825
13826
13827
13828
13829
13830
13831
13832
13833
13834
13836
13837 void tetgenmesh::splittetedge(point newpoint, triface* splittet,
13838 queue* flipqueue)
13839 {
13840 triface *bots, *newtops;
13841 triface oldtop, topcasing;
13842 triface spintet, tmpbond0, tmpbond1;
13843 face abseg, splitsh, topsh, spinsh;
13844 triface worktet;
13845 face n1n2seg, n2vseg, n1vseg;
13846 point pa, pb, n1, n2;
13847 REAL attrib, volume;
13848 int wrapcount, hitbdry;
13849 int i, j;
13850
13851 if (checksubfaces) {
13852
13853 tsspivot(splittet, &abseg);
13854 if (abseg.sh != dummysh) {
13855 abseg.shver = 0;
13856
13857 if (org(*splittet) != sorg(abseg)) {
13858 esymself(*splittet);
13859 }
13860 }
13861 }
13862 spintet = *splittet;
13863 pa = org(spintet);
13864 pb = dest(spintet);
13865
13866 if (b->verbose > 1) {
13867 printf(" Inserting point %d on edge (%d, %d).\n",
13868 pointmark(newpoint), pointmark(pa), pointmark(pb));
13869 }
13870
13871
13872 n1 = apex(spintet);
13873 hitbdry = 0;
13874 wrapcount = 1;
13875 if (checksubfaces && abseg.sh != dummysh) {
13876
13877
13878
13879 while (true) {
13880 if (!fnextself(spintet)) {
13881
13882 hitbdry ++;
13883 tspivot(spintet, spinsh);
13884 #ifdef SELF_CHECK
13885 assert(spinsh.sh != dummysh);
13886 #endif
13887 findedge(&spinsh, pa, pb);
13888 sfnextself(spinsh);
13889 stpivot(spinsh, spintet);
13890 #ifdef SELF_CHECK
13891 assert(spintet.tet != dummytet);
13892 #endif
13893 findedge(&spintet, pa, pb);
13894
13895 *splittet = spintet;
13896
13897 hullsize += 2;
13898 }
13899 if (apex(spintet) == n1) break;
13900 wrapcount ++;
13901 }
13902 if (hitbdry > 0) {
13903 wrapcount -= hitbdry;
13904 }
13905 } else {
13906
13907
13908 splitsh.sh = dummysh;
13909 while (hitbdry < 2) {
13910 if (checksubfaces && splitsh.sh == dummysh) {
13911 tspivot(spintet, splitsh);
13912 }
13913 if (fnextself(spintet)) {
13914 if (apex(spintet) == n1) break;
13915 wrapcount++;
13916 } else {
13917 hitbdry ++;
13918 if (hitbdry < 2) {
13919 esym(*splittet, spintet);
13920 }
13921 }
13922 }
13923 if (hitbdry > 0) {
13924
13925 wrapcount -= 1;
13926
13927 esym(spintet, *splittet);
13928
13929 hullsize += 2;
13930 }
13931 }
13932
13933
13934 bots = new triface[wrapcount];
13935 newtops = new triface[wrapcount];
13936
13937 spintet = *splittet;
13938 for (i = 0; i < wrapcount; i++) {
13939
13940 enext2fnext(spintet, bots[i]);
13941 esymself(bots[i]);
13942
13943 maketetrahedron(&(newtops[i]));
13944
13945 fnextself(spintet);
13946 if (checksubfaces && abseg.sh != dummysh) {
13947 if (!issymexist(&spintet)) {
13948
13949 tspivot(spintet, spinsh);
13950 #ifdef SELF_CHECK
13951 assert(spinsh.sh != dummysh);
13952 #endif
13953 findedge(&spinsh, pa, pb);
13954 sfnextself(spinsh);
13955 stpivot(spinsh, spintet);
13956 #ifdef SELF_CHECK
13957 assert(spintet.tet != dummytet);
13958 #endif
13959 findedge(&spintet, pa, pb);
13960 }
13961 }
13962 }
13963
13964
13965 for (i = 0; i < wrapcount; i++) {
13966
13967 setoppo(bots[i], newpoint);
13968
13969 n1 = dest(bots[i]);
13970 n2 = apex(bots[i]);
13971
13972 setorg(newtops[i], pb);
13973 setdest(newtops[i], n2);
13974 setapex(newtops[i], n1);
13975 setoppo(newtops[i], newpoint);
13976
13977 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
13978 attrib = elemattribute(bots[i].tet, j);
13979 setelemattribute(newtops[i].tet, j, attrib);
13980 }
13981 if (b->varvolume) {
13982
13983 volume = volumebound(bots[i].tet);
13984 setvolumebound(newtops[i].tet, volume);
13985 }
13986 #ifdef SELF_CHECK
13987
13988
13989
13990
13991
13992
13993
13994
13995
13996 #endif
13997 }
13998
13999
14000 for (i = 0; i < wrapcount; i++) {
14001
14002 enextfnext(bots[i], oldtop);
14003 sym(oldtop, topcasing);
14004 bond(newtops[i], topcasing);
14005 if (checksubfaces) {
14006 tspivot(oldtop, topsh);
14007 if (topsh.sh != dummysh) {
14008 tsdissolve(oldtop);
14009 tsbond(newtops[i], topsh);
14010 }
14011 }
14012 enextfnext(newtops[i], tmpbond0);
14013 bond(oldtop, tmpbond0);
14014 }
14015
14016 fnext(newtops[0], tmpbond0);
14017 enext2fnext(bots[0], spintet);
14018 for (i = 1; i < wrapcount; i ++) {
14019 if (issymexist(&spintet)) {
14020 enext2fnext(newtops[i], tmpbond1);
14021 bond(tmpbond0, tmpbond1);
14022 }
14023 fnext(newtops[i], tmpbond0);
14024 enext2fnext(bots[i], spintet);
14025 }
14026
14027 if (issymexist(&spintet)) {
14028 enext2fnext(newtops[0], tmpbond1);
14029 bond(tmpbond0, tmpbond1);
14030 }
14031 if (checksubsegs) {
14032 for (i = 0; i < wrapcount; i++) {
14033 enextfnext(bots[i], worktet);
14034 tsspivot1(worktet, n1n2seg);
14035 if (n1n2seg.sh != dummysh) {
14036 enext(newtops[i], tmpbond0);
14037 tssbond1(tmpbond0, n1n2seg);
14038 }
14039 enextself(worktet);
14040 tsspivot1(worktet, n2vseg);
14041 if (n2vseg.sh != dummysh) {
14042 tssdissolve1(worktet);
14043 tssbond1(newtops[i], n2vseg);
14044 }
14045 enextself(worktet);
14046 tsspivot1(worktet, n1vseg);
14047 if (n1vseg.sh != dummysh) {
14048 tssdissolve1(worktet);
14049 enext2(newtops[i], tmpbond0);
14050 tssbond1(tmpbond0, n1vseg);
14051 }
14052 }
14053 }
14054
14055
14056 if (checksubfaces) {
14057 if (abseg.sh != dummysh) {
14058
14059 spivot(abseg, splitsh);
14060 #ifdef SELF_CHECK
14061 assert(splitsh.sh != dummysh);
14062 #endif
14063 }
14064 if (splitsh.sh != dummysh) {
14065
14066 findedge(&splitsh, pa, pb);
14067 splitsubedge(newpoint, &splitsh, (queue *) NULL);
14068 }
14069 }
14070
14071 if (b->verbose > 3) {
14072 for (i = 0; i < wrapcount; i++) {
14073 printf(" Updating bots[%i] ", i);
14074 printtet(&(bots[i]));
14075 printf(" Creating newtops[%i] ", i);
14076 printtet(&(newtops[i]));
14077 }
14078 }
14079
14080 if (flipqueue != (queue *) NULL) {
14081 for (i = 0; i < wrapcount; i++) {
14082 enqueueflipface(bots[i], flipqueue);
14083 enqueueflipface(newtops[i], flipqueue);
14084 }
14085 }
14086
14087
14088
14089 fnext(bots[0], spintet);
14090 esymself(spintet);
14091 enextself(spintet);
14092 *splittet = spintet;
14093
14094 delete [] bots;
14095 delete [] newtops;
14096 }
14097
14099
14100
14101
14102
14103
14104
14105
14106
14107
14108
14109
14110
14111
14112
14113
14115
14116 void tetgenmesh::unsplittetedge(triface* splittet)
14117 {
14118 triface *bots, *newtops;
14119 triface oldtop, topcasing;
14120 triface spintet;
14121 face avseg, splitsh, topsh, spinsh;
14122 point pa, pv, n1;
14123 int wrapcount, hitbdry;
14124 int i;
14125
14126 spintet = *splittet;
14127 pa = org(spintet);
14128 pv = dest(spintet);
14129 if (checksubfaces) {
14130
14131 tsspivot(splittet, &avseg);
14132 if (avseg.sh != dummysh) {
14133
14134 if (sorg(avseg) != pa) {
14135 sesymself(avseg);
14136 }
14137 }
14138 }
14139
14140 n1 = apex(spintet);
14141 hitbdry = 0;
14142 wrapcount = 1;
14143 if (checksubfaces && avseg.sh != dummysh) {
14144
14145
14146
14147 while (true) {
14148 if (!fnextself(spintet)) {
14149
14150 hitbdry ++;
14151 tspivot(spintet, spinsh);
14152 #ifdef SELF_CHECK
14153 assert(spinsh.sh != dummysh);
14154 #endif
14155 findedge(&spinsh, pa, pv);
14156 sfnextself(spinsh);
14157 stpivot(spinsh, spintet);
14158 #ifdef SELF_CHECK
14159 assert(spintet.tet != dummytet);
14160 #endif
14161 findedge(&spintet, pa, pv);
14162
14163 *splittet = spintet;
14164
14165 hullsize += 2;
14166 }
14167 if (apex(spintet) == n1) break;
14168 wrapcount ++;
14169 }
14170 if (hitbdry > 0) {
14171 wrapcount -= hitbdry;
14172 }
14173 } else {
14174
14175
14176 splitsh.sh = dummysh;
14177 while (hitbdry < 2) {
14178 if (checksubfaces && splitsh.sh == dummysh) {
14179 tspivot(spintet, splitsh);
14180 }
14181 if (fnextself(spintet)) {
14182 if (apex(spintet) == n1) break;
14183 wrapcount++;
14184 } else {
14185 hitbdry ++;
14186 if (hitbdry < 2) {
14187 esym(*splittet, spintet);
14188 }
14189 }
14190 }
14191 if (hitbdry > 0) {
14192
14193 wrapcount -= 1;
14194
14195 esym(spintet, *splittet);
14196
14197 hullsize += 2;
14198 }
14199 }
14200
14201
14202 bots = new triface[wrapcount];
14203 newtops = new triface[wrapcount];
14204
14205 spintet = *splittet;
14206 for (i = 0; i < wrapcount; i++) {
14207
14208 enext2fnext(spintet, bots[i]);
14209 esymself(bots[i]);
14210
14211 enextfnext(bots[i], oldtop);
14212
14213 fnext(oldtop, newtops[i]);
14214 esymself(newtops[i]);
14215 enext2self(newtops[i]);
14216
14217 fnextself(spintet);
14218 if (checksubfaces && avseg.sh != dummysh) {
14219 if (!issymexist(&spintet)) {
14220
14221 tspivot(spintet, spinsh);
14222 #ifdef SELF_CHECK
14223 assert(spinsh.sh != dummysh);
14224 #endif
14225 findedge(&spinsh, pa, pv);
14226 sfnextself(spinsh);
14227 stpivot(spinsh, spintet);
14228 #ifdef SELF_CHECK
14229 assert(spintet.tet != dummytet);
14230 #endif
14231 findedge(&spintet, pa, pv);
14232 }
14233 }
14234 }
14235
14236 if (b->verbose > 1) {
14237 printf(" Removing point %d from edge (%d, %d).\n",
14238 pointmark(oppo(bots[0])), pointmark(org(bots[0])),
14239 pointmark(org(newtops[0])));
14240 }
14241
14242 for (i = 0; i < wrapcount; i++) {
14243
14244 setoppo(bots[i], org(newtops[i]));
14245
14246 enextfnext(bots[i], oldtop);
14247
14248 sym(newtops[i], topcasing);
14249
14250 bond(oldtop, topcasing);
14251 if (checksubfaces) {
14252 tspivot(newtops[i], topsh);
14253 if (topsh.sh != dummysh) {
14254 tsbond(oldtop, topsh);
14255 }
14256 }
14257
14258 tetrahedrondealloc(newtops[i].tet);
14259 }
14260
14261
14262 if (checksubfaces) {
14263 if (avseg.sh != dummysh) {
14264 spivot(avseg, splitsh);
14265 #ifdef SELF_CHECK
14266 assert(splitsh.sh != dummysh);
14267 #endif
14268 }
14269 if (splitsh.sh != dummysh) {
14270 findedge(&splitsh, pa, pv);
14271 unsplitsubedge(&splitsh);
14272 }
14273 }
14274
14275 delete [] bots;
14276 delete [] newtops;
14277 }
14278
14280
14281
14282
14283
14284
14285
14286
14287
14288
14289
14290
14291
14292
14293
14294
14295
14296
14297
14298
14299
14301
14302 void tetgenmesh::splitsubedge(point newpoint, face* splitsh, queue* flipqueue)
14303 {
14304 triface abcd, bace, vbcd, bvce;
14305 face startabc, spinabc, spinsh;
14306 face oldbc, bccasin, bccasout;
14307 face ab, bc;
14308 face avc, vbc, vbc1;
14309 face av, vb;
14310 point pa, pb;
14311
14312 startabc = *splitsh;
14313
14314 sspivot(startabc, ab);
14315 if (ab.sh != dummysh) {
14316 ab.shver = 0;
14317 if (sorg(startabc) != sorg(ab)) {
14318 sesymself(startabc);
14319 }
14320 }
14321 pa = sorg(startabc);
14322 pb = sdest(startabc);
14323
14324 if (b->verbose > 1) {
14325 printf(" Inserting point %d on subedge (%d, %d) %s.\n",
14326 pointmark(newpoint), pointmark(pa), pointmark(pb),
14327 (ab.sh != dummysh ? "(seg)" : " "));
14328 }
14329
14330
14331 spinabc = startabc;
14332 do {
14333
14334 if (sorg(spinabc) != pa) {
14335 sesymself(spinabc);
14336 }
14337
14338
14339 senext(spinabc, oldbc);
14340 spivot(oldbc, bccasout);
14341 sspivot(oldbc, bc);
14342 if (bc.sh != dummysh) {
14343 if (spinabc.sh != bccasout.sh) {
14344
14345 spinsh = bccasout;
14346 do {
14347 bccasin = spinsh;
14348 spivotself(spinsh);
14349 } while (spinsh.sh != oldbc.sh);
14350 } else {
14351 bccasout.sh = dummysh;
14352 }
14353 ssdissolve(oldbc);
14354 }
14355
14356 makeshellface(subfaces, &vbc);
14357
14358 avc = spinabc;
14359 setsdest(avc, newpoint);
14360
14361 vbc.shver = avc.shver;
14362 setsorg(vbc, newpoint);
14363 setsdest(vbc, pb);
14364 setsapex(vbc, sapex(avc));
14365 if (b->quality && varconstraint) {
14366
14367 setareabound(vbc, areabound(avc));
14368 }
14369
14370 setshellmark(vbc, shellmark(avc));
14371 setshelltype(vbc, shelltype(avc));
14372 if (checkpbcs) {
14373
14374 setshellpbcgroup(vbc, shellpbcgroup(avc));
14375 }
14376
14377 senext2self(vbc);
14378 sbond(vbc, oldbc);
14379
14380 senext2self(vbc);
14381 if (bc.sh != dummysh) {
14382 if (bccasout.sh != dummysh) {
14383
14384 sbond1(bccasin, vbc);
14385 sbond1(vbc, bccasout);
14386 } else {
14387
14388 sbond(vbc, vbc);
14389 }
14390 ssbond(vbc, bc);
14391 } else {
14392 sbond(vbc, bccasout);
14393 }
14394
14395 spivotself(spinabc);
14396 if (spinabc.sh == dummysh) {
14397 break;
14398 }
14399 } while (spinabc.sh != startabc.sh);
14400
14401
14402 senext(startabc, oldbc);
14403 spivot(oldbc, vbc);
14404 if (sorg(vbc) == newpoint) {
14405 sesymself(vbc);
14406 }
14407 #ifdef SELF_CHECK
14408 assert(sorg(vbc) == sdest(oldbc) && sdest(vbc) == sorg(oldbc));
14409 #endif
14410 senextself(vbc);
14411
14412 spinabc = startabc;
14413 do {
14414
14415 spivotself(spinabc);
14416 if (spinabc.sh == dummysh) {
14417 break;
14418 }
14419 if (sorg(spinabc) != pa) {
14420 sesymself(spinabc);
14421 }
14422
14423 senext(spinabc, oldbc);
14424 spivot(oldbc, vbc1);
14425 if (sorg(vbc1) == newpoint) {
14426 sesymself(vbc1);
14427 }
14428 #ifdef SELF_CHECK
14429 assert(sorg(vbc1) == sdest(oldbc) && sdest(vbc1) == sorg(oldbc));
14430 #endif
14431 senextself(vbc1);
14432
14433 sbond1(vbc, vbc1);
14434
14435 vbc = vbc1;
14436 } while (spinabc.sh != startabc.sh);
14437
14438
14439 if (ab.sh != dummysh) {
14440
14441 av = ab;
14442 setsdest(av, newpoint);
14443
14444 makeshellface(subsegs, &vb);
14445 setsorg(vb, newpoint);
14446 setsdest(vb, pb);
14447
14448 setshellmark(vb, shellmark(av));
14449 setshelltype(vb, shelltype(av));
14450 if (b->quality && varconstraint) {
14451
14452 setareabound(vb, areabound(av));
14453 }
14454
14455 senext(av, oldbc);
14456 spivot(oldbc, bccasout);
14457
14458 senext2(vb, bccasin);
14459 sbond(bccasin, oldbc);
14460 if (bccasout.sh != dummysh) {
14461
14462
14463 bccasout.shver = 0;
14464 if (sorg(bccasout) != pb) sesymself(bccasout);
14465 #ifdef SELF_CHECK
14466 assert(sorg(bccasout) == pb);
14467 #endif
14468 senext2self(bccasout);
14469 senext(vb, bccasin);
14470 sbond(bccasin, bccasout);
14471 }
14472
14473 spinabc = startabc;
14474 do {
14475
14476 if (sorg(spinabc) != pa) {
14477 sesymself(spinabc);
14478 }
14479
14480 senext(spinabc, oldbc);
14481 spivot(oldbc, vbc);
14482 if (sorg(vbc) == newpoint) {
14483 sesymself(vbc);
14484 }
14485 senextself(vbc);
14486
14487 ssbond(vbc, vb);
14488
14489 spivotself(spinabc);
14490 #ifdef SELF_CHECK
14491 assert(spinabc.sh != dummysh);
14492 #endif
14493 } while (spinabc.sh != startabc.sh);
14494 }
14495
14496
14497
14498 spinabc = startabc;
14499 do {
14500
14501 if (sorg(spinabc) != pa) {
14502 sesymself(spinabc);
14503 }
14504
14505 senext(spinabc, oldbc);
14506 spivot(oldbc, vbc);
14507 if (sorg(vbc) == newpoint) {
14508 sesymself(vbc);
14509 }
14510 senextself(vbc);
14511
14512 stpivot(spinabc, abcd);
14513 if (abcd.tet != dummytet) {
14514 findedge(&abcd, sorg(spinabc), sdest(spinabc));
14515 enextfnext(abcd, vbcd);
14516 fnextself(vbcd);
14517 #ifdef SELF_CHECK
14518 assert(vbcd.tet != dummytet);
14519 #endif
14520 tsbond(vbcd, vbc);
14521 sym(vbcd, bvce);
14522 sesymself(vbc);
14523 tsbond(bvce, vbc);
14524 } else {
14525
14526 sesymself(spinabc);
14527 stpivot(spinabc, bace);
14528 if (bace.tet != dummytet) {
14529 findedge(&bace, sorg(spinabc), sdest(spinabc));
14530 enext2fnext(bace, bvce);
14531 fnextself(bvce);
14532 #ifdef SELF_CHECK
14533 assert(bvce.tet != dummytet);
14534 #endif
14535 sesymself(vbc);
14536 tsbond(bvce, vbc);
14537 }
14538 }
14539
14540 spivotself(spinabc);
14541 if (spinabc.sh == dummysh) {
14542 break;
14543 }
14544 } while (spinabc.sh != startabc.sh);
14545
14546 if (b->verbose > 3) {
14547 spinabc = startabc;
14548 do {
14549
14550 if (sorg(spinabc) != pa) {
14551 sesymself(spinabc);
14552 }
14553 printf(" Updating abc:\n");
14554 printsh(&spinabc);
14555
14556 senext(spinabc, oldbc);
14557 spivot(oldbc, vbc);
14558 if (sorg(vbc) == newpoint) {
14559 sesymself(vbc);
14560 }
14561 senextself(vbc);
14562 printf(" Creating vbc:\n");
14563 printsh(&vbc);
14564
14565 spivotself(spinabc);
14566 if (spinabc.sh == dummysh) {
14567 break;
14568 }
14569 } while (spinabc.sh != startabc.sh);
14570 }
14571
14572 if (flipqueue != (queue *) NULL) {
14573 spinabc = startabc;
14574 do {
14575
14576 if (sorg(spinabc) != pa) {
14577 sesymself(spinabc);
14578 }
14579 senext2(spinabc, oldbc);
14580 enqueueflipedge(oldbc, flipqueue);
14581
14582 senext(spinabc, oldbc);
14583 spivot(oldbc, vbc);
14584 if (sorg(vbc) == newpoint) {
14585 sesymself(vbc);
14586 }
14587 senextself(vbc);
14588 senext(vbc, oldbc);
14589 enqueueflipedge(oldbc, flipqueue);
14590
14591 spivotself(spinabc);
14592 if (spinabc.sh == dummysh) {
14593 break;
14594 }
14595 } while (spinabc.sh != startabc.sh);
14596 }
14597 }
14598
14600
14601
14602
14603
14604
14605
14606
14607
14608
14609
14610
14611
14612
14613
14615
14616 void tetgenmesh::unsplitsubedge(face* splitsh)
14617 {
14618 face startavc, spinavc, spinbcv;
14619 face oldvc, bccasin, bccasout, spinsh;
14620 face av, vb, bc;
14621 point pa, pv, pb;
14622
14623 startavc = *splitsh;
14624 sspivot(startavc, av);
14625 if (av.sh != dummysh) {
14626
14627 if (sorg(av) != sorg(startavc)) {
14628 sesymself(av);
14629 }
14630 #ifdef SELF_CHECK
14631 assert(av.shver == 0);
14632 #endif
14633 }
14634 senext(startavc, oldvc);
14635 spivot(oldvc, vb);
14636 if (sorg(vb) != sdest(oldvc)) {
14637 sesymself(vb);
14638 }
14639 senextself(vb);
14640 pa = sorg(startavc);
14641 pv = sdest(startavc);
14642 pb = sdest(vb);
14643
14644 if (b->verbose > 1) {
14645 printf(" Removing point %d from subedge (%d, %d).\n",
14646 pointmark(pv), pointmark(pa), pointmark(pb));
14647 }
14648
14649
14650 spinavc = startavc;
14651 do {
14652
14653 if (sorg(spinavc) != pa) {
14654 sesymself(spinavc);
14655 }
14656
14657
14658 senext(spinavc, oldvc);
14659 spivot(oldvc, spinbcv);
14660 if (sorg(spinbcv) != sdest(oldvc)) {
14661 sesymself(spinbcv);
14662 }
14663 senext2self(spinbcv);
14664 spivot(spinbcv, bccasout);
14665 sspivot(spinbcv, bc);
14666 if (bc.sh != dummysh) {
14667 if (spinbcv.sh != bccasout.sh) {
14668
14669 spinsh = bccasout;
14670 do {
14671 bccasin = spinsh;
14672 spivotself(spinsh);
14673 } while (spinsh.sh != spinbcv.sh);
14674 } else {
14675 bccasout.sh = dummysh;
14676 }
14677 }
14678
14679 setsdest(spinavc, pb);
14680 if (bc.sh != dummysh) {
14681 if (bccasout.sh != dummysh) {
14682 sbond1(bccasin, oldvc);
14683 sbond1(oldvc, bccasout);
14684 } else {
14685
14686 sbond(oldvc, oldvc);
14687 }
14688 ssbond(oldvc, bc);
14689 } else {
14690 sbond(oldvc, bccasout);
14691 }
14692
14693 shellfacedealloc(subfaces, spinbcv.sh);
14694
14695 spivotself(spinavc);
14696 if (spinavc.sh == dummysh) {
14697 break;
14698 }
14699 } while (spinavc.sh != startavc.sh);
14700
14701
14702 if (av.sh != dummysh) {
14703 senext(av, oldvc);
14704 spivot(oldvc, vb);
14705 vb.shver = 0;
14706 #ifdef SELF_CHECK
14707 assert(sdest(av) == sorg(vb));
14708 #endif
14709 senext(vb, spinbcv);
14710 spivot(spinbcv, bccasout);
14711
14712 setsdest(av, pb);
14713 sbond(oldvc, bccasout);
14714
14715 shellfacedealloc(subsegs, vb.sh);
14716 }
14717 }
14718
14720
14721
14722
14723
14724
14725
14726
14727
14728
14729
14730
14731
14732
14733
14734
14735
14736
14737
14738
14740
14741 enum tetgenmesh::insertsiteresult tetgenmesh::insertsite(point newpoint,
14742 triface* searchtet, bool approx, queue* flipqueue)
14743 {
14744 enum locateresult intersect, exactloc;
14745 point checkpt;
14746 REAL epspp, checklen;
14747 int count;
14748
14749 if (b->verbose > 1) {
14750 printf(" Insert point to mesh: (%.12g, %.12g, %.12g) %d.\n",
14751 newpoint[0], newpoint[1], newpoint[2], pointmark(newpoint));
14752 }
14753
14754 if (searchtet->tet == (tetrahedron *) NULL) {
14755
14756 searchtet->tet = dummytet;
14757 exactloc = locate(newpoint, searchtet);
14758 } else {
14759
14760 exactloc = preciselocate(newpoint, searchtet, tetrahedrons->items);
14761 }
14762 intersect = exactloc;
14763 if (approx && (exactloc != ONVERTEX)) {
14764
14765 epspp = b->epsilon;
14766 count = 0;
14767 while (count < 16) {
14768 intersect = adjustlocate(newpoint, searchtet, exactloc, epspp);
14769 if (intersect == ONVERTEX) {
14770 checkpt = org(*searchtet);
14771 checklen = distance(checkpt, newpoint);
14772 if (checklen / longest > b->epsilon) {
14773 epspp *= 1e-2;
14774 count++;
14775 continue;
14776 }
14777 }
14778 break;
14779 }
14780 }
14781
14782 recenttet = *searchtet;
14783
14784
14785 switch (intersect) {
14786 case ONVERTEX:
14787
14788
14789 if (b->verbose > 1) {
14790 printf(" Not insert for duplicating point.\n");
14791 }
14792 return DUPLICATEPOINT;
14793
14794 case OUTSIDE:
14795 if (b->verbose > 1) {
14796 printf(" Not insert for locating outside the mesh.\n");
14797 }
14798 return OUTSIDEPOINT;
14799
14800 case ONEDGE:
14801
14802 splittetedge(newpoint, searchtet, flipqueue);
14803 return SUCCESSONEDGE;
14804
14805 case ONFACE:
14806
14807 splittetface(newpoint, searchtet, flipqueue);
14808 return SUCCESSONFACE;
14809
14810 case INTETRAHEDRON:
14811
14812 splittetrahedron(newpoint, searchtet, flipqueue);
14813 return SUCCESSINTET;
14814
14815 default:
14816
14817 return OUTSIDEPOINT;
14818 }
14819 }
14820
14822
14823
14824
14825
14826
14827
14828
14829
14830
14831
14833
14834 void tetgenmesh::undosite(enum insertsiteresult insresult, triface* splittet,
14835 point torg, point tdest, point tapex, point toppo)
14836 {
14837
14838 findface(splittet, torg, tdest, tapex);
14839 if (oppo(*splittet) != toppo) {
14840 symself(*splittet);
14841 #ifdef SELF_CHECK
14842 assert(oppo(*splittet) == toppo);
14843 #endif
14844
14845 findedge(splittet, torg, tdest);
14846 }
14847
14848
14849 switch (insresult) {
14850 case SUCCESSINTET:
14851
14852 unsplittetrahedron(splittet);
14853 break;
14854 case SUCCESSONFACE:
14855
14856
14857 unsplittetface(splittet);
14858 break;
14859 case SUCCESSONEDGE:
14860
14861 unsplittetedge(splittet);
14862 break;
14863 default:
14864 break;
14865 }
14866 }
14867
14869
14870
14871
14872
14873
14874
14875
14876
14877
14879
14880 void tetgenmesh::closeopenface(triface* openface, queue* flipque)
14881 {
14882 triface newtet, oldhull;
14883 triface newopenface, closeface;
14884 point inspoint, pa, pb, pc;
14885 REAL attrib, volume;
14886 int i;
14887
14888
14889 inspoint = apex(*openface);
14890
14891 esym(*openface, oldhull);
14892 while (fnextself(oldhull)) ;
14893 if (apex(oldhull) != inspoint) {
14894
14895 pa = org(oldhull);
14896 pb = dest(oldhull);
14897 pc = apex(oldhull);
14898 if (orient3d(pa, pb, pc, inspoint) < 0.0) {
14899
14900 maketetrahedron(&newtet);
14901 setorg(newtet, pa);
14902 setdest(newtet, pb);
14903 setapex(newtet, pc);
14904 setoppo(newtet, inspoint);
14905 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14906 attrib = elemattribute(oldhull.tet, i);
14907 setelemattribute(newtet.tet, i, attrib);
14908 }
14909 if (b->varvolume) {
14910 volume = volumebound(oldhull.tet);
14911 setvolumebound(newtet.tet, volume);
14912 }
14913
14914 bond(newtet, oldhull);
14915
14916 fnext(newtet, newopenface);
14917 bond(newopenface, *openface);
14918
14919 enqueueflipface(oldhull, flipque);
14920
14921 hullsize--;
14922
14923 enextself(newtet);
14924 for (i = 0; i < 2; i++) {
14925 fnext(newtet, newopenface);
14926 sym(newopenface, closeface);
14927 if (closeface.tet == dummytet) {
14928 closeopenface(&newopenface, flipque);
14929 }
14930 enextself(newtet);
14931 }
14932 } else {
14933
14934 hullsize++;
14935
14936 dummytet[0] = encode(*openface);
14937 }
14938 } else {
14939
14940 bond(*openface, oldhull);
14941
14942 enqueueflipface(*openface, flipque);
14943 }
14944 }
14945
14947
14948
14949
14950
14951
14952
14953
14954
14955
14956
14957
14958
14959
14960
14962
14963 void tetgenmesh::inserthullsite(point inspoint, triface* horiz, queue* flipque)
14964 {
14965 triface firstnewtet;
14966 triface openface, closeface;
14967 REAL attrib, volume;
14968 int i;
14969
14970
14971 adjustedgering(*horiz, CW);
14972
14973 maketetrahedron(&firstnewtet);
14974 setorg (firstnewtet, org(*horiz));
14975 setdest(firstnewtet, dest(*horiz));
14976 setapex(firstnewtet, apex(*horiz));
14977 setoppo(firstnewtet, inspoint);
14978 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14979 attrib = elemattribute(horiz->tet, i);
14980 setelemattribute(firstnewtet.tet, i, attrib);
14981 }
14982 if (b->varvolume) {
14983 volume = volumebound(horiz->tet);
14984 setvolumebound(firstnewtet.tet, volume);
14985 }
14986
14987 bond(firstnewtet, *horiz);
14988
14989 enqueueflipface(*horiz, flipque);
14990
14991 hullsize--;
14992
14993
14994 for (i = 0; i < 3; i++) {
14995
14996 fnext(firstnewtet, openface);
14997
14998 sym(openface, closeface);
14999 if (closeface.tet == dummytet) {
15000 closeopenface(&openface, flipque);
15001 }
15002
15003 enextself(firstnewtet);
15004 }
15005 }
15006
15008
15009
15010
15011
15012
15013
15014
15015
15016
15017
15018
15019
15020
15021
15022
15023
15025
15027
15028
15029
15030
15031
15032
15033
15034
15035
15037
15038 void tetgenmesh::formbowatcavitysub(point bp, face* bpseg, list* sublist,
15039 list* subceillist)
15040 {
15041 triface adjtet;
15042 face startsh, neighsh;
15043 face checkseg;
15044 point pa, pb, pc, pd;
15045 REAL sign;
15046 int i, j;
15047
15048
15049 for (i = 0; i < sublist->len(); i++) {
15050 startsh = * (face *)(* sublist)[i];
15051
15052 for (j = 0; j < 3; j++) {
15053 sspivot(startsh, checkseg);
15054 if (checkseg.sh == dummysh) {
15055
15056 spivot(startsh, neighsh);
15057
15058 if (!sinfected(neighsh)) {
15059 stpivot(neighsh, adjtet);
15060 if (adjtet.tet == dummytet) {
15061 sesymself(neighsh);
15062 stpivot(neighsh, adjtet);
15063 }
15064
15065 adjustedgering(adjtet, CW);
15066 pa = org(adjtet);
15067 pb = dest(adjtet);
15068 pc = apex(adjtet);
15069 pd = oppo(adjtet);
15070 sign = insphere(pa, pb, pc, pd, bp);
15071 if (sign >= 0.0) {
15072
15073 if (sorg(neighsh) != sdest(startsh)) sesymself(neighsh);
15074
15075 sinfect(neighsh);
15076 sublist->append(&neighsh);
15077 } else {
15078 subceillist->append(&startsh);
15079 }
15080 }
15081 } else {
15082
15083 if (bpseg != (face *) NULL) {
15084 if (checkseg.sh != bpseg->sh) {
15085 subceillist->append(&startsh);
15086 }
15087 } else {
15088 subceillist->append(&startsh);
15089 }
15090 }
15091 senextself(startsh);
15092 }
15093 }
15094
15095 if (b->verbose > 2) {
15096 printf(" Collect CBC(%d): %d subfaces, %d edges.\n", pointmark(bp),
15097 sublist->len(), subceillist->len());
15098 }
15099 }
15100
15102
15103
15104
15105
15106
15107
15108
15109
15110
15111
15112
15114
15115 void tetgenmesh::formbowatcavityquad(point bp, list* tetlist, list* ceillist)
15116 {
15117 triface starttet, neightet;
15118 face checksh;
15119 point pa, pb, pc, pd;
15120 REAL sign;
15121 int i;
15122
15123
15124 for (i = 0; i < tetlist->len(); i++) {
15125 starttet = * (triface *)(* tetlist)[i];
15126 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15127
15128 tspivot(starttet, checksh);
15129 if (checksh.sh == dummysh) {
15130
15131 sym(starttet, neightet);
15132
15133 if (!infected(neightet)) {
15134
15135 adjustedgering(neightet, CW);
15136 pa = org(neightet);
15137 pb = dest(neightet);
15138 pc = apex(neightet);
15139 pd = oppo(neightet);
15140 sign = insphere(pa, pb, pc, pd, bp);
15141 if (sign >= 0.0) {
15142
15143 infect(neightet);
15144 tetlist->append(&neightet);
15145 } else {
15146 ceillist->append(&starttet);
15147 }
15148 }
15149 } else {
15150
15151 if (!sinfected(checksh)) {
15152 ceillist->append(&starttet);
15153 }
15154 }
15155 }
15156 }
15157
15158 if (b->verbose > 2) {
15159 printf(" Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15160 tetlist->len(), ceillist->len());
15161 }
15162 }
15163
15165
15166
15167
15168
15169
15170
15171
15172
15173
15174
15175
15176
15177
15178
15180
15181 void tetgenmesh::formbowatcavitysegquad(point bp, list* tetlist,list* ceillist)
15182 {
15183 triface starttet, neightet, cavtet;
15184 face checksh;
15185 point pa, pb, pc, pd, pe;
15186 REAL sign;
15187 int i;
15188
15189
15190 for (i = 0; i < tetlist->len(); i++) {
15191 starttet = * (triface *)(* tetlist)[i];
15192 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15193
15194 tspivot(starttet, checksh);
15195 if (checksh.sh == dummysh) {
15196
15197 sym(starttet, neightet);
15198
15199 if (!infected(neightet)) {
15200
15201 adjustedgering(neightet, CW);
15202 pa = org(neightet);
15203 pb = dest(neightet);
15204 pc = apex(neightet);
15205 pd = oppo(neightet);
15206 sign = insphere(pa, pb, pc, pd, bp);
15207 if (sign >= 0.0) {
15208
15209 infect(neightet);
15210 tetlist->append(&neightet);
15211 } else {
15212
15213 pe = oppo(starttet);
15214 sign = insphere(pa, pb, pc, pd, pe);
15215 if (sign >= 0.0) {
15216
15217 infect(neightet);
15218 tetlist->append(&neightet);
15219 }
15220 }
15221 }
15222 }
15223 }
15224 }
15225
15226
15227 for (i = 0; i < tetlist->len(); i++) {
15228 cavtet = * (triface *)(* tetlist)[i];
15229 for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15230 tspivot(cavtet, checksh);
15231 if (checksh.sh == dummysh) {
15232 sym(cavtet, neightet);
15233 if (!infected(neightet)) {
15234 ceillist->append(&cavtet);
15235 }
15236 } else {
15237
15238 if (!sinfected(checksh)) {
15239 ceillist->append(&cavtet);
15240 }
15241 }
15242 }
15243 }
15244
15245 if (b->verbose > 2) {
15246 printf(" Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15247 tetlist->len(), ceillist->len());
15248 }
15249 }
15250
15252
15253
15254
15255
15256
15257
15258
15260
15261 void tetgenmesh::formbowatcavity(point bp, face* bpseg, face* bpsh, int* n,
15262 int* nmax, list** sublists, list** subceillists, list** tetlists,
15263 list** ceillists)
15264 {
15265 list *sublist;
15266 triface adjtet;
15267 face startsh, spinsh;
15268 point pa, pb;
15269 int i, j;
15270
15271 *n = 0;
15272 if (bpseg != (face *) NULL) {
15273
15274 bpseg->shver = 0;
15275 pa = sorg(*bpseg);
15276 pb = sdest(*bpseg);
15277
15278 spivot(*bpseg, startsh);
15279 spinsh = startsh;
15280 do {
15281 (*n)++;
15282 spivotself(spinsh);
15283 } while (spinsh.sh != startsh.sh);
15284
15285 if (*n > *nmax) {
15286
15287 delete [] tetlists;
15288 delete [] ceillists;
15289 delete [] sublists;
15290 delete [] subceillists;
15291 tetlists = new list*[*n];
15292 ceillists = new list*[*n];
15293 sublists = new list*[*n];
15294 subceillists = new list*[*n];
15295 *nmax = *n;
15296 }
15297
15298 spinsh = startsh;
15299 for (i = 0; i < *n; i++) {
15300 sublists[i] = new list(sizeof(face), NULL, 256);
15301 subceillists[i] = new list(sizeof(face), NULL, 256);
15302
15303 startsh = spinsh;
15304
15305 findedge(&startsh, pa, pb);
15306 sinfect(startsh);
15307 sublists[i]->append(&startsh);
15308 formbowatcavitysub(bp, bpseg, sublists[i], subceillists[i]);
15309
15310 spivotself(spinsh);
15311 }
15312 } else if (sublists != (list **) NULL) {
15313
15314 *n = 2;
15315
15316 sublists[0] = new list(sizeof(face), NULL, 256);
15317 subceillists[0] = new list(sizeof(face), NULL, 256);
15318 sinfect(*bpsh);
15319 sublists[0]->append(bpsh);
15320 formbowatcavitysub(bp, NULL, sublists[0], subceillists[0]);
15321 } else {
15322
15323 *n = 1;
15324 }
15325
15326
15327 for (i = 0; i < *n; i++) {
15328 tetlists[i] = new list(sizeof(triface), NULL, 256);
15329 ceillists[i] = new list(sizeof(triface), NULL, 256);
15330 if (sublists != (list **) NULL) {
15331
15332 sublist = ((bpseg == (face *) NULL) ? sublists[0] : sublists[i]);
15333
15334 for (j = 0; j < sublist->len(); j++) {
15335 startsh = * (face *)(* sublist)[j];
15336
15337 if ((bpseg == (face *) NULL) && (i == 1)) sesymself(startsh);
15338 stpivot(startsh, adjtet);
15339 if (adjtet.tet != dummytet) {
15340 if (!infected(adjtet)) {
15341 infect(adjtet);
15342 tetlists[i]->append(&adjtet);
15343 }
15344 }
15345 }
15346 if (bpseg != (face *) NULL) {
15347
15348 sublist = ((i < *n - 1) ? sublists[i + 1] : sublists[0]);
15349 for (j = 0; j < sublist->len(); j++) {
15350 startsh = * (face *)(* sublist)[j];
15351
15352 sesymself(startsh);
15353 stpivot(startsh, adjtet);
15354 if (adjtet.tet != dummytet) {
15355 if (!infected(adjtet)) {
15356 infect(adjtet);
15357 tetlists[i]->append(&adjtet);
15358 }
15359 }
15360 }
15361 }
15362 }
15363
15364 if (tetlists[i]->len() == 0) continue;
15365
15366
15367
15368
15369 formbowatcavityquad(bp, tetlists[i], ceillists[i]);
15370
15371 }
15372 }
15373
15375
15376
15377
15378
15380
15381 void tetgenmesh::releasebowatcavity(face* bpseg, int n, list** sublists,
15382 list** subceillist, list** tetlists, list** ceillists)
15383 {
15384 triface oldtet;
15385 face oldsh;
15386 int i, j;
15387
15388 if (sublists != (list **) NULL) {
15389
15390 for (i = 0; i < n; i++) {
15391
15392 for (j = 0; j < sublists[i]->len(); j++) {
15393 oldsh = * (face *)(* (sublists[i]))[j];
15394 #ifdef SELF_CHECK
15395 assert(sinfected(oldsh));
15396 #endif
15397 suninfect(oldsh);
15398 }
15399 delete sublists[i];
15400 delete subceillist[i];
15401 sublists[i] = (list *) NULL;
15402 subceillist[i] = (list *) NULL;
15403 if (bpseg == (face *) NULL) break;
15404 }
15405 }
15406
15407 for (i = 0; i < n; i++) {
15408
15409 for (j = 0; j < tetlists[i]->len(); j++) {
15410 oldtet = * (triface *)(* (tetlists[i]))[j];
15411 #ifdef SELF_CHECK
15412 assert(infected(oldtet));
15413 #endif
15414 uninfect(oldtet);
15415 }
15416 delete tetlists[i];
15417 delete ceillists[i];
15418 tetlists[i] = (list *) NULL;
15419 ceillists[i] = (list *) NULL;
15420 }
15421 }
15422
15424
15425
15426
15427
15428
15429
15430
15431
15432
15434
15435 bool tetgenmesh::validatebowatcavityquad(point bp,list* ceillist,REAL maxcosd)
15436 {
15437 triface ceiltet;
15438 point pa, pb, pc;
15439 REAL ori, cosd;
15440 int remcount, i;
15441
15442
15443 remcount = 0;
15444 for (i = 0; i < ceillist->len(); i++) {
15445 ceiltet = * (triface *)(* ceillist)[i];
15446 if (infected(ceiltet)) {
15447 adjustedgering(ceiltet, CCW);
15448 pa = org(ceiltet);
15449 pb = dest(ceiltet);
15450 pc = apex(ceiltet);
15451 ori = orient3d(pa, pb, pc, bp);
15452 if (ori >= 0.0) {
15453
15454 uninfect(ceiltet);
15455 remcount++;
15456 continue;
15457 }
15458
15459 if (maxcosd > -1.0) {
15460
15461 tetalldihedral(pa, pb, pc, bp, NULL, &cosd, NULL);
15462
15463 if (cosd < maxcosd) {
15464 uninfect(ceiltet);
15465 remcount++;
15466 }
15467 }
15468 }
15469 }
15470 return remcount == 0;
15471 }
15472
15474
15475
15476
15477
15478
15479
15480
15482
15483 void tetgenmesh::updatebowatcavityquad(list* tetlist, list* ceillist)
15484 {
15485 triface cavtet, neightet;
15486 face checksh;
15487 int remcount, i;
15488
15489 remcount = 0;
15490 for (i = 0; i < tetlist->len(); i++) {
15491 cavtet = * (triface *)(* tetlist)[i];
15492 if (!infected(cavtet)) {
15493 tetlist->del(i, 1);
15494 remcount++;
15495 i--;
15496 }
15497 }
15498
15499
15500 if (remcount > 0) {
15501
15502 ceillist->clear();
15503 for (i = 0; i < tetlist->len(); i++) {
15504 cavtet = * (triface *)(* tetlist)[i];
15505 for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15506 tspivot(cavtet, checksh);
15507 if (checksh.sh == dummysh) {
15508 sym(cavtet, neightet);
15509 if (!infected(neightet)) {
15510 ceillist->append(&cavtet);
15511 }
15512 } else {
15513
15514 if (!sinfected(checksh)) {
15515 ceillist->append(&cavtet);
15516 }
15517 }
15518 }
15519 }
15520 if (b->verbose > 2) {
15521 printf(" Update BC_i(p): %d tets, %d faces.\n", tetlist->len(),
15522 ceillist->len());
15523 }
15524 }
15525 }
15526
15528
15529
15530
15531
15532
15533
15534
15535
15536
15537
15538
15539
15540
15541
15542
15543
15544
15545
15546
15547
15548
15549
15550
15552
15553 void tetgenmesh::updatebowatcavitysub(list* sublist, list* subceillist,
15554 int* cutcount)
15555 {
15556 triface adjtet, rotface;
15557 face checksh, neighsh;
15558 face checkseg;
15559 point pa, pb, pc;
15560 REAL ori1, ori2;
15561 int remcount;
15562 int i, j;
15563
15564 remcount = 0;
15565
15566 for (i = 0; i < sublist->len(); i++) {
15567 checksh = * (face *)(* sublist)[i];
15568
15569 for (j = 0; j < 2; j++) {
15570 stpivot(checksh, adjtet);
15571 if (adjtet.tet != dummytet) {
15572 if (!infected(adjtet)) {
15573
15574 suninfect(checksh);
15575
15576 sesymself(checksh);
15577 stpivot(checksh, adjtet);
15578 if (adjtet.tet != dummytet) {
15579 if (infected(adjtet)) {
15580
15581 uninfect(adjtet);
15582 (*cutcount)++;
15583 }
15584 }
15585
15586 sublist->del(i, 1);
15587 i--;
15588 remcount++;
15589 break;
15590 }
15591 }
15592 sesymself(checksh);
15593 }
15594 }
15595 if (remcount > 0) {
15596 if (b->verbose > 2) {
15597 printf(" Removed %d subfaces from CBC(p).\n", remcount);
15598 }
15599
15600 subceillist->clear();
15601 for (i = 0; i < sublist->len(); i++) {
15602 checksh = * (face *)(* sublist)[i];
15603 for (j = 0; j < 3; j++) {
15604 spivot(checksh, neighsh);
15605 if (!sinfected(neighsh)) {
15606 subceillist->append(&checksh);
15607 }
15608 senextself(checksh);
15609 }
15610 }
15611 if (b->verbose > 2) {
15612 printf(" Update CBC(p): %d subs, %d edges.\n", sublist->len(),
15613 subceillist->len());
15614 }
15615 }
15616
15617
15618 for (i = 0; i < subceillist->len(); i++) {
15619 checksh = * (face *)(* subceillist)[i];
15620 sspivot(checksh, checkseg);
15621 if (checkseg.sh != dummysh) {
15622
15623 stpivot(checksh, adjtet);
15624 if (adjtet.tet == dummytet) {
15625 sesym(checksh, neighsh);
15626 stpivot(neighsh, adjtet);
15627 }
15628 findedge(&adjtet, sorg(checkseg), sdest(checkseg));
15629 adjustedgering(adjtet, CCW);
15630 fnext(adjtet, rotface);
15631
15632
15633
15634
15635 do {
15636 if (!infected(rotface)) break;
15637 tspivot(rotface, neighsh);
15638 if (neighsh.sh != dummysh) break;
15639
15640 fnextself(rotface);
15641 } while (apex(rotface) != apex(adjtet));
15642
15643 if (apex(rotface) == apex(adjtet)) {
15644
15645 pa = org(adjtet);
15646 pb = dest(adjtet);
15647 pc = apex(adjtet);
15648
15649
15650
15651 fnext(adjtet, rotface);
15652 do {
15653 fnextself(rotface);
15654 assert(infected(rotface));
15655 ori1 = orient3d(pa, pb, pc, apex(rotface));
15656 ori2 = orient3d(pa, pb, pc, oppo(rotface));
15657 } while (ori1 * ori2 > 0.0);
15658
15659 uninfect(rotface);
15660 (*cutcount)++;
15661 }
15662 } else {
15663
15664
15665
15666
15667
15668
15669
15670
15671
15672
15673
15674
15675
15676
15677
15678
15679
15680 }
15681 }
15682 }
15683
15685
15686
15687
15688
15689
15690
15691
15692
15693
15694
15695
15696
15697
15698
15699
15700
15701
15702
15703
15704
15705
15706
15708
15709 bool tetgenmesh::trimbowatcavity(point bp, face* bpseg, int n, list** sublists,
15710 list** subceillists, list** tetlists, list** ceillists, REAL maxcosd)
15711 {
15712 bool valflag;
15713 int oldnum, cutnum, cutcount;
15714 int i;
15715
15716 cutnum = 0;
15717 valflag = true;
15718
15719 do {
15720
15721 for (i = 0; i < n && valflag; i++) {
15722 oldnum = tetlists[i]->len();
15723
15724 while (!validatebowatcavityquad(bp, ceillists[i], maxcosd)) {
15725
15726 updatebowatcavityquad(tetlists[i], ceillists[i]);
15727 valflag = tetlists[i]->len() > 0;
15728 }
15729 cutnum += (oldnum - tetlists[i]->len());
15730 }
15731 if (valflag && (sublists != (list **) NULL)) {
15732
15733 cutcount = 0;
15734 for (i = 0; i < n; i++) {
15735 updatebowatcavitysub(sublists[i], subceillists[i], &cutcount);
15736
15737 if (bpseg == (face *) NULL) break;
15738 }
15739
15740 if (cutcount > 0) {
15741
15742 for (i = 0; i < n; i++) {
15743 if (tetlists[i]->len() > 0) {
15744 updatebowatcavityquad(tetlists[i], ceillists[i]);
15745 if (valflag) {
15746 valflag = tetlists[i]->len() > 0;
15747 }
15748 }
15749 }
15750 cutnum += cutcount;
15751
15752 continue;
15753 }
15754 }
15755 break;
15756 } while (true);
15757
15758
15759 if (valflag && (sublists != (list **) NULL)) {
15760 for (i = 0; i < n && valflag; i++) {
15761 valflag = (sublists[i]->len() > 0);
15762 if (bpseg == (face *) NULL) break;
15763 }
15764 }
15765
15766 if (valflag && (cutnum > 0)) {
15767
15768 if (bpseg != (face *) NULL) {
15769 updsegcount++;
15770 } else if (sublists != (list **) NULL) {
15771 updsubcount++;
15772 } else {
15773 updvolcount++;
15774 }
15775 }
15776
15777 if (!valflag) {
15778
15779 if (bpseg != (face *) NULL) {
15780 failsegcount++;
15781 } else if (sublists != (list **) NULL) {
15782 failsubcount++;
15783 } else {
15784 failvolcount++;
15785 }
15786 }
15787
15788 return valflag;
15789 }
15790
15792
15793
15794
15795
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
15824
15825 void tetgenmesh::bowatinsertsite(point bp,face* splitseg,int n,list** sublists,
15826 list** subceillists, list** tetlists, list** ceillists, list* verlist,
15827 queue* flipque, bool chkencseg, bool chkencsub, bool chkbadtet)
15828 {
15829 list *ceillist, *subceillist;
15830 triface oldtet, newtet, newface, rotface, neightet;
15831 face oldsh, newsh, newedge, checksh;
15832 face spinsh, casingin, casingout;
15833 face *apsegshs, *pbsegshs;
15834 face apseg, pbseg, checkseg;
15835 point pa, pb, pc;
15836 REAL attrib, volume;
15837 int idx, i, j, k;
15838
15839 apsegshs = NULL;
15840 pbsegshs = NULL;
15841
15842 if (b->verbose > 1) {
15843 printf(" Insert point %d (%.12g, %.12g, %.12g)", pointmark(bp), bp[0],
15844 bp[1], bp[2]);
15845 }
15846 if (splitseg != (face *) NULL) {
15847 if (b->verbose > 1) {
15848 printf(" on segment.\n");
15849 }
15850 bowatsegcount++;
15851 } else {
15852 if (subceillists != (list **) NULL) {
15853 if (b->verbose > 1) {
15854 printf(" on facet.\n");
15855 }
15856 bowatsubcount++;
15857 } else {
15858 if (b->verbose > 1) {
15859 printf(" in volume.\n");
15860 }
15861 bowatvolcount++;
15862 }
15863 }
15864
15865
15866 for (k = 0; k < n; k++) {
15867
15868 ceillist = ceillists[k];
15869 for (i = 0; i < ceillist->len(); i++) {
15870 oldtet = * (triface *)(* ceillist)[i];
15871 adjustedgering(oldtet, CCW);
15872 pa = org(oldtet);
15873 pb = dest(oldtet);
15874 pc = apex(oldtet);
15875 maketetrahedron(&newtet);
15876 setorg(newtet, pa);
15877 setdest(newtet, pb);
15878 setapex(newtet, pc);
15879 setoppo(newtet, bp);
15880 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
15881 attrib = elemattribute(oldtet.tet, j);
15882 setelemattribute(newtet.tet, j, attrib);
15883 }
15884 if (b->varvolume) {
15885 volume = volumebound(oldtet.tet);
15886 if (volume > 0.0) {
15887 if (!b->fixedvolume && b->refine) {
15888
15889
15890
15891 volume *= 1.2;
15892 }
15893 }
15894 setvolumebound(newtet.tet, volume);
15895 }
15896 sym(oldtet, neightet);
15897 tspivot(oldtet, checksh);
15898 if (neightet.tet != dummytet) {
15899 bond(newtet, neightet);
15900 }
15901 if (checksh.sh != dummysh) {
15902 tsbond(newtet, checksh);
15903 }
15904 if (verlist != (list *) NULL) {
15905
15906 idx = pointmark(pa);
15907 if (idx >= 0) {
15908 setpointmark(pa, -idx - 1);
15909 verlist->append(&pa);
15910 }
15911 idx = pointmark(pb);
15912 if (idx >= 0) {
15913 setpointmark(pb, -idx - 1);
15914 verlist->append(&pb);
15915 }
15916 idx = pointmark(pc);
15917 if (idx >= 0) {
15918 setpointmark(pc, -idx - 1);
15919 verlist->append(&pc);
15920 }
15921 }
15922
15923 * (triface *)(* ceillist)[i] = newtet;
15924 }
15925 }
15926 if (verlist != (list *) NULL) {
15927
15928 for (i = 0; i < verlist->len(); i++) {
15929 pa = * (point *)(* verlist)[i];
15930 idx = pointmark(pa);
15931 setpointmark(pa, -(idx + 1));
15932 }
15933 }
15934
15935
15936
15937 for (k = 0; k < n; k++) {
15938 ceillist = ceillists[k];
15939 for (i = 0; i < ceillist->len(); i++) {
15940 newtet = * (triface *)(* ceillist)[i];
15941 newtet.ver = 0;
15942 for (j = 0; j < 3; j++) {
15943 fnext(newtet, newface);
15944 sym(newface, neightet);
15945 if (neightet.tet == dummytet) {
15946
15947 esym(newtet, rotface);
15948 pa = org(rotface);
15949 pb = dest(rotface);
15950 while (fnextself(rotface));
15951
15952 tspivot(rotface, checksh);
15953 if (checksh.sh != dummysh) {
15954
15955 do {
15956 findedge(&checksh, pa, pb);
15957 sfnextself(checksh);
15958 assert((sorg(checksh) == pa) && (sdest(checksh) == pb));
15959 stpivot(checksh, rotface);
15960 if (infected(rotface)) {
15961
15962
15963 break;
15964 }
15965 findedge(&rotface, pa, pb);
15966 while (fnextself(rotface));
15967 tspivot(rotface, checksh);
15968 } while (checksh.sh != dummysh);
15969 }
15970
15971 if (apex(rotface) == apex(newface)) {
15972
15973 bond(newface, rotface);
15974
15975 if (flipque != (queue *) NULL) {
15976 enqueueflipface(newface, flipque);
15977 }
15978 }
15979 }
15980 enextself(newtet);
15981 }
15982 }
15983 }
15984
15985 if (subceillists != (list **) NULL) {
15986
15987 if (splitseg != (face *) NULL) {
15988
15989 splitseg->shver = 0;
15990 pa = sorg(*splitseg);
15991 pb = sdest(*splitseg);
15992
15993
15994 apsegshs = new face[n];
15995 pbsegshs = new face[n];
15996 }
15997
15998
15999
16000
16001 for (k = 0; k < n; k++) {
16002 subceillist = subceillists[k];
16003
16004
16005 oldsh = * (face *)(* subceillist)[0];
16006 stpivot(oldsh, neightet);
16007 if (neightet.tet != dummytet) {
16008 sesymself(oldsh);
16009 stpivot(oldsh, neightet);
16010 }
16011 if (neightet.tet == dummytet) {
16012
16013 hullsize += (subceillist->len() - sublists[k]->len());
16014 }
16015
16016
16017 for (i = 0; i < subceillist->len(); i++) {
16018 oldsh = * (face *)(* subceillist)[i];
16019 makeshellface(subfaces, &newsh);
16020 setsorg(newsh, sorg(oldsh));
16021 setsdest(newsh, sdest(oldsh));
16022 setsapex(newsh, bp);
16023 if (b->quality && varconstraint) {
16024 setareabound(newsh, areabound(oldsh));
16025 }
16026 setshellmark(newsh, shellmark(oldsh));
16027 setshelltype(newsh, shelltype(oldsh));
16028 if (checkpbcs) {
16029 setshellpbcgroup(newsh, shellpbcgroup(oldsh));
16030 }
16031
16032 spivot(oldsh, casingout);
16033 sspivot(oldsh, checkseg);
16034 if (checkseg.sh != dummysh) {
16035
16036 if (oldsh.sh != casingout.sh) {
16037
16038 spinsh = casingout;
16039 do {
16040 casingin = spinsh;
16041 spivotself(spinsh);
16042 } while (sapex(spinsh) != sapex(oldsh));
16043 assert(casingin.sh != oldsh.sh);
16044
16045 sbond1(casingin, newsh);
16046 sbond1(newsh, casingout);
16047 } else {
16048
16049 sbond(newsh, newsh);
16050 }
16051
16052 ssbond(newsh, checkseg);
16053 } else {
16054
16055 sbond(newsh, casingout);
16056 }
16057
16058
16059 stpivot(oldsh, neightet);
16060 if (neightet.tet == dummytet) {
16061 sesymself(oldsh);
16062 sesymself(newsh);
16063 stpivot(oldsh, neightet);
16064 }
16065 assert(infected(neightet));
16066
16067 findedge(&neightet, sorg(oldsh), sdest(oldsh));
16068
16069 adjustedgering(neightet, CCW);
16070 rotface = neightet;
16071
16072
16073
16074 do {
16075 fnextself(rotface);
16076 sym(rotface, neightet);
16077 if (neightet.tet == dummytet) {
16078 tspivot(rotface, checksh);
16079 assert(checksh.sh != dummysh);
16080 stpivot(checksh, newtet);
16081 break;
16082 } else if (!infected(neightet)) {
16083 sym(neightet, newtet);
16084 break;
16085 }
16086 } while (true);
16087 assert(newtet.tet != rotface.tet);
16088
16089 findedge(&newtet, sorg(oldsh), sdest(oldsh));
16090
16091 adjustedgering(newtet, CCW);
16092 fnext(newtet, newface);
16093 assert(apex(newface) == bp);
16094
16095 tsbond(newface, newsh);
16096 sym(newface, neightet);
16097 sesymself(newsh);
16098 tsbond(neightet, newsh);
16099
16100
16101 * (face *)(* subceillist)[i] = newsh;
16102 }
16103
16104
16105 for (i = 0; i < subceillist->len(); i++) {
16106
16107 newsh = * (face *)(* subceillist)[i];
16108
16109 stpivot(newsh, newtet);
16110 if (newtet.tet == dummytet) {
16111 sesymself(newsh);
16112 stpivot(newsh, newtet);
16113 }
16114 for (j = 0; j < 2; j++) {
16115 if (j == 0) {
16116 senext(newsh, newedge);
16117 } else {
16118 senext2(newsh, newedge);
16119 sesymself(newedge);
16120 }
16121 if (splitseg != (face *) NULL) {
16122
16123 if (sorg(newedge) == pa) {
16124 apsegshs[k] = newedge;
16125 continue;
16126 } else if (sorg(newedge) == pb) {
16127 pbsegshs[k] = newedge;
16128 continue;
16129 }
16130 }
16131
16132 sspivot(newedge, checkseg);
16133 assert(checkseg.sh == dummysh);
16134 spivot(newedge, casingout);
16135 if (casingout.sh == dummysh) {
16136 rotface = newtet;
16137 findedge(&rotface, sorg(newedge), sdest(newedge));
16138
16139
16140 adjustedgering(rotface, CCW);
16141 do {
16142 fnextself(rotface);
16143 tspivot(rotface, checksh);
16144 if (checksh.sh != dummysh) break;
16145 } while (true);
16146 findedge(&checksh, sorg(newedge), sdest(newedge));
16147 sbond(newedge, checksh);
16148 }
16149 }
16150 }
16151
16152 if (splitseg == (face *) NULL) break;
16153 }
16154
16155 if (splitseg != (face *) NULL) {
16156
16157 apseg = *splitseg;
16158 setsdest(apseg, bp);
16159
16160 makeshellface(subsegs, &pbseg);
16161 setsorg(pbseg, bp);
16162 setsdest(pbseg, pb);
16163
16164 setshellmark(pbseg, shellmark(apseg));
16165 setshelltype(pbseg, shelltype(apseg));
16166 if (b->quality && varconstraint) {
16167
16168 setareabound(pbseg, areabound(apseg));
16169 }
16170 senext(apseg, checkseg);
16171
16172 spivot(checkseg, casingout);
16173
16174 senext2(pbseg, casingin);
16175 sbond(casingin, checkseg);
16176 if (casingout.sh != dummysh) {
16177
16178 casingout.shver = 0;
16179 #ifdef SELF_CHECK
16180 assert(sorg(casingout) == pb);
16181 #endif
16182 senext2self(casingout);
16183 senext(pbseg, casingin);
16184 sbond(casingin, casingout);
16185 }
16186
16187
16188 for (i = 0; i < n; i++) {
16189 spinsh = apsegshs[i];
16190 findedge(&spinsh, pa, bp);
16191 ssbond(spinsh, apseg);
16192 spinsh = pbsegshs[i];
16193 findedge(&spinsh, bp, pb);
16194 ssbond(spinsh, pbseg);
16195 }
16196
16197 for (i = 0; i < n; i++) {
16198 spinsh = apsegshs[i];
16199 if (i < (n - 1)) {
16200 casingout = apsegshs[i + 1];
16201 } else {
16202 casingout = apsegshs[0];
16203 }
16204 sbond1(spinsh, casingout);
16205 }
16206
16207 for (i = 0; i < n; i++) {
16208 spinsh = pbsegshs[i];
16209 if (i < (n - 1)) {
16210 casingout = pbsegshs[i + 1];
16211 } else {
16212 casingout = pbsegshs[0];
16213 }
16214 sbond1(spinsh, casingout);
16215 }
16216 delete [] apsegshs;
16217 delete [] pbsegshs;
16218
16219
16220 if (chkencseg) {
16221
16222 checkseg4encroach(&apseg, NULL, NULL, true);
16223 checkseg4encroach(&pbseg, NULL, NULL, true);
16224
16225 tallencsegs(bp, n, ceillists);
16226 }
16227 }
16228
16229
16230 for (k = 0; k < n; k++) {
16231 for (i = 0; i < sublists[k]->len(); i++) {
16232 oldsh = * (face *)(* (sublists[k]))[i];
16233 shellfacedealloc(subfaces, oldsh.sh);
16234 }
16235
16236
16237 sublists[k]->clear();
16238
16239 if (splitseg == (face *) NULL) break;
16240 }
16241
16242
16243 if (chkencsub) {
16244
16245 for (k = 0; k < n; k++) {
16246 subceillist = subceillists[k];
16247 for (i = 0; i < subceillist->len(); i++) {
16248 newsh = * (face *)(* subceillist)[i];
16249 checksub4encroach(&newsh, NULL, true);
16250 }
16251
16252 if (splitseg == (face *) NULL) break;
16253 }
16254
16255 tallencsubs(bp, n, ceillists);
16256 }
16257 }
16258
16259
16260 for (k = 0; k < n; k++) {
16261 for (i = 0; i < tetlists[k]->len(); i++) {
16262 oldtet = * (triface *)(* (tetlists[k]))[i];
16263 tetrahedrondealloc(oldtet.tet);
16264 }
16265
16266
16267 tetlists[k]->clear();
16268 }
16269
16270
16271 if (chkbadtet) {
16272 for (k = 0; k < n; k++) {
16273 ceillist = ceillists[k];
16274 for (i = 0; i < ceillist->len(); i++) {
16275 newtet = * (triface *)(* ceillist)[i];
16276 checktet4badqual(&newtet, true);
16277 }
16278 }
16279 }
16280
16281 if (flipque != (queue *) NULL) {
16282
16283
16284
16285 repairflipcount += flip(flipque, NULL);
16286 }
16287 }
16288
16289
16290
16291
16292
16293
16294
16295
16296
16298
16299
16300
16301
16302
16303
16304
16305
16306
16307
16308
16310
16311 void tetgenmesh::formstarpolyhedron(point pt, list* tetlist, list* verlist,
16312 bool complete)
16313 {
16314 triface starttet, neightet;
16315 face checksh;
16316 point ver[3];
16317 int idx, i, j;
16318
16319
16320 starttet = * (triface *)(* tetlist)[0];
16321
16322 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
16323 if (oppo(starttet) == pt) break;
16324 }
16325 assert(starttet.loc < 4);
16326
16327 * (triface *)(* tetlist)[0] = starttet;
16328 infect(starttet);
16329 if (verlist != (list *) NULL) {
16330
16331 ver[0] = org(starttet);
16332 ver[1] = dest(starttet);
16333 ver[2] = apex(starttet);
16334 for (i = 0; i < 3; i++) {
16335
16336 idx = pointmark(ver[i]);
16337 setpointmark(ver[i], -idx - 1);
16338 verlist->append(&(ver[i]));
16339 }
16340 }
16341
16342
16343 for (i = 0; i < tetlist->len(); i++) {
16344 starttet = * (triface *)(* tetlist)[i];
16345 starttet.ver = 0;
16346 for (j = 0; j < 3; j++) {
16347 fnext(starttet, neightet);
16348 tspivot(neightet, checksh);
16349
16350 if ((checksh.sh == dummysh) || complete) {
16351
16352 symself(neightet);
16353 if ((neightet.tet != dummytet) && !infected(neightet)) {
16354
16355 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
16356 if (oppo(neightet) == pt) break;
16357 }
16358 assert(neightet.loc < 4);
16359
16360 infect(neightet);
16361 tetlist->append(&neightet);
16362 if (verlist != (list *) NULL) {
16363
16364 ver[0] = org(starttet);
16365 ver[1] = dest(starttet);
16366 findedge(&neightet, ver[0], ver[1]);
16367 ver[2] = apex(neightet);
16368 idx = pointmark(ver[2]);
16369 if (idx >= 0) {
16370 setpointmark(ver[2], -idx - 1);
16371 verlist->append(&(ver[2]));
16372 }
16373 }
16374 }
16375 }
16376 enextself(starttet);
16377 }
16378 }
16379
16380
16381 for (i = 0; i < tetlist->len(); i++) {
16382 starttet = * (triface *)(* tetlist)[i];
16383 uninfect(starttet);
16384 }
16385 if (verlist != (list *) NULL) {
16386
16387 for (i = 0; i < verlist->len(); i++) {
16388 ver[0] = * (point *)(* verlist)[i];
16389 idx = pointmark(ver[0]);
16390 setpointmark(ver[0], -(idx + 1));
16391 }
16392 }
16393 }
16394
16396
16397
16398
16399
16400
16401
16402
16403
16404
16406
16407 bool tetgenmesh::unifypoint(point testpt, triface *starttet, enum locateresult
16408 loc, REAL eps)
16409 {
16410 triface symtet, spintet;
16411 point checkpt, tapex;
16412 REAL tol;
16413 bool merged;
16414 int hitbdry;
16415 int i;
16416
16417 merged = false;
16418 tol = longest * eps;
16419 if ((loc == OUTSIDE) || (loc == INTETRAHEDRON) || (loc == ONFACE)) {
16420
16421 for (i = 0; i < 4; i++) {
16422 checkpt = (point) starttet->tet[4 + i];
16423 if (distance(testpt, checkpt) < tol) {
16424 merged = true;
16425 break;
16426 }
16427 }
16428 if (!merged && (loc == ONFACE)) {
16429
16430 sym(*starttet, symtet);
16431 if (symtet.tet != dummytet) {
16432 checkpt = oppo(symtet);
16433 if (distance(testpt, checkpt) < tol) {
16434 merged = true;
16435 }
16436 }
16437 }
16438 } else if (loc == ONEDGE) {
16439
16440 checkpt = org(*starttet);
16441 if (distance(testpt, checkpt) < tol) {
16442 merged = true;
16443 }
16444 if (!merged) {
16445 checkpt = dest(*starttet);
16446 if (distance(testpt, checkpt) < tol) {
16447 merged = true;
16448 }
16449 }
16450 if (!merged) {
16451
16452 spintet = *starttet;
16453 tapex = apex(*starttet);
16454 hitbdry = 0;
16455 do {
16456 checkpt = apex(spintet);
16457 if (distance(testpt, checkpt) < tol) {
16458 merged = true;
16459 break;
16460 }
16461 if (!fnextself(spintet)) {
16462 hitbdry++;
16463 if (hitbdry < 2) {
16464 esym(*starttet, spintet);
16465 if (!fnextself(spintet)) {
16466 hitbdry++;
16467 }
16468 }
16469 }
16470 } while ((apex(spintet) != tapex) && (hitbdry < 2));
16471 }
16472 }
16473 if (merged) {
16474 if (b->object != tetgenbehavior::STL) {
16475 if (!b->quiet) {
16476 printf("Warning: Point %d is unified to point %d.\n",
16477 pointmark(testpt), pointmark(checkpt));
16478 }
16479
16480 dupverts++;
16481 }
16482
16483 setpointtype(testpt, DUPLICATEDVERTEX);
16484
16485 setpoint2ppt(testpt, checkpt);
16486 }
16487 return merged;
16488 }
16489
16491
16492
16493
16494
16495
16496
16497
16498
16499
16500
16501
16502
16503
16504
16505
16506
16508
16509 void tetgenmesh::incrflipdelaunay(triface* oldtet, point* insertarray,
16510 long arraysize, bool jump, bool merge, REAL eps, queue* flipque)
16511 {
16512 triface newtet, searchtet;
16513 point swappt, lastpt;
16514 enum locateresult loc;
16515 REAL det, n[3];
16516 REAL attrib, volume;
16517 int i, j;
16518 #ifdef SELF_CHECK
16519 clock_t loc_start, loc_end;
16520 #endif
16521
16522 det = 0.0;
16523 if (b->verbose > 0) {
16524 printf(" Creating initial tetrahedralization.\n");
16525 }
16526
16527
16528
16529
16530
16531
16532 for (i = 1; i < arraysize; i++) {
16533 det = distance(insertarray[0], insertarray[i]);
16534 if (det > (longest * eps)) break;
16535 }
16536 if (i == arraysize) {
16537 printf("\nAll points seem to be identical.\n");
16538 return;
16539 } else {
16540
16541 swappt = insertarray[i];
16542 insertarray[i] = insertarray[1];
16543 insertarray[1] = swappt;
16544 }
16545
16546 for (i++; i < arraysize; i++) {
16547 if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
16548 break;
16549 }
16550 if (i == arraysize) {
16551 printf("\nAll points seem to be collinear.\n");
16552 return;
16553 } else {
16554
16555 swappt = insertarray[i];
16556 insertarray[i] = insertarray[2];
16557 insertarray[2] = swappt;
16558 }
16559
16560 for (i++; i < arraysize; i++) {
16561 det = orient3d(insertarray[0], insertarray[1], insertarray[2],
16562 insertarray[i]);
16563 if (det == 0.0) continue;
16564 if (!iscoplanar(insertarray[0], insertarray[1], insertarray[2],
16565 insertarray[i], det, eps)) break;
16566 }
16567 if (i == arraysize) {
16568
16569 in->mesh_dim = 2;
16570
16571 if (b->plc) {
16572
16573 facenormal(insertarray[0], insertarray[1], insertarray[2], n, &det);
16574 if (det != 0.0) for (j = 0; j < 3; j++) n[j] /= det;
16575
16576 det = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
16577
16578 makepoint(&lastpt);
16579 for (j = 0; j < 3; j++) lastpt[j] = insertarray[0][j] + det * n[j];
16580 abovepoint = lastpt;
16581 det = orient3d(insertarray[0], insertarray[1], insertarray[2], lastpt);
16582
16583 i = 3;
16584 } else {
16585 printf("\nAll points seem to be coplanar.\n");
16586 return;
16587 }
16588 } else {
16589
16590 swappt = insertarray[i];
16591 insertarray[i] = insertarray[3];
16592 insertarray[3] = swappt;
16593 lastpt = insertarray[3];
16594
16595 i = 4;
16596 }
16597
16598
16599 maketetrahedron(&newtet);
16600 if (det > 0.0) {
16601
16602 swappt = insertarray[0];
16603 insertarray[0] = insertarray[1];
16604 insertarray[1] = swappt;
16605 }
16606 if (b->verbose > 2) {
16607 printf(" Create the first tet (%d, %d, %d, %d).\n",
16608 pointmark(insertarray[0]), pointmark(insertarray[1]),
16609 pointmark(insertarray[2]), pointmark(lastpt));
16610 }
16611 setorg(newtet, insertarray[0]);
16612 setdest(newtet, insertarray[1]);
16613 setapex(newtet, insertarray[2]);
16614 setoppo(newtet, lastpt);
16615 if (oldtet != (triface *) NULL) {
16616 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
16617 attrib = elemattribute(oldtet->tet, j);
16618 setelemattribute(newtet.tet, j, attrib);
16619 }
16620 if (b->varvolume) {
16621 volume = volumebound(oldtet->tet);
16622 setvolumebound(newtet.tet, volume);
16623 }
16624 }
16625
16626 if (pointtype(insertarray[0]) == UNUSEDVERTEX) {
16627 setpointtype(insertarray[0], FREEVOLVERTEX);
16628 }
16629 if (pointtype(insertarray[1]) == UNUSEDVERTEX) {
16630 setpointtype(insertarray[1], FREEVOLVERTEX);
16631 }
16632 if (pointtype(insertarray[2]) == UNUSEDVERTEX) {
16633 setpointtype(insertarray[2], FREEVOLVERTEX);
16634 }
16635 if (pointtype(lastpt) == UNUSEDVERTEX) {
16636 setpointtype(lastpt, FREEVOLVERTEX);
16637 }
16638
16639 dummytet[0] = encode(newtet);
16640 if (b->verbose > 3) {
16641 printf(" Creating tetra ");
16642 printtet(&newtet);
16643 }
16644
16645 hullsize = 4;
16646
16647 if (b->verbose > 0) {
16648 printf(" Incrementally inserting points.\n");
16649 }
16650
16651 flip23s = flip32s = flip22s = flip44s = 0;
16652 searchtet.tet = (tetrahedron *) NULL;
16653
16654
16655 for (; i < arraysize; i++) {
16656
16657 #ifdef SELF_CHECK
16658 loc_start = clock();
16659 #endif
16660 if (jump) {
16661 loc = locate(insertarray[i], &searchtet);
16662 } else {
16663 loc = preciselocate(insertarray[i], &searchtet, tetrahedrons->items);
16664 }
16665 #ifdef SELF_CHECK
16666 loc_end = clock();
16667 tloctime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16668 #endif
16669
16670 recenttet = searchtet;
16671 if (loc == ONVERTEX) {
16672 if (b->object != tetgenbehavior::STL) {
16673 if (!b->quiet) {
16674 printf("Warning: Point %d is identical with point %d.\n",
16675 pointmark(insertarray[i]), pointmark(org(searchtet)));
16676 }
16677 }
16678
16679 dupverts++;
16680
16681 setpointtype(insertarray[i], DUPLICATEDVERTEX);
16682 if (b->plc || b->refine) {
16683
16684 setpoint2ppt(insertarray[i], org(searchtet));
16685 }
16686 continue;
16687 }
16688 if (merge) {
16689
16690 if (unifypoint(insertarray[i], &searchtet, loc, eps)) {
16691 continue;
16692 }
16693 }
16694
16695 if (loc != OUTSIDE) {
16696 if (b->verbose > 1) {
16697 printf(" Insert point %d in tetrahedralization.\n",
16698 pointmark(insertarray[i]));
16699 }
16700 if (loc == INTETRAHEDRON) {
16701 splittetrahedron(insertarray[i], &searchtet, flipque);
16702 } else if (loc == ONFACE) {
16703 splittetface(insertarray[i], &searchtet, flipque);
16704 } else if (loc == ONEDGE) {
16705 splittetedge(insertarray[i], &searchtet, flipque);
16706 }
16707 } else {
16708 if (b->verbose > 1) {
16709 printf(" Insert point %d on convex hull.\n",
16710 pointmark(insertarray[i]));
16711 }
16712 inserthullsite(insertarray[i], &searchtet, flipque);
16713 }
16714 if (pointtype(insertarray[i]) == UNUSEDVERTEX) {
16715
16716 setpointtype(insertarray[i], FREEVOLVERTEX);
16717 }
16718 #ifdef SELF_CHECK
16719 loc_start = clock();
16720 #endif
16721 if (!b->noflip) {
16722
16723 flip(flipque, NULL);
16724 } else {
16725 lawson(NULL, flipque);
16726
16727
16728 }
16729 #ifdef SELF_CHECK
16730 loc_end = clock();
16731 tfliptime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16732 #endif
16733 }
16734
16735 if (b->verbose > 0) {
16736 printf(" %ld Flips (T23 %ld, T32 %ld, T22 %ld, T44 %ld)\n",
16737 flip23s+flip32s+flip22s+flip44s, flip23s, flip32s, flip22s, flip44s);
16738 }
16739 }
16740
16742
16743
16744
16745
16746
16747
16748
16750
16751 long tetgenmesh::delaunizevertices()
16752 {
16753 queue *flipque;
16754 point *insertarray;
16755 long arraysize;
16756 int i, j;
16757
16758 if (!b->quiet) {
16759 if (!b->noflip) {
16760 printf("Constructing Delaunay tetrahedralization.\n");
16761 } else {
16762 printf("Constructing regular tetrahedralization.\n");
16763 }
16764 }
16765
16766 flipque = new queue(sizeof(badface));
16767
16768 arraysize = points->items;
16769 insertarray = new point[arraysize];
16770 points->traversalinit();
16771
16772
16773
16774 for (i = 0; i < arraysize; i++) {
16775 j = (int) randomnation(i + 1);
16776 insertarray[i] = insertarray[j];
16777 insertarray[j] = pointtraverse();
16778 }
16779
16780
16781 b->noflip = 1;
16782
16783
16784 incrflipdelaunay(NULL, insertarray, arraysize, true, b->plc, b->epsilon,
16785 flipque);
16786
16787 b->noflip = 0;
16788
16789 delete [] insertarray;
16790 delete flipque;
16791 return hullsize;
16792 }
16793
16794
16795
16796
16797
16798
16799
16800
16801
16803
16804
16805
16806
16807
16808
16809
16810
16811
16812
16814
16815 void tetgenmesh::formstarpolygon(point pt, list* trilist, list* vertlist)
16816 {
16817 face steinsh, lnextsh, rnextsh;
16818 face checkseg;
16819 point pa, pb, pc, pd;
16820 int i;
16821
16822
16823 steinsh = * (face *)(* trilist)[0];
16824 steinsh.shver = 0;
16825
16826 for (i = 0; i < 3; i++) {
16827 if (sapex(steinsh) == pt) break;
16828 senextself(steinsh);
16829 }
16830 assert(i < 3);
16831
16832 * (face *)(* trilist)[0] = steinsh;
16833 pa = sorg(steinsh);
16834 pb = sdest(steinsh);
16835 if (vertlist != (list *) NULL) {
16836
16837 vertlist->append(&pa);
16838 vertlist->append(&pb);
16839 }
16840
16841
16842 lnextsh = steinsh;
16843 pc = pa;
16844 do {
16845 senext2self(lnextsh);
16846 assert(sorg(lnextsh) == pt);
16847 sspivot(lnextsh, checkseg);
16848 if (checkseg.sh != dummysh) break;
16849
16850 spivotself(lnextsh);
16851 if (lnextsh.sh == dummysh) break;
16852
16853 if (sdest(lnextsh) != pt) sesymself(lnextsh);
16854 assert(sdest(lnextsh) == pt);
16855 senext2self(lnextsh);
16856
16857 trilist->append(&lnextsh);
16858
16859 pc = sorg(lnextsh);
16860 if (pc == pb) break;
16861 if (vertlist != (list *) NULL) {
16862
16863 vertlist->append(&pc);
16864 }
16865 } while (true);
16866
16867 if (pc != pb) {
16868
16869 rnextsh = steinsh;
16870 do {
16871 senextself(rnextsh);
16872 assert(sdest(rnextsh) == pt);
16873 sspivot(rnextsh, checkseg);
16874 if (checkseg.sh != dummysh) break;
16875
16876 spivotself(rnextsh);
16877 if (rnextsh.sh == dummysh) break;
16878
16879 if (sorg(rnextsh) != pt) sesymself(rnextsh);
16880 assert(sorg(rnextsh) == pt);
16881 senextself(rnextsh);
16882
16883 trilist->append(&rnextsh);
16884
16885 pd = sdest(rnextsh);
16886 if (pd == pa) break;
16887 if (vertlist != (list *) NULL) {
16888
16889 vertlist->append(&pd);
16890 }
16891 } while (true);
16892 }
16893 }
16894
16896
16897
16898
16899
16900
16901
16902
16903
16904
16905
16906
16907
16908
16909
16910
16912
16914
16915
16916
16917
16918
16919
16921
16922 void tetgenmesh::getfacetabovepoint(face* facetsh)
16923 {
16924 list *verlist, *trilist, *tetlist;
16925 triface adjtet;
16926 face symsh;
16927 point p1, p2, p3, pa;
16928 enum locateresult loc;
16929 REAL smallcos, cosa;
16930 REAL largevol, volume;
16931 REAL v1[3], v2[3], len;
16932 int smallidx, largeidx;
16933 int shmark;
16934 int i, j;
16935
16936 abovecount++;
16937
16938 verlist = new list(sizeof(point *), NULL);
16939 trilist = new list(sizeof(face), NULL);
16940 tetlist = new list(sizeof(triface), NULL);
16941
16942
16943
16944
16945
16946 p1 = sorg(*facetsh);
16947 pa = sdest(*facetsh);
16948 if (pointmark(pa) < pointmark(p1)) p1 = pa;
16949 pa = sapex(*facetsh);
16950 if (pointmark(pa) < pointmark(p1)) p1 = pa;
16951
16952 trilist->append(facetsh);
16953 formstarpolygon(p1, trilist, verlist);
16954
16955
16956 p2 = * (point *)(* verlist)[0];
16957
16958 for (i = 0; i < 3; i++) v1[i] = p2[i] - p1[i];
16959 len = sqrt(dot(v1, v1));
16960 assert(len > 0.0);
16961 for (i = 0; i < 3; i++) v1[i] /= len;
16962
16963
16964
16965 smallcos = 1.0;
16966 smallidx = 1;
16967 for (i = 1; i < verlist->len(); i++) {
16968 p3 = * (point *)(* verlist)[i];
16969 for (j = 0; j < 3; j++) v2[j] = p3[j] - p1[j];
16970 len = sqrt(dot(v2, v2));
16971 if (len > 0.0) {
16972 cosa = fabs(dot(v1, v2)) / len;
16973 if (cosa < smallcos) {
16974 smallidx = i;
16975 smallcos = cosa;
16976 }
16977 }
16978 }
16979 assert(smallcos < 1.0);
16980 p3 = * (point *)(* verlist)[smallidx];
16981 verlist->clear();
16982
16983 if (tetrahedrons->items > 0l) {
16984
16985 stpivot(*facetsh, adjtet);
16986 if (adjtet.tet == dummytet) {
16987 sesym(*facetsh, symsh);
16988 stpivot(symsh, adjtet);
16989 }
16990 if (adjtet.tet == dummytet) {
16991 decode(point2tet(p1), adjtet);
16992 if (isdead(&adjtet)) {
16993 adjtet.tet = dummytet;
16994 } else {
16995 if (!findorg(&adjtet, p1)) {
16996 adjtet.tet = dummytet;
16997 }
16998 }
16999 }
17000 if (adjtet.tet == dummytet) {
17001 loc = locate(p1, &adjtet);
17002 if (loc == ONVERTEX) {
17003 setpoint2tet(p1, encode(adjtet));
17004 } else {
17005 adjtet.tet = dummytet;
17006 }
17007 }
17008 if (adjtet.tet != dummytet) {
17009
17010 tetlist->append(&adjtet);
17011 formstarpolyhedron(p1, tetlist, verlist, false);
17012 }
17013 }
17014
17015
17016
17017 largevol = 0.0;
17018 largeidx = 0;
17019 for (i = 0; i < verlist->len(); i++) {
17020 pa = * (point *)(* verlist)[i];
17021 volume = orient3d(p1, p2, p3, pa);
17022 if (!iscoplanar(p1, p2, p3, pa, volume, b->epsilon * 1e+2)) {
17023 if (fabs(volume) > largevol) {
17024 largevol = fabs(volume);
17025 largeidx = i;
17026 }
17027 }
17028 }
17029
17030
17031 if (largevol > 0.0) {
17032 abovepoint = * (point *)(* verlist)[largeidx];
17033 if (b->verbose > 1) {
17034 printf(" Chosen abovepoint %d for facet %d.\n", pointmark(abovepoint),
17035 shellmark(*facetsh));
17036 }
17037 } else {
17038
17039 facenormal(p1, p2, p3, v1, &len);
17040 if (len != 0.0) for (i = 0; i < 3; i++) v1[i] /= len;
17041
17042 len = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
17043
17044 makepoint(&abovepoint);
17045 setpointtype(abovepoint, UNUSEDVERTEX);
17046 unuverts++;
17047 for (i = 0; i < 3; i++) abovepoint[i] = p1[i] + len * v1[i];
17048 if (b->verbose > 1) {
17049 printf(" Calculated abovepoint %d for facet %d.\n",
17050 pointmark(abovepoint), shellmark(*facetsh));
17051 }
17052 }
17053
17054 shmark = shellmark(*facetsh);
17055 facetabovepointarray[shmark] = abovepoint;
17056
17057 delete trilist;
17058 delete tetlist;
17059 delete verlist;
17060 }
17061
17063
17064
17065
17066
17067
17068
17070
17071 void tetgenmesh::collectcavsubs(point newpoint, list* cavsublist)
17072 {
17073 face startsub, neighsub;
17074 face checkseg;
17075 point pa, pb, pc;
17076 REAL sign, ori;
17077 int i, j;
17078
17079
17080 for (i = 0; i < cavsublist->len(); i++) {
17081 startsub = * (face *)(* cavsublist)[i];
17082 sinfect(startsub);
17083 }
17084
17085 for (i = 0; i < cavsublist->len(); i++) {
17086 startsub = * (face *)(* cavsublist)[i];
17087 for (j = 0; j < 3; j++) {
17088 sspivot(startsub, checkseg);
17089
17090 if (checkseg.sh == dummysh) {
17091
17092 spivot(startsub, neighsub);
17093 if (!sinfected(neighsub)) {
17094 pa = sorg(neighsub);
17095 pb = sdest(neighsub);
17096 pc = sapex(neighsub);
17097 sign = insphere(pa, pb, pc, abovepoint, newpoint);
17098 ori = orient3d(pa, pb, pc, abovepoint);
17099 if (sign != 0.0) {
17100
17101 sign = ori > 0.0 ? sign : -sign;
17102 }
17103 if (sign > 0.0) {
17104
17105 sinfect(neighsub);
17106 cavsublist->append(&neighsub);
17107 }
17108 }
17109 }
17110 senextself(startsub);
17111 }
17112 }
17113
17114 for (i = 0; i < cavsublist->len(); i++) {
17115 startsub = * (face *)(* cavsublist)[i];
17116 suninfect(startsub);
17117 }
17118 }
17119
17121
17122
17123
17124
17125
17126
17127
17128
17129
17131
17132 void tetgenmesh::collectvisiblesubs(int shmark, point inspoint, face* horiz,
17133 queue* flipqueue)
17134 {
17135 face newsh, hullsh;
17136 face rightsh, leftsh, spinedge;
17137 point horg, hdest;
17138 bool aboveflag;
17139 REAL ori, sign;
17140
17141
17142 adjustedgering(*horiz, CCW);
17143 horg = sorg(*horiz);
17144 hdest = sdest(*horiz);
17145 ori = orient3d(horg, hdest, sapex(*horiz), abovepoint);
17146 sign = ori > 0.0 ? -1 : 1;
17147
17148
17149 makeshellface(subfaces, &newsh);
17150 setsorg(newsh, hdest);
17151 setsdest(newsh, horg);
17152 setsapex(newsh, inspoint);
17153 setshellmark(newsh, shmark);
17154 if (b->quality && varconstraint) {
17155 setareabound(newsh, areabound(*horiz));
17156 }
17157 if (checkpbcs) {
17158 setshellpbcgroup(newsh, shellpbcgroup(*horiz));
17159 }
17160
17161 sbond(newsh, *horiz);
17162
17163 enqueueflipedge(*horiz, flipqueue);
17164
17165
17166 hullsh = *horiz;
17167 while (1) {
17168 senext(newsh, rightsh);
17169
17170
17171 spinedge = hullsh;
17172 do {
17173 hullsh = spinedge;
17174 senext2self(hullsh);
17175 spivot(hullsh, spinedge);
17176 if (spinedge.sh == dummysh) break;
17177 if (sorg(spinedge) != horg) sesymself(spinedge);
17178 assert(sorg(spinedge) == horg);
17179 } while (true);
17180 horg = sorg(hullsh);
17181
17182 ori = orient3d(horg, sdest(hullsh), abovepoint, inspoint);
17183 ori *= sign;
17184 aboveflag = ori < 0.0;
17185 if (aboveflag) {
17186
17187 makeshellface(subfaces, &newsh);
17188 setsorg(newsh, sdest(hullsh));
17189 setsdest(newsh, horg);
17190 setsapex(newsh, inspoint);
17191 setshellmark(newsh, shmark);
17192 if (b->quality && varconstraint) {
17193 setareabound(newsh, areabound(hullsh));
17194 }
17195 if (checkpbcs) {
17196 setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17197 }
17198
17199 sbond(newsh, hullsh);
17200 senext2(newsh, leftsh);
17201 sbond(leftsh, rightsh);
17202
17203 enqueueflipedge(hullsh, flipqueue);
17204 } else {
17205
17206 dummysh[0] = sencode(rightsh);
17207 break;
17208 }
17209 }
17210
17211
17212 hullsh = *horiz;
17213 spivot(*horiz, newsh);
17214 while (1) {
17215 senext2(newsh, leftsh);
17216
17217 spinedge = hullsh;
17218 do {
17219 hullsh = spinedge;
17220 senextself(hullsh);
17221 spivot(hullsh, spinedge);
17222 if (spinedge.sh == dummysh) break;
17223 if (sdest(spinedge) != hdest) sesymself(spinedge);
17224 assert(sdest(spinedge) == hdest);
17225 } while (true);
17226
17227 hdest = sdest(hullsh);
17228
17229 ori = orient3d(sorg(hullsh), hdest, abovepoint, inspoint);
17230 ori *= sign;
17231 aboveflag = ori < 0.0;
17232 if (aboveflag) {
17233
17234 makeshellface(subfaces, &newsh);
17235 setsorg(newsh, hdest);
17236 setsdest(newsh, sorg(hullsh));
17237 setsapex(newsh, inspoint);
17238 setshellmark(newsh, shmark);
17239 if (b->quality && varconstraint) {
17240 setareabound(newsh, areabound(hullsh));
17241 }
17242 if (checkpbcs) {
17243 setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17244 }
17245
17246 sbond(newsh, hullsh);
17247 senext(newsh, rightsh);
17248 sbond(rightsh, leftsh);
17249
17250 enqueueflipedge(hullsh, flipqueue);
17251 } else {
17252
17253 dummysh[0] = sencode(leftsh);
17254 break;
17255 }
17256 }
17257 }
17258
17260
17261
17262
17263
17264
17265
17266
17268
17269 void tetgenmesh::incrflipdelaunaysub(int shmark, REAL eps, list* ptlist,
17270 int holes, REAL* holelist, queue* flipque)
17271 {
17272 face newsh, startsh;
17273 point *insertarray;
17274 point swappt;
17275 pbcdata *pd;
17276 enum locateresult loc;
17277 REAL det, area;
17278 bool aboveflag;
17279 int arraysize;
17280 int epscount;
17281 int fmarker;
17282 int idx, i, j, k;
17283
17284
17285 insertarray = (point *) ptlist->base;
17286 arraysize = ptlist->len();
17287 if (arraysize < 3) return;
17288
17289
17290 aboveflag = (arraysize > 3);
17291
17292
17293
17294
17295
17296 epscount = 0;
17297 while (true) {
17298 for (i = 1; i < arraysize; i++) {
17299 det = distance(insertarray[0], insertarray[i]);
17300 if (det > (longest * eps)) break;
17301 }
17302 if (i < arraysize) {
17303
17304 swappt = insertarray[i];
17305 insertarray[i] = insertarray[1];
17306 insertarray[1] = swappt;
17307 }
17308
17309 for (i++; i < arraysize; i++) {
17310 if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
17311 break;
17312 }
17313 if (i < arraysize) {
17314
17315 swappt = insertarray[i];
17316 insertarray[i] = insertarray[2];
17317 insertarray[2] = swappt;
17318 i = 3;
17319 } else {
17320
17321
17322
17323 if ((eps == 0.0) || (epscount > 16)) {
17324 printf("Error: Invalid PLC.\n");
17325 printf(" Facet (%d, %d, %d", pointmark(insertarray[0]),
17326 pointmark(insertarray[1]), pointmark(insertarray[2]));
17327 if (ptlist->len() > 3) {
17328 printf(", ...");
17329 }
17330 printf(") (%d) is not a valid polygon.\n", shmark);
17331 terminatetetgen(1);
17332 }
17333
17334 eps *= 1e-2;
17335 epscount++;
17336 continue;
17337 }
17338 break;
17339 }
17340
17341
17342 makeshellface(subfaces, &newsh);
17343 setsorg(newsh, insertarray[0]);
17344 setsdest(newsh, insertarray[1]);
17345 setsapex(newsh, insertarray[2]);
17346
17347 setshellmark(newsh, shmark);
17348
17349 if (pointtype(insertarray[0]) == FREEVOLVERTEX) {
17350 setpointtype(insertarray[0], FREESUBVERTEX);
17351 }
17352 if (pointtype(insertarray[1]) == FREEVOLVERTEX) {
17353 setpointtype(insertarray[1], FREESUBVERTEX);
17354 }
17355 if (pointtype(insertarray[2]) == FREEVOLVERTEX) {
17356 setpointtype(insertarray[2], FREESUBVERTEX);
17357 }
17358
17359 dummysh[0] = sencode(newsh);
17360
17361
17362 if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
17363 idx = in->facetmarkerlist[shmark - 1];
17364 for (k = 0; k < in->numberoffacetconstraints; k++) {
17365 fmarker = (int) in->facetconstraintlist[k * 2];
17366 if (fmarker == idx) {
17367 area = in->facetconstraintlist[k * 2 + 1];
17368 setareabound(newsh, area);
17369 break;
17370 }
17371 }
17372 }
17373
17374
17375 if (checkpbcs) {
17376 idx = in->facetmarkerlist[shmark - 1];
17377 for (k = 0; k < in->numberofpbcgroups; k++) {
17378 pd = &subpbcgrouptable[k];
17379 for (j = 0; j < 2; j++) {
17380 if (pd->fmark[j] == idx) {
17381 setshellpbcgroup(newsh, k);
17382 pd->ss[j] = newsh;
17383 }
17384 }
17385 }
17386 }
17387
17388 if (aboveflag) {
17389
17390 abovepoint = facetabovepointarray[shmark];
17391 if (abovepoint == (point) NULL) {
17392 getfacetabovepoint(&newsh);
17393 }
17394 }
17395
17396 if (holes > 0) {
17397
17398 REAL prj[3];
17399 for (k = 0; k < holes; k++) {
17400 projpt2face(&(holelist[k * 3]), insertarray[0], insertarray[1],
17401 insertarray[2], prj);
17402 for (j = 0; j < 3; j++) holelist[k * 3 + j] = prj[j];
17403 }
17404 }
17405
17406
17407 for (; i < arraysize; i++) {
17408
17409 startsh.sh = dummysh;
17410 loc = locatesub(insertarray[i], &startsh, 0, 0.0);
17411 if (loc == ONFACE) {
17412 splitsubface(insertarray[i], &startsh, flipque);
17413 } else if (loc == ONEDGE) {
17414 splitsubedge(insertarray[i], &startsh, flipque);
17415 } else if (loc == OUTSIDE) {
17416 collectvisiblesubs(shmark, insertarray[i], &startsh, flipque);
17417 } else if (loc == ONVERTEX) {
17418
17419 }
17420
17421 if (pointtype(insertarray[i]) == FREEVOLVERTEX) {
17422 setpointtype(insertarray[i], FREESUBVERTEX);
17423 }
17424 flipsub(flipque);
17425 }
17426 }
17427
17429
17430
17431
17432
17433
17434
17435
17436
17437
17438
17439
17440
17442
17443 enum tetgenmesh::finddirectionresult tetgenmesh::finddirectionsub(
17444 face* searchsh, point tend)
17445 {
17446 face checksh;
17447 point startpoint, leftpoint, rightpoint;
17448 REAL leftccw, rightccw;
17449 REAL ori, sign;
17450 int leftflag, rightflag;
17451
17452 startpoint = sorg(*searchsh);
17453
17454 adjustedgering(*searchsh, CCW);
17455
17456 if (sorg(*searchsh) != startpoint) senextself(*searchsh);
17457 rightpoint = sdest(*searchsh);
17458 leftpoint = sapex(*searchsh);
17459 ori = orient3d(startpoint, rightpoint, leftpoint, abovepoint);
17460 sign = ori > 0.0 ? -1 : 1;
17461
17462
17463 ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17464 leftccw = ori * sign;
17465 leftflag = leftccw > 0.0;
17466
17467 ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17468 rightccw = ori * sign;
17469 rightflag = rightccw > 0.0;
17470 if (leftflag && rightflag) {
17471
17472
17473 senext2(*searchsh, checksh);
17474 spivotself(checksh);
17475 if (checksh.sh == dummysh) {
17476 leftflag = 0;
17477 } else {
17478 rightflag = 0;
17479 }
17480 }
17481 while (leftflag) {
17482
17483 senext2self(*searchsh);
17484 spivotself(*searchsh);
17485 if (searchsh->sh == dummysh) {
17486 printf("Internal error in finddirectionsub(): Unable to find a\n");
17487 printf(" subface leading from %d to %d.\n", pointmark(startpoint),
17488 pointmark(tend));
17489 internalerror();
17490 }
17491 if (sorg(*searchsh) != startpoint) sesymself(*searchsh);
17492 assert(sorg(*searchsh) == startpoint);
17493 leftpoint = sapex(*searchsh);
17494 rightccw = leftccw;
17495 ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17496 leftccw = ori * sign;
17497 leftflag = leftccw > 0.0;
17498 }
17499 while (rightflag) {
17500
17501 spivotself(*searchsh);
17502 if (searchsh->sh == dummysh) {
17503 printf("Internal error in finddirectionsub(): Unable to find a\n");
17504 printf(" subface leading from %d to %d.\n", pointmark(startpoint),
17505 pointmark(tend));
17506 internalerror();
17507 }
17508 if (sdest(*searchsh) != startpoint) sesymself(*searchsh);
17509 assert(sdest(*searchsh) == startpoint);
17510 senextself(*searchsh);
17511 rightpoint = sdest(*searchsh);
17512 leftccw = rightccw;
17513 ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17514 rightccw = ori * sign;
17515 rightflag = rightccw > 0.0;
17516 }
17517 if (leftccw == 0.0) {
17518 return LEFTCOLLINEAR;
17519 } else if (rightccw == 0.0) {
17520 return RIGHTCOLLINEAR;
17521 } else {
17522 return ACROSSEDGE;
17523 }
17524 }
17525
17527
17528
17529
17530
17531
17532
17533
17534
17536
17537 void tetgenmesh::insertsubseg(face* tri)
17538 {
17539 face oppotri;
17540 face newsubseg;
17541 point pa, pb;
17542 REAL len;
17543 int e1, e2;
17544 int i;
17545
17546
17547 sspivot(*tri, newsubseg);
17548 if (newsubseg.sh == dummysh) {
17549
17550 makeshellface(subsegs, &newsubseg);
17551 pa = sorg(*tri);
17552 pb = sdest(*tri);
17553 setsorg(newsubseg, pa);
17554 setsdest(newsubseg, pb);
17555
17556 if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
17557 for (i = 0; i < in->numberofsegmentconstraints; i++) {
17558 e1 = (int) in->segmentconstraintlist[i * 3];
17559 e2 = (int) in->segmentconstraintlist[i * 3 + 1];
17560 if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
17561 ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
17562 len = in->segmentconstraintlist[i * 3 + 2];
17563 setareabound(newsubseg, len);
17564 break;
17565 }
17566 }
17567 }
17568
17569 ssbond(*tri, newsubseg);
17570 spivot(*tri, oppotri);
17571
17572 if (oppotri.sh != dummysh) {
17573 ssbond(oppotri, newsubseg);
17574 }
17575
17576
17577
17578 }
17579 }
17580
17582
17583
17584
17585
17586
17587
17588
17589
17590
17592
17593 bool tetgenmesh::scoutsegmentsub(face* searchsh, point tend)
17594 {
17595 face newsubseg;
17596 face crosssub, crosssubseg;
17597 point leftpoint, rightpoint;
17598 enum finddirectionresult collinear;
17599
17600 collinear = finddirectionsub(searchsh, tend);
17601 rightpoint = sdest(*searchsh);
17602 leftpoint = sapex(*searchsh);
17603 if (rightpoint == tend || leftpoint == tend) {
17604
17605 if (leftpoint == tend) {
17606 senext2self(*searchsh);
17607 }
17608
17609 insertsubseg(searchsh);
17610 return true;
17611 } else if (collinear == LEFTCOLLINEAR) {
17612
17613
17614 senextself(*searchsh);
17615
17616 insertsubseg(searchsh);
17617
17618 return scoutsegmentsub(searchsh, tend);
17619 } else if (collinear == RIGHTCOLLINEAR) {
17620
17621
17622 insertsubseg(searchsh);
17623
17624 senextself(*searchsh);
17625
17626 return scoutsegmentsub(searchsh, tend);
17627 } else {
17628 senext(*searchsh, crosssub);
17629
17630 sspivot(crosssub, crosssubseg);
17631 #ifdef SELF_CHECK
17632 assert(crosssubseg.sh == dummysh);
17633 #endif
17634 return false;
17635 }
17636 }
17637
17639
17640
17641
17642
17643
17644
17645
17646
17647
17649
17650 void tetgenmesh::flipedgerecursive(face* flipedge, queue* flipqueue)
17651 {
17652 face fixupsh;
17653 point pa, pb, pc, pd;
17654 REAL oria, orib;
17655 bool doflip;
17656
17657 pa = sorg(*flipedge);
17658 pb = sdest(*flipedge);
17659 pc = sapex(*flipedge);
17660 do {
17661 spivot(*flipedge, fixupsh);
17662 pd = sapex(fixupsh);
17663 oria = orient3d(pc, pd, abovepoint, pa);
17664 orib = orient3d(pc, pd, abovepoint, pb);
17665 doflip = (oria * orib < 0.0);
17666 if (doflip) {
17667
17668 flip22sub(flipedge, flipqueue);
17669
17670 findedge(flipedge, pc, pd);
17671 } else {
17672
17673 if (sorg(fixupsh) != pb) sesymself(fixupsh);
17674 assert(sdest(fixupsh) == pa);
17675 if (fabs(oria) > fabs(orib)) {
17676
17677 senextself(fixupsh);
17678 } else {
17679
17680 senext2self(fixupsh);
17681 }
17682
17683 flipedgerecursive(&fixupsh, flipqueue);
17684 }
17685 } while (!doflip);
17686 }
17687
17689
17690
17691
17692
17693
17694
17695
17696
17697
17699
17700 void tetgenmesh::constrainededge(face* startsh, point tend, queue* flipqueue)
17701 {
17702 point tstart, tright, tleft;
17703 REAL rori, lori;
17704 bool collision;
17705
17706 tstart = sorg(*startsh);
17707 do {
17708
17709 do {
17710 tright = sdest(*startsh);
17711 tleft = sapex(*startsh);
17712
17713 rori = orient3d(tstart, tright, abovepoint, tend);
17714 collision = (rori == 0.0);
17715 if (collision) break;
17716 lori = orient3d(tstart, tleft, abovepoint, tend);
17717 collision = (lori == 0.0);
17718 if (collision) {
17719 senext2self(*startsh);
17720 break;
17721 }
17722 if (rori * lori < 0.0) break;
17723
17724 finddirectionsub(startsh, tend);
17725 } while (true);
17726 if (collision) break;
17727
17728 senextself(*startsh);
17729
17730 flipedgerecursive(startsh, flipqueue);
17731
17732 assert(sorg(*startsh) == tstart);
17733 } while (sdest(*startsh) != tend);
17734
17735
17736 insertsubseg(startsh);
17737
17738
17739 if (collision) {
17740
17741 if (!scoutsegmentsub(startsh, tend)) {
17742 constrainededge(startsh, tend, flipqueue);
17743 }
17744 }
17745 }
17746
17748
17749
17750
17752
17753 void tetgenmesh::recoversegment(point tstart, point tend, queue* flipqueue)
17754 {
17755 face searchsh;
17756
17757 if (b->verbose > 2) {
17758 printf(" Insert seg (%d, %d).\n", pointmark(tstart), pointmark(tend));
17759 }
17760
17761
17762 searchsh.sh = dummysh;
17763
17764 if (locatesub(tstart, &searchsh, 0, 0.0) != ONVERTEX) {
17765
17766 list *newshlist;
17767 int i, j;
17768 newshlist = new list(sizeof(face), NULL, 256);
17769
17770 retrievenewsubs(newshlist, false);
17771
17772 for (i = 0; i < newshlist->len(); i++) {
17773 searchsh = * (face *)(* newshlist)[i];
17774 for (j = 0; j < 3; j++) {
17775 if (sorg(searchsh) == tstart) break;
17776 senextself(searchsh);
17777 }
17778 if (j < 3) break;
17779 }
17780 delete newshlist;
17781 if (sorg(searchsh) != tstart) {
17782 printf("Internal error in recoversegment(): Vertex location failed.\n");
17783 internalerror();
17784 }
17785 }
17786
17787 if (scoutsegmentsub(&searchsh, tend)) {
17788
17789 return;
17790 }
17791
17792 constrainededge(&searchsh, tend, flipqueue);
17793
17794 flipsub(flipqueue);
17795 }
17796
17798
17799
17800
17801
17803
17804 void tetgenmesh::infecthullsub(memorypool* viri)
17805 {
17806 face hulltri, nexttri, starttri;
17807 face hullsubseg;
17808 shellface **deadshellface;
17809
17810
17811 hulltri.sh = dummysh;
17812 hulltri.shver = 0;
17813 spivotself(hulltri);
17814 adjustedgering(hulltri, CCW);
17815
17816 starttri = hulltri;
17817
17818 do {
17819
17820 if (!sinfected(hulltri)) {
17821
17822 sspivot(hulltri, hullsubseg);
17823 if (hullsubseg.sh == dummysh) {
17824
17825 if (!sinfected(hulltri)) {
17826 sinfect(hulltri);
17827 deadshellface = (shellface **) viri->alloc();
17828 *deadshellface = hulltri.sh;
17829 }
17830 }
17831 }
17832
17833 senextself(hulltri);
17834 spivot(hulltri, nexttri);
17835 if (nexttri.sh == hulltri.sh) {
17836 nexttri.sh = dummysh;
17837 } else {
17838 adjustedgering(nexttri, CCW);
17839 senextself(nexttri);
17840 }
17841 while (nexttri.sh != dummysh) {
17842 hulltri = nexttri;
17843 spivot(hulltri, nexttri);
17844 if (nexttri.sh == hulltri.sh) {
17845 nexttri.sh = dummysh;
17846 } else {
17847 adjustedgering(nexttri, CCW);
17848 senextself(nexttri);
17849 }
17850 }
17851 } while (hulltri != starttri);
17852 }
17853
17855
17856
17857
17858
17859
17860
17861
17863
17864 void tetgenmesh::plaguesub(memorypool* viri)
17865 {
17866 face testtri, neighbor, ghostsh;
17867 face neighborsubseg;
17868 shellface **virusloop;
17869 shellface **deadshellface;
17870 int i;
17871
17872
17873
17874 viri->traversalinit();
17875 virusloop = (shellface **) viri->traverse();
17876 while (virusloop != (shellface **) NULL) {
17877 testtri.sh = *virusloop;
17878
17879 for (i = 0; i < 3; i++) {
17880
17881 spivot(testtri, neighbor);
17882
17883 sspivot(testtri, neighborsubseg);
17884
17885 if ((neighbor.sh == dummysh) || sinfected(neighbor)) {
17886 if (neighborsubseg.sh != dummysh) {
17887
17888
17889
17890 shellfacedealloc(subsegs, neighborsubseg.sh);
17891 if (neighbor.sh != dummysh) {
17892
17893
17894 ssdissolve(neighbor);
17895 }
17896 }
17897 } else {
17898 if (neighborsubseg.sh == dummysh) {
17899
17900
17901 sinfect(neighbor);
17902
17903 deadshellface = (shellface **) viri->alloc();
17904 *deadshellface = neighbor.sh;
17905 } else {
17906
17907 ssbond(neighbor, neighborsubseg);
17908 }
17909 }
17910 senextself(testtri);
17911 }
17912 virusloop = (shellface **) viri->traverse();
17913 }
17914
17915 ghostsh.sh = dummysh;
17916 viri->traversalinit();
17917 virusloop = (shellface **) viri->traverse();
17918 while (virusloop != (shellface **) NULL) {
17919 testtri.sh = *virusloop;
17920
17921
17922 for (i = 0; i < 3; i++) {
17923 spivot(testtri, neighbor);
17924 if (neighbor.sh != dummysh) {
17925
17926
17927 sbond(neighbor, ghostsh);
17928 }
17929 senextself(testtri);
17930 }
17931
17932 shellfacedealloc(subfaces, testtri.sh);
17933 virusloop = (shellface **) viri->traverse();
17934 }
17935
17936 viri->restart();
17937 }
17938
17940
17941
17942
17943
17944
17945
17946
17947
17949
17950 void tetgenmesh::carveholessub(int holes, REAL* holelist, memorypool *viri)
17951 {
17952 face searchtri, triangleloop;
17953 shellface **holetri;
17954 enum locateresult intersect;
17955 int i;
17956
17957
17958
17959 infecthullsub(viri);
17960
17961 if (holes > 0) {
17962
17963 for (i = 0; i < 3 * holes; i += 3) {
17964
17965 if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
17966 && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)
17967 && (holelist[i + 2] >= zmin) && (holelist[i + 2] <= zmax)) {
17968
17969 searchtri.sh = dummysh;
17970
17971 intersect = locatesub(&holelist[i], &searchtri, 0, 0.0);
17972 if ((intersect != OUTSIDE) && (!sinfected(searchtri))) {
17973
17974
17975 sinfect(searchtri);
17976 holetri = (shellface **) viri->alloc();
17977 *holetri = searchtri.sh;
17978 }
17979 }
17980 }
17981 }
17982
17983 if (viri->items > 0) {
17984
17985 plaguesub(viri);
17986 }
17987
17988 }
17989
17991
17992
17993
17994
17995
17996
17997
17998
17999
18000
18001
18002
18003
18004
18005
18007
18008 void tetgenmesh::triangulate(int shmark, REAL eps, list* ptlist, list* conlist,
18009 int holes, REAL* holelist, memorypool* viri, queue* flipqueue)
18010 {
18011 face newsh;
18012 point *cons;
18013 int i;
18014
18015 if (b->verbose > 1) {
18016 printf(" %d vertices, %d segments", ptlist->len(), conlist->len());
18017 if (holes > 0) {
18018 printf(", %d holes", holes);
18019 }
18020 printf(", shmark: %d.\n", shmark);
18021 }
18022
18023
18024 incrflipdelaunaysub(shmark, eps, ptlist, holes, holelist, flipqueue);
18025
18026 if (ptlist->len() > 3) {
18027
18028 for (i = 0; i < conlist->len(); i++) {
18029 cons = (point *)(* conlist)[i];
18030 recoversegment(cons[0], cons[1], flipqueue);
18031 }
18032
18033 carveholessub(holes, holelist, viri);
18034 } else if (ptlist->len() == 3) {
18035
18036 newsh.sh = dummysh;
18037 newsh.shver = 0;
18038 spivotself(newsh);
18039 for (i = 0; i < 3; i++) {
18040 insertsubseg(&newsh);
18041 senextself(newsh);
18042 }
18043 } else if (ptlist->len() == 2) {
18044
18045
18046
18047 cons = (point *)(* conlist)[0];
18048 makeshellface(subsegs, &newsh);
18049 setsorg(newsh, cons[0]);
18050 setsdest(newsh, cons[1]);
18051 }
18052 }
18053
18055
18056
18057
18058
18059
18060
18061
18062
18063
18064
18066
18067 void tetgenmesh::retrievenewsubs(list* newshlist, bool removeseg)
18068 {
18069 face startsh, neighsh;
18070 face deadseg;
18071 int i, j;
18072
18073
18074 startsh.sh = dummysh;
18075 startsh.shver = 0;
18076 spivotself(startsh);
18077 assert(startsh.sh != dummysh);
18078 sinfect(startsh);
18079 newshlist->append(&startsh);
18080
18081
18082 for (i = 0; i < newshlist->len(); i++) {
18083
18084 startsh = * (face *)(* newshlist)[i];
18085 for (j = 0; j < 3; j++) {
18086 spivot(startsh, neighsh);
18087 if (neighsh.sh != dummysh) {
18088 if (!sinfected(neighsh)) {
18089
18090 sinfect(neighsh);
18091 newshlist->append(&neighsh);
18092 }
18093 } else {
18094
18095 if (removeseg) {
18096
18097 sspivot(startsh, deadseg);
18098 if (deadseg.sh != dummysh) {
18099
18100 ssdissolve(startsh);
18101
18102 shellfacedealloc(subsegs, deadseg.sh);
18103 }
18104 }
18105 }
18106 senextself(startsh);
18107 }
18108 }
18109 for (i = 0; i < newshlist->len(); i++) {
18110 startsh = * (face *)(* newshlist)[i];
18111 suninfect(startsh);
18112 }
18113 }
18114
18116
18117
18118
18119
18120
18121
18122
18123
18124
18125
18126
18127
18128
18129
18131
18132 void tetgenmesh::unifysegments()
18133 {
18134 list *sfacelist;
18135 shellface **facesperverlist;
18136 face subsegloop, testseg;
18137 face sface, sface1, sface2;
18138 point torg, tdest;
18139 REAL da1, da2;
18140 int *idx2facelist;
18141 int segmarker;
18142 int idx, k, m;
18143
18144 if (b->verbose > 0) {
18145 printf(" Unifying segments.\n");
18146 }
18147
18148
18149 makesubfacemap(idx2facelist, facesperverlist);
18150
18151 sfacelist = new list(sizeof(face), NULL);
18152
18153 segmarker = 1;
18154 subsegs->traversalinit();
18155 subsegloop.sh = shellfacetraverse(subsegs);
18156 while (subsegloop.sh != (shellface *) NULL) {
18157 subsegloop.shver = 0;
18158 torg = sorg(subsegloop);
18159 tdest = sdest(subsegloop);
18160 idx = pointmark(torg) - in->firstnumber;
18161
18162
18163
18164
18165 for (k = idx2facelist[idx]; k < idx2facelist[idx + 1]; k++) {
18166 sface.sh = facesperverlist[k];
18167 sface.shver = 0;
18168
18169 if (!isdead(&sface) && isfacehasedge(&sface, torg, tdest)) {
18170
18171 findedge(&sface, torg, tdest);
18172
18173 if (sfacelist->len() < 2) {
18174 sfacelist->append(&sface);
18175 } else {
18176 for (m = 0; m < sfacelist->len() - 1; m++) {
18177 sface1 = * (face *)(* sfacelist)[m];
18178 sface2 = * (face *)(* sfacelist)[m + 1];
18179 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(sface));
18180 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
18181 if (da1 < da2) {
18182 break;
18183 }
18184 }
18185 sfacelist->insert(m + 1, &sface);
18186 }
18187 }
18188 }
18189 if (b->verbose > 1) {
18190 printf(" Identifying %d segments of (%d %d).\n", sfacelist->len(),
18191 pointmark(torg), pointmark(tdest));
18192 }
18193
18194
18195 for (k = 0; k < sfacelist->len(); k++) {
18196 sface = *(face *)(* sfacelist)[k];
18197 sspivot(sface, testseg);
18198
18199
18200
18201 if ((testseg.sh != subsegloop.sh) && !isdead(&testseg)) {
18202 shellfacedealloc(subsegs, testseg.sh);
18203 }
18204
18205
18206 ssbond(sface, subsegloop);
18207 }
18208
18209 sface = *(face *)(* sfacelist)[0];
18210 for (k = 1; k <= sfacelist->len(); k++) {
18211 if (k < sfacelist->len()) {
18212 sface1 = *(face *)(* sfacelist)[k];
18213 } else {
18214 sface1 = *(face *)(* sfacelist)[0];
18215 }
18216
18217
18218
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 if (b->verbose > 2) {
18244 printf(" Bond subfaces (%d, %d, %d) and (%d, %d, %d).\n",
18245 pointmark(torg), pointmark(tdest), pointmark(sapex(sface)),
18246 pointmark(torg), pointmark(tdest), pointmark(sapex(sface1)));
18247 }
18248 sbond1(sface, sface1);
18249 sface = sface1;
18250 }
18251
18252 setshellmark(subsegloop, segmarker);
18253
18254 segmarker++;
18255
18256 sfacelist->clear();
18257 subsegloop.sh = shellfacetraverse(subsegs);
18258 }
18259
18260 delete [] idx2facelist;
18261 delete [] facesperverlist;
18262 delete sfacelist;
18263 }
18264
18266
18267
18268
18269
18270
18271
18272
18273
18274
18276
18277 void tetgenmesh::mergefacets(queue* flipqueue)
18278 {
18279 face parentsh, neighsh, neineighsh;
18280 face segloop;
18281 point eorg, edest;
18282 REAL ori;
18283 bool mergeflag, pbcflag;
18284 int* segspernodelist;
18285 int fidx1, fidx2;
18286 int i, j;
18287
18288 if (b->verbose > 0) {
18289 printf(" Merging coplanar facets.\n");
18290 }
18291
18292 segspernodelist = new int[points->items + 1];
18293 for (i = 0; i < points->items + 1; i++) segspernodelist[i] = 0;
18294
18295
18296 subsegs->traversalinit();
18297 segloop.sh = shellfacetraverse(subsegs);
18298 while (segloop.sh != (shellface *) NULL) {
18299
18300 for (i = 0; i < 2; i++) {
18301 j = pointmark((point) segloop.sh[3 + i]);
18302 segspernodelist[j]++;
18303 }
18304 segloop.sh = shellfacetraverse(subsegs);
18305 }
18306
18307
18308 subsegs->traversalinit();
18309 segloop.sh = shellfacetraverse(subsegs);
18310 while (segloop.sh != (shellface *) NULL) {
18311 eorg = sorg(segloop);
18312 edest = sdest(segloop);
18313 spivot(segloop, parentsh);
18314 spivot(parentsh, neighsh);
18315 spivot(neighsh, neineighsh);
18316 if (parentsh.sh != neighsh.sh && parentsh.sh == neineighsh.sh) {
18317
18318 fidx1 = shellmark(parentsh) - 1;
18319 fidx2 = shellmark(neighsh) - 1;
18320 pbcflag = false;
18321 if (checkpbcs) {
18322 pbcflag = (shellpbcgroup(parentsh) >= 0)
18323 || (shellpbcgroup(neighsh) >= 0);
18324 }
18325
18326 if ((fidx1 != fidx2) && !pbcflag) {
18327
18328 ori = orient3d(eorg, edest, sapex(parentsh), sapex(neighsh));
18329 if (ori != 0.0) {
18330 if (iscoplanar(eorg, edest, sapex(parentsh), sapex(neighsh), ori,
18331 b->epsilon)) {
18332 ori = 0.0;
18333 }
18334 }
18335 if (ori == 0.0) {
18336 mergeflag = (in->facetmarkerlist == (int *) NULL ||
18337 in->facetmarkerlist[fidx1] == in->facetmarkerlist[fidx2]);
18338 if (mergeflag) {
18339
18340 if (b->verbose > 1) {
18341 printf(" Removing segment (%d, %d).\n", pointmark(eorg),
18342 pointmark(edest));
18343 }
18344 ssdissolve(parentsh);
18345 ssdissolve(neighsh);
18346 shellfacedealloc(subsegs, segloop.sh);
18347 j = pointmark(eorg);
18348 segspernodelist[j]--;
18349 if (segspernodelist[j] == 0) {
18350 setpointtype(eorg, FREESUBVERTEX);
18351 }
18352 j = pointmark(edest);
18353 segspernodelist[j]--;
18354 if (segspernodelist[j] == 0) {
18355 setpointtype(edest, FREESUBVERTEX);
18356 }
18357
18358 enqueueflipedge(parentsh, flipqueue);
18359 }
18360 }
18361 }
18362 }
18363 segloop.sh = shellfacetraverse(subsegs);
18364 }
18365
18366 if (!flipqueue->empty()) {
18367
18368 flipsub(flipqueue);
18369 }
18370
18371 delete [] segspernodelist;
18372 }
18373
18375
18376
18377
18378
18379
18380
18381
18382
18383
18384
18385
18386
18387
18388
18389
18390
18391
18393
18394 long tetgenmesh::meshsurface()
18395 {
18396 list *ptlist, *conlist;
18397 queue *flipqueue;
18398 tetgenio::facet *f;
18399 tetgenio::polygon *p;
18400 memorypool *viri;
18401 point *idx2verlist;
18402 point tstart, tend, *cons;
18403 int *worklist;
18404 int end1, end2;
18405 int shmark, i, j;
18406
18407 if (!b->quiet) {
18408 printf("Creating surface mesh.\n");
18409 }
18410
18411
18412 makeindex2pointmap(idx2verlist);
18413
18414 makepoint2tetmap();
18415
18416 facetabovepointarray = new point[in->numberoffacets + 1];
18417 for (i = 0; i < in->numberoffacets + 1; i++) {
18418 facetabovepointarray[i] = (point) NULL;
18419 }
18420 if (checkpbcs) {
18421
18422 createsubpbcgrouptable();
18423 }
18424
18425
18426 viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
18427 flipqueue = new queue(sizeof(badface));
18428 ptlist = new list(sizeof(point *), NULL, 256);
18429 conlist = new list(sizeof(point *) * 2, NULL, 256);
18430 worklist = new int[points->items + 1];
18431 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
18432
18433
18434
18435
18436 for (shmark = 1; shmark <= in->numberoffacets; shmark++) {
18437
18438 f = &in->facetlist[shmark - 1];
18439
18440
18441
18442
18443
18444 if ((b->object == tetgenbehavior::STL) || dupverts) {
18445
18446 for (i = 0; i < f->numberofpolygons; i++) {
18447 p = &(f->polygonlist[i]);
18448
18449 for (j = 0; j < p->numberofvertices; j++) {
18450 end1 = p->vertexlist[j];
18451 tstart = idx2verlist[end1 - in->firstnumber];
18452 if (pointtype(tstart) == DUPLICATEDVERTEX) {
18453
18454 tend = point2ppt(tstart);
18455 end2 = pointmark(tend);
18456 p->vertexlist[j] = end2;
18457 }
18458 }
18459 }
18460 }
18461
18462
18463 for (i = 0; i < f->numberofpolygons; i++) {
18464
18465 p = &(f->polygonlist[i]);
18466
18467 end1 = p->vertexlist[0];
18468 if ((end1 < in->firstnumber) ||
18469 (end1 >= in->firstnumber + in->numberofpoints)) {
18470 if (!b->quiet) {
18471 printf("Warning: Invalid the 1st vertex %d of polygon", end1);
18472 printf(" %d in facet %d.\n", i + 1, shmark);
18473 }
18474 continue;
18475 }
18476 tstart = idx2verlist[end1 - in->firstnumber];
18477
18478 if (worklist[end1] == 0) {
18479 ptlist->append(&tstart);
18480 worklist[end1] = 1;
18481 }
18482
18483 for (j = 1; j <= p->numberofvertices; j++) {
18484
18485 if (j < p->numberofvertices) {
18486 end2 = p->vertexlist[j];
18487 } else {
18488 end2 = p->vertexlist[0];
18489 }
18490 if ((end2 < in->firstnumber) ||
18491 (end2 >= in->firstnumber + in->numberofpoints)) {
18492 if (!b->quiet) {
18493 printf("Warning: Invalid vertex %d in polygon %d", end2, i + 1);
18494 printf(" in facet %d.\n", shmark);
18495 }
18496 } else {
18497 if (end1 != end2) {
18498
18499 tend = idx2verlist[end2 - in->firstnumber];
18500
18501 if (worklist[end2] == 0) {
18502 ptlist->append(&tend);
18503 worklist[end2] = 1;
18504 }
18505
18506 cons = (point *) conlist->append(NULL);
18507 cons[0] = tstart;
18508 cons[1] = tend;
18509
18510 end1 = end2;
18511 tstart = tend;
18512 } else {
18513
18514 if (p->numberofvertices > 2) {
18515
18516
18517 if (!b->quiet) {
18518 printf("Warning: Polygon %d has two identical verts", i + 1);
18519 printf(" in facet %d.\n", shmark);
18520 }
18521 }
18522
18523 }
18524 }
18525
18526 if (p->numberofvertices == 2) break;
18527 }
18528 }
18529
18530 for (i = 0; i < ptlist->len(); i++) {
18531 tstart = * (point *)(* ptlist)[i];
18532 end1 = pointmark(tstart);
18533 assert(worklist[end1] == 1);
18534 worklist[end1] = 0;
18535 }
18536
18537
18538 triangulate(shmark, b->epsilon * 1e+2, ptlist, conlist, f->numberofholes,
18539 f->holelist, viri, flipqueue);
18540
18541 ptlist->clear();
18542 conlist->clear();
18543 viri->restart();
18544 }
18545
18546
18547
18548 unifysegments();
18549
18550 insegments = subsegs->items;
18551
18552 if (checkpbcs) {
18553
18554 createsegpbcgrouptable();
18555 }
18556
18557 if (b->object == tetgenbehavior::STL) {
18558
18559 jettisonnodes();
18560 }
18561
18562 if (!b->nomerge && !b->nobisect && !checkpbcs) {
18563
18564 mergefacets(flipqueue);
18565 }
18566
18567 delete [] idx2verlist;
18568 delete [] worklist;
18569 delete ptlist;
18570 delete conlist;
18571 delete flipqueue;
18572 delete viri;
18573
18574 return subsegs->items;
18575 }
18576
18577
18578
18579
18580
18582
18583
18584
18585
18586
18587
18588
18589
18590
18591
18592
18593
18594
18595
18596
18597
18598
18599
18600
18601
18602
18604
18605 void tetgenmesh::
18606 interecursive(shellface** subfacearray, int arraysize, int axis, REAL bxmin,
18607 REAL bxmax, REAL bymin, REAL bymax, REAL bzmin, REAL bzmax,
18608 int* internum)
18609 {
18610 shellface **leftarray, **rightarray;
18611 face sface1, sface2;
18612 point p1, p2, p3;
18613 point p4, p5, p6;
18614 enum interresult intersect;
18615 REAL split;
18616 bool toleft, toright;
18617 int leftsize, rightsize;
18618 int i, j;
18619
18620 if (b->verbose > 1) {
18621 printf(" Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
18622 arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
18623 axis == 0 ? "x" : (axis == 1 ? "y" : "z"));
18624 }
18625
18626 leftarray = new shellface*[arraysize];
18627 if (leftarray == NULL) {
18628 printf("Error in interecursive(): Insufficient memory.\n");
18629 terminatetetgen(1);
18630 }
18631 rightarray = new shellface*[arraysize];
18632 if (rightarray == NULL) {
18633 printf("Error in interecursive(): Insufficient memory.\n");
18634 terminatetetgen(1);
18635 }
18636 leftsize = rightsize = 0;
18637
18638 if (axis == 0) {
18639
18640 split = 0.5 * (bxmin + bxmax);
18641 } else if (axis == 1) {
18642
18643 split = 0.5 * (bymin + bymax);
18644 } else {
18645
18646 split = 0.5 * (bzmin + bzmax);
18647 }
18648
18649 for (i = 0; i < arraysize; i++) {
18650 sface1.sh = subfacearray[i];
18651 p1 = (point) sface1.sh[3];
18652 p2 = (point) sface1.sh[4];
18653 p3 = (point) sface1.sh[5];
18654 toleft = toright = false;
18655 if (p1[axis] < split) {
18656 toleft = true;
18657 if (p2[axis] >= split || p3[axis] >= split) {
18658 toright = true;
18659 }
18660 } else if (p1[axis] > split) {
18661 toright = true;
18662 if (p2[axis] <= split || p3[axis] <= split) {
18663 toleft = true;
18664 }
18665 } else {
18666
18667 toleft = true;
18668 toright = true;
18669 }
18670
18671 #ifdef SELF_CHECK
18672 assert(!(toleft == false && toright == false));
18673 #endif
18674 if (toleft) {
18675 leftarray[leftsize] = sface1.sh;
18676 leftsize++;
18677 }
18678 if (toright) {
18679 rightarray[rightsize] = sface1.sh;
18680 rightsize++;
18681 }
18682 }
18683
18684 if (leftsize < arraysize && rightsize < arraysize) {
18685
18686
18687
18688
18689 delete [] subfacearray;
18690
18691 if (axis == 0) {
18692 interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax,
18693 bzmin, bzmax, internum);
18694 interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax,
18695 bzmin, bzmax, internum);
18696 } else if (axis == 1) {
18697 interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split,
18698 bzmin, bzmax, internum);
18699 interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax,
18700 bzmin, bzmax, internum);
18701 } else {
18702 interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax,
18703 bzmin, split, internum);
18704 interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax,
18705 split, bzmax, internum);
18706 }
18707 } else {
18708 if (b->verbose > 1) {
18709 printf(" Checking intersecting faces.\n");
18710 }
18711
18712 for (i = 0; i < arraysize; i++) {
18713 sface1.sh = subfacearray[i];
18714 p1 = (point) sface1.sh[3];
18715 p2 = (point) sface1.sh[4];
18716 p3 = (point) sface1.sh[5];
18717 for (j = i + 1; j < arraysize; j++) {
18718 sface2.sh = subfacearray[j];
18719 p4 = (point) sface2.sh[3];
18720 p5 = (point) sface2.sh[4];
18721 p6 = (point) sface2.sh[5];
18722 intersect = tri_tri_inter(p1, p2, p3, p4, p5, p6);
18723 if (intersect == INTERSECT || intersect == SHAREFACE) {
18724 if (!b->quiet) {
18725 if (intersect == INTERSECT) {
18726 printf(" Facet #%d intersects facet #%d at triangles:\n",
18727 shellmark(sface1), shellmark(sface2));
18728 printf(" (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
18729 pointmark(p1), pointmark(p2), pointmark(p3),
18730 pointmark(p4), pointmark(p5), pointmark(p6));
18731 } else {
18732 printf(" Facet #%d duplicates facet #%d at triangle:\n",
18733 shellmark(sface1), shellmark(sface2));
18734 printf(" (%4d, %4d, %4d)\n", pointmark(p1), pointmark(p2),
18735 pointmark(p3));
18736 }
18737 }
18738
18739 (*internum)++;
18740
18741 sinfect(sface1);
18742 sinfect(sface2);
18743 }
18744 }
18745 }
18746
18747 delete [] leftarray;
18748 delete [] rightarray;
18749 delete [] subfacearray;
18750 }
18751 }
18752
18754
18755
18756
18757
18758
18759
18760
18761
18762
18763
18764
18765
18766
18767
18768
18769
18770
18771
18772
18773
18774
18775
18777
18778 void tetgenmesh::detectinterfaces()
18779 {
18780 shellface **subfacearray;
18781 face shloop;
18782 int internum;
18783 int i;
18784
18785 if (!b->quiet) {
18786 printf("Detecting intersecting facets.\n");
18787 }
18788
18789
18790 subfacearray = new shellface*[subfaces->items];
18791 subfaces->traversalinit();
18792 shloop.sh = shellfacetraverse(subfaces);
18793 i = 0;
18794 while (shloop.sh != (shellface *) NULL) {
18795 subfacearray[i] = shloop.sh;
18796 shloop.sh = shellfacetraverse(subfaces);
18797 i++;
18798 }
18799
18800 internum = 0;
18801
18802
18803
18804 interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax,
18805 zmin, zmax, &internum);
18806
18807 if (!b->quiet) {
18808 if (internum > 0) {
18809 printf("\n!! Found %d pairs of faces are intersecting.\n\n", internum);
18810 } else {
18811 printf("\nNo faces are intersecting.\n\n");
18812 }
18813 }
18814
18815 if (internum > 0) {
18816
18817
18818
18819 subfaces->traversalinit();
18820 shloop.sh = shellfacetraverse(subfaces);
18821 while (shloop.sh != (shellface *) NULL) {
18822 if (sinfected(shloop)) {
18823 suninfect(shloop);
18824 } else {
18825 shellfacedealloc(subfaces, shloop.sh);
18826 }
18827 shloop.sh = shellfacetraverse(subfaces);
18828 }
18829 } else {
18830
18831 subfaces->restart();
18832 }
18833 }
18834
18835
18836
18837
18838
18840
18841
18842
18843
18844
18845
18846
18847
18848
18849
18850
18852
18853 void tetgenmesh::createsubpbcgrouptable()
18854 {
18855 tetgenio::pbcgroup *pg;
18856 pbcdata *pd;
18857 REAL A[4][4], rhs[4], D;
18858 int indx[4];
18859 int i, j, k;
18860
18861 subpbcgrouptable = new pbcdata[in->numberofpbcgroups];
18862 for (i = 0; i < in->numberofpbcgroups; i++) {
18863 pg = &(in->pbcgrouplist[i]);
18864 pd = &(subpbcgrouptable[i]);
18865
18866 pd->fmark[0] = pg->fmark1;
18867 pd->fmark[1] = pg->fmark2;
18868
18869 pd->ss[0].sh = dummysh;
18870 pd->ss[1].sh = dummysh;
18871
18872 for (j = 0; j < 4; j++) {
18873 for (k = 0; k < 4; k++) {
18874 pd->transmat[0][j][k] = pg->transmat[j][k];
18875
18876 A[j][k] = pg->transmat[j][k];
18877 }
18878 }
18879
18880 lu_decmp(A, 4, indx, &D, 0);
18881 for (j = 0; j < 4; j++) {
18882 for (k = 0; k < 4; k++) rhs[k] = 0.0;
18883 rhs[j] = 1.0;
18884 lu_solve(A, 4, indx, rhs, 0);
18885 for (k = 0; k < 4; k++) pd->transmat[1][k][j] = rhs[k];
18886 }
18887 }
18888 }
18889
18891
18892
18893
18894
18895
18896
18897
18899
18900 void tetgenmesh::getsubpbcgroup(face* pbcsub, pbcdata** pd, int *f1, int *f2)
18901 {
18902 int groupid, fmark, idx;
18903
18904 groupid = shellpbcgroup(*pbcsub);
18905 *pd = &subpbcgrouptable[groupid];
18906
18907
18908 idx = shellmark(*pbcsub);
18909
18910 fmark = in->facetmarkerlist[idx - 1];
18911 if ((*pd)->fmark[0] == fmark) {
18912 *f1 = 0;
18913 } else {
18914 #ifdef SELF_CHECK
18915 assert((*pd)->fmark[1] == fmark);
18916 #endif
18917 *f1 = 1;
18918 }
18919 *f2 = 1 - (*f1);
18920 }
18921
18923
18924
18925
18926
18927
18928
18929
18931
18932 enum tetgenmesh::locateresult tetgenmesh:: getsubpbcsympoint(point newpoint,
18933 face* splitsub, point sympoint, face* symsplitsub)
18934 {
18935 pbcdata *pd;
18936 face subloop;
18937 point pa, pb, pc;
18938 enum locateresult symloc;
18939 REAL ori;
18940 int f1, f2, i;
18941
18942
18943 getsubpbcgroup(splitsub, &pd, &f1, &f2);
18944
18945
18946 for (i = 0; i < 3; i++) {
18947 sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
18948 + pd->transmat[f1][i][1] * newpoint[1]
18949 + pd->transmat[f1][i][2] * newpoint[2]
18950 + pd->transmat[f1][i][3] * 1.0;
18951 }
18952
18953 symloc = OUTSIDE;
18954 *symsplitsub = pd->ss[f2];
18955
18956 if ((symsplitsub->sh != dummysh) && !isdead(symsplitsub)) {
18957
18958 i = shellmark(*symsplitsub);
18959 if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18960
18961 pa = sorg(*symsplitsub);
18962 pb = sdest(*symsplitsub);
18963 pc = sapex(*symsplitsub);
18964
18965
18966 ori = orient3d(pa, pb, pc, sympoint);
18967 if (iscoplanar(pa, pb, pc, sympoint, ori, b->epsilon * 1e+2)) {
18968
18969 abovepoint = facetabovepointarray[shellmark(*symsplitsub)];
18970 if (abovepoint == (point) NULL) {
18971 getfacetabovepoint(symsplitsub);
18972 }
18973 symloc = locatesub(sympoint, symsplitsub, 0, b->epsilon * 1e+2);
18974 }
18975 }
18976 }
18977 if (symloc == OUTSIDE) {
18978
18979 REAL epspp = b->epsilon * 1e+2;
18980 int lcount = 0;
18981 do {
18982
18983 subfaces->traversalinit();
18984 subloop.sh = shellfacetraverse(subfaces);
18985 while (subloop.sh != (shellface *) NULL) {
18986 i = shellmark(subloop);
18987 if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18988
18989 pa = sorg(subloop);
18990 pb = sdest(subloop);
18991 pc = sapex(subloop);
18992
18993
18994 ori = orient3d(pa, pb, pc, sympoint);
18995 if (iscoplanar(pa, pb, pc, sympoint, ori, epspp)) {
18996
18997
18998 abovepoint = facetabovepointarray[shellmark(subloop)];
18999
19000 if (abovepoint == (point) NULL) {
19001 getfacetabovepoint(&subloop);
19002 }
19003
19004 symloc = locatesub(sympoint, &subloop, 0, epspp);
19005 if (symloc != OUTSIDE) break;
19006 }
19007 }
19008 subloop.sh = shellfacetraverse(subfaces);
19009 }
19010 lcount++;
19011 epspp *= 10.0;
19012 } while ((symloc == OUTSIDE) && (lcount < 3));
19013 #ifdef SELF_CHECK
19014
19015 assert(symloc != OUTSIDE);
19016 #endif
19017
19018 *symsplitsub = subloop;
19019
19020 pd->ss[f2] = *symsplitsub;
19021 }
19022
19023 return adjustlocatesub(sympoint, symsplitsub, symloc, b->epsilon);
19024 }
19025
19027
19028
19029
19030
19031
19032
19033
19034
19035
19036
19038
19039 void tetgenmesh::createsegpbcgrouptable()
19040 {
19041 shellface** segsperverlist;
19042 pbcdata *pd, *ppd, pd1, pd2;
19043 face segloop, symseg;
19044 face startsh, spinsh, symsh;
19045 point pa, pb, syma, symb;
19046 enum locateresult symloc;
19047 REAL testpt[3], sympt[3];
19048 bool inflag;
19049 int *idx2seglist;
19050 int segid1, segid2;
19051 int f1, f2;
19052 int i, j, k, l;
19053
19054
19055 segpbcgrouptable = new list(sizeof(pbcdata), NULL, 256);
19056
19057 if (b->refine) {
19058
19059 makesegmentmap(idx2seglist, segsperverlist);
19060 }
19061
19062
19063 subsegs->traversalinit();
19064 segloop.sh = shellfacetraverse(subsegs);
19065 while (segloop.sh != (shellface *) NULL) {
19066
19067 pa = sorg(segloop);
19068 pb = sdest(segloop);
19069 segid1 = shellmark(segloop);
19070 spivot(segloop, startsh);
19071 spinsh = startsh;
19072 do {
19073
19074 if (sorg(spinsh) != pa) {
19075 sesymself(spinsh);
19076 }
19077
19078 if (shellpbcgroup(spinsh) != -1) {
19079
19080 if (b->refine) {
19081 getsubpbcgroup(&spinsh, &pd, &f1, &f2);
19082
19083 for (i = 0; i < 3; i++) {
19084 sympt[i] = pd->transmat[f1][i][0] * pa[0]
19085 + pd->transmat[f1][i][1] * pa[1]
19086 + pd->transmat[f1][i][2] * pa[2]
19087 + pd->transmat[f1][i][3] * 1.0;
19088 }
19089 syma = point2pbcpt(pa);
19090
19091 if (distance(sympt, syma) > (longest * b->epsilon)) {
19092
19093 symloc = getsubpbcsympoint(pa, &spinsh, sympt, &symsh);
19094 syma = sorg(symsh);
19095 if (symloc != ONVERTEX) {
19096
19097 assert(0);
19098 }
19099 }
19100
19101 for (i = 0; i < 3; i++) {
19102 sympt[i] = pd->transmat[f1][i][0] * pb[0]
19103 + pd->transmat[f1][i][1] * pb[1]
19104 + pd->transmat[f1][i][2] * pb[2]
19105 + pd->transmat[f1][i][3] * 1.0;
19106 }
19107
19108 symseg.shver = 0;
19109 j = pointmark(syma) - in->firstnumber;
19110 for (i = idx2seglist[j]; i < idx2seglist[j + 1]; i++) {
19111 symseg.sh = segsperverlist[i];
19112 if (sorg(symseg) == syma) symb = sdest(symseg);
19113 else symb = sorg(symseg);
19114 if (distance(sympt, symb) <= (longest * b->epsilon)) break;
19115 }
19116 assert(i < idx2seglist[j + 1]);
19117 } else {
19118
19119 for (i = 0; i < 3; i++) testpt[i] = 0.5 * (pa[i] + pb[i]);
19120 symloc = getsubpbcsympoint(testpt, &spinsh, sympt, &symsh);
19121 #ifdef SELF_CHECK
19122 assert(symloc == ONEDGE);
19123 #endif
19124 sspivot(symsh, symseg);
19125 }
19126 #ifdef SELF_CHECK
19127 assert(symseg.sh != dummysh);
19128 #endif
19129
19130 segid2 = shellmark(symseg);
19131 inflag = false;
19132 for (i = 0; i < segpbcgrouptable->len() && !inflag; i++) {
19133 pd = (pbcdata *)(* segpbcgrouptable)[i];
19134 if (pd->segid[0] == segid1) {
19135 if (pd->segid[1] == segid2) inflag = true;
19136 } else if (pd->segid[0] == segid2) {
19137 if (pd->segid[1] == segid1) inflag = true;
19138 }
19139 }
19140 if (!inflag) {
19141
19142 pd = (pbcdata *) segpbcgrouptable->append(NULL);
19143
19144 pd->segid[0] = segid1;
19145 pd->segid[1] = segid2;
19146
19147 pd->ss[0] = segloop;
19148 pd->ss[1] = symseg;
19149
19150 getsubpbcgroup(&spinsh, &ppd, &f1, &f2);
19151 pd->fmark[0] = ppd->fmark[f1];
19152 pd->fmark[1] = ppd->fmark[f2];
19153
19154 for (i = 0; i < 4; i++) {
19155 for (j = 0; j < 4; j++) {
19156 pd->transmat[0][i][j] = ppd->transmat[f1][i][j];
19157 }
19158 }
19159
19160 for (i = 0; i < 4; i++) {
19161 for (j = 0; j < 4; j++) {
19162 pd->transmat[1][i][j] = ppd->transmat[f2][i][j];
19163 }
19164 }
19165 }
19166 }
19167
19168 spivotself(spinsh);
19169 } while (spinsh.sh != startsh.sh);
19170 segloop.sh = shellfacetraverse(subsegs);
19171 }
19172
19173 if (b->refine) {
19174 delete [] segsperverlist;
19175 delete [] idx2seglist;
19176 }
19177
19178
19179
19180
19181
19182 for (i = 0; i < segpbcgrouptable->len(); i++) {
19183 pd1 = * (pbcdata *)(* segpbcgrouptable)[i];
19184 for (f1 = 0; f1 < 2; f1++) {
19185
19186 for (j = 0; j < segpbcgrouptable->len(); j++) {
19187 if (j == i) continue;
19188 pd2 = * (pbcdata *)(* segpbcgrouptable)[j];
19189 f2 = -1;
19190 if (pd1.segid[f1] == pd2.segid[0]) {
19191 f2 = 0;
19192 } else if (pd1.segid[f1] == pd2.segid[1]) {
19193 f2 = 1;
19194 }
19195 if (f2 != -1) {
19196 #ifdef SELF_CHECK
19197 assert(pd1.segid[f1] == pd2.segid[f2]);
19198 #endif
19199 segid1 = pd1.segid[1 - f1];
19200 segid2 = pd2.segid[1 - f2];
19201
19202 inflag = false;
19203 for (k = 0; k < segpbcgrouptable->len() && !inflag; k++) {
19204 pd = (pbcdata *)(* segpbcgrouptable)[k];
19205 if (pd->segid[0] == segid1) {
19206 if (pd->segid[1] == segid2) inflag = true;
19207 } else if (pd->segid[0] == segid2) {
19208 if (pd->segid[1] == segid1) inflag = true;
19209 }
19210 }
19211 if (!inflag) {
19212 pd = (pbcdata *) segpbcgrouptable->append(NULL);
19213 pd->segid[0] = pd1.segid[1 - f1];
19214 pd->segid[1] = pd2.segid[1 - f2];
19215 pd->ss[0] = pd1.ss[1 - f1];
19216 pd->ss[1] = pd2.ss[1 - f2];
19217
19218 pd->fmark[0] = pd->fmark[1] = 0;
19219
19220
19221 for (k = 0; k < 4; k++) {
19222 for (l = 0; l < 4; l++) {
19223 pd->transmat[0][k][l] = pd2.transmat[f2][k][l];
19224 }
19225 }
19226 m4xm4(pd->transmat[0], pd1.transmat[1 - f1]);
19227
19228
19229 for (k = 0; k < 4; k++) {
19230 for (l = 0; l < 4; l++) {
19231 pd->transmat[1][k][l] = pd1.transmat[f1][k][l];
19232 }
19233 }
19234 m4xm4(pd->transmat[1], pd2.transmat[1 - f2]);
19235 }
19236 }
19237 }
19238 }
19239 }
19240
19241
19242 idx2segpglist = new int[subsegs->items + 1];
19243 for (i = 0; i < subsegs->items + 1; i++) idx2segpglist[i] = 0;
19244
19245
19246 for (i = 0; i < segpbcgrouptable->len(); i++) {
19247 pd = (pbcdata *)(* segpbcgrouptable)[i];
19248 for (j = 0; j < 2; j++) {
19249 k = pd->segid[j] - 1;
19250 idx2segpglist[k]++;
19251 }
19252 }
19253
19254 j = idx2segpglist[0];
19255 idx2segpglist[0] = 0;
19256 for (i = 0; i < subsegs->items; i++) {
19257 k = idx2segpglist[i + 1];
19258 idx2segpglist[i + 1] = idx2segpglist[i] + j;
19259 j = k;
19260 }
19261
19262 segpglist = new int[idx2segpglist[i]];
19263
19264 for (i = 0; i < segpbcgrouptable->len(); i++) {
19265 pd = (pbcdata *)(* segpbcgrouptable)[i];
19266 for (j = 0; j < 2; j++) {
19267 k = pd->segid[j] - 1;
19268 segpglist[idx2segpglist[k]] = i;
19269 idx2segpglist[k]++;
19270 }
19271 }
19272
19273 for (i = subsegs->items - 1; i >= 0; i--) {
19274 idx2segpglist[i + 1] = idx2segpglist[i];
19275 }
19276 idx2segpglist[0] = 0;
19277 }
19278
19280
19281
19282
19283
19284
19285
19286
19288
19289 enum tetgenmesh::locateresult tetgenmesh::
19290 getsegpbcsympoint(point newpoint, face* splitseg, point sympoint,
19291 face* symsplitseg, int groupid)
19292 {
19293 pbcdata *pd;
19294 enum locateresult symloc;
19295 int segid, f1, f2, i;
19296
19297 pd = (pbcdata *)(* segpbcgrouptable)[groupid];
19298 segid = shellmark(*splitseg);
19299 if (pd->segid[0] == segid) {
19300 f1 = 0;
19301 } else {
19302 #ifdef SELF_CHECK
19303 assert(pd->segid[1] == segid);
19304 #endif
19305 f1 = 1;
19306 }
19307 f2 = 1 - f1;
19308
19309
19310 for (i = 0; i < 3; i++) {
19311 sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
19312 + pd->transmat[f1][i][1] * newpoint[1]
19313 + pd->transmat[f1][i][2] * newpoint[2]
19314 + pd->transmat[f1][i][3] * 1.0;
19315 }
19316
19317 *symsplitseg = pd->ss[f2];
19318 #ifdef SELF_CHECK
19319 assert(symsplitseg->sh != dummysh);
19320 #endif
19321
19322 symloc = locateseg(sympoint, symsplitseg);
19323 symloc = adjustlocateseg(sympoint, symsplitseg, symloc, b->epsilon * 1e+2);
19324 return symloc;
19325 }
19326
19327
19328
19329
19330
19331
19332
19333
19334
19336
19337
19338
19340
19341 REAL tetgenmesh::randgenerator(REAL range)
19342 {
19343 REAL worknumber, result;
19344 int expo;
19345
19346 if (range == 0.0) return 0.0;
19347
19348 expo = 0;
19349 worknumber = fabs(range);
19350
19351 if (worknumber > 10.0) {
19352 while (worknumber > 10.0) {
19353 worknumber /= 10.0;
19354 expo++;
19355 }
19356 } else if (worknumber < 1.0) {
19357 while (worknumber < 1.0) {
19358 worknumber *= 10.0;
19359 expo--;
19360 }
19361 }
19362 #ifdef SELF_CHECK
19363 assert(worknumber >= 1.0 && worknumber <= 10.0);
19364 #endif
19365
19366
19367 worknumber *= 1e+3;
19368 expo -= 3;
19369
19370 result = (double) randomnation((int) worknumber);
19371
19372
19373 if (expo > 0) {
19374 while (expo != 0) {
19375 result *= 10.0;
19376 expo--;
19377 }
19378 } else if (expo < 0) {
19379 while (expo != 0) {
19380 result /= 10.0;
19381 expo++;
19382 }
19383 }
19384 #ifdef SELF_CHECK
19385 assert((result >= 0.0) && (result <= fabs(range)));
19386 #endif
19387
19388 return result;
19389 }
19390
19392
19393
19394
19395
19396
19397
19398
19399
19400
19401
19402
19403
19404
19406
19407 bool tetgenmesh::checksub4cocir(face* testsub, REAL eps, bool once,
19408 bool enqflag)
19409 {
19410 badface *cocirsub;
19411 face subloop, neighsub;
19412 face checkseg;
19413 point pa, pb, pc, pd;
19414 REAL sign;
19415 int i;
19416
19417 subloop = *testsub;
19418 subloop.shver = 0;
19419
19420 abovepoint = facetabovepointarray[shellmark(subloop)];
19421
19422 if (abovepoint == (point) NULL) {
19423 getfacetabovepoint(&subloop);
19424 }
19425
19426 for (i = 0; i < 3; i++) {
19427 sspivot(subloop, checkseg);
19428 if (checkseg.sh == dummysh) {
19429
19430 spivot(subloop, neighsub);
19431
19432 if (!once || (once && (neighsub.sh > subloop.sh))) {
19433 pa = sorg(subloop);
19434 pb = sdest(subloop);
19435 pc = sapex(subloop);
19436 pd = sapex(neighsub);
19437 sign = insphere(pa, pb, pc, abovepoint, pd);
19438 if ((sign != 0.0) && (eps > 0.0)) {
19439 if (iscospheric(pa, pb, pc, abovepoint, pd, sign, eps)) sign = 0.0;
19440 }
19441 if (sign == 0.0) {
19442
19443 if (enqflag && badsubfaces != (memorypool *) NULL) {
19444
19445 cocirsub = (badface *) badsubfaces->alloc();
19446 cocirsub->ss = subloop;
19447 cocirsub->forg = pa;
19448 cocirsub->fdest = pb;
19449 cocirsub->fapex = pc;
19450 cocirsub->foppo = pd;
19451 setshell2badface(cocirsub->ss, cocirsub);
19452 }
19453 if (b->verbose > 1) {
19454 printf(" Found set (%d, %d, %d, %d).\n", pointmark(pa),
19455 pointmark(pb), pointmark(pc), pointmark(pd));
19456 }
19457 return true;
19458 }
19459 }
19460 }
19461 senextself(subloop);
19462 }
19463
19464 return false;
19465 }
19466
19468
19469
19470
19472
19473 void tetgenmesh::tallcocirsubs(REAL eps, bool enqflag)
19474 {
19475 face subloop;
19476
19477
19478 subfaces->traversalinit();
19479 subloop.sh = shellfacetraverse(subfaces);
19480 while (subloop.sh != (shellface *) NULL) {
19481 checksub4cocir(&subloop, eps, true, enqflag);
19482 subloop.sh = shellfacetraverse(subfaces);
19483 }
19484 }
19485
19487
19488
19489
19491
19492 bool tetgenmesh::tallencsegsfsubs(point testpt, list* cavsublist)
19493 {
19494 face startsub, checkseg;
19495 long oldencnum;
19496 int i, j;
19497
19498
19499 oldencnum = badsubsegs->items;
19500
19501
19502 for (i = 0; i < cavsublist->len(); i++) {
19503 startsub = * (face *)(* cavsublist)[i];
19504
19505 for (j = 0; j < 3; j++) {
19506 sspivot(startsub, checkseg);
19507 if (checkseg.sh != dummysh) {
19508 if (!shell2badface(checkseg)) {
19509 checkseg4encroach(&checkseg, testpt, NULL, true);
19510 }
19511 }
19512 senextself(startsub);
19513 }
19514 }
19515
19516 return (badsubsegs->items > oldencnum);
19517 }
19518
19520
19521
19522
19523
19524
19525
19526
19527
19529
19530 void tetgenmesh::
19531 collectflipedges(point inspoint, face* splitseg, queue* flipqueue)
19532 {
19533 face startsh, spinsh, checksh;
19534 face nextseg;
19535 point pa, pb;
19536
19537
19538 splitseg->shver = 0;
19539 if (sdest(*splitseg) != inspoint) {
19540 sesymself(*splitseg);
19541 }
19542 #ifdef SELF_CHECK
19543 assert(sdest(*splitseg) == inspoint);
19544 #endif
19545 pa = sorg(*splitseg);
19546 spivot(*splitseg, startsh);
19547 spinsh = startsh;
19548 do {
19549 findedge(&spinsh, pa, inspoint);
19550 senext2(spinsh, checksh);
19551 enqueueflipedge(checksh, flipqueue);
19552 spivotself(spinsh);
19553 } while (spinsh.sh != startsh.sh);
19554
19555
19556 senext(*splitseg, nextseg);
19557 spivotself(nextseg);
19558 #ifdef SELF_CHECK
19559 assert(nextseg.sh != (shellface *) NULL);
19560 #endif
19561
19562
19563 nextseg.shver = 0;
19564 if (sorg(nextseg) != inspoint) {
19565 sesymself(nextseg);
19566 }
19567 #ifdef SELF_CHECK
19568 assert(sorg(nextseg) == inspoint);
19569 #endif
19570 pb = sdest(nextseg);
19571 spivot(nextseg, startsh);
19572 spinsh = startsh;
19573 do {
19574 findedge(&spinsh, inspoint, pb);
19575 senext(spinsh, checksh);
19576 enqueueflipedge(checksh, flipqueue);
19577 spivotself(spinsh);
19578 } while (spinsh.sh != startsh.sh);
19579 }
19580
19582
19583
19584
19585
19586
19587
19589
19590 void tetgenmesh::perturbrepairencsegs(queue* flipqueue)
19591 {
19592 badface *encloop;
19593 tetrahedron encodedtet;
19594 triface splittet;
19595 face splitsub, symsplitsub;
19596 face splitseg, symsplitseg;
19597 point newpoint, sympoint;
19598 point pa, pb, pc;
19599 enum insertsiteresult success;
19600 enum locateresult loc, symloc;
19601 REAL cent[3], d1, ps, rs;
19602 int i, j;
19603
19604
19605
19606 badsubsegs->traversalinit();
19607 encloop = badfacetraverse(badsubsegs);
19608 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19609 splitseg = encloop->ss;
19610 #ifdef SELF_CHECK
19611 assert(shell2badface(splitseg) == encloop);
19612 #endif
19613 setshell2badface(splitseg, NULL);
19614 pa = sorg(splitseg);
19615 pb = sdest(splitseg);
19616 if ((pa == encloop->forg) && (pb == encloop->fdest)) {
19617 if (b->verbose > 1) {
19618 printf(" Get seg (%d, %d).\n", pointmark(pa), pointmark(pb));
19619 }
19620
19621 makepoint(&newpoint);
19622
19623 for (i = 0; i < 3; i++) cent[i] = 0.5 * (pa[i] + pb[i]);
19624 d1 = 0.5 * distance(pa, pb);
19625
19626 ps = randgenerator(d1 * 1.0e-3);
19627 rs = ps / d1;
19628
19629 for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19630 setpointtype(newpoint, FREESEGVERTEX);
19631
19632 setpoint2sh(newpoint, sencode(splitseg));
19633
19634
19635 if (checkpbcs) {
19636
19637 i = shellmark(splitseg) - 1;
19638 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
19639 makepoint(&sympoint);
19640 symloc = getsegpbcsympoint(newpoint, &splitseg, sympoint,
19641 &symsplitseg, segpglist[j]);
19642 #ifdef SELF_CHECK
19643 assert(symloc != OUTSIDE);
19644 #endif
19645
19646
19647 if ((symloc == ONEDGE) && (symsplitseg.sh != splitseg.sh)) {
19648 setpointtype(sympoint, FREESEGVERTEX);
19649 setpoint2sh(sympoint, sencode(symsplitseg));
19650
19651 pc = sorg(symsplitseg);
19652 splittet.tet = dummytet;
19653
19654 encodedtet = point2tet(pc);
19655 if (encodedtet != (tetrahedron) NULL) {
19656 decode(encodedtet, splittet);
19657 if (isdead(&splittet)) {
19658 splittet.tet = dummytet;
19659 }
19660 }
19661
19662 success = insertsite(sympoint, &splittet, false, flipqueue);
19663 #ifdef SELF_CHECK
19664 assert(success != DUPLICATEPOINT);
19665 #endif
19666 if (success == OUTSIDEPOINT) {
19667 inserthullsite(sympoint, &splittet, flipqueue);
19668 }
19669 if (steinerleft > 0) steinerleft--;
19670
19671 setpoint2tet(sympoint, encode(splittet));
19672
19673 flip(flipqueue, NULL);
19674
19675 symloc = locateseg(sympoint, &symsplitseg);
19676 if (symloc == ONEDGE) {
19677 symsplitseg.shver = 0;
19678 spivot(symsplitseg, symsplitsub);
19679
19680 splitsubedge(sympoint, &symsplitsub, flipqueue);
19681 } else {
19682
19683 #ifdef SELF_CHECK
19684 assert(symloc == ONVERTEX);
19685 assert(checksubfaces);
19686 #endif
19687
19688 collectflipedges(sympoint, &symsplitseg, flipqueue);
19689 }
19690
19691 flipsub(flipqueue);
19692 } else {
19693
19694
19695 pointdealloc(sympoint);
19696 }
19697 }
19698 }
19699
19700
19701 splittet.tet = dummytet;
19702
19703 encodedtet = point2tet(pa);
19704 if (encodedtet != (tetrahedron) NULL) {
19705 decode(encodedtet, splittet);
19706 if (isdead(&splittet)) {
19707 splittet.tet = dummytet;
19708 }
19709 }
19710 if (splittet.tet == dummytet) {
19711 encodedtet = point2tet(pb);
19712 if (encodedtet != (tetrahedron) NULL) {
19713 decode(encodedtet, splittet);
19714 if (isdead(&splittet)) {
19715 splittet.tet = dummytet;
19716 }
19717 }
19718 }
19719
19720 success = insertsite(newpoint, &splittet, false, flipqueue);
19721 #ifdef SELF_CHECK
19722 assert(success != DUPLICATEPOINT);
19723 #endif
19724 if (success == OUTSIDEPOINT) {
19725
19726
19727
19728 inserthullsite(newpoint, &splittet, flipqueue);
19729 }
19730 if (steinerleft > 0) steinerleft--;
19731
19732 setpoint2tet(newpoint, encode(splittet));
19733
19734 flip(flipqueue, NULL);
19735
19736 loc = locateseg(newpoint, &splitseg);
19737 if (loc == ONEDGE) {
19738 splitseg.shver = 0;
19739 spivot(splitseg, splitsub);
19740
19741 splitsubedge(newpoint, &splitsub, flipqueue);
19742 } else {
19743
19744 #ifdef SELF_CHECK
19745 assert(loc == ONVERTEX);
19746 assert(checksubfaces);
19747 #endif
19748
19749 collectflipedges(newpoint, &splitseg, flipqueue);
19750 }
19751
19752 flipsub(flipqueue);
19753 }
19754
19755 badfacedealloc(badsubsegs, encloop);
19756
19757 encloop = badfacetraverse(badsubsegs);
19758 }
19759 }
19760
19762
19763
19764
19765
19766
19767
19768
19769
19771
19772 void tetgenmesh::perturbrepairencsubs(list* cavsublist, queue* flipqueue)
19773 {
19774 badface *encloop, *encsubseg;
19775 tetrahedron encodedtet;
19776 triface splittet;
19777 face splitsub, symsplitsub;
19778 face checkseg, symsplitseg;
19779 point newpoint, sympoint;
19780 point pa, pb, pc, pd;
19781 enum insertsiteresult success;
19782 enum locateresult loc, symloc;
19783 REAL cent[3], d1, ps, rs;
19784 bool reject;
19785 int i;
19786
19787
19788
19789 while ((badsubfaces->items > 0) && (steinerleft != 0)) {
19790 badsubfaces->traversalinit();
19791 encloop = badfacetraverse(badsubfaces);
19792 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19793 splitsub = encloop->ss;
19794 #ifdef SELF_CHECK
19795 assert(shell2badface(splitsub) == encloop);
19796 #endif
19797 setshell2badface(splitsub, NULL);
19798 pa = sorg(splitsub);
19799 pb = sdest(splitsub);
19800 pc = sapex(splitsub);
19801
19802
19803
19804 if ((pa == encloop->forg) && (pb == encloop->fdest) &&
19805 (pc == encloop->fapex)) {
19806 if (b->verbose > 1) {
19807 printf(" Get subface (%d, %d, %d).\n", pointmark(pa),
19808 pointmark(pb), pointmark(pc));
19809 }
19810
19811 makepoint(&newpoint);
19812
19813 circumsphere(pa, pb, pc, NULL, cent, &d1);
19814 #ifdef SELF_CHECK
19815 assert(d1 > 0.0);
19816 #endif
19817
19818
19819 ps = randgenerator(d1 * 1.0e-3);
19820 rs = ps / d1;
19821
19822 for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19823
19824 abovepoint = facetabovepointarray[shellmark(splitsub)];
19825
19826 if (abovepoint == (point) NULL) {
19827 getfacetabovepoint(&splitsub);
19828 }
19829 loc = locatesub(newpoint, &splitsub, 1, 0.0);
19830 #ifdef SELF_CHECK
19831 assert(loc != ONVERTEX);
19832 #endif
19833 if (loc != OUTSIDE) {
19834
19835 cavsublist->append(&splitsub);
19836
19837 collectcavsubs(newpoint, cavsublist);
19838
19839 reject = tallencsegsfsubs(newpoint, cavsublist);
19840
19841 cavsublist->clear();
19842 } else {
19843
19844 sspivot(splitsub, checkseg);
19845 #ifdef SELF_CHECK
19846 assert(checkseg.sh != dummysh);
19847 #endif
19848
19849 if (b->verbose > 2) {
19850 printf(" Queuing boundary segment (%d, %d).\n",
19851 pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
19852 }
19853 encsubseg = (badface *) badsubsegs->alloc();
19854 encsubseg->ss = checkseg;
19855 encsubseg->forg = sorg(checkseg);
19856 encsubseg->fdest = sdest(checkseg);
19857 encsubseg->foppo = (point) NULL;
19858 setshell2badface(encsubseg->ss, encsubseg);
19859
19860 reject = true;
19861 }
19862
19863 if (!reject) {
19864
19865
19866
19867 if (checkpbcs) {
19868 if (shellpbcgroup(splitsub) >= 0) {
19869
19870 makepoint(&sympoint);
19871
19872 symloc = getsubpbcsympoint(newpoint, &splitsub, sympoint,
19873 &symsplitsub);
19874 #ifdef SELF_CHECK
19875 assert(symloc != ONVERTEX);
19876 #endif
19877 setpoint2pbcpt(newpoint, sympoint);
19878 setpoint2pbcpt(sympoint, newpoint);
19879 setpointtype(sympoint, FREESUBVERTEX);
19880
19881
19882 pd = sorg(symsplitsub);
19883 splittet.tet = dummytet;
19884
19885 encodedtet = point2tet(pd);
19886 if (encodedtet != (tetrahedron) NULL) {
19887 decode(encodedtet, splittet);
19888 if (isdead(&splittet)) {
19889 splittet.tet = dummytet;
19890 }
19891 }
19892
19893 success = insertsite(sympoint, &splittet, false, flipqueue);
19894 #ifdef SELF_CHECK
19895 assert(success != DUPLICATEPOINT);
19896 #endif
19897 if (success == OUTSIDEPOINT) {
19898 inserthullsite(sympoint, &splittet, flipqueue);
19899 }
19900 if (steinerleft > 0) steinerleft--;
19901
19902 setpoint2tet(sympoint, encode(splittet));
19903
19904 flip(flipqueue, NULL);
19905
19906
19907
19908 if (symloc == ONFACE) {
19909 splitsubface(sympoint, &symsplitsub, flipqueue);
19910 } else if (symloc == ONEDGE) {
19911 splitsubedge(sympoint, &symsplitsub, flipqueue);
19912 } else {
19913
19914 #ifdef SELF_CHECK
19915 assert(symloc == ONVERTEX);
19916 assert(checksubfaces);
19917 #endif
19918
19919 flipqueue->clear();
19920 }
19921
19922 flipsub(flipqueue);
19923 }
19924 }
19925
19926
19927 splittet.tet = dummytet;
19928
19929 encodedtet = point2tet(pa);
19930 if (encodedtet != (tetrahedron) NULL) {
19931 decode(encodedtet, splittet);
19932 if (isdead(&splittet)) {
19933 splittet.tet = dummytet;
19934 }
19935 }
19936 if (splittet.tet == dummytet) {
19937 encodedtet = point2tet(pb);
19938 if (encodedtet != (tetrahedron) NULL) {
19939 decode(encodedtet, splittet);
19940 if (isdead(&splittet)) {
19941 splittet.tet = dummytet;
19942 }
19943 }
19944 }
19945
19946 success = insertsite(newpoint, &splittet, false, flipqueue);
19947 #ifdef SELF_CHECK
19948 assert(success != DUPLICATEPOINT);
19949 #endif
19950 if (success == OUTSIDEPOINT) {
19951 inserthullsite(newpoint, &splittet, flipqueue);
19952 }
19953 if (steinerleft > 0) steinerleft--;
19954
19955 setpoint2tet(newpoint, encode(splittet));
19956
19957 flip(flipqueue, NULL);
19958
19959
19960
19961
19962
19963
19964 if (loc == ONFACE) {
19965
19966 splitsubface(newpoint, &splitsub, flipqueue);
19967 } else if (loc == ONEDGE) {
19968
19969 splitsubedge(newpoint, &splitsub, flipqueue);
19970 } else {
19971
19972 #ifdef SELF_CHECK
19973 assert(loc == ONVERTEX);
19974 assert(checksubfaces);
19975 #endif
19976
19977 flipqueue->clear();
19978 }
19979
19980 setpointtype(newpoint, FREESUBVERTEX);
19981
19982
19983
19984 flipsub(flipqueue);
19985
19986
19987 badfacedealloc(badsubfaces, encloop);
19988 } else {
19989
19990 pointdealloc(newpoint);
19991
19992 perturbrepairencsegs(flipqueue);
19993
19994 setshell2badface(encloop->ss, encloop);
19995 }
19996 } else {
19997
19998 badfacedealloc(badsubfaces, encloop);
19999
20000
20001 }
20002
20003 encloop = badfacetraverse(badsubfaces);
20004 }
20005 }
20006 }
20007
20009
20010
20011
20012
20013
20014
20015
20016
20017
20018
20019
20020
20022
20023 void tetgenmesh::incrperturbvertices(REAL eps)
20024 {
20025 queue *flipqueue;
20026 list *cavsublist;
20027 long vertcount;
20028
20029 if (!b->quiet) {
20030 printf("Perturbing vertices.\n");
20031 }
20032
20033 vertcount = points->items;
20034
20035
20036
20037
20038 flipqueue = new queue(sizeof(badface));
20039 cavsublist = new list(sizeof(face), NULL, 256);
20040
20041 badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20042 badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
20043
20044 tallcocirsubs(eps, true);
20045 if (b->verbose && badsubfaces->items > 0) {
20046 printf(" Removing degenerate subfaces.\n");
20047 }
20048 perturbrepairencsubs(cavsublist, flipqueue);
20049
20050 if (b->verbose > 0) {
20051 printf(" %ld break points.\n", points->items - vertcount);
20052 }
20053
20054 delete cavsublist;
20055 delete flipqueue;
20056 delete badsubfaces;
20057 delete badsubsegs;
20058 badsubsegs = (memorypool *) NULL;
20059 badsubfaces = (memorypool *) NULL;
20060 }
20061
20062
20063
20064
20065
20066
20067
20068
20069
20071
20072
20073
20074
20075
20076
20077
20078
20079
20080
20081
20082
20083
20084
20086
20087 void tetgenmesh::markacutevertices(REAL acuteangle)
20088 {
20089 shellface **segsperverlist;
20090 face segloop, nextseg;
20091 point pointloop, edest, eapex;
20092 REAL cosbound, anglearc;
20093 REAL v1[3], v2[3], L, D;
20094 bool isacute;
20095 int *idx2seglist;
20096 int acutecount;
20097 int idx, i, j, k;
20098
20099 if (b->verbose > 0) {
20100 printf(" Marking acute vertices.\n");
20101 }
20102
20103 anglearc = acuteangle * PI / 180.0;
20104 cosbound = cos(anglearc);
20105 acutecount = 0;
20106
20107 makesegmentmap(idx2seglist, segsperverlist);
20108
20109
20110 points->traversalinit();
20111 pointloop = pointtraverse();
20112 while (pointloop != (point) NULL) {
20113 idx = pointmark(pointloop) - in->firstnumber;
20114
20115 if (idx2seglist[idx + 1] > idx2seglist[idx]) {
20116
20117 setpointtype(pointloop, NACUTEVERTEX);
20118 isacute = false;
20119
20120 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isacute; i++) {
20121 segloop.sh = segsperverlist[i];
20122
20123 if (sorg(segloop) != pointloop) sesymself(segloop);
20124 edest = sdest(segloop);
20125 for (j = i + 1; j < idx2seglist[idx + 1] && !isacute; j++) {
20126 nextseg.sh = segsperverlist[j];
20127
20128 if (sorg(nextseg) != pointloop) sesymself(nextseg);
20129 eapex = sdest(nextseg);
20130
20131 for (k = 0; k < 3; k++) {
20132 v1[k] = edest[k] - pointloop[k];
20133 v2[k] = eapex[k] - pointloop[k];
20134 }
20135 L = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
20136 for (k = 0; k < 3; k++) v1[k] /= L;
20137 L = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
20138 for (k = 0; k < 3; k++) v2[k] /= L;
20139 D = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
20140
20141 isacute = (D >= cosbound);
20142 }
20143 }
20144 if (isacute) {
20145
20146 setpointtype(pointloop, ACUTEVERTEX);
20147 acutecount++;
20148 }
20149 }
20150 pointloop = pointtraverse();
20151 }
20152
20153 delete [] idx2seglist;
20154 delete [] segsperverlist;
20155
20156 if ((b->verbose > 0) && (acutecount > 0)) {
20157 printf(" %d acute vertices.\n", acutecount);
20158 }
20159 }
20160
20162
20163
20164
20165
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
20193
20194 enum tetgenmesh::finddirectionresult tetgenmesh::
20195 finddirection(triface *searchtet, point tend, long maxtetnumber)
20196 {
20197 triface neightet;
20198 point tstart, tdest, tapex, toppo;
20199 REAL ori1, ori2, ori3;
20200 long tetnumber;
20201
20202 tstart = org(*searchtet);
20203 #ifdef SELF_CHECK
20204 assert(tstart != tend);
20205 #endif
20206 adjustedgering(*searchtet, CCW);
20207 if (tstart != org(*searchtet)) {
20208 enextself(*searchtet);
20209 }
20210 tdest = dest(*searchtet);
20211 if (tdest == tend) {
20212 return RIGHTCOLLINEAR;
20213 }
20214 tapex = apex(*searchtet);
20215 if (tapex == tend) {
20216 return LEFTCOLLINEAR;
20217 }
20218
20219 ori1 = orient3d(tstart, tdest, tapex, tend);
20220 if (ori1 > 0.0) {
20221
20222 sym(*searchtet, neightet);
20223 if (neightet.tet != dummytet) {
20224 findorg(&neightet, tstart);
20225 adjustedgering(neightet, CCW);
20226 if (org(neightet) != tstart) {
20227 enextself(neightet);
20228 }
20229
20230 *searchtet = neightet;
20231 ori1 = -1.0;
20232 tdest = dest(*searchtet);
20233 tapex = apex(*searchtet);
20234 } else {
20235
20236 #ifdef SELF_CHECK
20237 assert(nonconvex);
20238 #endif
20239 return BELOWHULL;
20240 }
20241 }
20242
20243
20244
20245
20246 tetnumber = 0l;
20247 while ((maxtetnumber > 0) && (tetnumber <= maxtetnumber)) {
20248 tetnumber++;
20249 toppo = oppo(*searchtet);
20250 if (toppo == tend) {
20251 return TOPCOLLINEAR;
20252 }
20253 ori2 = orient3d(tstart, toppo, tdest, tend);
20254 if (ori2 > 0.0) {
20255
20256 fnext(*searchtet, neightet);
20257 symself(neightet);
20258 if (neightet.tet != dummytet) {
20259 findorg(&neightet, tstart);
20260 adjustedgering(neightet, CCW);
20261 if (org(neightet) != tstart) {
20262 enextself(neightet);
20263 }
20264
20265 *searchtet = neightet;
20266 ori1 = -1.0;
20267 tdest = dest(*searchtet);
20268 tapex = apex(*searchtet);
20269
20270 continue;
20271 } else {
20272
20273 #ifdef SELF_CHECK
20274 assert(nonconvex);
20275 #endif
20276 return BELOWHULL;
20277 }
20278 }
20279 ori3 = orient3d(tapex, toppo, tstart, tend);
20280 if (ori3 > 0.0) {
20281
20282 enext2fnext(*searchtet, neightet);
20283 symself(neightet);
20284 if (neightet.tet != dummytet) {
20285 findorg(&neightet, tstart);
20286 adjustedgering(neightet, CCW);
20287 if (org(neightet) != tstart) {
20288 enextself(neightet);
20289 }
20290
20291 *searchtet = neightet;
20292 ori1 = -1.0;
20293 tdest = dest(*searchtet);
20294 tapex = apex(*searchtet);
20295
20296 continue;
20297 } else {
20298
20299 #ifdef SELF_CHECK
20300 assert(nonconvex);
20301 #endif
20302 return BELOWHULL;
20303 }
20304 }
20305
20306 if (ori1 < 0.0) {
20307
20308 if (ori2 < 0.0) {
20309 if (ori3 < 0.0) {
20310 return ACROSSFACE;
20311 } else {
20312
20313 enext2fnextself(*searchtet);
20314 esymself(*searchtet);
20315 return ACROSSEDGE;
20316 }
20317 } else {
20318 if (ori3 < 0.0) {
20319
20320 fnextself(*searchtet);
20321 esymself(*searchtet);
20322 enextself(*searchtet);
20323 return ACROSSEDGE;
20324 } else {
20325
20326 return TOPCOLLINEAR;
20327 }
20328 }
20329 } else {
20330
20331 if (ori2 < 0.0) {
20332 if (ori3 < 0.0) {
20333
20334 return ACROSSEDGE;
20335 } else {
20336
20337 return LEFTCOLLINEAR;
20338 }
20339 } else {
20340 #ifdef SELF_CHECK
20341 assert(ori3 != 0.0);
20342 #endif
20343
20344 return RIGHTCOLLINEAR;
20345 }
20346 }
20347 }
20348
20349 return BELOWHULL;
20350 }
20351
20353
20354
20355
20356
20357
20358
20359
20361
20362 void tetgenmesh::getsearchtet(point p1, point p2, triface* searchtet,
20363 point* tend)
20364 {
20365 tetrahedron encodedtet1, encodedtet2;
20366
20367
20368 if ((searchtet->tet != (tetrahedron *) NULL) && !isdead(searchtet)) {
20369
20370 if (findorg(searchtet, p1)) {
20371 *tend = p2;
20372 return;
20373 } else {
20374 if (findorg(searchtet, p2)) {
20375 *tend = p1;
20376 return;
20377 }
20378 }
20379 }
20380
20381 *tend = (point) NULL;
20382 encodedtet1 = point2tet(p1);
20383 encodedtet2 = point2tet(p2);
20384 if (encodedtet1 != (tetrahedron) NULL) {
20385 decode(encodedtet1, *searchtet);
20386
20387 if (findorg(searchtet, p1)) {
20388 *tend = p2;
20389 }
20390 } else if (encodedtet2 != (tetrahedron) NULL) {
20391 decode(encodedtet2, *searchtet);
20392
20393 if (findorg(searchtet, p2)) {
20394 *tend = p1;
20395 }
20396 }
20397
20398
20399
20400 if (*tend == (point) NULL) {
20401 if (encodedtet1 != (tetrahedron) NULL) {
20402 decode(encodedtet1, *searchtet);
20403
20404 }
20405 if (isdead(searchtet)) {
20406 if (encodedtet2 != (tetrahedron) NULL) {
20407 decode(encodedtet2, *searchtet);
20408
20409 }
20410 if (isdead(searchtet)) {
20411 searchtet->tet = dummytet;
20412 searchtet->loc = 0;
20413 symself(*searchtet);
20414 }
20415 #ifdef SELF_CHECK
20416 assert(!isdead(searchtet));
20417 #endif
20418 }
20419 if (locate(p1, searchtet) != ONVERTEX) {
20420 printf("Internal error in getsearchtet(): Failed to locate point\n");
20421 internalerror();
20422 }
20423
20424 setpoint2tet(p1, encode(*searchtet));
20425 *tend = p2;
20426 }
20427 }
20428
20430
20431
20432
20433
20434
20435
20436
20437
20439
20440 bool tetgenmesh::isedgeencroached(point p1, point p2, point testpt,
20441 bool degflag)
20442 {
20443 REAL dotproduct;
20444
20445
20446 dotproduct = (p1[0] - testpt[0]) * (p2[0] - testpt[0])
20447 + (p1[1] - testpt[1]) * (p2[1] - testpt[1])
20448 + (p1[2] - testpt[2]) * (p2[2] - testpt[2]);
20449 if (dotproduct < 0) {
20450 return true;
20451 } else if (dotproduct == 0 && degflag) {
20452 return true;
20453 } else {
20454 return false;
20455 }
20456 }
20457
20459
20460
20461
20462
20463
20464
20465
20466
20467
20468
20469
20470
20471
20473
20474 tetgenmesh::point tetgenmesh::scoutrefpoint(triface* searchtet, point tend)
20475 {
20476 triface checkface;
20477 point tstart, testpt, refpoint;
20478 REAL cent[3], radius, largest;
20479 REAL ahead;
20480 bool ncollinear;
20481 int sides;
20482
20483 if (b->verbose > 2) {
20484 printf(" Scout the reference point of segment (%d, %d).\n",
20485 pointmark(org(*searchtet)), pointmark(tend));
20486 }
20487
20488 tstart = org(*searchtet);
20489 refpoint = (point) NULL;
20490 largest = 0;
20491
20492
20493 testpt = apex(*searchtet);
20494 if (isedgeencroached(tstart, tend, testpt, true)) {
20495 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20496 #ifdef SELF_CHECK
20497 assert(ncollinear);
20498 #endif
20499 refpoint = testpt;
20500 largest = radius;
20501 }
20502 testpt = dest(*searchtet);
20503 if (isedgeencroached(tstart, tend, testpt, true)) {
20504 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20505 #ifdef SELF_CHECK
20506 assert(ncollinear);
20507 #endif
20508 if (refpoint == (point) NULL) {
20509 refpoint = testpt;
20510 largest = radius;
20511 } else {
20512 if (radius > largest) {
20513 refpoint = testpt;
20514 largest = radius;
20515 }
20516 }
20517 }
20518 testpt = oppo(*searchtet);
20519 if (isedgeencroached(tstart, tend, testpt, true)) {
20520 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20521 #ifdef SELF_CHECK
20522 assert(ncollinear);
20523 #endif
20524 if (refpoint == (point) NULL) {
20525 refpoint = testpt;
20526 largest = radius;
20527 } else {
20528 if (radius > largest) {
20529 refpoint = testpt;
20530 largest = radius;
20531 }
20532 }
20533 }
20534
20535
20536 sym(*searchtet, checkface);
20537 if (checkface.tet != dummytet) {
20538 testpt = oppo(checkface);
20539 if (isedgeencroached(tstart, tend, testpt, true)) {
20540 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20541 #ifdef SELF_CHECK
20542 assert(ncollinear);
20543 #endif
20544 if (refpoint == (point) NULL) {
20545 refpoint = testpt;
20546 largest = radius;
20547 } else {
20548 if (radius > largest) {
20549 refpoint = testpt;
20550 largest = radius;
20551 }
20552 }
20553 }
20554 }
20555
20556
20557 enextfnext(*searchtet, checkface);
20558 sym(checkface, *searchtet);
20559 while (true) {
20560
20561 #ifdef SELF_CHECK
20562 assert(searchtet->tet != dummytet);
20563 #endif
20564
20565 searchtet->ver = 0;
20566
20567 testpt = oppo(*searchtet);
20568 if (testpt == tend) {
20569
20570 break;
20571 } else {
20572
20573 if ((testpt != tstart) && (testpt != refpoint)) {
20574 if (isedgeencroached(tstart, tend, testpt, true)) {
20575 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20576 if (!ncollinear) {
20577
20578
20579
20580
20581
20582 refpoint = testpt;
20583 break;
20584 }
20585 if (refpoint == (point) NULL) {
20586 refpoint = testpt;
20587 largest = radius;
20588 } else {
20589 if (radius > largest) {
20590 refpoint = testpt;
20591 largest = radius;
20592 }
20593 }
20594 }
20595 }
20596 }
20597
20598
20599 for (sides = 0; sides < 3; sides++) {
20600 fnext(*searchtet, checkface);
20601 ahead = orient3d(org(checkface), dest(checkface), testpt, tend);
20602 if (ahead < 0.0) {
20603
20604 sym(checkface, *searchtet);
20605 break;
20606 }
20607 enextself(*searchtet);
20608 }
20609 #ifdef SELF_CHECK
20610 assert (sides < 3);
20611 #endif
20612 }
20613
20614 #ifdef SELF_CHECK
20615 assert(refpoint != (point) NULL);
20616 #endif
20617 return refpoint;
20618 }
20619
20621
20622
20623
20624
20625
20626
20627
20628
20630
20631 tetgenmesh::point tetgenmesh::getsegmentorigin(face* splitseg)
20632 {
20633 face workseg;
20634 point farorg;
20635
20636 farorg = sorg(*splitseg);
20637 if ((pointtype(farorg) != ACUTEVERTEX) &&
20638 (pointtype(farorg) != NACUTEVERTEX)) {
20639 workseg = *splitseg;
20640 do {
20641 senext2self(workseg);
20642 spivotself(workseg);
20643 if (workseg.sh != dummysh) {
20644 workseg.shver = 0;
20645 if (sdest(workseg) != farorg) {
20646 sesymself(workseg);
20647 #ifdef SELF_CHECK
20648 assert(sdest(workseg) == farorg);
20649 #endif
20650 }
20651 farorg = sorg(workseg);
20652 if ((pointtype(farorg) == ACUTEVERTEX) ||
20653 (pointtype(farorg) == NACUTEVERTEX)) break;
20654 }
20655 } while (workseg.sh != dummysh);
20656 }
20657 #ifdef SELF_CHECK
20658 assert((pointtype(farorg) == ACUTEVERTEX) ||
20659 (pointtype(farorg) == NACUTEVERTEX));
20660 #endif
20661 return farorg;
20662 }
20663
20665
20666
20667
20668
20669
20670
20671
20672
20673
20674
20675
20676
20677
20678
20680
20681 tetgenmesh::point tetgenmesh::getsplitpoint(face* splitseg, point refpoint)
20682 {
20683 point splitpoint;
20684 point farorg, fardest;
20685 point ei, ej, ek, c;
20686 REAL v[3], r, split;
20687 REAL d1, d2, ps, rs;
20688 bool acuteorg, acutedest;
20689 int stype, rule;
20690 int i;
20691
20692
20693 farorg = getsegmentorigin(splitseg);
20694 acuteorg = (pointtype(farorg) == ACUTEVERTEX);
20695 sesymself(*splitseg);
20696 fardest = getsegmentorigin(splitseg);
20697 acutedest = (pointtype(fardest) == ACUTEVERTEX);
20698 sesymself(*splitseg);
20699
20700 ek = (point) NULL;
20701
20702 if (acuteorg) {
20703 if (acutedest) {
20704 stype = 3;
20705 } else {
20706 stype = 2;
20707 ek = farorg;
20708 }
20709 } else {
20710 if (acutedest) {
20711 stype = 2;
20712
20713 sesymself(*splitseg);
20714 ek = fardest;
20715 } else {
20716 stype = 1;
20717 }
20718 }
20719 ei = sorg(*splitseg);
20720 ej = sdest(*splitseg);
20721
20722 if (b->verbose > 1) {
20723 printf(" Splitting segment (%d, %d) type-%d with refpoint %d.\n",
20724 pointmark(ei), pointmark(ej), stype, pointmark(refpoint));
20725 }
20726
20727 if (stype == 1 || stype == 3) {
20728
20729 REAL eij, eip, ejp;
20730 eij = distance(ei, ej);
20731 eip = distance(ei, refpoint);
20732 ejp = distance(ej, refpoint);
20733 if ((eip < ejp) && (eip < 0.5 * eij)) {
20734 c = ei;
20735 r = eip;
20736 } else if ((eip > ejp) && (ejp < 0.5 * eij)) {
20737 c = ej;
20738 ej = ei;
20739 r = ejp;
20740 } else {
20741 c = ei;
20742 r = 0.5 * eij;
20743 }
20744 split = r / eij;
20745 for (i = 0; i < 3; i++) {
20746 v[i] = c[i] + split * (ej[i] - c[i]);
20747 }
20748 rule = 1;
20749 } else {
20750
20751 REAL eki, ekj, ekp, evj, evp, eiv;
20752 c = ek;
20753 eki = distance(ek, ei);
20754 ekj = distance(ek, ej);
20755 ekp = distance(ek, refpoint);
20756
20757 r = ekp;
20758
20759 if (!(eki < r && r < ekj)) {
20760 printf("Error: Invalid PLC.\n");
20761 printf(" Hint: Use -d switch to check it.\n");
20762 terminatetetgen(1);
20763 }
20764 split = r / ekj;
20765 for (i = 0; i < 3; i++) {
20766 v[i] = c[i] + split * (ej[i] - c[i]);
20767 }
20768 rule = 2;
20769 evj = ekj - r;
20770 evp = distance(v, refpoint);
20771 if (evj < evp) {
20772
20773 eiv = distance(ei, v);
20774 if (evp <= 0.5 * eiv) {
20775 r = eki + eiv - evp;
20776 } else {
20777 r = eki + 0.5 * eiv;
20778 }
20779 #ifdef SELF_CHECK
20780 assert(eki < r && r < ekj);
20781 #endif
20782 split = r / ekj;
20783 for (i = 0; i < 3; i++) {
20784 v[i] = c[i] + split * (ej[i] - c[i]);
20785 }
20786 if (b->verbose > 1) {
20787 printf(" Using rule-3.\n");
20788 }
20789 rule = 3;
20790 }
20791 }
20792
20793
20794 if (rule == 1) r1count++;
20795 else if (rule == 2) r2count++;
20796 else if (rule == 3) r3count++;
20797
20798 if (b->verbose > 1) {
20799 if (stype == 2) {
20800 printf(" Split = %.12g.\n", distance(ei, v) / distance(ei, ej));
20801 } else {
20802 printf(" Split = %.12g.\n", distance(c, v) / distance(c, ej));
20803 }
20804 }
20805
20806
20807 makepoint(&splitpoint);
20808
20809 d1 = distance(c, v);
20810 d2 = distance(refpoint, v);
20811 if (stype == 1 || stype == 3) {
20812 ps = randgenerator(d1 * 1.0e-3);
20813 } else {
20814
20815
20816
20817 ps = randgenerator(d2 * 1.0e-5);
20818 }
20819 rs = ps / d1;
20820
20821 for (i = 0; i < 3; i++) {
20822 splitpoint[i] = c[i] + (1.0 + rs) * (v[i] - c[i]);
20823 }
20824
20825
20826
20827 if (stype == 3) {
20828
20829 setpointtype(splitpoint, NACUTEVERTEX);
20830 } else {
20831
20832 setpointtype(splitpoint, FREESEGVERTEX);
20833 }
20834 setpoint2sh(splitpoint, sencode(*splitseg));
20835
20836 return splitpoint;
20837 }
20838
20840
20841
20842
20844
20845 bool tetgenmesh::insertsegment(face *insseg, list *misseglist)
20846 {
20847 badface *misseg;
20848 triface searchtet, spintet;
20849 point tend, checkpoint;
20850 point p1, p2;
20851 enum finddirectionresult collinear;
20852 int hitbdry;
20853
20854
20855 p1 = (point) insseg->sh[3];
20856 p2 = (point) insseg->sh[4];
20857 getsearchtet(p1, p2, &searchtet, &tend);
20858 collinear = finddirection(&searchtet, tend, tetrahedrons->items);
20859 if (collinear == LEFTCOLLINEAR) {
20860 checkpoint = apex(searchtet);
20861 enext2self(searchtet);
20862 esymself(searchtet);
20863 } else if (collinear == RIGHTCOLLINEAR) {
20864 checkpoint = dest(searchtet);
20865 } else if (collinear == TOPCOLLINEAR) {
20866 checkpoint = oppo(searchtet);
20867 fnextself(searchtet);
20868 enext2self(searchtet);
20869 esymself(searchtet);
20870 } else {
20871
20872 checkpoint = (point) NULL;
20873 }
20874 if (checkpoint == tend) {
20875
20876 hitbdry = 0;
20877 adjustedgering(searchtet, CCW);
20878 fnextself(searchtet);
20879 spintet = searchtet;
20880 do {
20881 tssbond1(spintet, *insseg);
20882 if (!fnextself(spintet)) {
20883 hitbdry++;
20884 if (hitbdry < 2) {
20885 esym(searchtet, spintet);
20886 if (!fnextself(spintet)) {
20887 hitbdry++;
20888 }
20889 }
20890 }
20891 } while ((apex(spintet) != apex(searchtet)) && (hitbdry < 2));
20892 return true;
20893 } else {
20894
20895 if (misseglist != (list *) NULL) {
20896 if (b->verbose > 2) {
20897 printf(" Queuing missing segment (%d, %d).\n", pointmark(p1),
20898 pointmark(p2));
20899 }
20900 misseg = (badface *) misseglist->append(NULL);
20901 misseg->ss = *insseg;
20902 misseg->forg = p1;
20903 misseg->fdest = p2;
20904 misseg->foppo = (point) NULL;
20905
20906 }
20907 return false;
20908 }
20909 }
20910
20912
20913
20914
20916
20917 void tetgenmesh::tallmissegs(list *misseglist)
20918 {
20919 face segloop;
20920
20921 if (b->verbose) {
20922 printf(" Queuing missing segments.\n");
20923 }
20924
20925 subsegs->traversalinit();
20926 segloop.sh = shellfacetraverse(subsegs);
20927 while (segloop.sh != (shellface *) NULL) {
20928 insertsegment(&segloop, misseglist);
20929 segloop.sh = shellfacetraverse(subsegs);
20930 }
20931 }
20932
20934
20935
20936
20937
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
20969
20970 void tetgenmesh::delaunizesegments()
20971 {
20972 list *misseglist;
20973 queue *flipqueue;
20974 badface *misloop;
20975 tetrahedron encodedtet;
20976 triface searchtet, splittet;
20977 face splitsh, symsplitsub;
20978 face segloop, symsplitseg;
20979 point refpoint, splitpoint, sympoint;
20980 point tend, checkpoint;
20981 point p1, p2, pa;
20982 enum finddirectionresult collinear;
20983 enum insertsiteresult success;
20984 enum locateresult symloc;
20985 bool coll;
20986 long vertcount;
20987 int i, j;
20988
20989 if (!b->quiet) {
20990 printf("Delaunizing segments.\n");
20991 }
20992
20993
20994 makepoint2tetmap();
20995
20996 flipqueue = new queue(sizeof(badface));
20997
20998 misseglist = new list(sizeof(badface), NULL, SUBPERBLOCK);
20999
21000 tallmissegs(misseglist);
21001
21002 checksubsegs = 1;
21003
21004 vertcount = points->items;
21005
21006 r1count = r2count = r3count = 0l;
21007
21008
21009 while (misseglist->items > 0) {
21010
21011 i = randomnation(misseglist->items);
21012 misloop = (badface *)(* misseglist)[i];
21013 segloop = misloop->ss;
21014
21015 *misloop = *(badface *)(* misseglist)[misseglist->items - 1];
21016 misseglist->items--;
21017
21018 p1 = (point) segloop.sh[3];
21019 p2 = (point) segloop.sh[4];
21020 if (b->verbose > 1) {
21021 printf(" Recover segment (%d, %d).\n", pointmark(p1), pointmark(p2));
21022 }
21023 getsearchtet(p1, p2, &searchtet, &tend);
21024 collinear = finddirection(&searchtet, tend, tetrahedrons->items);
21025 if (collinear == LEFTCOLLINEAR) {
21026 checkpoint = apex(searchtet);
21027 } else if (collinear == RIGHTCOLLINEAR) {
21028 checkpoint = dest(searchtet);
21029 } else if (collinear == TOPCOLLINEAR) {
21030 checkpoint = oppo(searchtet);
21031 } else {
21032 #ifdef SELF_CHECK
21033 assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
21034 #endif
21035 checkpoint = (point) NULL;
21036 }
21037 if (checkpoint != tend) {
21038
21039 splitpoint = (point) NULL;
21040 if (checkpoint != (point) NULL) {
21041
21042
21043
21044 splitpoint = checkpoint;
21045 if (pointtype(checkpoint) == FREEVOLVERTEX) {
21046
21047 setpointtype(splitpoint, NACUTEVERTEX);
21048 } else if (pointtype(checkpoint) == ACUTEVERTEX) {
21049
21050 } else if (pointtype(checkpoint) == NACUTEVERTEX) {
21051
21052 } else {
21053
21054 }
21055 } else {
21056
21057 refpoint = scoutrefpoint(&searchtet, tend);
21058 if (pointtype(refpoint) == FREEVOLVERTEX) {
21059
21060 coll = iscollinear(p1, p2, refpoint, b->epsilon);
21061 if (coll) {
21062
21063
21064 splitpoint = refpoint;
21065 setpointtype(splitpoint, NACUTEVERTEX);
21066 }
21067 }
21068 if (splitpoint == (point) NULL) {
21069
21070 splitpoint = getsplitpoint(&segloop, refpoint);
21071
21072
21073 if (checkpbcs) {
21074
21075 i = shellmark(segloop) - 1;
21076 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
21077 makepoint(&sympoint);
21078 symloc = getsegpbcsympoint(splitpoint, &segloop, sympoint,
21079 &symsplitseg, segpglist[j]);
21080 #ifdef SELF_CHECK
21081 assert(symloc != OUTSIDE);
21082 #endif
21083 if ((symloc == ONEDGE) && (symsplitseg.sh != segloop.sh)) {
21084 #ifdef SELF_CHECK
21085 assert(symsplitseg.sh != dummysh);
21086 #endif
21087 setpointtype(sympoint, FREESEGVERTEX);
21088 setpoint2sh(sympoint, sencode(symsplitseg));
21089
21090 pa = sorg(symsplitseg);
21091 splittet.tet = dummytet;
21092
21093 encodedtet = point2tet(pa);
21094 if (encodedtet != (tetrahedron) NULL) {
21095 decode(encodedtet, splittet);
21096 if (isdead(&splittet)) {
21097 splittet.tet = dummytet;
21098 }
21099 }
21100
21101 success = insertsite(sympoint, &splittet, false, flipqueue);
21102 #ifdef SELF_CHECK
21103 assert(success != DUPLICATEPOINT);
21104 #endif
21105 if (success == OUTSIDEPOINT) {
21106 inserthullsite(sympoint, &splittet, flipqueue);
21107 }
21108 if (steinerleft > 0) steinerleft--;
21109
21110 setpoint2tet(sympoint, encode(splittet));
21111
21112 lawson(misseglist, flipqueue);
21113
21114 symsplitseg.shver = 0;
21115 spivot(symsplitseg, symsplitsub);
21116
21117 splitsubedge(sympoint, &symsplitsub, flipqueue);
21118
21119 flipsub(flipqueue);
21120
21121 symsplitseg.shver = 0;
21122 insertsegment(&symsplitseg, misseglist);
21123 senextself(symsplitseg);
21124 spivotself(symsplitseg);
21125 symsplitseg.shver = 0;
21126 insertsegment(&symsplitseg, misseglist);
21127 } else {
21128
21129
21130 pointdealloc(sympoint);
21131 }
21132 }
21133 }
21134
21135
21136 if (isdead(&searchtet)) searchtet.tet = dummytet;
21137 success = insertsite(splitpoint, &searchtet, false, flipqueue);
21138 if (success == OUTSIDEPOINT) {
21139
21140
21141
21142 inserthullsite(splitpoint, &searchtet, flipqueue);
21143 }
21144 if (steinerleft > 0) steinerleft--;
21145
21146
21147 setpoint2tet(splitpoint, encode(searchtet));
21148
21149 lawson(misseglist, flipqueue);
21150 }
21151 }
21152
21153 spivot(segloop, splitsh);
21154 splitsubedge(splitpoint, &splitsh, flipqueue);
21155 flipsub(flipqueue);
21156
21157 segloop.shver = 0;
21158 insertsegment(&segloop, misseglist);
21159 senextself(segloop);
21160 spivotself(segloop);
21161 segloop.shver = 0;
21162 insertsegment(&segloop, misseglist);
21163 }
21164 }
21165
21166
21167 tetrahedrons->traversalinit();
21168 searchtet.tet = tetrahedrontraverse();
21169 while (searchtet.tet != (tetrahedron *) NULL) {
21170 for (i = 0; i < 6; i++) {
21171 searchtet.tet[8 + i] = (tetrahedron) dummysh;
21172 }
21173 searchtet.tet = tetrahedrontraverse();
21174 }
21175
21176 checksubsegs = 0;
21177
21178 if (b->verbose > 0) {
21179 printf(" %ld protect points.\n", points->items - vertcount);
21180 printf(" R1: %ld, R2: %ld, R3: %ld.\n", r1count, r2count, r3count);
21181 }
21182
21183 delete flipqueue;
21184 delete misseglist;
21185 }
21186
21187
21188
21189
21190
21191
21192
21193
21194
21196
21197
21198
21199
21200
21201
21203
21204 bool tetgenmesh::insertsubface(face* insertsh, triface* searchtet)
21205 {
21206 triface spintet, symtet;
21207 face testsh, testseg;
21208 face spinsh, casin, casout;
21209 point tapex, checkpoint;
21210 enum finddirectionresult collinear;
21211 int hitbdry;
21212
21213
21214 getsearchtet(sorg(*insertsh), sdest(*insertsh), searchtet, &checkpoint);
21215 collinear = finddirection(searchtet, checkpoint, tetrahedrons->items);
21216 if (collinear == LEFTCOLLINEAR) {
21217 enext2self(*searchtet);
21218 esymself(*searchtet);
21219 } else if (collinear == TOPCOLLINEAR) {
21220 fnextself(*searchtet);
21221 enext2self(*searchtet);
21222 esymself(*searchtet);
21223 }
21224 if (dest(*searchtet) != checkpoint) {
21225
21226 return false;
21227 }
21228
21229
21230 tapex = sapex(*insertsh);
21231 spintet = *searchtet;
21232 hitbdry = 0;
21233 do {
21234 if (apex(spintet) == tapex) {
21235
21236 tspivot(spintet, testsh);
21237 if (testsh.sh == dummysh) {
21238 adjustedgering(spintet, CCW);
21239 findedge(insertsh, org(spintet), dest(spintet));
21240 tsbond(spintet, *insertsh);
21241 sym(spintet, symtet);
21242 sesymself(*insertsh);
21243 tsbond(symtet, *insertsh);
21244 } else {
21245
21246 if (!b->quiet) {
21247 printf("Warning: Two subfaces are found duplicated at ");
21248 printf("(%d, %d, %d)\n", pointmark(sorg(testsh)),
21249 pointmark(sdest(testsh)), pointmark(sapex(testsh)));
21250 printf(" Subface of facet #%d is deleted.\n", shellmark(*insertsh));
21251
21252 }
21253 shellfacedealloc(subfaces, insertsh->sh);
21254 }
21255 return true;
21256 }
21257 if (!fnextself(spintet)) {
21258 hitbdry ++;
21259 if (hitbdry < 2) {
21260 esym(*searchtet, spintet);
21261 if (!fnextself(spintet)) {
21262 hitbdry ++;
21263 }
21264 }
21265 }
21266 } while (hitbdry < 2 && apex(spintet) != apex(*searchtet));
21267
21268
21269 return false;
21270 }
21271
21273
21274
21275
21276
21277
21278
21279
21280
21282
21283 bool tetgenmesh::tritritest(triface* checktet, point p1, point p2, point p3)
21284 {
21285 point forg, fdest, fapex;
21286 enum interresult intersect;
21287
21288 forg = org(*checktet);
21289 fdest = dest(*checktet);
21290 fapex = apex(*checktet);
21291
21292 #ifdef SELF_CHECK
21293 REAL ax, ay, az, bx, by, bz;
21294 REAL n[3];
21295
21296
21297 ax = forg[0] - fdest[0];
21298 ay = forg[1] - fdest[1];
21299 az = forg[2] - fdest[2];
21300 bx = forg[0] - fapex[0];
21301 by = forg[1] - fapex[1];
21302 bz = forg[2] - fapex[2];
21303 n[0] = ay * bz - by * az;
21304 n[1] = az * bx - bz * ax;
21305 n[2] = ax * by - bx * ay;
21306 assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21307
21308
21309 ax = p1[0] - p2[0];
21310 ay = p1[1] - p2[1];
21311 az = p1[2] - p2[2];
21312 bx = p1[0] - p3[0];
21313 by = p1[1] - p3[1];
21314 bz = p1[2] - p3[2];
21315 n[0] = ay * bz - by * az;
21316 n[1] = az * bx - bz * ax;
21317 n[2] = ax * by - bx * ay;
21318 assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21319
21320 #endif
21321
21322 intersect = tri_tri_inter(forg, fdest, fapex, p1, p2, p3);
21323 return intersect == INTERSECT;
21324 }
21325
21327
21328
21329
21330
21331
21332
21333
21334
21335
21336
21337
21338
21339
21341
21342 void tetgenmesh::initializecavity(list* floorlist, list* ceillist,
21343 list* frontlist)
21344 {
21345 triface neightet, casingtet;
21346 triface faketet;
21347 face worksh;
21348 int i;
21349
21350
21351 for (i = 0; i < floorlist->len(); i++) {
21352
21353 worksh = * (face *)(* floorlist)[i];
21354 #ifdef SELF_CHECK
21355
21356 stpivot(worksh, neightet);
21357 assert(neightet.tet == dummytet);
21358 #endif
21359
21360 sesymself(worksh);
21361 stpivot(worksh, casingtet);
21362
21363 if (casingtet.tet == dummytet) {
21364
21365 maketetrahedron(&faketet);
21366 setorg(faketet, sorg(worksh));
21367 setdest(faketet, sdest(worksh));
21368 setapex(faketet, sapex(worksh));
21369 setoppo(faketet, (point) NULL);
21370 tsbond(faketet, worksh);
21371 frontlist->append(&faketet);
21372 } else {
21373 frontlist->append(&casingtet);
21374 }
21375 }
21376
21377 for (i = 0; i < ceillist->len(); i++) {
21378
21379 neightet = * (triface *) (* ceillist)[i];
21380 #ifdef SELF_CHECK
21381
21382 assert(infected(neightet));
21383 #endif
21384
21385 sym(neightet, casingtet);
21386
21387 if (casingtet.tet == dummytet) {
21388
21389 maketetrahedron(&faketet);
21390
21391 adjustedgering(neightet, CW);
21392 setorg(faketet, org(neightet));
21393 setdest(faketet, dest(neightet));
21394 setapex(faketet, apex(neightet));
21395 setoppo(faketet, (point) NULL);
21396
21397 tspivot(neightet, worksh);
21398 if (worksh.sh != dummysh) {
21399 sesymself(worksh);
21400 tsbond(faketet, worksh);
21401 }
21402
21403 bond(faketet, neightet);
21404
21405 infect(neightet);
21406 frontlist->append(&faketet);
21407 } else {
21408 frontlist->append(&casingtet);
21409 }
21410 }
21411 }
21412
21414
21415
21416
21417
21418
21419
21421
21422 void tetgenmesh::retrievenewtets(list* newtetlist)
21423 {
21424 triface searchtet, casingtet;
21425 int i;
21426
21427
21428 for (i = 0; i < newtetlist->len(); i++) {
21429 searchtet = * (triface *)(* newtetlist)[i];
21430 if (isdead(&searchtet)) {
21431 newtetlist->del(i, 0); i--;
21432 continue;
21433 }
21434 infect(searchtet);
21435 }
21436
21437 for (i = 0; i < newtetlist->len(); i++) {
21438 searchtet = * (triface *)(* newtetlist)[i];
21439 for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
21440 sym(searchtet, casingtet);
21441 if ((casingtet.tet != dummytet) && !infected(casingtet)) {
21442 infect(casingtet);
21443 newtetlist->append(&casingtet);
21444 }
21445 }
21446 }
21447
21448 for (i = 0; i < newtetlist->len(); i++) {
21449 searchtet = * (triface *)(* newtetlist)[i];
21450 uninfect(searchtet);
21451 }
21452 }
21453
21455
21456
21457
21458
21459
21460
21461
21462
21463
21464
21466
21467 void tetgenmesh::delaunizecavvertices(triface* oldtet, list* floorptlist,
21468 list* ceilptlist, list* newtetlist, queue* flipque)
21469 {
21470 point *insertarray;
21471 triface bakhulltet, newtet;
21472 long bakhullsize;
21473 long arraysize;
21474 int bakchksub;
21475 int i, j;
21476
21477
21478 arraysize = floorptlist->len();
21479 if (ceilptlist != (list *) NULL) {
21480 arraysize += ceilptlist->len();
21481 }
21482 insertarray = new point[arraysize];
21483 for (i = 0; i < floorptlist->len(); i++) {
21484 insertarray[i] = * (point *)(* floorptlist)[i];
21485 }
21486 if (ceilptlist != (list *) NULL) {
21487 for (j = 0; j < ceilptlist->len(); j++) {
21488 insertarray[i + j] = * (point *)(* ceilptlist)[j];
21489 }
21490 }
21491
21492
21493 decode(dummytet[0], bakhulltet);
21494 bakhullsize = hullsize;
21495 bakchksub = checksubfaces;
21496 checksubfaces = 0;
21497 b->verbose--;
21498
21499
21500
21501 incrflipdelaunay(oldtet, insertarray, arraysize, false, false, 0.0, flipque);
21502
21503
21504 decode(dummytet[0], newtet);
21505 newtetlist->append(&newtet);
21506
21507 retrievenewtets(newtetlist);
21508
21509
21510 dummytet[0] = encode(bakhulltet);
21511 hullsize = bakhullsize;
21512 checksubfaces = bakchksub;
21513 b->verbose++;
21514
21515 delete [] insertarray;
21516 }
21517
21519
21520
21521
21522
21523
21524
21525
21526
21527
21528
21529
21531
21532 void tetgenmesh::insertauxsubface(triface* front, triface* idfront)
21533 {
21534 triface neightet;
21535 face auxsh;
21536
21537
21538 makeshellface(subfaces, &auxsh);
21539
21540 tsbond(*idfront, auxsh);
21541
21542 sym(*idfront, neightet);
21543 if (neightet.tet != dummytet) {
21544
21545 sesymself(auxsh);
21546 tsbond(neightet, auxsh);
21547 }
21548
21549 auxsh.sh[0] = (shellface) encode(*front);
21550 }
21551
21553
21554
21555
21556
21557
21558
21560
21561 bool tetgenmesh::scoutfront(triface* front, triface* idfront, list* newtetlist)
21562 {
21563 triface spintet;
21564 point pa, pb, pc;
21565 enum locateresult loc;
21566 enum finddirectionresult col;
21567 int hitbdry;
21568 int i;
21569
21570
21571 pa = org(*front);
21572 pb = dest(*front);
21573
21574 *idfront = recenttet;
21575
21576 if (isdead(idfront)) {
21577
21578 for (i = 0; i < newtetlist->len(); i++) {
21579 recenttet = * (triface *)(* newtetlist)[i];
21580 if (!isdead(&recenttet)) break;
21581 }
21582 assert(i < newtetlist->len());
21583 }
21584
21585
21586 loc = preciselocate(pa, idfront, (long) newtetlist->len());
21587 assert(loc == ONVERTEX);
21588 recenttet = *idfront;
21589
21590 col = finddirection(idfront, pb, (long) newtetlist->len());
21591 if (col == RIGHTCOLLINEAR) {
21592
21593 } else if (col == LEFTCOLLINEAR) {
21594 enext2self(*idfront);
21595 esymself(*idfront);
21596 } else if (col == TOPCOLLINEAR) {
21597 fnextself(*idfront);
21598 enext2self(*idfront);
21599 esymself(*idfront);
21600 }
21601
21602 if (dest(*idfront) == pb) {
21603
21604 pc = apex(*front);
21605 spintet = *idfront;
21606 hitbdry = 0;
21607 do {
21608 if (apex(spintet) == pc) {
21609
21610
21611 *idfront = spintet;
21612 return true;
21613 }
21614 if (!fnextself(spintet)) {
21615 hitbdry ++;
21616 if (hitbdry < 2) {
21617 esym(*idfront, spintet);
21618 if (!fnextself(spintet)) {
21619 hitbdry ++;
21620 }
21621 }
21622 }
21623 if (apex(spintet) == apex(*idfront)) break;
21624 } while (hitbdry < 2);
21625 }
21626
21627
21628 if (b->verbose > 2) {
21629 printf(" Front (%d, %d, %d) is missing.\n", pointmark(pa),
21630 pointmark(pb), pointmark(apex(*front)));
21631 }
21632 return false;
21633 }
21634
21636
21637
21638
21639
21640
21641
21642
21643
21645
21646 void tetgenmesh::gluefronts(triface* front, triface* front1)
21647 {
21648 face consh;
21649
21650
21651
21652
21653
21654
21655
21656
21657
21658 tspivot(*front, consh);
21659 if (consh.sh != dummysh) {
21660 sesymself(consh);
21661 tsbond(*front1, consh);
21662 sesymself(consh);
21663 }
21664
21665 if (oppo(*front) == (point) NULL) {
21666
21667 assert(oppo(*front1) != (point) NULL);
21668
21669 if (consh.sh != dummysh) {
21670 stdissolve(consh);
21671 }
21672
21673 tetrahedrondealloc(front->tet);
21674
21675 dummytet[0] = encode(*front1);
21676 } else {
21677
21678 bond(*front, *front1);
21679 }
21680
21681 if (!isdead(front)) {
21682
21683 tspivot(*front1, consh);
21684
21685 if (oppo(*front1) == (point) NULL) {
21686
21687 assert(oppo(*front) != (point) NULL);
21688
21689 if (consh.sh != dummysh) {
21690 stdissolve(consh);
21691 sesymself(consh);
21692 tsbond(*front, consh);
21693 }
21694
21695 dissolve(*front);
21696
21697 tetrahedrondealloc(front1->tet);
21698
21699 dummytet[0] = encode(*front);
21700 } else {
21701
21702 if (consh.sh != dummysh) {
21703 sesymself(consh);
21704 tsbond(*front, consh);
21705 }
21706 }
21707 }
21708 }
21709
21711
21712
21713
21714
21715
21716
21717
21718
21720
21721 bool tetgenmesh::identifyfronts(list* frontlist, list* misfrontlist,
21722 list* newtetlist)
21723 {
21724 triface front, front1, tfront;
21725 triface idfront, neightet;
21726 face auxsh;
21727 int len, i, j;
21728
21729 misfrontlist->clear();
21730
21731 recenttet = * (triface *)(* newtetlist)[0];
21732
21733
21734 for (i = 0; i < frontlist->len(); i++) {
21735
21736 front = * (triface *)( *frontlist)[i];
21737 if (scoutfront(&front, &idfront, newtetlist)) {
21738
21739 assert((idfront.tet != dummytet) && !isdead(&idfront));
21740
21741 tspivot(idfront, auxsh);
21742 if (auxsh.sh != dummysh) {
21743
21744 decode((tetrahedron) auxsh.sh[0], front1);
21745 assert((front1.tet != dummytet) && !infected(front1));
21746
21747 tsdissolve(idfront);
21748 sym(idfront, neightet);
21749 if (neightet.tet != dummytet) {
21750 tsdissolve(neightet);
21751 }
21752
21753 shellfacedealloc(subfaces, auxsh.sh);
21754
21755 frontlist->del(i, 1); i--;
21756
21757 len = frontlist->len();
21758 for (j = 0; j < frontlist->len(); j++) {
21759 tfront = * (triface *)(* frontlist)[j];
21760 if ((tfront.tet == front1.tet) && (tfront.loc == front1.loc)) {
21761
21762 assert((tfront.tet != front.tet) || (tfront.loc != front.loc));
21763 frontlist->del(j, 1); i--;
21764 break;
21765 }
21766 }
21767 assert((frontlist->len() + 1) == len);
21768
21769 gluefronts(&front, &front1);
21770 } else {
21771
21772 insertauxsubface(&front, &idfront);
21773 }
21774 } else {
21775
21776 frontlist->del(i, 1); i--;
21777
21778 for (j = 0; j < misfrontlist->len(); j++) {
21779 front1 = * (triface *)(* misfrontlist)[j];
21780 if (isfacehaspoint(&front1, org(front)) &&
21781 isfacehaspoint(&front1, dest(front)) &&
21782 isfacehaspoint(&front1, apex(front))) break;
21783 }
21784 if (j < misfrontlist->len()) {
21785
21786 misfrontlist->del(j, 1);
21787
21788 gluefronts(&front, &front1);
21789 } else {
21790
21791 misfrontlist->append(&front);
21792 }
21793 }
21794 }
21795 return misfrontlist->len() == 0;
21796 }
21797
21799
21800
21801
21802
21803
21804
21805
21806
21808
21809 void tetgenmesh::detachauxsubfaces(list* newtetlist)
21810 {
21811 triface newtet, neightet;
21812 face auxsh;
21813 int i;
21814
21815 for (i = 0; i < newtetlist->len(); i++) {
21816
21817 newtet = * (triface *)(* newtetlist)[i];
21818
21819 if (isdead(&newtet)) continue;
21820 assert(!infected(newtet));
21821
21822 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
21823 tspivot(newtet, auxsh);
21824 if (auxsh.sh != dummysh) {
21825
21826 assert(sorg(auxsh) == (point) NULL);
21827 tsdissolve(newtet);
21828 sym(newtet, neightet);
21829 if (neightet.tet != dummytet) {
21830 assert(!isdead(&neightet));
21831 tsdissolve(neightet);
21832 }
21833
21834 shellfacedealloc(subfaces, auxsh.sh);
21835 }
21836 }
21837 }
21838 }
21839
21841
21842
21843
21844
21845
21846
21847
21848
21849
21851
21852 void tetgenmesh::expandcavity(list* frontlist, list* misfrontlist,
21853 list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
21854 {
21855 triface misfront, newfront, casingtet, crosstet;
21856 triface searchtet, faketet, bakhulltet;
21857 face checksh;
21858 point pd;
21859 enum insertsiteresult success;
21860 long bakhullsize;
21861 int bakchksub;
21862 int i, j, k;
21863
21864 if (b->verbose > 1) {
21865 printf(" Expand cavity (%d missing fronts).\n", misfrontlist->len());
21866 }
21867
21868 expcavcount++;
21869
21870 decode(dummytet[0], bakhulltet);
21871 bakhullsize = hullsize;
21872 bakchksub = checksubfaces;
21873 checksubfaces = 0;
21874 b->verbose--;
21875
21876
21877 recenttet = * (triface *)(* newtetlist)[0];
21878 assert((recenttet.tet != dummytet) && !isdead(&recenttet));
21879
21880
21881 for (i = 0; i < misfrontlist->len(); i++) {
21882
21883 misfront = * (triface *)(* misfrontlist)[i];
21884
21885 if (b->verbose > 1) {
21886 printf(" Get misfront (%d, %d, %d).\n", pointmark(org(misfront)),
21887 pointmark(dest(misfront)), pointmark(apex(misfront)));
21888 }
21889
21890 tspivot(misfront, checksh);
21891 if (checksh.sh != dummysh) {
21892
21893 sym(misfront, crosstet);
21894 if (!infected(crosstet)) {
21895
21896
21897 assert(checkpbcs);
21898
21899 continue;
21900 }
21901
21902 if (b->verbose > 1) {
21903 printf(" Queuing subface (%d, %d, %d).\n",
21904 pointmark(sorg(checksh)), pointmark(sdest(checksh)),
21905 pointmark(sapex(checksh)));
21906 }
21907
21908 tsdissolve(misfront);
21909 tsdissolve(crosstet);
21910
21911 stdissolve(checksh);
21912 sesymself(checksh);
21913 stdissolve(checksh);
21914
21915 sinfect(checksh);
21916 missingshqueue->push(&checksh);
21917 }
21918
21919 if (infected(misfront)) continue;
21920
21921 pd = oppo(misfront);
21922 #ifdef SELF_CHECK
21923
21924 assert(pd != (point) NULL);
21925 #endif
21926
21927
21928
21929 searchtet = recenttet;
21930
21931 if (isdead(&searchtet)) {
21932
21933 for (j = 0; j < newtetlist->len(); j++) {
21934 recenttet = * (triface *)(* newtetlist)[j];
21935 if (!isdead(&recenttet)) break;
21936 }
21937 assert(j < newtetlist->len());
21938 searchtet = recenttet;
21939 }
21940 success = insertsite(pd, &searchtet, false, flipque);
21941 if (success == OUTSIDEPOINT) {
21942
21943 inserthullsite(pd, &searchtet, flipque);
21944 }
21945 if (success != DUPLICATEPOINT) {
21946
21947 flip(flipque, NULL);
21948 }
21949
21950
21951
21952 adjustedgering(misfront, CCW);
21953 for (j = 0; j < 3; j++) {
21954
21955
21956
21957 fnext(misfront, newfront);
21958
21959 sym(newfront, casingtet);
21960
21961 if (!infected(casingtet)) {
21962
21963
21964 if (casingtet.tet == dummytet) {
21965
21966 maketetrahedron(&faketet);
21967
21968 adjustedgering(newfront, CW);
21969 setorg(faketet, org(newfront));
21970 setdest(faketet, dest(newfront));
21971 setapex(faketet, apex(newfront));
21972 setoppo(faketet, (point) NULL);
21973
21974 tspivot(newfront, checksh);
21975 if (checksh.sh != dummysh) {
21976 sesymself(checksh);
21977 tsbond(faketet, checksh);
21978 }
21979
21980 bond(faketet, newfront);
21981 frontlist->append(&faketet);
21982 } else {
21983
21984 frontlist->append(&casingtet);
21985 }
21986 } else {
21987
21988
21989
21990 for (k = frontlist->len() - 1; k >= 0; k--) {
21991 searchtet = * (triface *)(* frontlist)[k];
21992 if ((newfront.tet == searchtet.tet) &&
21993 (newfront.loc == searchtet.loc)) {
21994 frontlist->del(k, 0);
21995 break;
21996 }
21997 }
21998
21999 tspivot(newfront, checksh);
22000 if (checksh.sh != dummysh) {
22001
22002 if (b->verbose > 2) {
22003 printf(" Queuing subface (%d, %d, %d).\n",
22004 pointmark(sorg(checksh)), pointmark(sdest(checksh)),
22005 pointmark(sapex(checksh)));
22006 }
22007 tsdissolve(newfront);
22008 tsdissolve(casingtet);
22009
22010 stdissolve(checksh);
22011 sesymself(checksh);
22012 stdissolve(checksh);
22013 sinfect(checksh);
22014 missingshqueue->push(&checksh);
22015 }
22016 }
22017 enextself(misfront);
22018 }
22019
22020 if (!infected(misfront)) {
22021
22022 infect(misfront);
22023 crosstetlist->append(&misfront);
22024 }
22025 }
22026
22027
22028 for (i = 0; i < misfrontlist->len(); i++) {
22029 misfront = * (triface *)(* misfrontlist)[i];
22030 if (infected(misfront)) {
22031
22032 misfrontlist->del(i, 1);
22033 i--;
22034 }
22035 }
22036
22037
22038 if (misfrontlist->len() > 0) {
22039
22040
22041 assert(0);
22042 }
22043
22044
22045 retrievenewtets(newtetlist);
22046
22047
22048 dummytet[0] = encode(bakhulltet);
22049 hullsize = bakhullsize;
22050 checksubfaces = bakchksub;
22051 b->verbose++;
22052 }
22053
22055
22056
22057
22058
22059
22060
22061
22062
22063
22064
22065
22066
22067
22068
22069
22070
22072
22073 void tetgenmesh::carvecavity(list* newtetlist, list* outtetlist,
22074 queue* flipque)
22075 {
22076 triface newtet, neightet, front, outtet;
22077 face auxsh, consh;
22078 point pointptr;
22079 REAL ori;
22080 int i;
22081
22082
22083 outtetlist->clear();
22084
22085
22086 for (i = 0; i < newtetlist->len(); i++) {
22087
22088 newtet = * (triface *)(* newtetlist)[i];
22089 assert(!isdead(&newtet));
22090
22091 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22092 tspivot(newtet, auxsh);
22093 if (auxsh.sh != dummysh) {
22094
22095 sym(newtet, neightet);
22096 if (neightet.tet != dummytet) {
22097
22098
22099 decode((tetrahedron) auxsh.sh[0], front);
22100
22101 adjustedgering(front, CW);
22102 ori = orient3d(org(front), dest(front), apex(front), oppo(newtet));
22103 assert(ori != 0.0);
22104 if (ori < 0.0) {
22105
22106 outtet = neightet;
22107 } else {
22108
22109 outtet = newtet;
22110 }
22111
22112 if (!infected(outtet)) {
22113 infect(outtet);
22114 outtetlist->append(&outtet);
22115 }
22116 }
22117 }
22118 }
22119 }
22120
22121
22122 for (i = 0; i < outtetlist->len(); i++) {
22123 outtet = * (triface *)(* outtetlist)[i];
22124 for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22125 sym(outtet, neightet);
22126
22127 if ((neightet.tet != dummytet) && !infected(neightet)) {
22128
22129 tspivot(outtet, auxsh);
22130 if (auxsh.sh == dummysh) {
22131
22132 infect(neightet);
22133 outtetlist->append(&neightet);
22134 }
22135 }
22136 }
22137 }
22138
22139
22140 for (i = 0; i < outtetlist->len(); i++) {
22141
22142 outtet = * (triface *)(* outtetlist)[i];
22143
22144 for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22145
22146 tspivot(outtet, auxsh);
22147 if (auxsh.sh != dummysh) {
22148
22149 sym(outtet, neightet);
22150 assert(!infected(neightet));
22151
22152 dissolve(neightet);
22153 }
22154 }
22155
22156 tetrahedrondealloc(outtet.tet);
22157 }
22158
22159
22160 for (i = 0; i < newtetlist->len(); i++) {
22161
22162 newtet = * (triface *)(* newtetlist)[i];
22163
22164 if (isdead(&newtet)) continue;
22165
22166 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22167
22168 tspivot(newtet, auxsh);
22169 if (auxsh.sh != dummysh) {
22170
22171 decode((tetrahedron) auxsh.sh[0], front);
22172 assert((front.tet != dummytet) && !infected(front));
22173
22174 tsdissolve(newtet);
22175
22176 shellfacedealloc(subfaces, auxsh.sh);
22177
22178
22179 tspivot(front, consh);
22180 if (consh.sh != dummysh) {
22181 sesymself(consh);
22182
22183 tsbond(newtet, consh);
22184 }
22185
22186 if (oppo(front) == (point) NULL) {
22187
22188 if (consh.sh != dummysh) {
22189 sesymself(consh);
22190
22191 stdissolve(consh);
22192 }
22193
22194 tetrahedrondealloc(front.tet);
22195
22196 dummytet[0] = encode(newtet);
22197 } else {
22198
22199 bond(newtet, front);
22200 }
22201
22202 if (flipque != (queue *) NULL) {
22203 enqueueflipface(newtet, flipque);
22204 }
22205 }
22206 }
22207
22208 pointptr = org(newtet);
22209 setpoint2tet(pointptr, encode(newtet));
22210 pointptr = dest(newtet);
22211 setpoint2tet(pointptr, encode(newtet));
22212 pointptr = apex(newtet);
22213 setpoint2tet(pointptr, encode(newtet));
22214 pointptr = oppo(newtet);
22215 setpoint2tet(pointptr, encode(newtet));
22216 }
22217
22218 }
22219
22221
22222
22223
22224
22225
22226
22227
22229
22230 void tetgenmesh::delaunizecavity(list* floorlist, list* ceillist,
22231 list* ceilptlist, list* floorptlist, list* frontlist, list* misfrontlist,
22232 list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
22233 {
22234 int vertnum;
22235
22236 vertnum = floorptlist->len();
22237 vertnum += (ceilptlist != (list *) NULL ? ceilptlist->len() : 0);
22238 if (b->verbose > 1) {
22239 printf(" Delaunizing cavity (%d floors, %d ceilings, %d vertices).\n",
22240 floorlist->len(), ceillist->len(), vertnum);
22241 }
22242
22243 if ((floorlist->len() + ceillist->len()) > maxcavfaces) {
22244 maxcavfaces = floorlist->len() + ceillist->len();
22245 }
22246 if (vertnum > maxcavverts) {
22247 maxcavverts = vertnum;
22248 }
22249
22250
22251 frontlist->clear();
22252 misfrontlist->clear();
22253 newtetlist->clear();
22254
22255
22256 initializecavity(floorlist, ceillist, frontlist);
22257
22258 delaunizecavvertices(NULL, floorptlist, ceilptlist, newtetlist, flipque);
22259
22260 while (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
22261
22262 detachauxsubfaces(newtetlist);
22263
22264 expandcavity(frontlist, misfrontlist, newtetlist, crosstetlist,
22265 missingshqueue, flipque);
22266 }
22267
22268
22269 carvecavity(newtetlist, misfrontlist, NULL);
22270 }
22271
22273
22274
22275
22276
22277
22278
22279
22280
22281
22282
22283
22284
22285
22287
22288 void tetgenmesh::formmissingregion(face* missingsh, list* missingshlist,
22289 list* equatptlist, int* worklist)
22290 {
22291 face neighsh, worksh, workseg;
22292 point workpt[3];
22293 int idx, i, j;
22294
22295
22296 missingshlist->append(missingsh);
22297
22298 workpt[0] = sorg(*missingsh);
22299 workpt[1] = sdest(*missingsh);
22300 workpt[2] = sapex(*missingsh);
22301 for (i = 0; i < 3; i++) {
22302 idx = pointmark(workpt[i]) - in->firstnumber;
22303 worklist[idx] = 1;
22304 equatptlist->append(&workpt[i]);
22305 }
22306
22307 suninfect(*missingsh);
22308
22309
22310 for (i = 0; i < missingshlist->len(); i++) {
22311
22312 worksh = * (face *)(* missingshlist)[i];
22313
22314 for (j = 0; j < 3; j++) {
22315 sspivot(worksh, workseg);
22316 if (workseg.sh == dummysh) {
22317 spivot(worksh, neighsh);
22318 if (sinfected(neighsh)) {
22319
22320 if (sorg(neighsh) != sdest(worksh)) {
22321 sesymself(neighsh);
22322 }
22323 if (b->verbose > 2) {
22324 printf(" Add missing subface (%d, %d, %d).\n",
22325 pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
22326 pointmark(sapex(neighsh)));
22327 }
22328 missingshlist->append(&neighsh);
22329
22330 workpt[0] = sapex(neighsh);
22331 idx = pointmark(workpt[0]) - in->firstnumber;
22332
22333 if (worklist[idx] == 0) {
22334 worklist[idx] = 1;
22335 equatptlist->append(&workpt[0]);
22336 }
22337
22338 suninfect(neighsh);
22339 }
22340 }
22341 senextself(worksh);
22342 }
22343 }
22344
22345
22346 for (i = 0; i < missingshlist->len(); i++) {
22347 worksh = * (face *)(* missingshlist)[i];
22348 sinfect(worksh);
22349 }
22350 }
22351
22353
22354
22355
22356
22357
22358
22359
22360
22361
22362
22363
22364
22365
22366
22367
22369
22370 void tetgenmesh::rearrangesubfaces(list* missingshlist, list* boundedgelist,
22371 list* equatptlist, int* worklist)
22372 {
22373 link *boundedgelink;
22374 link *newshlink;
22375 triface starttet, spintet, neightet, worktet;
22376 face shloop, newsh, neighsh, spinsh, worksh;
22377 face workseg, casingin, casingout;
22378 point torg, tdest, workpt;
22379 point spt1, spt2, spt3;
22380 enum finddirectionresult collinear;
22381 enum shestype shtype;
22382 REAL area;
22383 bool matchflag, finishflag;
22384 int shmark, pbcgp, idx, hitbdry;
22385 int i, j;
22386
22387
22388 boundedgelink = new link(sizeof(face), NULL, 256);
22389
22390 newshlink = new link(sizeof(face), NULL, 256);
22391
22392
22393 worksh = * (face *)(* missingshlist)[0];
22394 shtype = shelltype(worksh);
22395
22396 for (i = 1; i < missingshlist->len(); i++) {
22397 worksh = * (face *)(* missingshlist)[i];
22398 assert(shelltype(worksh) == shtype);
22399 }
22400
22401 shmark = pbcgp = 0;
22402 area = 0.0;
22403
22404
22405 for (i = 0; i < boundedgelist->len(); i++) {
22406 shloop = * (face *)(* boundedgelist)[i];
22407 if (i == 0) {
22408
22409 shmark = shellmark(shloop);
22410 if (b->quality && varconstraint) {
22411
22412 area = areabound(shloop);
22413 }
22414 if (checkpbcs) {
22415
22416 pbcgp = shellpbcgroup(shloop);
22417 }
22418
22419 abovepoint = facetabovepointarray[shellmark(shloop)];
22420 if (abovepoint == (point) NULL) {
22421 getfacetabovepoint(&shloop);
22422 }
22423 }
22424 sspivot(shloop, workseg);
22425 if (workseg.sh == dummysh) {
22426
22427 spivot(shloop, neighsh);
22428 boundedgelink->add(&neighsh);
22429 } else {
22430
22431 boundedgelink->add(&shloop);
22432 }
22433 }
22434
22435
22436
22437
22438
22439
22440
22441
22442
22443
22444
22445 while (boundedgelink->len() > 0) {
22446
22447 shloop = * (face *) boundedgelink->del(1);
22448
22449 sspivot(shloop, workseg);
22450 torg = sorg(shloop);
22451 tdest = sdest(shloop);
22452
22453 getsearchtet(torg, tdest, &starttet, &workpt);
22454 collinear = finddirection(&starttet, workpt, tetrahedrons->items);
22455 if (collinear == LEFTCOLLINEAR) {
22456 enext2self(starttet);
22457 esymself(starttet);
22458 } else if (collinear == TOPCOLLINEAR) {
22459 fnextself(starttet);
22460 enext2self(starttet);
22461 esymself(starttet);
22462 }
22463 assert(dest(starttet) == workpt);
22464
22465 matchflag = false;
22466 spintet = starttet;
22467 hitbdry = 0;
22468 do {
22469 workpt = apex(spintet);
22470 idx = pointmark(workpt) - in->firstnumber;
22471 if (worklist[idx] == 1) {
22472
22473 finishflag = false;
22474 for (i = 0; i < missingshlist->len(); i++) {
22475 worksh = * (face *)(* missingshlist)[i];
22476 spt1 = sorg(worksh);
22477 spt2 = sdest(worksh);
22478 spt3 = sapex(worksh);
22479
22480 if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22481 == INTERSECT) {
22482 finishflag = true; break;
22483 }
22484
22485 if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22486 == INTERSECT) {
22487 finishflag = true; break;
22488 }
22489
22490 if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22491 == INTERSECT) {
22492 finishflag = true; break;
22493 }
22494 }
22495 if (finishflag) {
22496
22497 matchflag = true;
22498 for (i = 0; i < newshlink->len() && matchflag; i++) {
22499 worksh = * (face *) newshlink->getnitem(i + 1);
22500 spt1 = sorg(worksh);
22501 spt2 = sdest(worksh);
22502 spt3 = sapex(worksh);
22503
22504 if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22505 == INTERSECT) {
22506 matchflag = false; break;
22507 }
22508
22509 if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22510 == INTERSECT) {
22511 matchflag = false; break;
22512 }
22513
22514 if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22515 == INTERSECT) {
22516 matchflag = false; break;
22517 }
22518 }
22519 }
22520 if (matchflag == true) {
22521
22522 break;
22523 }
22524 }
22525 if (!fnextself(spintet)) {
22526 hitbdry ++;
22527 if (hitbdry < 2) {
22528 esym(starttet, spintet);
22529 if (!fnextself(spintet)) {
22530 hitbdry ++;
22531 }
22532 }
22533 }
22534 } while (hitbdry < 2 && apex(spintet) != apex(starttet));
22535 assert(matchflag == true);
22536 tspivot(spintet, neighsh);
22537 if (neighsh.sh != dummysh) {
22538 printf("Error: Invalid PLC.\n");
22539 printf(" Facet #%d and facet #%d overlap each other.\n",
22540 shellmark(neighsh), shellmark(shloop));
22541 printf(" It might be caused by a facet is defined more than once.\n");
22542 printf(" Hint: Use -d switch to find all overlapping facets.\n");
22543 exit(1);
22544 }
22545
22546 adjustedgering(spintet, CCW);
22547
22548 makeshellface(subfaces, &newsh);
22549 setsorg(newsh, org(spintet));
22550 setsdest(newsh, dest(spintet));
22551 setsapex(newsh, apex(spintet));
22552 if (b->quality && varconstraint) {
22553 setareabound(newsh, area);
22554 }
22555 if (checkpbcs) {
22556 setshellpbcgroup(newsh, pbcgp);
22557 }
22558 setshellmark(newsh, shmark);
22559 setshelltype(newsh, shtype);
22560
22561 newshlink->add(&newsh);
22562
22563 tsbond(spintet, newsh);
22564 sym(spintet, neightet);
22565 if (neightet.tet != dummytet) {
22566 sesym(newsh, neighsh);
22567 tsbond(neightet, neighsh);
22568 }
22569
22570 sspivot(shloop, workseg);
22571 if (workseg.sh == dummysh) {
22572 sbond(shloop, newsh);
22573 } else {
22574
22575
22576
22577
22578
22579
22580
22581 spivot(shloop, casingout);
22582 if (shloop.sh != casingout.sh) {
22583
22584 spinsh = casingout;
22585 do {
22586 casingin = spinsh;
22587 spivotself(spinsh);
22588 } while (sapex(spinsh) != sapex(shloop));
22589 assert(casingin.sh != shloop.sh);
22590
22591 sbond1(casingin, newsh);
22592 sbond1(newsh, casingout);
22593 } else {
22594
22595 sbond(newsh, newsh);
22596 }
22597
22598 ssbond(newsh, workseg);
22599 }
22600
22601
22602 for (i = 0; i < 2; i++) {
22603 if (i == 0) {
22604 senext(newsh, worksh);
22605 } else {
22606 senext2(newsh, worksh);
22607 }
22608 torg = sorg(worksh);
22609 tdest = sdest(worksh);
22610 finishflag = false;
22611 for (j = 0; j < boundedgelink->len() && !finishflag; j++) {
22612 neighsh = * (face *) boundedgelink->getnitem(j + 1);
22613 if ((sorg(neighsh) == torg && sdest(neighsh) == tdest) ||
22614 (sorg(neighsh) == tdest && sdest(neighsh) == torg)) {
22615
22616 sspivot(neighsh, workseg);
22617 if (workseg.sh == dummysh) {
22618 sbond(neighsh, worksh);
22619 } else {
22620
22621
22622 spivot(neighsh, casingout);
22623 if (neighsh.sh != casingout.sh) {
22624
22625 spinsh = casingout;
22626 do {
22627 casingin = spinsh;
22628 spivotself(spinsh);
22629 } while (sapex(spinsh) != sapex(neighsh));
22630 assert(casingin.sh != neighsh.sh);
22631
22632 sbond1(casingin, worksh);
22633 sbond1(worksh, casingout);
22634 } else {
22635
22636 sbond(worksh, worksh);
22637 }
22638
22639 ssbond(worksh, workseg);
22640 }
22641
22642 boundedgelink->del(j + 1);
22643 finishflag = true;
22644 }
22645 }
22646 if (!finishflag) {
22647
22648 boundedgelink->add(&worksh);
22649 }
22650 }
22651 }
22652
22653
22654 for (i = 0; i < missingshlist->len(); i++) {
22655 worksh = * (face *)(* missingshlist)[i];
22656 shellfacedealloc(subfaces, worksh.sh);
22657 }
22658
22659 for (i = 0; i < equatptlist->len(); i++) {
22660 workpt = * (point *)(* equatptlist)[i];
22661 idx = pointmark(workpt) - in->firstnumber;
22662 worklist[idx] = 0;
22663 }
22664
22665 delete boundedgelink;
22666 delete newshlink;
22667 }
22668
22670
22671
22672
22673
22674
22675
22676
22677
22678
22679
22680
22681
22683
22684 bool tetgenmesh::scoutcrossingedge(list* missingshlist, list* boundedgelist,
22685 list* crossedgelist, int* worklist)
22686 {
22687 triface starttet, spintet, worktet;
22688 face startsh, neighsh, worksh, workseg;
22689 point torg, tdest, tapex;
22690 point workpt[3], pa, pb, pc;
22691 enum finddirectionresult collinear;
22692 REAL ori1, ori2;
22693 bool crossflag;
22694 int hitbdry;
22695 int i, j, k;
22696
22697
22698
22699
22700 for (i = 0; i < missingshlist->len(); i++) {
22701 worksh = * (face *)(* missingshlist)[i];
22702 for (j = 0; j < 3; j++) {
22703 sspivot(worksh, workseg);
22704 if (workseg.sh == dummysh) {
22705 spivot(worksh, neighsh);
22706 if (!sinfected(neighsh)) {
22707 boundedgelist->append(&worksh);
22708 }
22709 } else {
22710 boundedgelist->append(&worksh);
22711 }
22712 senextself(worksh);
22713 }
22714 }
22715
22716 crossflag = false;
22717
22718
22719 for (i = 0; i < boundedgelist->len() && !crossflag; i++) {
22720 startsh = * (face *)(* boundedgelist)[i];
22721
22722 torg = sorg(startsh);
22723 tdest = sdest(startsh);
22724 tapex = sapex(startsh);
22725 getsearchtet(torg, tdest, &starttet, &workpt[0]);
22726 collinear = finddirection(&starttet, workpt[0], tetrahedrons->items);
22727 if (collinear == LEFTCOLLINEAR) {
22728 enext2self(starttet);
22729 esymself(starttet);
22730 } else if (collinear == TOPCOLLINEAR) {
22731 fnextself(starttet);
22732 enext2self(starttet);
22733 esymself(starttet);
22734 }
22735 #ifdef SELF_CHECK
22736 assert(dest(starttet) == workpt[0]);
22737 #endif
22738
22739 spintet = starttet;
22740 hitbdry = 0;
22741 do {
22742 if (fnextself(spintet)) {
22743
22744 workpt[1] = apex(spintet);
22745 workpt[2] = oppo(spintet);
22746 j = pointmark(workpt[1]) - in->firstnumber;
22747 k = pointmark(workpt[2]) - in->firstnumber;
22748 if (worklist[j] == 1) {
22749 ori1 = 0.0;
22750 } else {
22751
22752 ori1 = orient3d(torg, tdest, tapex, workpt[1]);
22753 }
22754 if (worklist[k] == 1) {
22755 ori2 = 0.0;
22756 } else {
22757
22758 ori2 = orient3d(torg, tdest, tapex, workpt[2]);
22759 }
22760
22761 if (ori1 * ori2 < 0.0) {
22762
22763 for (j = 0; j < missingshlist->len(); j++) {
22764 worksh = * (face *)(* missingshlist)[j];
22765 pa = sorg(worksh);
22766 pb = sdest(worksh);
22767 pc = sapex(worksh);
22768 crossflag = (tri_tri_inter(pa, pb, pc, workpt[0], workpt[1],
22769 workpt[2]) == INTERSECT);
22770 if (crossflag) {
22771
22772 worktet = spintet;
22773 adjustedgering(worktet, CCW);
22774 enextfnextself(worktet);
22775 enextself(worktet);
22776
22777 crossedgelist->append(&worktet);
22778 break;
22779 }
22780 }
22781 if (crossflag) break;
22782 }
22783 if (apex(spintet) == apex(starttet)) break;
22784 } else {
22785 hitbdry++;
22786
22787 if (hitbdry < 2) {
22788 esym(starttet, spintet);
22789 }
22790 }
22791 } while (hitbdry < 2);
22792 }
22793
22794 return crossflag;
22795 }
22796
22798
22799
22800
22801
22802
22803
22804
22805
22806
22807
22808
22809
22810
22811
22812
22813
22814
22815
22816
22817
22818
22819
22820
22821
22822
22823
22824
22826
22827 void tetgenmesh::formcavity(list* missingshlist, list* crossedgelist,
22828 list* equatptlist, list* crossshlist, list* crosstetlist,
22829 list* belowfacelist, list* abovefacelist, list* horizptlist,
22830 list* belowptlist, list* aboveptlist, queue* missingshqueue, int* worklist)
22831 {
22832 triface starttet, spintet, neightet, worktet;
22833 face startsh, neighsh, worksh, workseg;
22834 point torg, tdest, tapex, workpt[3];
22835 REAL checksign, orgori, destori;
22836 bool crossflag, inlistflag;
22837 bool belowflag, aboveflag;
22838 int idx, share;
22839 int i, j, k;
22840
22841
22842 startsh = * (face *)(* missingshlist)[0];
22843 torg = sorg(startsh);
22844 tdest = sdest(startsh);
22845 tapex = sapex(startsh);
22846
22847
22848 for (i = 0; i < crossedgelist->len(); i++) {
22849
22850 starttet = * (triface *)(* crossedgelist)[i];
22851 adjustedgering(starttet, CCW);
22852 if (b->verbose > 2) {
22853 printf(" Collect tets containing edge (%d, %d).\n",
22854 pointmark(org(starttet)), pointmark(dest(starttet)));
22855 }
22856 orgori = orient3d(torg, tdest, tapex, org(starttet));
22857 destori = orient3d(torg, tdest, tapex, dest(starttet));
22858 #ifdef SELF_CHECK
22859 assert(orgori * destori < 0.0);
22860 #endif
22861 spintet = starttet;
22862 do {
22863
22864 fnextself(spintet);
22865
22866 tspivot(spintet, worksh);
22867 if (worksh.sh != dummysh) {
22868 printf("Error: Invalid PLC.\n");
22869 printf(" Two subfaces (%d, %d, %d) and (%d, %d, %d)\n",
22870 pointmark(torg), pointmark(tdest), pointmark(tapex),
22871 pointmark(sorg(worksh)), pointmark(sdest(worksh)),
22872 pointmark(sapex(worksh)));
22873 printf(" are found intersecting each other.\n");
22874 printf(" Hint: Use -d switch to find all intersecting facets.\n");
22875 terminatetetgen(1);
22876 }
22877 if (!infected(spintet)) {
22878 if (b->verbose > 2) {
22879 printf(" Add crossing tet (%d, %d, %d, %d).\n",
22880 pointmark(org(spintet)), pointmark(dest(spintet)),
22881 pointmark(apex(spintet)), pointmark(oppo(spintet)));
22882 }
22883 infect(spintet);
22884 crosstetlist->append(&spintet);
22885 }
22886
22887
22888
22889 workpt[0] = apex(spintet);
22890 idx = pointmark(workpt[0]) - in->firstnumber;
22891 if (worklist[idx] != 1) {
22892
22893 checksign = orient3d(torg, tdest, tapex, workpt[0]);
22894 #ifdef SELF_CHECK
22895 assert(checksign != 0.0);
22896 #endif
22897 if (checksign * orgori < 0.0) {
22898 enext2(spintet, worktet);
22899 workpt[1] = org(spintet);
22900 } else {
22901 #ifdef SELF_CHECK
22902 assert(checksign * destori < 0.0);
22903 #endif
22904 enext(spintet, worktet);
22905 workpt[1] = dest(spintet);
22906 }
22907
22908
22909 inlistflag = false;
22910 for (j = 0; j < crossedgelist->len() && !inlistflag; j++) {
22911 neightet = * (triface *)(* crossedgelist)[j];
22912 if (org(neightet) == workpt[0]) {
22913 if (dest(neightet) == workpt[1]) inlistflag = true;
22914 } else if (org(neightet) == workpt[1]) {
22915 if (dest(neightet) == workpt[0]) inlistflag = true;
22916 }
22917 }
22918 if (!inlistflag) {
22919 crossedgelist->append(&worktet);
22920 }
22921 }
22922 } while (apex(spintet) != apex(starttet));
22923 }
22924
22925
22926
22927
22928 for (i = 0; i < crosstetlist->len(); i++) {
22929
22930 starttet = * (triface *)(* crosstetlist)[i];
22931 #ifdef SELF_CHECK
22932 assert(infected(starttet));
22933 #endif
22934 adjustedgering(starttet, CCW);
22935
22936
22937 for (j = 0; j < 2; j++) {
22938 if (j == 0) {
22939 enextfnext(starttet, worktet);
22940 } else {
22941 enext2fnext(starttet, worktet);
22942 }
22943 sym(worktet, neightet);
22944
22945
22946 if ((neightet.tet == dummytet) || !infected(neightet)) {
22947 workpt[0] = org(worktet);
22948 workpt[1] = dest(worktet);
22949 workpt[2] = apex(worktet);
22950 belowflag = aboveflag = false;
22951 share = 0;
22952 for (k = 0; k < 3; k++) {
22953 idx = pointmark(workpt[k]) - in->firstnumber;
22954 if (worklist[idx] == 0) {
22955
22956 checksign = orient3d(torg, tdest, tapex, workpt[k]);
22957 #ifdef SELF_CHECK
22958 assert(checksign != 0.0);
22959 #endif
22960 if (checksign > 0.0) {
22961
22962 worklist[idx] = 2;
22963 belowptlist->append(&workpt[k]);
22964 } else if (checksign < 0.0) {
22965
22966 worklist[idx] = 3;
22967 aboveptlist->append(&workpt[k]);
22968 }
22969 }
22970 if (worklist[idx] == 2) {
22971
22972 belowflag = true;
22973 } else if (worklist[idx] == 3) {
22974
22975 aboveflag = true;
22976 } else {
22977 #ifdef SELF_CHECK
22978
22979 assert(worklist[idx] == 1);
22980 #endif
22981 share++;
22982 }
22983 }
22984 #ifdef SELF_CHECK
22985
22986 assert(share < 3);
22987
22988 assert(belowflag ^ aboveflag);
22989 #endif
22990 if (belowflag) {
22991 belowfacelist->append(&worktet);
22992 } else if (aboveflag) {
22993 abovefacelist->append(&worktet);
22994 }
22995 }
22996 }
22997 }
22998
22999
23000
23001
23002 for (i = 0; i < missingshlist->len(); i++) {
23003 worksh = * (face *)(* missingshlist)[i];
23004 #ifdef SELF_CHECK
23005 assert(sinfected(worksh));
23006 #endif
23007 workpt[0] = sorg(worksh);
23008 workpt[1] = sdest(worksh);
23009 workpt[2] = sapex(worksh);
23010 crossflag = false;
23011 for (j = 0; j < crosstetlist->len() && !crossflag; j++) {
23012
23013 starttet = * (triface *)(* crosstetlist)[j];
23014 adjustedgering(starttet, CCW);
23015
23016 for (k = 0; k < 2 && !crossflag; k++) {
23017 if (k == 0) {
23018 worktet = starttet;
23019 } else {
23020 fnext(starttet, worktet);
23021 }
23022 crossflag = tritritest(&worktet, workpt[0], workpt[1], workpt[2]);
23023 }
23024 }
23025 if (crossflag) {
23026
23027 suninfect(worksh);
23028 crossshlist->append(&worksh);
23029
23030 for (k = 0; k < 3; k++) {
23031 idx = pointmark(workpt[k]) - in->firstnumber;
23032 if (worklist[idx] != 4) {
23033 worklist[idx] = 4;
23034 horizptlist->append(&workpt[k]);
23035 }
23036 }
23037 }
23038 }
23039
23040
23041 for (i = 0; i < crosstetlist->len(); i++) {
23042 starttet = * (triface *)(* crosstetlist)[i];
23043 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
23044 sym(starttet, neightet);
23045
23046 if ((neightet.tet != dummytet) && infected(neightet)) {
23047 tspivot(starttet, worksh);
23048 if (worksh.sh != dummysh) {
23049
23050 if (b->verbose > 2) {
23051 printf(" Queuing subface (%d, %d, %d).\n",
23052 pointmark(sorg(worksh)), pointmark(sdest(worksh)),
23053 pointmark(sapex(worksh)));
23054 }
23055 tsdissolve(neightet);
23056 tsdissolve(starttet);
23057
23058 stdissolve(worksh);
23059 sesymself(worksh);
23060 stdissolve(worksh);
23061 sinfect(worksh);
23062 missingshqueue->push(&worksh);
23063 }
23064 }
23065 }
23066 }
23067
23068
23069 for (i = 0; i < equatptlist->len(); i++) {
23070 workpt[0] = * (point *)(* equatptlist)[i];
23071 idx = pointmark(workpt[0]) - in->firstnumber;
23072 #ifdef SELF_CHECK
23073 assert((worklist[idx] == 1) || (worklist[idx] == 4));
23074 #endif
23075 worklist[idx] = 0;
23076 }
23077 for (i = 0; i < belowptlist->len(); i++) {
23078 workpt[0] = * (point *)(* belowptlist)[i];
23079 idx = pointmark(workpt[0]) - in->firstnumber;
23080 #ifdef SELF_CHECK
23081 assert(worklist[idx] == 2);
23082 #endif
23083 worklist[idx] = 0;
23084 }
23085 for (i = 0; i < aboveptlist->len(); i++) {
23086 workpt[0] = * (point *)(* aboveptlist)[i];
23087 idx = pointmark(workpt[0]) - in->firstnumber;
23088 #ifdef SELF_CHECK
23089 assert(worklist[idx] == 3);
23090 #endif
23091 worklist[idx] = 0;
23092 }
23093 }
23094
23096
23097
23098
23099
23100
23101
23102
23104
23105 void tetgenmesh::insertallsubfaces(queue* missingshqueue)
23106 {
23107 triface searchtet;
23108 face subloop;
23109
23110 searchtet.tet = (tetrahedron *) NULL;
23111 subfaces->traversalinit();
23112 subloop.sh = shellfacetraverse(subfaces);
23113 while (subloop.sh != (shellface *) NULL) {
23114 if (!insertsubface(&subloop, &searchtet)) {
23115 if (b->verbose > 1) {
23116 printf(" Queuing subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23117 pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23118 }
23119 sinfect(subloop);
23120 missingshqueue->push(&subloop);
23121 }
23122 subloop.sh = shellfacetraverse(subfaces);
23123 }
23124 }
23125
23127
23128
23129
23130
23131
23132
23133
23134
23135
23136
23137
23138
23139
23140
23141
23142
23143
23144
23145
23146
23147
23149
23150 void tetgenmesh::constrainedfacets()
23151 {
23152 queue *missingshqueue, *flipque;
23153 list *missingshlist, *equatptlist;
23154 list *boundedgelist, *crossedgelist, *crosstetlist;
23155 list *crossshlist, *belowfacelist, *abovefacelist;
23156 list *horizptlist, *belowptlist, *aboveptlist;
23157 list *frontlist, *misfrontlist, *newtetlist;
23158 triface searchtet, worktet;
23159 face subloop, worksh;
23160 int *worklist;
23161 int i;
23162
23163 if (!b->quiet) {
23164 printf("Constraining facets.\n");
23165 }
23166
23167
23168 missingshqueue = new queue(sizeof(face));
23169 flipque = new queue(sizeof(badface));
23170
23171 missingshlist = new list(sizeof(face), NULL);
23172 boundedgelist = new list(sizeof(face), NULL);
23173 crossedgelist = new list(sizeof(triface), NULL);
23174 equatptlist = new list((char*) "point *");
23175 crossshlist = new list(sizeof(face), NULL);
23176 crosstetlist = new list(sizeof(triface), NULL);
23177 belowfacelist = new list(sizeof(triface), NULL);
23178 abovefacelist = new list(sizeof(triface), NULL);
23179 horizptlist = new list((char*)"point *");
23180 belowptlist = new list((char*)"point *");
23181 aboveptlist = new list((char*)"point *");
23182 frontlist = new list(sizeof(triface), NULL);
23183 misfrontlist = new list(sizeof(triface), NULL);
23184 newtetlist = new list(sizeof(triface), NULL);
23185
23186 worklist = new int[points->items + 1];
23187 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
23188
23189
23190 makepoint2tetmap();
23191
23192
23193 insertallsubfaces(missingshqueue);
23194
23195
23196 while (!missingshqueue->empty()) {
23197
23198 subloop = * (face *) missingshqueue->pop();
23199
23200 if (isdead(&subloop)) continue;
23201
23202 if (!sinfected(subloop)) continue;
23203
23204 if (insertsubface(&subloop, &searchtet)) {
23205 suninfect(subloop);
23206 continue;
23207 }
23208 if (b->verbose > 1) {
23209 printf(" Recover subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23210 pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23211 }
23212
23213 formmissingregion(&subloop, missingshlist, equatptlist, worklist);
23214
23215 if (scoutcrossingedge(missingshlist, boundedgelist, crossedgelist,
23216 worklist)) {
23217
23218 formcavity(missingshlist, crossedgelist, equatptlist, crossshlist,
23219 crosstetlist, belowfacelist, abovefacelist, horizptlist,
23220 belowptlist, aboveptlist, missingshqueue, worklist);
23221
23222 delaunizecavity(crossshlist, abovefacelist, aboveptlist, horizptlist,
23223 frontlist, misfrontlist, newtetlist, crosstetlist,
23224 missingshqueue, flipque);
23225
23226 for (i = 0; i < crossshlist->len(); i++) {
23227 worksh = * (face *)(* crossshlist)[i];
23228 sesymself(worksh);
23229 * (face *)(* crossshlist)[i] = worksh;
23230 }
23231
23232 delaunizecavity(crossshlist, belowfacelist, belowptlist, horizptlist,
23233 frontlist, misfrontlist, newtetlist, crosstetlist,
23234 missingshqueue, flipque);
23235
23236 for (i = 0; i < crosstetlist->len(); i++) {
23237 worktet = * (triface *)(* crosstetlist)[i];
23238 tetrahedrondealloc(worktet.tet);
23239 }
23240
23241
23242 for (i = 0; i < missingshlist->len(); i++) {
23243 worksh = * (face *)(* missingshlist)[i];
23244 if (sinfected(worksh)) {
23245
23246 missingshqueue->push(&worksh);
23247 }
23248 }
23249 crossshlist->clear();
23250 belowfacelist->clear();
23251 abovefacelist->clear();
23252 horizptlist->clear();
23253 belowptlist->clear();
23254 aboveptlist->clear();
23255 crosstetlist->clear();
23256 } else {
23257
23258
23259 rearrangesubfaces(missingshlist, boundedgelist, equatptlist, worklist);
23260 }
23261
23262 missingshlist->clear();
23263 boundedgelist->clear();
23264 crossedgelist->clear();
23265 equatptlist->clear();
23266 }
23267
23268
23269 checksubfaces = 1;
23270
23271 if (b->verbose > 0) {
23272 printf(" The biggest cavity: %d faces, %d vertices\n", maxcavfaces,
23273 maxcavverts);
23274 printf(" Enlarged %d times\n", expcavcount);
23275 }
23276
23277 delete missingshqueue;
23278 delete flipque;
23279 delete missingshlist;
23280 delete boundedgelist;
23281 delete crossedgelist;
23282 delete equatptlist;
23283 delete crossshlist;
23284 delete crosstetlist;
23285 delete belowfacelist;
23286 delete abovefacelist;
23287 delete horizptlist;
23288 delete belowptlist;
23289 delete aboveptlist;
23290 delete frontlist;
23291 delete misfrontlist;
23292 delete newtetlist;
23293 delete [] worklist;
23294 }
23295
23296
23297
23298
23299
23300
23301
23302
23303
23305
23306
23307
23308
23309
23310
23311
23313
23314 void tetgenmesh::infecthull(memorypool *viri)
23315 {
23316 triface tetloop, tsymtet;
23317 tetrahedron **deadtet;
23318 face hullface;
23319
23320
23321 if (b->verbose > 0) {
23322 printf(" Marking concavities for elimination.\n");
23323 }
23324 tetrahedrons->traversalinit();
23325 tetloop.tet = tetrahedrontraverse();
23326 while (tetloop.tet != (tetrahedron *) NULL) {
23327
23328 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
23329 sym(tetloop, tsymtet);
23330 if (tsymtet.tet == dummytet) {
23331
23332 tspivot(tetloop, hullface);
23333 if (hullface.sh == dummysh) {
23334
23335 if (!infected(tetloop)) {
23336 infect(tetloop);
23337 deadtet = (tetrahedron **) viri->alloc();
23338 *deadtet = tetloop.tet;
23339 break;
23340 }
23341 } else {
23342
23343 if (shellmark(hullface) == 0) {
23344 setshellmark(hullface, 1);
23345
23346
23347
23348
23349
23350
23351
23352
23353
23354
23355
23356
23357
23358
23359 }
23360 }
23361 }
23362 }
23363 tetloop.tet = tetrahedrontraverse();
23364 }
23365 }
23366
23368
23369
23370
23371
23372
23373
23374
23375
23376
23378
23379 void tetgenmesh::plague(memorypool *viri)
23380 {
23381 tetrahedron **virusloop;
23382 tetrahedron **deadtet;
23383 triface testtet, neighbor;
23384 face neighsh, testseg;
23385 face spinsh, casingin, casingout;
23386 int firstdadsub;
23387 int i;
23388
23389 if (b->verbose > 0) {
23390 printf(" Marking neighbors of marked tetrahedra.\n");
23391 }
23392 firstdadsub = 0;
23393
23394
23395 viri->traversalinit();
23396 virusloop = (tetrahedron **) viri->traverse();
23397 while (virusloop != (tetrahedron **) NULL) {
23398 testtet.tet = *virusloop;
23399
23400 uninfect(testtet);
23401
23402 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23403
23404 sym(testtet, neighbor);
23405
23406 tspivot(testtet, neighsh);
23407
23408 if ((neighbor.tet == dummytet) || infected(neighbor)) {
23409 if (neighsh.sh != dummysh) {
23410
23411
23412
23413
23414 neighsh.shver = 0;
23415 if (!firstdadsub) {
23416 firstdadsub = 1;
23417 if (!b->quiet) {
23418 printf("Warning: Detecting an open face (%d, %d, %d).\n",
23419 pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
23420 pointmark(sapex(neighsh)));
23421 }
23422 }
23423
23424 findedge(&testtet, sorg(neighsh), sdest(neighsh));
23425 for (i = 0; i < 3; i++) {
23426 sspivot(neighsh, testseg);
23427 if (testseg.sh != dummysh) {
23428
23429
23430 testseg.shver = 0;
23431 spinsh = neighsh;
23432 if (sorg(spinsh) != sorg(testseg)) {
23433 sesymself(spinsh);
23434 }
23435 spivot(spinsh, casingout);
23436 if (casingout.sh == spinsh.sh) {
23437
23438
23439 shellfacedealloc(subsegs, testseg.sh);
23440 } else {
23441 spinsh = casingout;
23442 do {
23443 casingin = spinsh;
23444 spivotself(spinsh);
23445 } while (spinsh.sh != neighsh.sh);
23446
23447 sbond1(casingin, casingout);
23448
23449 ssbond(casingin, testseg);
23450 }
23451 }
23452 senextself(neighsh);
23453 enextself(testtet);
23454 }
23455 if (neighbor.tet != dummytet) {
23456
23457
23458 tsdissolve(neighbor);
23459 }
23460
23461 if (in->mesh_dim > 2) {
23462 shellfacedealloc(subfaces, neighsh.sh);
23463 } else {
23464
23465
23466 stdissolve(neighsh);
23467 sesymself(neighsh);
23468 stdissolve(neighsh);
23469 }
23470 }
23471 } else {
23472 if (neighsh.sh == dummysh) {
23473
23474 infect(neighbor);
23475
23476 deadtet = (tetrahedron **) viri->alloc();
23477 *deadtet = neighbor.tet;
23478 } else {
23479
23480 stdissolve(neighsh);
23481
23482 if (shellmark(neighsh) == 0) {
23483 setshellmark(neighsh, 1);
23484 }
23485
23486 dummytet[0] = encode(neighbor);
23487 }
23488 }
23489 }
23490
23491
23492 infect(testtet);
23493 virusloop = (tetrahedron **) viri->traverse();
23494 }
23495 }
23496
23498
23499
23500
23501
23502
23503
23504
23505
23507
23508 void tetgenmesh::
23509 regionplague(memorypool *regionviri, REAL attribute, REAL volume)
23510 {
23511 tetrahedron **virusloop;
23512 tetrahedron **regiontet;
23513 triface testtet, neighbor;
23514 face neighsh;
23515
23516 if (b->verbose > 1) {
23517 printf(" Marking neighbors of marked tetrahedra.\n");
23518 }
23519
23520
23521
23522 regionviri->traversalinit();
23523 virusloop = (tetrahedron **) regionviri->traverse();
23524 while (virusloop != (tetrahedron **) NULL) {
23525 testtet.tet = *virusloop;
23526
23527 uninfect(testtet);
23528 if (b->regionattrib) {
23529
23530 setelemattribute(testtet.tet, in->numberoftetrahedronattributes,
23531 attribute);
23532 }
23533 if (b->varvolume) {
23534
23535 setvolumebound(testtet.tet, volume);
23536 }
23537
23538 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23539
23540 sym(testtet, neighbor);
23541
23542 tspivot(testtet, neighsh);
23543
23544
23545
23546 if ((neighbor.tet != dummytet) && !infected(neighbor)
23547 && (neighsh.sh == dummysh)) {
23548
23549 infect(neighbor);
23550
23551 regiontet = (tetrahedron **) regionviri->alloc();
23552 *regiontet = neighbor.tet;
23553 }
23554 }
23555
23556
23557 infect(testtet);
23558 virusloop = (tetrahedron **) regionviri->traverse();
23559 }
23560
23561
23562 if (b->verbose > 1) {
23563 printf(" Unmarking marked tetrahedra.\n");
23564 }
23565 regionviri->traversalinit();
23566 virusloop = (tetrahedron **) regionviri->traverse();
23567 while (virusloop != (tetrahedron **) NULL) {
23568 testtet.tet = *virusloop;
23569 uninfect(testtet);
23570 virusloop = (tetrahedron **) regionviri->traverse();
23571 }
23572
23573 regionviri->restart();
23574 }
23575
23577
23578
23579
23581
23582 void tetgenmesh::removeholetets(memorypool* viri)
23583 {
23584 tetrahedron **virusloop;
23585 triface testtet, neighbor;
23586 point checkpt;
23587 int *tetspernodelist;
23588 int i, j;
23589
23590 if (b->verbose > 0) {
23591 printf(" Deleting marked tetrahedra.\n");
23592 }
23593
23594
23595 tetspernodelist = new int[points->items + 1];
23596 for (i = 0; i < points->items + 1; i++) tetspernodelist[i] = 0;
23597
23598
23599 tetrahedrons->traversalinit();
23600 testtet.tet = tetrahedrontraverse();
23601 while (testtet.tet != (tetrahedron *) NULL) {
23602
23603 for (i = 0; i < 4; i++) {
23604 j = pointmark((point) testtet.tet[4 + i]);
23605 tetspernodelist[j]++;
23606 }
23607 testtet.tet = tetrahedrontraverse();
23608 }
23609
23610 viri->traversalinit();
23611 virusloop = (tetrahedron **) viri->traverse();
23612 while (virusloop != (tetrahedron **) NULL) {
23613 testtet.tet = *virusloop;
23614
23615
23616 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23617 sym(testtet, neighbor);
23618 if (neighbor.tet == dummytet) {
23619
23620
23621
23622 hullsize--;
23623 } else {
23624
23625 dissolve(neighbor);
23626
23627
23628 hullsize++;
23629 }
23630 }
23631
23632 for (i = 0; i < 4; i++) {
23633 checkpt = (point) testtet.tet[4 + i];
23634 j = pointmark(checkpt);
23635 tetspernodelist[j]--;
23636 if (tetspernodelist[j] == 0) {
23637
23638 if ((pointtype(checkpt) == FREEVOLVERTEX) || !b->nojettison) {
23639 setpointtype(checkpt, UNUSEDVERTEX);
23640 unuverts++;
23641 }
23642 }
23643 }
23644
23645 tetrahedrondealloc(testtet.tet);
23646 virusloop = (tetrahedron **) viri->traverse();
23647 }
23648
23649 delete [] tetspernodelist;
23650 }
23651
23653
23654
23655
23656
23657
23658
23659
23660
23661
23663
23664 void tetgenmesh::assignregionattribs()
23665 {
23666 list *regionnumlist;
23667 list *regiontetlist;
23668 triface tetloop, regiontet, neightet;
23669 face checksh;
23670 bool flag;
23671 int regionnum, num;
23672 int attridx, count;
23673 int i;
23674
23675 if (b->verbose > 0) {
23676 printf(" Assign region numbers.\n");
23677 }
23678
23679 regionnumlist = new list(sizeof(int), NULL, 256);
23680 regiontetlist = new list(sizeof(triface), NULL, 1024);
23681 attridx = in->numberoftetrahedronattributes;
23682
23683
23684
23685 tetrahedrons->traversalinit();
23686 tetloop.tet = tetrahedrontraverse();
23687 while (tetloop.tet != (tetrahedron *) NULL) {
23688 if (!infected(tetloop)) {
23689 regionnum = (int) elemattribute(tetloop.tet, attridx);
23690 if (regionnum != 0.0) {
23691
23692 infect(tetloop);
23693 regiontetlist->append(&tetloop);
23694
23695 for (i = 0; i < regiontetlist->len(); i++) {
23696 regiontet = * (triface *)(* regiontetlist)[i];
23697 for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23698
23699 tspivot(regiontet, checksh);
23700 if (checksh.sh == dummysh) {
23701 sym(regiontet, neightet);
23702 if ((neightet.tet != dummytet) && !infected(neightet)) {
23703 #ifdef SELF_CHECK
23704
23705 num = (int) elemattribute(neightet.tet, attridx);
23706 assert(num == regionnum);
23707 #endif
23708 infect(neightet);
23709 regiontetlist->append(&neightet);
23710 }
23711 }
23712 }
23713 }
23714
23715 flag = false;
23716 for (i = 0; i < regionnumlist->len() && !flag; i++) {
23717 num = * (int *)(* regionnumlist)[i];
23718 flag = (num == regionnum);
23719 }
23720 if (!flag) regionnumlist->append(®ionnum);
23721
23722 regiontetlist->clear();
23723 }
23724 }
23725 tetloop.tet = tetrahedrontraverse();
23726 }
23727
23728 if (b->verbose > 0) {
23729 printf(" %d user-specified regions.\n", regionnumlist->len());
23730 }
23731
23732
23733 tetrahedrons->traversalinit();
23734 tetloop.tet = tetrahedrontraverse();
23735 regionnum = 1;
23736 count = 0;
23737 while (tetloop.tet != (tetrahedron *) NULL) {
23738 if (!infected(tetloop)) {
23739
23740 count++;
23741 do {
23742 flag = false;
23743
23744 for (i = 0; i < regionnumlist->len() && !flag; i++) {
23745 num = * (int *)(* regionnumlist)[i];
23746 flag = (num == regionnum);
23747 }
23748 if (flag) regionnum++;
23749 } while (flag);
23750 setelemattribute(tetloop.tet, attridx, (REAL) regionnum);
23751 infect(tetloop);
23752 regiontetlist->append(&tetloop);
23753
23754 for (i = 0; i < regiontetlist->len(); i++) {
23755 regiontet = * (triface *)(* regiontetlist)[i];
23756 for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23757
23758 tspivot(regiontet, checksh);
23759 if (checksh.sh == dummysh) {
23760 sym(regiontet, neightet);
23761 if ((neightet.tet != dummytet) && !infected(neightet)) {
23762 #ifdef SELF_CHECK
23763
23764 num = (int) elemattribute(neightet.tet, attridx);
23765 assert(num == 0);
23766 #endif
23767 setelemattribute(neightet.tet, attridx, (REAL) regionnum);
23768 infect(neightet);
23769 regiontetlist->append(&neightet);
23770 }
23771 }
23772 }
23773 }
23774 regiontetlist->clear();
23775 regionnum++;
23776 }
23777 tetloop.tet = tetrahedrontraverse();
23778 }
23779
23780
23781 tetrahedrons->traversalinit();
23782 tetloop.tet = tetrahedrontraverse();
23783 while (tetloop.tet != (tetrahedron *) NULL) {
23784 #ifdef SELF_CHECK
23785 assert(infected(tetloop));
23786 #endif
23787 uninfect(tetloop);
23788 tetloop.tet = tetrahedrontraverse();
23789 }
23790
23791 if (b->verbose > 0) {
23792 printf(" %d regions are numbered.\n", count);
23793 }
23794
23795 delete regionnumlist;
23796 delete regiontetlist;
23797 }
23798
23800
23801
23802
23803
23804
23805
23806
23807
23809
23810 void tetgenmesh::carveholes()
23811 {
23812 memorypool *holeviri, *regionviri;
23813 tetrahedron *tptr, **holetet, **regiontet;
23814 triface searchtet, *holetets, *regiontets;
23815 enum locateresult intersect;
23816 int i;
23817
23818 if (!b->quiet) {
23819 printf("Removing unwanted tetrahedra.\n");
23820 if (b->verbose && (in->numberofholes > 0)) {
23821 printf(" Marking holes for elimination.\n");
23822 }
23823 }
23824
23825
23826 holeviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23827
23828 infecthull(holeviri);
23829
23830 if (in->numberofholes > 0) {
23831
23832 holetets = (triface *) new triface[in->numberofholes];
23833
23834 for (i = 0; i < 3 * in->numberofholes; i += 3) {
23835
23836 if ((in->holelist[i] >= xmin) && (in->holelist[i] <= xmax)
23837 && (in->holelist[i + 1] >= ymin)
23838 && (in->holelist[i + 1] <= ymax)
23839 && (in->holelist[i + 2] >= zmin)
23840 && (in->holelist[i + 2] <= zmax)) {
23841 searchtet.tet = dummytet;
23842
23843 intersect = locate(&in->holelist[i], &searchtet);
23844 if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23845
23846 holetets[i / 3] = searchtet;
23847 }
23848 }
23849 }
23850
23851
23852 for (i = 0; i < in->numberofholes; i++) {
23853 infect(holetets[i]);
23854 holetet = (tetrahedron **) holeviri->alloc();
23855 *holetet = holetets[i].tet;
23856 }
23857
23858 delete [] holetets;
23859 }
23860
23861
23862 plague(holeviri);
23863
23864
23865
23866 if (b->regionattrib) {
23867
23868 tetrahedrons->traversalinit();
23869 tptr = tetrahedrontraverse();
23870 while (tptr != (tetrahedron *) NULL) {
23871 setelemattribute(tptr, in->numberoftetrahedronattributes, 0.0);
23872 tptr = tetrahedrontraverse();
23873 }
23874 }
23875
23876 if (in->numberofregions > 0) {
23877 if (!b->quiet) {
23878 if (b->regionattrib) {
23879 if (b->varvolume) {
23880 printf("Spreading regional attributes and volume constraints.\n");
23881 } else {
23882 printf("Spreading regional attributes.\n");
23883 }
23884 } else {
23885 printf("Spreading regional volume constraints.\n");
23886 }
23887 }
23888
23889 regiontets = (triface *) new triface[in->numberofregions];
23890
23891 for (i = 0; i < in->numberofregions; i++) {
23892 regiontets[i].tet = dummytet;
23893
23894 if ((in->regionlist[5 * i] >= xmin)
23895 && (in->regionlist[5 * i] <= xmax)
23896 && (in->regionlist[5 * i + 1] >= ymin)
23897 && (in->regionlist[5 * i + 1] <= ymax)
23898 && (in->regionlist[5 * i + 2] >= zmin)
23899 && (in->regionlist[5 * i + 2] <= zmax)) {
23900 searchtet.tet = dummytet;
23901
23902 intersect = locate(&in->regionlist[5 * i], &searchtet);
23903 if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23904
23905
23906 regiontets[i] = searchtet;
23907 }
23908 }
23909 }
23910
23911
23912 regionviri = new memorypool(sizeof(tetrahedron *), 1024, POINTER, 0);
23913
23914 for (i = 0; i < in->numberofregions; i++) {
23915 if (regiontets[i].tet != dummytet) {
23916
23917
23918 if (!isdead(&(regiontets[i]))) {
23919
23920 infect(regiontets[i]);
23921 regiontet = (tetrahedron **) regionviri->alloc();
23922 *regiontet = regiontets[i].tet;
23923
23924 regionplague(regionviri, in->regionlist[5 * i + 3],
23925 in->regionlist[5 * i + 4]);
23926
23927 }
23928 }
23929 }
23930
23931 delete [] regiontets;
23932 delete regionviri;
23933 }
23934
23935
23936 removeholetets(holeviri);
23937
23938 nonconvex = 1;
23939
23940 if (b->regionattrib) {
23941 if (b->regionattrib > 1) {
23942
23943 assignregionattribs();
23944 }
23945
23946 in->numberoftetrahedronattributes++;
23947 }
23948
23949
23950 delete holeviri;
23951 }
23952
23953
23954
23955
23956
23957
23958
23959
23960
23962
23963
23964
23965
23966
23967
23968
23969
23970
23971
23973
23974 void tetgenmesh::replacepolygonsubs(list* oldshlist, list* newshlist)
23975 {
23976 face newsh, oldsh, spinsh;
23977 face casingout, casingin;
23978 face checkseg;
23979 point pa, pb;
23980 int i, j, k, l;
23981
23982 for (i = 0; i < newshlist->len(); i++) {
23983
23984 newsh = * (face *)(* newshlist)[i];
23985
23986 for (k = 0; k < 3; k++) {
23987 spivot(newsh, casingout);
23988
23989 if (casingout.sh == dummysh) {
23990
23991 pa = sorg(newsh);
23992 pb = sdest(newsh);
23993 for (j = 0; j < oldshlist->len(); j++) {
23994 oldsh = * (face *)(* oldshlist)[j];
23995 for (l = 0; l < 3; l++) {
23996 if (((sorg(oldsh) == pa) && (sdest(oldsh) == pb)) ||
23997 ((sorg(oldsh) == pb) && (sdest(oldsh) == pa))) break;
23998 senextself(oldsh);
23999 }
24000 if (l < 3) break;
24001 }
24002
24003 if (j < oldshlist->len()) {
24004
24005 spivot(oldsh, casingout);
24006 sspivot(oldsh, checkseg);
24007 if (checkseg.sh != dummysh) {
24008
24009 if (oldsh.sh != casingout.sh) {
24010
24011 spinsh = casingout;
24012 do {
24013 casingin = spinsh;
24014 spivotself(spinsh);
24015 } while (sapex(spinsh) != sapex(oldsh));
24016 assert(casingin.sh != oldsh.sh);
24017
24018 sbond1(casingin, newsh);
24019 sbond1(newsh, casingout);
24020 } else {
24021
24022 sbond(newsh, newsh);
24023 }
24024
24025 ssbond(newsh, checkseg);
24026 } else {
24027
24028 sbond(newsh, casingout);
24029 }
24030
24031
24032 sdissolve(oldsh);
24033 ssdissolve(oldsh);
24034 }
24035 }
24036
24037 senextself(newsh);
24038 }
24039 }
24040 }
24041
24043
24044
24045
24046
24047
24048
24049
24050
24052
24053 void tetgenmesh::orientnewsubs(list* newshlist, face* orientsh, REAL* norm)
24054 {
24055 face *newsh;
24056 point pa, pb, pc;
24057 REAL ref[3], ori, len;
24058 int i;
24059
24060
24061 pa = sorg(*orientsh);
24062 pb = sdest(*orientsh);
24063 pc = sapex(*orientsh);
24064 facenormal(pa, pb, pc, norm, &len);
24065 for (i = 0; i < 3; i++) ref[i] = pa[i] + norm[i];
24066 for (i = 0; i < 3; i++) norm[i] /= len;
24067
24068
24069 for (i = 0; i < newshlist->len(); i++) {
24070 newsh = (face *)(* newshlist)[i];
24071 pa = sorg(*newsh);
24072 pb = sdest(*newsh);
24073 pc = sapex(*newsh);
24074 ori = orient3d(pa, pb, pc, ref);
24075 assert(ori != 0.0);
24076 if (ori > 0.0) {
24077 sesymself(*newsh);
24078 }
24079 }
24080 }
24081
24083
24084
24085
24086
24087
24088
24089
24090
24091
24092
24093
24094
24095
24096
24097
24098
24099
24100
24102
24103 bool tetgenmesh::constrainedflip(triface* flipface, triface* front,
24104 queue* flipque)
24105 {
24106 triface symface, spintet;
24107 face checksh;
24108 point pa, pb, pc, pd, pe;
24109 enum fliptype fc;
24110 REAL sign;
24111 bool doflip;
24112 int ia, ib, ic, id, ie;
24113 int i;
24114
24115
24116 tspivot(*flipface, checksh);
24117 if (checksh.sh != dummysh) return false;
24118
24119 sym(*flipface, symface);
24120 if (symface.tet == dummytet) return false;
24121
24122 adjustedgering(*flipface, CCW);
24123 pa = dest(*flipface);
24124 pb = org(*flipface);
24125 pc = apex(*flipface);
24126 pd = oppo(*flipface);
24127 pe = oppo(symface);
24128
24129 ia = pointmark(pa);
24130 ib = pointmark(pb);
24131 ic = pointmark(pc);
24132 id = pointmark(pd);
24133 ie = pointmark(pe);
24134 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24135 assert(sign != 0.0);
24136
24137
24138
24139 if (sign <= 0.0) {
24140
24141 checksubfaces = 0;
24142 fc = categorizeface(*flipface);
24143 checksubfaces = 1;
24144 if (fc == T23) {
24145 doflip = true;
24146
24147
24148
24149
24150
24151
24152
24153
24154
24155
24156
24157
24158
24159 if (doflip) {
24160 flip23(flipface, flipque);
24161 return true;
24162 }
24163 } else if (fc == T32) {
24164
24165 doflip = true;
24166 spintet = *flipface;
24167 for (i = 0; i < 2; i++) {
24168 fnextself(spintet);
24169 tspivot(spintet, checksh);
24170 if (checksh.sh != dummysh) {
24171 doflip = false; break;
24172 }
24173 }
24174 if (doflip) {
24175 flip32(flipface, flipque);
24176 return true;
24177 }
24178 } else if (fc == T22 || fc == T44) {
24179
24180 doflip = true;
24181 if (fc == T22) {
24182 for (i = 0; i < 2; i++) {
24183 spintet = *flipface;
24184 if (i == 1) {
24185 esymself(spintet);
24186 }
24187 fnextself(spintet);
24188 tspivot(spintet, checksh);
24189 if (checksh.sh != dummysh) {
24190 doflip = false; break;
24191 }
24192 }
24193 } else if (fc == T44) {
24194 spintet = *flipface;
24195 for (i = 0; i < 3; i++) {
24196 fnextself(spintet);
24197 tspivot(spintet, checksh);
24198 if (checksh.sh != dummysh) {
24199 doflip = false; break;
24200 }
24201 }
24202 }
24203 if (doflip) {
24204 flip22(flipface, flipque);
24205 return true;
24206 }
24207 } else if (fc == N32) {
24208
24209 if (front != (triface *) NULL) {
24210
24211 spintet = *flipface;
24212 while (fnextself(spintet)) {
24213 if (apex(spintet) == apex(*flipface)) break;
24214
24215 if (constrainedflip(&spintet, NULL, flipque)) {
24216
24217 return true;
24218 }
24219
24220 findedge(&spintet, org(*flipface), dest(*flipface));
24221 }
24222 }
24223 }
24224 }
24225
24226
24227 if (front != (triface *) NULL) {
24228
24229 pa = org(*front);
24230 pb = dest(*front);
24231 pc = apex(*front);
24232
24233
24234 if (oppo(symface) != pc) {
24235 adjustedgering(symface, CCW);
24236 for (i = 0; i < 3; i++) {
24237 fnext(symface, spintet);
24238
24239 sign = orient3d(org(spintet), dest(spintet), apex(spintet), pc);
24240 if (sign < 0.0) {
24241 if (tritritest(&spintet, pa, pb, pc)) {
24242 if (b->verbose > 2) {
24243 printf(" Next crossface (%d, %d, %d).\n",
24244 pointmark(org(spintet)), pointmark(dest(spintet)),
24245 pointmark(apex(spintet)));
24246 }
24247 return constrainedflip(&spintet, front, flipque);
24248
24249 }
24250 }
24251 enextself(symface);
24252 }
24253 }
24254 }
24255 return false;
24256 }
24257
24259
24260
24261
24262
24263
24264
24266
24267 bool tetgenmesh::recoverfront(triface* front, list* newtetlist, queue* flipque)
24268 {
24269 triface idfront, starttet, spintet;
24270 point pa, pb, pc, pd, ref;
24271 enum locateresult loc;
24272 enum finddirectionresult col;
24273 REAL ori, ori1, ori2, sign;
24274 int hitbdry;
24275 int i, j;
24276
24277
24278 for (i = 0; i < 3; i++) {
24279 pa = org(*front);
24280 pb = dest(*front);
24281
24282 idfront = recenttet;
24283
24284 if (isdead(&idfront)) {
24285
24286 for (j = 0; j < newtetlist->len(); j++) {
24287 recenttet = * (triface *)(* newtetlist)[j];
24288 if (!isdead(&recenttet)) break;
24289 }
24290 assert(j < newtetlist->len());
24291 }
24292 loc = preciselocate(pa, &idfront, (long) newtetlist->len());
24293 if (loc != ONVERTEX) {
24294
24295 for (j = 0; j < newtetlist->len(); j++) {
24296 idfront = * (triface *)(* newtetlist)[j];
24297 if (isdead(&idfront)) continue;
24298 if (findorg(&idfront, pa)) break;
24299 }
24300 assert(j < newtetlist->len());
24301 }
24302 recenttet = idfront;
24303
24304 col = finddirection(&idfront, pb, (long) newtetlist->len());
24305 if (col == BELOWHULL) {
24306
24307 for (j = 0; j < newtetlist->len(); j++) {
24308 idfront = * (triface *)(* newtetlist)[j];
24309 if (isdead(&idfront)) continue;
24310 if (findorg(&idfront, pa)) {
24311 assert(org(idfront) == pa);
24312 if (dest(idfront) == pb) {
24313 col = RIGHTCOLLINEAR; break;
24314 } else if (apex(idfront) == pb) {
24315 col = LEFTCOLLINEAR; break;
24316 } else if (oppo(idfront) == pb) {
24317 col = TOPCOLLINEAR; break;
24318 }
24319 }
24320 }
24321 }
24322 if (col == RIGHTCOLLINEAR) {
24323
24324 } else if (col == LEFTCOLLINEAR) {
24325 enext2self(idfront);
24326 esymself(idfront);
24327 } else if (col == TOPCOLLINEAR) {
24328 fnextself(idfront);
24329 enext2self(idfront);
24330 esymself(idfront);
24331 }
24332 if (dest(idfront) == pb) break;
24333
24334 enextself(*front);
24335 }
24336 if (i == 3) {
24337
24338 return false;
24339 }
24340
24341
24342 pc = apex(*front);
24343 spintet = idfront;
24344 hitbdry = 0;
24345 do {
24346 if (apex(spintet) == pc) {
24347
24348 insertauxsubface(front, &spintet);
24349 return true;
24350 }
24351 if (!fnextself(spintet)) {
24352 hitbdry ++;
24353 if (hitbdry < 2) {
24354 esym(idfront, spintet);
24355 if (!fnextself(spintet)) {
24356 hitbdry ++;
24357 }
24358 }
24359 }
24360 if (apex(spintet) == apex(idfront)) break;
24361 } while (hitbdry < 2);
24362
24363
24364 pd = apex(idfront);
24365 assert(pd != pc);
24366
24367 ori = orient3d(pa, pb, pc, pd);
24368 if (ori < 0.0) {
24369
24370 esym(idfront, starttet);
24371 sign = -1.0;
24372 } else if (ori > 0.0) {
24373
24374 starttet = idfront;
24375 sign = 1.0;
24376 } else {
24377 assert(ori == 0.0);
24378
24379 ref = oppo(idfront);
24380 ori1 = orient3d(pa, pb, ref, pc);
24381 ori2 = orient3d(pa, pb, ref, pd);
24382 assert(ori1 * ori2 != 0.0);
24383 if (ori1 * ori2 > 0) {
24384
24385
24386 ori1 = orient3d(pb, pc, ref, pd);
24387 ori2 = orient3d(pb, pc, ref, pa);
24388 assert(ori1 * ori2 != 0.0);
24389 if (ori1 * ori2 > 0) {
24390
24391 enextself(idfront);
24392 } else {
24393
24394 enext2self(idfront);
24395 }
24396 adjustedgering(idfront, CCW);
24397 fnextself(idfront);
24398 if (b->verbose > 2) {
24399 printf(" Get crossface (%d, %d, %d).\n", pointmark(org(idfront)),
24400 pointmark(dest(idfront)), pointmark(apex(idfront)));
24401 }
24402 if (constrainedflip(&idfront, front, flipque)) {
24403
24404 return recoverfront(front, newtetlist, flipque);
24405 }
24406
24407 return false;
24408 } else {
24409
24410 starttet = idfront;
24411 if (fnextself(starttet)) {
24412
24413 sign = 1.0;
24414 } else {
24415
24416 esym(idfront, starttet);
24417 sign = -1.0;
24418 }
24419 }
24420 }
24421
24422 assert(sign != 0.0);
24423 if (sign == -1) {
24424
24425 pa = org(starttet);
24426 pb = dest(starttet);
24427
24428 sign = -sign;
24429 }
24430
24431
24432 spintet = starttet;
24433 while (fnextself(spintet)) {
24434 pd = apex(spintet);
24435 assert(pd != pc);
24436
24437 ori = orient3d(pa, pb, pc, pd);
24438 if (ori == 0.0) {
24439
24440 ref = oppo(spintet);
24441 ori1 = orient3d(pb, pc, ref, pd);
24442 ori2 = orient3d(pb, pc, ref, pa);
24443 assert(ori1 * ori2 != 0.0);
24444 if (ori1 * ori2 > 0) {
24445
24446 enextself(spintet);
24447 } else {
24448
24449 enext2self(spintet);
24450 }
24451 adjustedgering(spintet, CCW);
24452 fnextself(spintet);
24453 if (b->verbose > 2) {
24454 printf(" Get crossface (%d, %d, %d).\n", pointmark(org(spintet)),
24455 pointmark(dest(spintet)), pointmark(apex(spintet)));
24456 }
24457 if (constrainedflip(&spintet, front, flipque)) {
24458
24459 return recoverfront(front, newtetlist, flipque);
24460 }
24461
24462 return false;
24463 } else if (ori * sign < 0.0) {
24464
24465 adjustedgering(spintet, CCW);
24466 enextself(spintet);
24467 for (i = 0; i < 2; i++) {
24468
24469 fnext(spintet, starttet);
24470 if (tritritest(&starttet, pa, pb, pc)) {
24471 if (b->verbose > 2) {
24472 printf(" Get crossface (%d, %d, %d).\n",
24473 pointmark(org(starttet)), pointmark(dest(starttet)),
24474 pointmark(apex(starttet)));
24475 }
24476 if (constrainedflip(&starttet, front, flipque)) {
24477
24478 return recoverfront(front, newtetlist, flipque);
24479 }
24480 }
24481 enextself(spintet);
24482 }
24483
24484 return false;
24485 }
24486 }
24487
24488 assert(0);
24489 return false;
24490 }
24491
24493
24494
24495
24497
24498 void tetgenmesh::repairflips(queue* flipque)
24499 {
24500 badface *qface;
24501 triface flipface, symface, spintet;
24502 face checksh;
24503 point pa, pb, pc, pd, pe;
24504 enum fliptype fc;
24505 REAL sign;
24506 long flipcount;
24507 bool doflip;
24508 int ia, ib, ic, id, ie;
24509 int i;
24510
24511 if (b->verbose > 1) {
24512 printf(" Repair flip %ld faces.\n", flipque->len());
24513 }
24514 flipcount = flip23s + flip32s + flip22s + flip44s;
24515
24516 while (!flipque->empty()) {
24517 qface = (badface *) flipque->pop();
24518 flipface = qface->tt;
24519
24520 if (isdead(&flipface) || flipface.tet == dummytet ||
24521 (org(flipface) != qface->forg) ||
24522 (dest(flipface) != qface->fdest) ||
24523 (apex(flipface) != qface->fapex) ||
24524 (oppo(flipface) == (point) NULL)) continue;
24525
24526 tspivot(flipface, checksh);
24527 if (checksh.sh != dummysh) continue;
24528
24529 sym(flipface, symface);
24530 if (symface.tet == dummytet) continue;
24531
24532 adjustedgering(flipface, CW);
24533 pa = org(flipface);
24534 pb = dest(flipface);
24535 pc = apex(flipface);
24536 pd = oppo(flipface);
24537 pe = oppo(symface);
24538
24539 ia = pointmark(pa);
24540 ib = pointmark(pb);
24541 ic = pointmark(pc);
24542 id = pointmark(pd);
24543 ie = pointmark(pe);
24544 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic, id, ie);
24545 assert(sign != 0.0);
24546
24547
24548
24549 if (sign > 0.0) {
24550
24551 checksubfaces = 0;
24552 fc = categorizeface(flipface);
24553 checksubfaces = 1;
24554 if (fc == T23) {
24555 doflip = true;
24556
24557
24558
24559
24560
24561
24562
24563
24564
24565
24566
24567
24568
24569 if (doflip) {
24570 flip23(&flipface, flipque);
24571 }
24572 } else if (fc == T32) {
24573
24574 doflip = true;
24575 spintet = flipface;
24576 for (i = 0; i < 2; i++) {
24577 fnextself(spintet);
24578 tspivot(spintet, checksh);
24579 if (checksh.sh != dummysh) {
24580 doflip = false; break;
24581 }
24582 }
24583 if (doflip) {
24584 flip32(&flipface, flipque);
24585 }
24586 } else if (fc == T22 || fc == T44) {
24587
24588 doflip = true;
24589 if (fc == T22) {
24590 for (i = 0; i < 2; i++) {
24591 spintet = flipface;
24592 if (i == 1) {
24593 esymself(spintet);
24594 }
24595 fnextself(spintet);
24596 tspivot(spintet, checksh);
24597 if (checksh.sh != dummysh) {
24598 doflip = false; break;
24599 }
24600 }
24601 } else if (fc == T44) {
24602 spintet = flipface;
24603 for (i = 0; i < 3; i++) {
24604 fnextself(spintet);
24605 tspivot(spintet, checksh);
24606 if (checksh.sh != dummysh) {
24607 doflip = false; break;
24608 }
24609 }
24610 }
24611 if (doflip) {
24612 flip22(&flipface, flipque);
24613 }
24614 }
24615 }
24616 }
24617 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
24618 if (b->verbose > 1) {
24619 printf(" %ld flips.\n", flipcount);
24620 }
24621 }
24622
24624
24625
24626
24627
24628
24629
24631
24632 bool tetgenmesh::constrainedcavity(triface* oldtet, list* floorlist,
24633 list* ceillist, list* ptlist, list* frontlist, list* misfrontlist,
24634 list* newtetlist, queue* flipque)
24635 {
24636 triface misfront, newtet;
24637 long facenum;
24638 int i;
24639
24640 if (b->verbose > 1) {
24641 printf(" Constrained cavity (%d floors, %d ceilings, %d vertices).\n",
24642 floorlist->len(), ceillist->len(), ptlist->len());
24643 }
24644
24645
24646
24647
24648 initializecavity(floorlist, ceillist, frontlist);
24649
24650 delaunizecavvertices(oldtet, ptlist, NULL, newtetlist, flipque);
24651
24652
24653 if (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
24654
24655 recenttet = * (triface *)(* newtetlist)[0];
24656 assert((recenttet.tet != dummytet) && !isdead(&recenttet));
24657
24658 do {
24659 facenum = misfrontlist->len();
24660 for (i = 0; i < misfrontlist->len(); i++) {
24661
24662 misfront = * (triface *)(* misfrontlist)[i];
24663
24664 adjustedgering(misfront, CW);
24665 if (b->verbose > 1) {
24666 printf(" Recover face (%d, %d, %d).\n", pointmark(org(misfront)),
24667 pointmark(dest(misfront)), pointmark(apex(misfront)));
24668 }
24669 if (recoverfront(&misfront, newtetlist, flipque)) {
24670
24671 frontlist->append(&misfront);
24672 misfrontlist->del(i, 0); i--;
24673 }
24674
24675 repairflips(flipque);
24676 }
24677
24678 if (misfrontlist->len() == 0) break;
24679
24680
24681 } while (misfrontlist->len() < facenum);
24682
24683 retrievenewtets(newtetlist);
24684 }
24685
24686
24687
24688 if (misfrontlist->len() == 0) {
24689
24690
24691
24692 carvecavity(newtetlist, misfrontlist, NULL);
24693
24694
24695 return true;
24696 } else {
24697
24698
24699 detachauxsubfaces(newtetlist);
24700
24701 for (i = 0; i < newtetlist->len(); i++) {
24702 newtet = * (triface *)(* newtetlist)[i];
24703 assert(!isdead(&newtet));
24704 tetrahedrondealloc(newtet.tet);
24705 }
24706 newtetlist->clear();
24707
24708 for (i = 0; i < misfrontlist->len(); i++) {
24709 misfront = * (triface *)(* misfrontlist)[i];
24710 frontlist->append(&misfront);
24711 }
24712 return false;
24713 }
24714 }
24715
24717
24718
24719
24720
24721
24722
24724
24725 void tetgenmesh::expandsteinercavity(point steinpt, REAL eps, list* frontlist,
24726 list* oldtetlist)
24727 {
24728 triface front, symfront, newfront, oldfront;
24729 face frontsh;
24730 point pa, pb, pc;
24731 REAL ori;
24732 bool expflag, newflag;
24733 int i, j;
24734
24735 do {
24736 expflag = false;
24737 for (i = 0; i < frontlist->len(); i++) {
24738
24739 front = * (triface *)(* frontlist)[i];
24740
24741 tspivot(front, frontsh);
24742 if (frontsh.sh == dummysh) {
24743
24744 adjustedgering(front, CW);
24745 pa = org(front);
24746 pb = dest(front);
24747 pc = apex(front);
24748 ori = orient3d(pa, pb, pc, steinpt);
24749 if (ori != 0.0) {
24750 if (iscoplanar(pa, pb, pc, steinpt, ori, eps)) {
24751 ori = 0.0;
24752 }
24753 }
24754 if (ori >= 0.0) {
24755
24756 if (b->verbose > 2) {
24757 printf(" Remove front (%d, %d, %d).\n", pointmark(pa),
24758 pointmark(pb), pointmark(pc));
24759 }
24760 frontlist->del(i, 1);
24761 expflag = true;
24762 break;
24763 }
24764 }
24765 }
24766 if (expflag) {
24767 assert(!infected(front) && (oppo(front) != NULL));
24768
24769 adjustedgering(front, CCW);
24770 for (i = 0; i < 3; i++) {
24771 newflag = true;
24772
24773 fnext(front, symfront);
24774 tspivot(symfront, frontsh);
24775 sym(symfront, newfront);
24776 if (frontsh.sh == dummysh) {
24777 assert(newfront.tet != dummytet);
24778
24779 if (infected(newfront)) {
24780 for (j = 0; j < frontlist->len(); j++) {
24781 oldfront = * (triface *)(* frontlist)[j];
24782 if ((oldfront.tet == symfront.tet) &&
24783 (oldfront.loc == symfront.loc)) {
24784
24785 if (b->verbose > 2) {
24786 printf(" Remove front (%d, %d, %d).\n",
24787 pointmark(org(oldfront)), pointmark(dest(oldfront)),
24788 pointmark(apex(oldfront)));
24789 }
24790 frontlist->del(j, 1);
24791 newflag = false;
24792 break;
24793 }
24794 }
24795 }
24796 } else {
24797
24798 if (newfront.tet == dummytet) {
24799 sesymself(frontsh);
24800
24801 maketetrahedron(&newfront);
24802 setorg(newfront, sorg(frontsh));
24803 setdest(newfront, sdest(frontsh));
24804 setapex(newfront, sapex(frontsh));
24805 setoppo(newfront, (point) NULL);
24806 tsbond(newfront, frontsh);
24807 } else {
24808
24809 assert(!infected(newfront));
24810 }
24811 }
24812 if (newflag) {
24813 if (b->verbose > 2) {
24814 printf(" Add front (%d, %d, %d).\n", pointmark(org(newfront)),
24815 pointmark(dest(newfront)), pointmark(apex(newfront)));
24816 }
24817 frontlist->append(&newfront);
24818 }
24819 enextself(front);
24820 }
24821
24822 infect(front);
24823 oldtetlist->append(&front);
24824 expcavcount++;
24825 }
24826 } while (expflag);
24827 }
24828
24830
24831
24832
24833
24834
24835
24837
24838 bool tetgenmesh::findrelocatepoint(point sp, point np, REAL* n,
24839 list* frontlist, list* oldtetlist)
24840 {
24841 triface front;
24842 point pa, pb, pc;
24843 REAL tp[3], tvol, mvol;
24844 REAL ori, eps;
24845 bool visible;
24846 int i, j, k;
24847
24848 if (b->verbose > 1) {
24849 printf(" Find new location for point %d.\n", pointmark(sp));
24850 }
24851
24852
24853 tvol = mvol = 0.0;
24854 visible = false;
24855
24856 eps = b->epsilon;
24857
24858 for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24859
24860 for (i = 0; i < 3; i++) tp[i] = np[i];
24861
24862 j = 0;
24863 do {
24864 for (i = 0; i < frontlist->len(); i++) {
24865
24866 front = * (triface *)(* frontlist)[i];
24867
24868 adjustedgering(front, CW);
24869 pa = org(front);
24870 pb = dest(front);
24871 pc = apex(front);
24872 ori = orient3d(pa, pb, pc, np);
24873 visible = (ori < 0.0);
24874 if (!visible) {
24875
24876 for (i = 0; i < 3; i++) np[i] = sp[i] + 0.5 * (sp[i] - np[i]);
24877
24878 if ((tp[0] == np[0]) && (tp[1] == np[1]) && (tp[2] == np[2])) {
24879
24880 expandsteinercavity(sp, eps, frontlist, oldtetlist);
24881 eps *= 10.0;
24882 if (eps > b->epsilon * 1000.0) {
24883
24884
24885 return false;
24886 }
24887
24888 for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24889 }
24890 if (j % 2) {
24891
24892 for (i = 0; i < 3; i++) tp[i] = np[i];
24893 }
24894 break;
24895 } else {
24896
24897 if (i == 0) {
24898 mvol = fabs(ori);
24899 } else {
24900 mvol = fabs(ori) < mvol ? fabs(ori) : mvol;
24901 }
24902 }
24903 }
24904 j++;
24905 } while (!visible);
24906
24907 if (b->verbose > 1) {
24908 printf(" %d iterations. minvol = %.12g.\n", j, mvol);
24909 }
24910
24911
24912
24913 k = 0;
24914 do {
24915 j = 0;
24916 do {
24917 if (k == 0) {
24918
24919 for (i = 0; i < 3; i++) tp[i] = sp[i] + 0.9 * (np[i] - sp[i]);
24920 } else {
24921
24922 for (i = 0; i < 3; i++) tp[i] = sp[i] + 1.1 * (np[i] - sp[i]);
24923 }
24924
24925 for (i = 0; i < frontlist->len(); i++) {
24926
24927 front = * (triface *)(* frontlist)[i];
24928
24929 adjustedgering(front, CW);
24930 pa = org(front);
24931 pb = dest(front);
24932 pc = apex(front);
24933 ori = orient3d(pa, pb, pc, tp);
24934 visible = (ori < 0.0);
24935 if (visible) {
24936
24937 if (i == 0) {
24938 tvol = fabs(ori);
24939 } else {
24940 tvol = fabs(ori) < tvol ? fabs(ori) : tvol;
24941 }
24942 } else {
24943
24944 tvol = 0.0;
24945 break;
24946 }
24947 }
24948 if (tvol > mvol) {
24949
24950 for (i = 0; i < 3; i++) np[i] = tp[i];
24951 mvol = tvol;
24952 } else {
24953
24954 break;
24955 }
24956
24957 j++;
24958 } while (true);
24959
24960 if (j > 0) break;
24961
24962 k++;
24963 } while (k < 2);
24964
24965 if (b->verbose > 1) {
24966 printf(" %d adjust iterations. minvol = %.12g.\n", j, mvol);
24967 }
24968 return true;
24969 }
24970
24972
24973
24974
24975
24976
24977
24978
24980
24981 void tetgenmesh::relocatepoint(point steinpt, triface* oldtet, list* frontlist,
24982 list* newtetlist, queue* flipque)
24983 {
24984 triface front, newtet, newface, neightet;
24985 face checksh;
24986 point pa, pb;
24987 REAL attrib, volume;
24988 bool bdflag;
24989 int i, j, k, l;
24990
24991 if (b->verbose > 1) {
24992 printf(" Insert Steiner point (%.12g, %.12g, %.12g) %d.\n",
24993 steinpt[0], steinpt[1], steinpt[2], pointmark(steinpt));
24994 }
24995
24996 newtetlist->clear();
24997
24998
24999 for (i = 0; i < frontlist->len(); i++) {
25000
25001 front = * (triface *)(* frontlist)[i];
25002
25003 adjustedgering(front, CW);
25004 if (b->verbose > 2) {
25005 printf(" Get front (%d, %d, %d).\n", pointmark(org(front)),
25006 pointmark(dest(front)), pointmark(apex(front)));
25007 }
25008 maketetrahedron(&newtet);
25009 newtetlist->append(&newtet);
25010 setorg(newtet, org(front));
25011 setdest(newtet, dest(front));
25012 setapex(newtet, apex(front));
25013 setoppo(newtet, steinpt);
25014 if (oldtet != (triface *) NULL) {
25015 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
25016 attrib = elemattribute(oldtet->tet, j);
25017 setelemattribute(newtet.tet, j, attrib);
25018 }
25019 if (b->varvolume) {
25020 volume = volumebound(oldtet->tet);
25021 setvolumebound(newtet.tet, volume);
25022 }
25023 }
25024
25025 tspivot(front, checksh);
25026 if (oppo(front) == (point) NULL) {
25027 if (checksh.sh != dummysh) {
25028 stdissolve(checksh);
25029 }
25030
25031 tetrahedrondealloc(front.tet);
25032
25033
25034
25035 dummytet[0] = encode(newtet);
25036 } else {
25037
25038 bond(newtet, front);
25039 }
25040 if (checksh.sh != dummysh) {
25041 sesymself(checksh);
25042 tsbond(newtet, checksh);
25043 }
25044 if (flipque != (queue *) NULL) {
25045
25046 enqueueflipface(newtet, flipque);
25047 }
25048
25049 }
25050
25051
25052 for (i = 0; i < newtetlist->len(); i++) {
25053 newtet = * (triface *)(* newtetlist)[i];
25054 newtet.ver = 0;
25055 for (j = 0; j < 3; j++) {
25056 fnext(newtet, newface);
25057 sym(newface, neightet);
25058 if (neightet.tet == dummytet) {
25059
25060 bdflag = false;
25061 pa = org(newface);
25062 pb = dest(newface);
25063 assert(apex(newface) == steinpt);
25064 for (k = i + 1; k < newtetlist->len() && !bdflag; k++) {
25065 neightet = * (triface *)(* newtetlist)[k];
25066 neightet.ver = 0;
25067 for (l = 0; l < 3; l++) {
25068 if ((org(neightet) == pa && dest(neightet) == pb) ||
25069 (org(neightet) == pb && dest(neightet) == pa)) {
25070
25071 fnextself(neightet);
25072 assert(apex(neightet) == steinpt);
25073
25074 bond(newface, neightet);
25075 bdflag = true;
25076 break;
25077 }
25078 enextself(neightet);
25079 }
25080 }
25081 assert(bdflag);
25082 }
25083 enextself(newtet);
25084 }
25085
25086 pa = org(newtet);
25087 setpoint2tet(pa, encode(newtet));
25088 pa = dest(newtet);
25089 setpoint2tet(pa, encode(newtet));
25090 pa = apex(newtet);
25091 setpoint2tet(pa, encode(newtet));
25092 pa = oppo(newtet);
25093 setpoint2tet(pa, encode(newtet));
25094 }
25095
25096 if (flipque != (queue *) NULL) {
25097
25098 flip(flipque, NULL);
25099 }
25100 }
25101
25103
25104
25105
25107
25108 bool tetgenmesh::findcollapseedge(point suppt, point *conpt, list* oldtetlist,
25109 list* ptlist)
25110 {
25111 triface front;
25112 point pt, pa, pb, pc;
25113 REAL *lenarray, ltmp, ori;
25114 bool visflag;
25115 int *idxarray, itmp;
25116 int n, i, j;
25117
25118 if (b->verbose > 2) {
25119 printf(" Search an edge (in %d edges) for collapse %d.\n",
25120 ptlist->len(), pointmark(suppt));
25121 }
25122
25123
25124 n = ptlist->len();
25125 lenarray = new REAL[n];
25126 idxarray = new int[n];
25127
25128 for (i = 0; i < n; i++) {
25129 pt = * (point *)(* ptlist)[i];
25130 lenarray[i] = distance(suppt, pt);
25131 idxarray[i] = i;
25132 }
25133
25134 for (i = 0; i < n - 1; i++) {
25135 for (j = 0; j < n - 1 - i; j++) {
25136 if (lenarray[j + 1] < lenarray[j]) {
25137 ltmp = lenarray[j];
25138 lenarray[j] = lenarray[j + 1];
25139 lenarray[j + 1] = ltmp;
25140 itmp = idxarray[j];
25141 idxarray[j] = idxarray[j + 1];
25142 idxarray[j + 1] = itmp;
25143 }
25144 }
25145 }
25146
25147 for (i = 0; i < n; i++) {
25148 pt = * (point *)(* ptlist)[idxarray[i]];
25149
25150 lenarray[i] = 0.0;
25151 visflag = true;
25152 for (j = 0; j < oldtetlist->len() && visflag; j++) {
25153 front = * (triface *)(* oldtetlist)[j];
25154
25155 adjustedgering(front, CCW);
25156 pa = org(front);
25157 pb = dest(front);
25158 pc = apex(front);
25159
25160 if ((pa != pt) && (pb != pt) && (pc != pt)) {
25161 ori = orient3d(pa, pb, pc, pt);
25162 if (ori != 0.0) {
25163 if (iscoplanar(pa, pb, pc, pt, ori, b->epsilon * 1e+2)) ori = 0.0;
25164 }
25165 visflag = ori < 0.0;
25166 if (visflag) {
25167
25168 if (j == 0) {
25169 lenarray[i] = fabs(ori);
25170 } else {
25171 lenarray[i] = fabs(ori) < lenarray[i] ? fabs(ori) : lenarray[i];
25172 }
25173 } else {
25174
25175 lenarray[i] = 0.0;
25176 }
25177 }
25178 }
25179 if ((b->verbose > 2) && visflag) {
25180 printf(" Got candidate %d vol(%g).\n", pointmark(pt), lenarray[i]);
25181 }
25182 }
25183
25184
25185 ltmp = lenarray[0];
25186 itmp = idxarray[0];
25187 for (i = 1; i < n; i++) {
25188 if (lenarray[i] != 0.0) {
25189 if (lenarray[i] > ltmp) {
25190 ltmp = lenarray[i];
25191 itmp = idxarray[i];
25192 }
25193 }
25194 }
25195
25196 delete [] lenarray;
25197 delete [] idxarray;
25198
25199 if (ltmp == 0.0) {
25200
25201 *conpt = (point) NULL;
25202 return false;
25203 } else {
25204 pt = * (point *)(* ptlist)[itmp];
25205 *conpt = pt;
25206 return true;
25207 }
25208 }
25209
25211
25212
25213
25215
25216 void tetgenmesh::collapseedge(point suppt, point conpt, list* oldtetlist,
25217 list* deadtetlist)
25218 {
25219 triface oldtet, deadtet;
25220 triface adjtet1, adjtet2;
25221 face adjsh;
25222 point pa, pb, pc;
25223 int i, j;
25224
25225 if (b->verbose > 2) {
25226 printf(" Collapse edge (%d,%d).\n", pointmark(suppt), pointmark(conpt));
25227 }
25228
25229
25230 for (i = 0; i < oldtetlist->len(); i++) {
25231 oldtet = * (triface *)(* oldtetlist)[i];
25232 uninfect(oldtet);
25233 pa = org(oldtet);
25234 pb = dest(oldtet);
25235 pc = apex(oldtet);
25236 assert(oppo(oldtet) == suppt);
25237 setoppo(oldtet, conpt);
25238 if ((pa == conpt) || (pb == conpt) || (pc == conpt)) {
25239 deadtetlist->append(&oldtet);
25240 }
25241 }
25242
25243 for (i = 0; i < deadtetlist->len(); i++) {
25244 deadtet = * (triface *)(* deadtetlist)[i];
25245
25246 sym(deadtet, adjtet1);
25247 tspivot(deadtet, adjsh);
25248
25249 adjustedgering(deadtet, CCW);
25250 for (j = 0; j < 3; j++) {
25251 if (apex(deadtet) == conpt) break;
25252 enextself(deadtet);
25253 }
25254 assert(j < 3);
25255
25256 fnext(deadtet, adjtet2);
25257 symself(adjtet2);
25258 assert(adjtet2.tet != dummytet);
25259 if (adjtet1.tet != dummytet) {
25260 bond(adjtet1, adjtet2);
25261 } else {
25262 dissolve(adjtet2);
25263 dummytet[0] = encode(adjtet2);
25264 }
25265 if (adjsh.sh != dummysh) {
25266 tsbond(adjtet2, adjsh);
25267 }
25268
25269 tetrahedrondealloc(deadtet.tet);
25270 }
25271 deadtetlist->clear();
25272 }
25273
25275
25276
25277
25278
25279
25280
25281
25283
25284 void tetgenmesh::deallocfaketets(list* frontlist)
25285 {
25286 triface front, neightet;
25287 face checksh;
25288 bool infectflag;
25289 int i;
25290
25291 for (i = 0; i < frontlist->len(); i++) {
25292
25293 front = * (triface *)(* frontlist)[i];
25294
25295 adjustedgering(front, CW);
25296 sym(front, neightet);
25297 tspivot(front, checksh);
25298 if (oppo(front) == (point) NULL) {
25299 if (b->verbose > 2) {
25300 printf(" Get fake tet (%d, %d, %d).\n", pointmark(org(front)),
25301 pointmark(dest(front)), pointmark(apex(front)));
25302 }
25303 if (neightet.tet != dummytet) {
25304
25305
25306 infectflag = infected(neightet);
25307 dissolve(neightet);
25308 if (infectflag) {
25309 infect(neightet);
25310 }
25311 }
25312 if (checksh.sh != dummysh) {
25313 infectflag = sinfected(checksh);
25314 stdissolve(checksh);
25315 if (infectflag) {
25316 sinfect(checksh);
25317 }
25318 }
25319
25320 tetrahedrondealloc(front.tet);
25321
25322
25323
25324 if (neightet.tet != dummytet) {
25325 dummytet[0] = encode(neightet);
25326 }
25327 }
25328 }
25329 }
25330
25332
25333
25334
25335
25336
25337
25338
25339
25340
25341
25342
25344
25345 void tetgenmesh::restorepolyhedron(list* oldtetlist)
25346 {
25347 triface oldtet, neightet, neineitet;
25348 face checksh;
25349 int i;
25350
25351 for (i = 0; i < oldtetlist->len(); i++) {
25352
25353 oldtet = * (triface *)(* oldtetlist)[i];
25354
25355 for (oldtet.loc = 0; oldtet.loc < 4; oldtet.loc++) {
25356 sym(oldtet, neightet);
25357 tspivot(oldtet, checksh);
25358 if (neightet.tet != dummytet) {
25359 sym(neightet, neineitet);
25360 if (neineitet.tet != oldtet.tet) {
25361
25362 bond(neightet, oldtet);
25363 if (checksh.sh != dummysh) {
25364 tsbond(oldtet, checksh);
25365 }
25366 }
25367 } else {
25368
25369 #ifdef SELF_CHECK
25370 assert(checksh.sh != dummysh);
25371 stpivot(checksh, neineitet);
25372 assert(neineitet.tet != oldtet.tet);
25373 #endif
25374 tsbond(oldtet, checksh);
25375
25376 dummytet[0] = encode(oldtet);
25377 }
25378 }
25379 }
25380 }
25381
25383
25384
25385
25386
25387
25388
25389
25390
25391
25392
25393
25394
25396
25397 bool tetgenmesh::suppressfacetpoint(face* supsh, list* frontlist,
25398 list* misfrontlist, list* ptlist, list* conlist, memorypool* viri,
25399 queue* flipque, bool noreloc, bool optflag)
25400 {
25401 list *oldtetlist[2], *newtetlist[2];
25402 list *oldshlist, *newshlist;
25403 triface oldtet, newtet;
25404 face oldsh, newsh;
25405 point suppt, newpt[2];
25406 point *cons;
25407 REAL norm[3];
25408 bool success;
25409 int shmark;
25410 int i, j;
25411
25412 suppt = sapex(*supsh);
25413 if (b->verbose > 1) {
25414 printf(" Suppress point %d in facet.\n", pointmark(suppt));
25415 }
25416
25417
25418 for (i = 0; i < 2; i++) {
25419 oldtetlist[i] = (list *) NULL;
25420 newtetlist[i] = (list *) NULL;
25421 newpt[i] = (point) NULL;
25422 }
25423 oldshlist = new list(sizeof(face), NULL, 256);
25424 newshlist = new list(sizeof(face), NULL, 256);
25425 success = true;
25426
25427
25428 oldshlist->append(supsh);
25429 formstarpolygon(suppt, oldshlist, ptlist);
25430
25431 for (i = 0; i < oldshlist->len(); i++) {
25432 oldsh = * (face *)(* oldshlist)[i];
25433 cons = (point *) conlist->append(NULL);
25434 cons[0] = sorg(oldsh);
25435 cons[1] = sdest(oldsh);
25436 }
25437
25438 shmark = shellmark(*supsh);
25439 triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25440
25441 retrievenewsubs(newshlist, true);
25442
25443 replacepolygonsubs(oldshlist, newshlist);
25444
25445 ptlist->clear();
25446 conlist->clear();
25447 flipque->clear();
25448 viri->restart();
25449
25450
25451
25452 for (i = 0; i < 2 && success; i++) {
25453 if (i == 1) sesymself(*supsh);
25454
25455 stpivot(*supsh, oldtet);
25456
25457 if (oldtet.tet == dummytet) continue;
25458
25459 oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25460 newtetlist[i] = new list(sizeof(triface), NULL, 256);
25461
25462 assert(!isdead(&oldtet));
25463 oldtetlist[i]->append(&oldtet);
25464 formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25465
25466 for (j = 0; j < oldtetlist[i]->len(); j++) {
25467 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25468 infect(oldtet);
25469 }
25470
25471 orientnewsubs(newshlist, supsh, norm);
25472
25473 success = constrainedcavity(&oldtet, newshlist, oldtetlist[i], ptlist,
25474 frontlist, misfrontlist, newtetlist[i], flipque);
25475
25476 if (!success && !noreloc) {
25477
25478 makepoint(&(newpt[i]));
25479 success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25480 oldtetlist[i]);
25481
25482
25483
25484 if (success) {
25485
25486
25487 relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25488 setpointtype(newpt[i], FREEVOLVERTEX);
25489 relverts++;
25490 } else {
25491
25492 deallocfaketets(frontlist);
25493 pointdealloc(newpt[i]);
25494 newpt[i] = (point) NULL;
25495 assert(newtetlist[i]->len() == 0);
25496 }
25497 }
25498 if (!success && noreloc) {
25499
25500 deallocfaketets(frontlist);
25501 }
25502
25503 ptlist->clear();
25504 frontlist->clear();
25505 misfrontlist->clear();
25506 flipque->clear();
25507 }
25508
25509 if (success) {
25510
25511 setpointtype(suppt, UNUSEDVERTEX);
25512 unuverts++;
25513
25514 for (i = 0; i < oldshlist->len(); i++) {
25515 oldsh = * (face *)(* oldshlist)[i];
25516 if (i == 0) {
25517
25518 stpivot(oldsh, oldtet);
25519 if (oldtet.tet != dummytet) {
25520 sesymself(oldsh);
25521 stpivot(oldsh, oldtet);
25522 }
25523 if (oldtet.tet == dummytet) {
25524
25525 j = oldshlist->len() - newshlist->len();
25526 assert(j > 0);
25527 hullsize -= j;
25528 }
25529 }
25530 shellfacedealloc(subfaces, oldsh.sh);
25531 }
25532
25533 for (i = 0; i < 2; i++) {
25534 if (oldtetlist[i] != (list *) NULL) {
25535
25536 for (j = 0; j < oldtetlist[i]->len(); j++) {
25537 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25538 assert(!isdead(&oldtet));
25539 tetrahedrondealloc(oldtet.tet);
25540 }
25541 }
25542 }
25543 if (optflag) {
25544
25545 for (i = 0; i < 2; i++) {
25546 if (newtetlist[i] != (list *) NULL) {
25547 for (j = 0; j < newtetlist[i]->len(); j++) {
25548 newtet = * (triface *)(* (newtetlist[i]))[j];
25549 if (!isdead(&newtet)) checktet4opt(&newtet, true);
25550 }
25551 }
25552 }
25553 }
25554 } else {
25555
25556 unsupverts++;
25557
25558 replacepolygonsubs(newshlist, oldshlist);
25559
25560 for (i = 0; i < newshlist->len(); i++) {
25561 newsh = * (face *)(* newshlist)[i];
25562 shellfacedealloc(subfaces, newsh.sh);
25563 }
25564
25565 for (i = 0; i < 2; i++) {
25566 if (oldtetlist[i] != (list *) NULL) {
25567
25568 for (j = 0; j < oldtetlist[i]->len(); j++) {
25569 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25570 assert(infected(oldtet));
25571 uninfect(oldtet);
25572 }
25573
25574 if (newtetlist[i]->len() > 0) {
25575
25576 restorepolyhedron(oldtetlist[i]);
25577
25578 for (j = 0; j < newtetlist[i]->len(); j++) {
25579 newtet = * (triface *)(* (newtetlist[i]))[j];
25580
25581 if (!isdead(&newtet)) {
25582 tetrahedrondealloc(newtet.tet);
25583 }
25584 }
25585 }
25586
25587 if (newpt[i] != (point) NULL) {
25588 pointdealloc(newpt[i]);
25589 relverts--;
25590 }
25591 }
25592 }
25593 }
25594
25595
25596 delete oldshlist;
25597 delete newshlist;
25598 for (i = 0; i < 2; i++) {
25599 if (oldtetlist[i] != (list *) NULL) {
25600 delete oldtetlist[i];
25601 delete newtetlist[i];
25602 }
25603 }
25604
25605 return success;
25606 }
25607
25609
25610
25611
25612
25613
25614
25615
25616
25617
25619
25620 bool tetgenmesh::suppresssegpoint(face* supseg, list* spinshlist,
25621 list* newsegshlist, list* frontlist, list* misfrontlist, list* ptlist,
25622 list* conlist, memorypool* viri, queue* flipque, bool noreloc, bool optflag)
25623 {
25624 list **oldtetlist, **newtetlist;
25625 list **oldshlist, **newshlist;
25626 list *pnewshlist, *dnewshlist;
25627 triface oldtet, newtet;
25628 face oldsh, newsh;
25629 face startsh, spinsh, segsh1, segsh2;
25630 face nsupseg, newseg, prevseg, nextseg;
25631 point suppt, *newpt;
25632 point pa, pb, *cons;
25633 REAL pnorm[2][3], norm[3];
25634 bool success;
25635 int shmark;
25636 int n, i, j, k;
25637
25638
25639 assert(supseg->shver < 2);
25640 suppt = sdest(*supseg);
25641
25642 senext(*supseg, nsupseg);
25643 spivotself(nsupseg);
25644 assert(nsupseg.sh != dummysh);
25645 nsupseg.shver = 0;
25646 if (sorg(nsupseg) != suppt) sesymself(nsupseg);
25647 assert(sorg(nsupseg) == suppt);
25648 pa = sorg(*supseg);
25649 pb = sdest(nsupseg);
25650 if (b->verbose > 1) {
25651 printf(" Remove point %d on segment (%d, %d).\n",
25652 pointmark(suppt), pointmark(pa), pointmark(pb));
25653 }
25654
25655
25656 spivot(*supseg, startsh);
25657 spinsh = startsh;
25658 do {
25659
25660 spinshlist->append(&spinsh);
25661
25662 spivotself(spinsh);
25663 } while (spinsh.sh != startsh.sh);
25664 if (spinshlist->len() == 1) {
25665
25666
25667 spinshlist->clear();
25668 unsupverts++;
25669 return false;
25670 }
25671
25672
25673
25674 n = spinshlist->len();
25675 oldtetlist = new list*[n];
25676 newtetlist = new list*[n];
25677 oldshlist = new list*[n];
25678 newshlist = new list*[n];
25679 newpt = new point[n];
25680 for (i = 0; i < n; i++) {
25681 oldtetlist[i] = (list *) NULL;
25682 newtetlist[i] = (list *) NULL;
25683 oldshlist[i] = (list *) NULL;
25684 newshlist[i] = (list *) NULL;
25685 newpt[i] = (point) NULL;
25686 }
25687
25688
25689 makeshellface(subsegs, &newseg);
25690 setsorg(newseg, pa);
25691 setsdest(newseg, pb);
25692
25693 setshellmark(newseg, shellmark(*supseg));
25694 setshelltype(newseg, shelltype(*supseg));
25695 if (b->quality && varconstraint) {
25696
25697 setareabound(newseg, areabound(*supseg));
25698 }
25699
25700 senext2(*supseg, prevseg);
25701 spivotself(prevseg);
25702 if (prevseg.sh != dummysh) {
25703 prevseg.shver = 0;
25704 if (sdest(prevseg) != pa) sesymself(prevseg);
25705 assert(sdest(prevseg) == pa);
25706 senextself(prevseg);
25707 senext2self(newseg);
25708 sbond(newseg, prevseg);
25709 newseg.shver = 0;
25710 }
25711
25712 senext(nsupseg, nextseg);
25713 spivotself(nextseg);
25714 if (nextseg.sh != dummysh) {
25715 nextseg.shver = 0;
25716 if (sorg(nextseg) != pb) sesymself(nextseg);
25717 assert(sorg(nextseg) == pb);
25718 senext2self(nextseg);
25719 senextself(newseg);
25720 sbond(newseg, nextseg);
25721 newseg.shver = 0;
25722 }
25723
25724
25725 for (i = 0; i < spinshlist->len(); i++) {
25726 spinsh = * (face *)(* spinshlist)[i];
25727
25728 oldshlist[i] = new list(sizeof(face), NULL, 256);
25729 newshlist[i] = new list(sizeof(face), NULL, 256);
25730
25731 oldshlist[i]->append(&spinsh);
25732 formstarpolygon(suppt, oldshlist[i], ptlist);
25733
25734 for (j = 0; j < oldshlist[i]->len(); j++) {
25735 oldsh = * (face *)(* (oldshlist[i]))[j];
25736 cons = (point *) conlist->append(NULL);
25737 cons[0] = sorg(oldsh);
25738 cons[1] = sdest(oldsh);
25739 }
25740
25741 cons = (point *) conlist->append(NULL);
25742 cons[0] = pa;
25743 cons[1] = pb;
25744
25745 shmark = shellmark(spinsh);
25746 triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25747
25748 retrievenewsubs(newshlist[i], true);
25749
25750 replacepolygonsubs(oldshlist[i], newshlist[i]);
25751
25752 for (j = 0; j < newshlist[i]->len(); j++) {
25753 segsh1 = * (face *)(* (newshlist[i]))[j];
25754 for (k = 0; k < 3; k++) {
25755 if (((sorg(segsh1) == pa) && (sdest(segsh1) == pb)) ||
25756 ((sorg(segsh1) == pb) && (sdest(segsh1) == pa))) break;
25757 senextself(segsh1);
25758 }
25759 if (k < 3) break;
25760 }
25761 assert(j < newshlist[i]->len());
25762
25763 ssbond(segsh1, newseg);
25764
25765 newsegshlist->append(&segsh1);
25766
25767 ptlist->clear();
25768 conlist->clear();
25769 flipque->clear();
25770 viri->restart();
25771 }
25772
25773 for (i = 0; i < newsegshlist->len(); i++) {
25774 segsh1 = * (face *)(* newsegshlist)[i];
25775 if ((i + 1) == newsegshlist->len()) {
25776 segsh2 = * (face *)(* newsegshlist)[0];
25777 } else {
25778 segsh2 = * (face *)(* newsegshlist)[i + 1];
25779 }
25780 sbond1(segsh1, segsh2);
25781 }
25782
25783
25784 dnewshlist = new list(sizeof(face), NULL, 256);
25785 success = true;
25786
25787
25788 for (i = 0; i < spinshlist->len() && success; i++) {
25789
25790 spinsh = * (face *)(* spinshlist)[i];
25791
25792
25793 if (sorg(spinsh) != pa) sesymself(spinsh);
25794
25795 stpivot(spinsh, oldtet);
25796
25797 if (oldtet.tet == dummytet) continue;
25798
25799 oldtetlist[i] = new list(sizeof(triface), NULL, 256);
25800 newtetlist[i] = new list(sizeof(triface), NULL, 256);
25801
25802 oldtetlist[i]->append(&oldtet);
25803 formstarpolyhedron(suppt, oldtetlist[i], ptlist, false);
25804
25805 for (j = 0; j < oldtetlist[i]->len(); j++) {
25806 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25807 infect(oldtet);
25808 }
25809
25810 for (k = 0; k < 2; k++) {
25811 if ((i + k) < spinshlist->len()) {
25812 pnewshlist = newshlist[i + k];
25813 segsh1 = * (face *)(* spinshlist)[i + k];
25814 } else {
25815 pnewshlist = newshlist[0];
25816 segsh1 = * (face *)(* spinshlist)[0];
25817 }
25818
25819 if (k == 0) {
25820 if (sorg(segsh1) != pa) sesymself(segsh1);
25821 assert(sorg(segsh1) == pa);
25822 } else {
25823 if (sdest(segsh1) != pa) sesymself(segsh1);
25824 assert(sdest(segsh1) == pa);
25825 }
25826
25827 orientnewsubs(pnewshlist, &segsh1, pnorm[k]);
25828 for (j = 0; j < pnewshlist->len(); j++) {
25829 dnewshlist->append((face *)(* pnewshlist)[j]);
25830 }
25831 }
25832
25833 success = constrainedcavity(&oldtet, dnewshlist, oldtetlist[i], ptlist,
25834 frontlist, misfrontlist, newtetlist[i], flipque);
25835 if (!success && !noreloc) {
25836
25837 makepoint(&(newpt[i]));
25838 for (j = 0; j < 3; j++) norm[j] = 0.5 * (pnorm[0][j] + pnorm[1][j]);
25839 success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25840 oldtetlist[i]);
25841
25842
25843 if (success) {
25844
25845
25846 relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25847 setpointtype(newpt[i], FREEVOLVERTEX);
25848 relverts++;
25849 } else {
25850
25851 deallocfaketets(frontlist);
25852 pointdealloc(newpt[i]);
25853 newpt[i] = (point) NULL;
25854 assert(newtetlist[i]->len() == 0);
25855 }
25856 }
25857 if (!success && noreloc) {
25858
25859 deallocfaketets(frontlist);
25860 }
25861
25862 dnewshlist->clear();
25863 ptlist->clear();
25864 frontlist->clear();
25865 misfrontlist->clear();
25866 flipque->clear();
25867 }
25868
25869 if (success) {
25870
25871 setpointtype(suppt, UNUSEDVERTEX);
25872 unuverts++;
25873
25874 setpoint2sh(pa, sencode(newseg));
25875 setpoint2sh(pb, sencode(newseg));
25876
25877 shellfacedealloc(subsegs, supseg->sh);
25878 shellfacedealloc(subsegs, nsupseg.sh);
25879
25880 for (i = 0; i < spinshlist->len(); i++) {
25881 for (j = 0; j < oldshlist[i]->len(); j++) {
25882 oldsh = * (face *)(* (oldshlist[i]))[j];
25883 if (j == 0) {
25884
25885 stpivot(oldsh, oldtet);
25886 if (oldtet.tet != dummytet) {
25887 sesymself(oldsh);
25888 stpivot(oldsh, oldtet);
25889 }
25890 if (oldtet.tet == dummytet) {
25891
25892 k = oldshlist[i]->len() - newshlist[i]->len();
25893 assert(k > 0);
25894 hullsize -= k;
25895 }
25896 }
25897 shellfacedealloc(subfaces, oldsh.sh);
25898 }
25899 }
25900
25901 for (i = 0; i < spinshlist->len(); i++) {
25902
25903 if (oldtetlist[i] != (list *) NULL) {
25904 for (j = 0; j < oldtetlist[i]->len(); j++) {
25905 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25906 assert(!isdead(&oldtet));
25907 tetrahedrondealloc(oldtet.tet);
25908 }
25909 }
25910 }
25911 if (optflag) {
25912 for (i = 0; i < spinshlist->len(); i++) {
25913
25914 if (newtetlist[i] != (list *) NULL) {
25915 for (j = 0; j < newtetlist[i]->len(); j++) {
25916 newtet = * (triface *)(* (newtetlist[i]))[j];
25917 if (!isdead(&newtet)) checktet4opt(&newtet, true);
25918 }
25919 }
25920 }
25921 }
25922 } else {
25923
25924 unsupverts++;
25925
25926 senext2(*supseg, prevseg);
25927 spivotself(prevseg);
25928 if (prevseg.sh != dummysh) {
25929 prevseg.shver = 0;
25930 if (sdest(prevseg) != pa) sesymself(prevseg);
25931 assert(sdest(prevseg) == pa);
25932 senextself(prevseg);
25933 senext2self(*supseg);
25934 sbond(*supseg, prevseg);
25935 senextself(*supseg);
25936 assert(supseg->shver < 2);
25937 }
25938
25939 senext(nsupseg, nextseg);
25940 spivotself(nextseg);
25941 if (nextseg.sh != dummysh) {
25942 nextseg.shver = 0;
25943 if (sorg(nextseg) != pb) sesymself(nextseg);
25944 assert(sorg(nextseg) == pb);
25945 senext2self(nextseg);
25946 senextself(nsupseg);
25947 sbond(nsupseg, nextseg);
25948
25949 senext2self(nsupseg);
25950 assert(nsupseg.shver < 2);
25951 }
25952
25953 shellfacedealloc(subsegs, newseg.sh);
25954
25955 for (i = 0; i < spinshlist->len(); i++) {
25956 replacepolygonsubs(newshlist[i], oldshlist[i]);
25957
25958 for (j = 0; j < newshlist[i]->len(); j++) {
25959 newsh = * (face *)(* (newshlist[i]))[j];
25960 shellfacedealloc(subfaces, newsh.sh);
25961 }
25962 }
25963
25964 for (i = 0; i < spinshlist->len(); i++) {
25965 if (oldtetlist[i] != (list *) NULL) {
25966
25967 for (j = 0; j < oldtetlist[i]->len(); j++) {
25968 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25969 assert(infected(oldtet));
25970 uninfect(oldtet);
25971 }
25972
25973 if (newtetlist[i]->len() > 0) {
25974
25975 restorepolyhedron(oldtetlist[i]);
25976
25977 for (j = 0; j < newtetlist[i]->len(); j++) {
25978 newtet = * (triface *)(* (newtetlist[i]))[j];
25979
25980 if (!isdead(&newtet)) {
25981 tetrahedrondealloc(newtet.tet);
25982 }
25983 }
25984 }
25985
25986 if (newpt[i] != (point) NULL) {
25987 pointdealloc(newpt[i]);
25988 relverts--;
25989 }
25990 }
25991 }
25992 }
25993
25994
25995 delete dnewshlist;
25996 for (i = 0; i < spinshlist->len(); i++) {
25997 delete oldshlist[i];
25998 delete newshlist[i];
25999 }
26000 delete [] oldshlist;
26001 delete [] newshlist;
26002 for (i = 0; i < spinshlist->len(); i++) {
26003 if (oldtetlist[i] != (list *) NULL) {
26004 delete oldtetlist[i];
26005 delete newtetlist[i];
26006 }
26007 }
26008 delete [] oldtetlist;
26009 delete [] newtetlist;
26010
26011 newsegshlist->clear();
26012 spinshlist->clear();
26013
26014 return success;
26015 }
26016
26018
26019
26020
26021
26022
26023
26024
26025
26026
26028
26029 bool tetgenmesh::suppressvolpoint(triface* suptet, list* frontlist,
26030 list* misfrontlist, list* ptlist, queue* flipque, bool optflag)
26031 {
26032 list *myfrontlist, *mymisfrontlist, *myptlist;
26033 list *oldtetlist, *newtetlist;
26034 list *newshlist;
26035 queue *myflipque;
26036 triface oldtet, newtet;
26037 point suppt, conpt;
26038 bool success;
26039 int j;
26040
26041
26042 oldtetlist = new list(sizeof(triface), NULL, 256);
26043 newtetlist = new list(sizeof(triface), NULL, 256);
26044 newshlist = new list(sizeof(face), NULL, 256);
26045
26046 myfrontlist = mymisfrontlist = myptlist = (list *) NULL;
26047 myflipque = (queue *) NULL;
26048 if (frontlist == (list *) NULL) {
26049 myfrontlist = new list(sizeof(triface), NULL, 256);
26050 frontlist = myfrontlist;
26051 mymisfrontlist = new list(sizeof(triface), NULL, 256);
26052 misfrontlist = mymisfrontlist;
26053 myptlist = new list(sizeof(point *), NULL, 256);
26054 ptlist = myptlist;
26055 myflipque = new queue(sizeof(badface));
26056 flipque = myflipque;
26057 }
26058
26059 suppt = org(*suptet);
26060 oldtet = *suptet;
26061 success = true;
26062
26063 if (b->verbose > 1) {
26064 printf(" Remove point %d in mesh.\n", pointmark(suppt));
26065 }
26066
26067
26068 oldtetlist->append(&oldtet);
26069 formstarpolyhedron(suppt, oldtetlist, ptlist, false);
26070
26071 for (j = 0; j < oldtetlist->len(); j++) {
26072 oldtet = * (triface *)(* oldtetlist)[j];
26073 infect(oldtet);
26074 }
26075
26076 success = constrainedcavity(&oldtet, newshlist, oldtetlist, ptlist,
26077 frontlist, misfrontlist, newtetlist, flipque);
26078 if (!success) {
26079
26080 deallocfaketets(frontlist);
26081
26082 conpt = (point) NULL;
26083 assert(newtetlist->len() == 0);
26084 if (findcollapseedge(suppt, &conpt, oldtetlist, ptlist)) {
26085
26086 collapseedge(suppt, conpt, oldtetlist, newtetlist);
26087
26088 if (optflag) {
26089 assert(newtetlist->len() == 0);
26090 for (j = 0; j < oldtetlist->len(); j++) {
26091 newtet = * (triface *)(* oldtetlist)[j];
26092 newtetlist->append(&newtet);
26093 }
26094 }
26095 oldtetlist->clear();
26096 collapverts++;
26097 success = true;
26098 }
26099 }
26100 if (success) {
26101
26102 setpointtype(suppt, UNUSEDVERTEX);
26103 unuverts++;
26104 suprelverts++;
26105
26106 for (j = 0; j < oldtetlist->len(); j++) {
26107 oldtet = * (triface *)(* oldtetlist)[j];
26108 assert(!isdead(&oldtet));
26109 tetrahedrondealloc(oldtet.tet);
26110 }
26111 if (optflag) {
26112
26113 for (j = 0; j < newtetlist->len(); j++) {
26114 newtet = * (triface *)(* newtetlist)[j];
26115 if (!isdead(&newtet)) checktet4opt(&newtet, true);
26116 }
26117 }
26118 } else {
26119
26120
26121 for (j = 0; j < oldtetlist->len(); j++) {
26122 oldtet = * (triface *)(* oldtetlist)[j];
26123 assert(infected(oldtet));
26124 uninfect(oldtet);
26125 }
26126 }
26127
26128
26129 ptlist->clear();
26130 frontlist->clear();
26131 misfrontlist->clear();
26132 flipque->clear();
26133
26134 if (myfrontlist != (list *) NULL) {
26135 delete myfrontlist;
26136 delete mymisfrontlist;
26137 delete myptlist;
26138 delete myflipque;
26139 }
26140 delete oldtetlist;
26141 delete newtetlist;
26142 delete newshlist;
26143
26144 return success;
26145 }
26146
26148
26149
26150
26151
26152
26153
26154
26155
26156
26157
26158
26159
26160
26161
26163
26164 bool tetgenmesh::smoothpoint(point smthpt, point e1, point e2, list *starlist,
26165 bool invtori, REAL *key)
26166 {
26167 triface starttet;
26168 point pa, pb, pc;
26169 REAL fcent[3], startpt[3], nextpt[3], bestpt[3];
26170 REAL iniTmax, oldTmax, newTmax;
26171 REAL ori, aspT, aspTmax, imprate;
26172 REAL cosd, maxcosd;
26173 bool segflag, randflag;
26174 int numdirs;
26175 int iter, i, j;
26176
26177
26178 segflag = (e1 != (point) NULL);
26179
26180 numdirs = segflag ? 2 : starlist->len();
26181 randflag = numdirs > 10;
26182 if (randflag) {
26183 numdirs = 10;
26184 }
26185
26186 aspTmax = 0.0;
26187
26188 for (i = 0; i < starlist->len(); i++) {
26189 starttet = * (triface *)(* starlist)[i];
26190 adjustedgering(starttet, !invtori ? CCW : CW);
26191 pa = org(starttet);
26192 pb = dest(starttet);
26193 pc = apex(starttet);
26194 aspT = tetaspectratio(pa, pb, pc, smthpt);
26195 if (i == 0) {
26196 aspTmax = aspT;
26197 } else {
26198 aspTmax = aspT > aspTmax ? aspT : aspTmax;
26199 }
26200 }
26201 iniTmax = aspTmax;
26202
26203 if (b->verbose > 1) {
26204 printf(" Smooth %s point %d (%g, %g, %g).\n", segflag ? "seg" : "vol",
26205 pointmark(smthpt), smthpt[0], smthpt[1], smthpt[2]);
26206 printf(" Initial max L/h = %g.\n", iniTmax);
26207 }
26208 for (i = 0; i < 3; i++) {
26209 bestpt[i] = startpt[i] = smthpt[i];
26210 }
26211
26212
26213 newTmax = iniTmax;
26214 iter = 0;
26215 while (true) {
26216
26217 oldTmax = newTmax;
26218 for (i = 0; i < numdirs; i++) {
26219
26220 if (!segflag) {
26221 if (randflag) {
26222
26223 j = (int) randomnation(starlist->len());
26224 } else {
26225 j = i;
26226 }
26227 starttet = * (triface *)(* starlist)[j];
26228 adjustedgering(starttet, !invtori ? CCW : CW);
26229 pa = org(starttet);
26230 pb = dest(starttet);
26231 pc = apex(starttet);
26232 for (j = 0; j < 3; j++) {
26233 fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0;
26234 }
26235 } else {
26236 for (j = 0; j < 3; j++) {
26237 fcent[j] = (i == 0 ? e1[j] : e2[j]);
26238 }
26239 }
26240 for (j = 0; j < 3; j++) {
26241 nextpt[j] = startpt[j] + 0.01 * (fcent[j] - startpt[j]);
26242 }
26243
26244 for (j = 0; j < starlist->len(); j++) {
26245 starttet = * (triface *)(* starlist)[j];
26246 adjustedgering(starttet, !invtori ? CCW : CW);
26247 pa = org(starttet);
26248 pb = dest(starttet);
26249 pc = apex(starttet);
26250 ori = orient3d(pa, pb, pc, nextpt);
26251 if (ori < 0.0) {
26252 aspT = tetaspectratio(pa, pb, pc, nextpt);
26253 if (j == 0) {
26254 aspTmax = aspT;
26255 } else {
26256 aspTmax = aspT > aspTmax ? aspT : aspTmax;
26257 }
26258 } else {
26259
26260 aspTmax = newTmax;
26261 }
26262
26263 if (aspTmax >= newTmax) break;
26264 }
26265 if (aspTmax < newTmax) {
26266
26267 newTmax = aspTmax;
26268 for (j = 0; j < 3; j++) bestpt[j] = nextpt[j];
26269 }
26270 }
26271
26272 imprate = fabs(oldTmax - newTmax) / oldTmax;
26273 if (imprate < 1e-3) break;
26274
26275 for (j = 0; j < 3; j++) startpt[j] = bestpt[j];
26276 iter++;
26277 }
26278
26279 if (iter > 0) {
26280
26281 if (key) {
26282
26283 maxcosd = 0.0;
26284 for (j = 0; j < starlist->len(); j++) {
26285 starttet = * (triface *)(* starlist)[j];
26286 adjustedgering(starttet, !invtori ? CCW : CW);
26287 pa = org(starttet);
26288 pb = dest(starttet);
26289 pc = apex(starttet);
26290 tetalldihedral(pa, pb, pc, startpt, NULL, &cosd, NULL);
26291 if (cosd < *key) {
26292
26293 iter = 0; break;
26294 } else {
26295
26296 maxcosd = maxcosd < cosd ? maxcosd : cosd;
26297 }
26298 }
26299 if (iter > 0) *key = maxcosd;
26300 }
26301 }
26302
26303 if (iter > 0) {
26304 segflag ? smoothsegverts++ : smoothvolverts++;
26305 for (i = 0; i < 3; i++) smthpt[i] = startpt[i];
26306 if (b->verbose > 1) {
26307 printf(" Move to new location (%g, %g, %g).\n", smthpt[0], smthpt[1],
26308 smthpt[2]);
26309 printf(" Final max L/h = %g. (%d iterations)\n", newTmax, iter);
26310 if (key) {
26311 printf(" Max. dihed = %g (degree).\n", acos(*key) / PI * 180.0);
26312 }
26313 }
26314 return true;
26315 } else {
26316 if (b->verbose > 1) {
26317 printf(" Not smoothed.\n");
26318 }
26319 return false;
26320 }
26321 }
26322
26324
26325
26326
26328
26329 void tetgenmesh::removesteiners(bool coarseflag)
26330 {
26331 list *frontlist, *misfrontlist;
26332 list *spinshlist, *newsegshlist;
26333 list *ptlist, *conlist;
26334 memorypool *viri;
26335 queue *flipque;
26336 triface checktet;
26337 face shloop;
26338 face segloop, nextseg;
26339 point pa, neipt;
26340 REAL len;
26341 bool remflag;
26342 int *worklist;
26343 int oldnum, rmstein;
26344 int i, j;
26345
26346 if (!b->quiet) {
26347 if (!coarseflag) {
26348 printf("Removing Steiner points.\n");
26349 } else {
26350 printf("Coarsening mesh.\n");
26351 }
26352 }
26353
26354
26355 frontlist = new list(sizeof(triface), NULL);
26356 misfrontlist = new list(sizeof(triface), NULL);
26357 spinshlist = new list(sizeof(face), NULL);
26358 newsegshlist = new list(sizeof(face), NULL);
26359 ptlist = new list(sizeof(point *), NULL);
26360 conlist = new list(sizeof(point *) * 2, NULL);
26361 flipque = new queue(sizeof(badface));
26362 viri = new memorypool(sizeof(shellface *), 1024, POINTER, 0);
26363 oldnum = unuverts;
26364 relverts = suprelverts = collapverts = unsupverts;
26365 smoothvolverts = 0;
26366 expcavcount = 0;
26367
26368
26369 do {
26370 rmstein = unuverts;
26371 subfaces->traversalinit();
26372 shloop.sh = shellfacetraverse(subfaces);
26373 while (shloop.sh != (shellface *) NULL) {
26374 remflag = false;
26375
26376 shloop.shver = 0;
26377 for (i = 0; i < 3; i++) {
26378 pa = sapex(shloop);
26379 if (pointtype(pa) == FREESUBVERTEX) {
26380 if (!coarseflag) {
26381
26382 j = pointmark(pa) - in->firstnumber;
26383 if (j >= in->numberofpoints) {
26384 if (b->nobisect == 1) {
26385
26386 stpivot(shloop, checktet);
26387 if (checktet.tet != dummytet) {
26388 sesymself(shloop);
26389 stpivot(shloop, checktet);
26390 }
26391 remflag = (checktet.tet == dummytet);
26392 } else {
26393
26394 remflag = true;
26395 }
26396 }
26397 } else {
26398
26399 if (b->nobisect == 0) {
26400
26401 if (b->metric) {
26402
26403
26404 spinshlist->append(&shloop);
26405 formstarpolygon(pa, spinshlist, ptlist);
26406 len = 0.0;
26407 for (j = 0; j < ptlist->len(); j++) {
26408 neipt = * (point *)(* ptlist)[j];
26409 len += distance(pa, neipt);
26410 }
26411 len /= ptlist->len();
26412
26413 remflag = len < pa[pointmtrindex];
26414 spinshlist->clear();
26415 ptlist->clear();
26416 } else {
26417
26418
26419 remflag = true;
26420 j = pointmark(pa) - in->firstnumber;
26421 if (j < in->numberofpoints) {
26422 remflag = (in->pointmarkerlist[j] == 0);
26423 }
26424 }
26425 }
26426 }
26427 if (remflag) break;
26428 }
26429 senextself(shloop);
26430 }
26431 if (remflag) {
26432 suppressfacetpoint(&shloop, frontlist, misfrontlist, ptlist, conlist,
26433 viri, flipque, coarseflag, false);
26434 }
26435 shloop.sh = shellfacetraverse(subfaces);
26436 }
26437
26438 } while (unuverts > rmstein);
26439
26440 if (coarseflag) {
26441 shellface **segsperverlist;
26442 int *idx2seglist;
26443 face seg1, seg2;
26444 point e1, e2;
26445
26446
26447 makesegmentmap(idx2seglist, segsperverlist);
26448 subsegs->traversalinit();
26449 segloop.sh = shellfacetraverse(subsegs);
26450 while (segloop.sh != (shellface *) NULL) {
26451 for (i = 0; i < 2; i++) {
26452 segloop.shver = i;
26453 senext(segloop, nextseg);
26454 spivotself(nextseg);
26455 if ((nextseg.sh == dummysh) || (nextseg.sh > segloop.sh)) {
26456
26457 pa = sdest(segloop);
26458 j = pointmark(pa) - in->firstnumber;
26459 if (idx2seglist[j + 1] - idx2seglist[j] == 2) {
26460
26461 nextseg.sh = segsperverlist[idx2seglist[j]];
26462 if (nextseg.sh == segloop.sh) {
26463 nextseg.sh = segsperverlist[idx2seglist[j] + 1];
26464 }
26465 nextseg.shver = 0;
26466 if (sorg(nextseg) != pa) sesymself(nextseg);
26467
26468 e1 = sorg(segloop);
26469 e2 = sdest(nextseg);
26470 if (iscollinear(e1, pa, e2, b->epsilon)) {
26471
26472 if (b->verbose > 1) {
26473 printf(" Glue two insegs (%d, %d) at %d.\n", pointmark(e1),
26474 pointmark(e2), pointmark(pa));
26475 }
26476 senext(segloop, seg1);
26477 senext2(nextseg, seg2);
26478 sbond(seg1, seg2);
26479 }
26480 }
26481 }
26482 }
26483 segloop.sh = shellfacetraverse(subsegs);
26484 }
26485 delete [] segsperverlist;
26486 delete [] idx2seglist;
26487 }
26488
26489
26490 do {
26491 rmstein = unuverts;
26492 subsegs->traversalinit();
26493 segloop.sh = shellfacetraverse(subsegs);
26494 while (segloop.sh != (shellface *) NULL) {
26495 remflag = false;
26496
26497
26498
26499 segloop.shver = 0;
26500 senext(segloop, nextseg);
26501 spivotself(nextseg);
26502 if (nextseg.sh != dummysh) {
26503 pa = sdest(segloop);
26504 nextseg.shver = 0;
26505 if (sorg(nextseg) != pa) sesymself(nextseg);
26506 assert(sorg(nextseg) == pa);
26507 if (!coarseflag) {
26508
26509 j = pointmark(pa) - in->firstnumber;
26510 if (j >= in->numberofpoints) {
26511 if (b->nobisect == 1) {
26512
26513 sstpivot(&segloop, &checktet);
26514 assert(checktet.tet != dummytet);
26515 pa = apex(checktet);
26516 do {
26517 if (!fnextself(checktet)) {
26518
26519 remflag = true; break;
26520 }
26521 } while (pa != apex(checktet));
26522 } else {
26523
26524 remflag = true;
26525 }
26526 }
26527 } else {
26528
26529 if (b->nobisect == 0) {
26530 if (b->metric) {
26531
26532 len = 0.0;
26533 neipt = sorg(segloop);
26534 for (j = 0; j < 2; j++) {
26535 len += distance(pa, neipt);
26536
26537
26538
26539
26540
26541 neipt = sdest(nextseg);
26542 }
26543 len /= 2.0;
26544
26545 remflag = len < pa[pointmtrindex];
26546 } else {
26547
26548
26549 remflag = true;
26550 j = pointmark(pa) - in->firstnumber;
26551 if (j < in->numberofpoints) {
26552 remflag = (in->pointmarkerlist[j] == 0);
26553 }
26554 }
26555 }
26556 }
26557 }
26558
26559
26560 if (remflag) {
26561 suppresssegpoint(&segloop, spinshlist, newsegshlist, frontlist,
26562 misfrontlist, ptlist, conlist, viri, flipque, coarseflag, false);
26563 }
26564 segloop.sh = shellfacetraverse(subsegs);
26565 }
26566
26567 } while (unuverts > rmstein);
26568
26569 if ((relverts > 0) || coarseflag) {
26570 worklist = new int[points->items + 1];
26571
26572 do {
26573
26574
26575 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26576 rmstein = unuverts;
26577 tetrahedrons->traversalinit();
26578 checktet.tet = tetrahedrontraverse();
26579 while (checktet.tet != (tetrahedron *) NULL) {
26580 remflag = false;
26581 for (i = 0; i < 4; i++) {
26582 pa = (point) checktet.tet[4 + i];
26583 if (pointtype(pa) == FREEVOLVERTEX) {
26584
26585
26586
26587
26588
26589
26590 if (worklist[pointmark(pa)] < 3) {
26591 worklist[pointmark(pa)]++;
26592 if (!coarseflag) {
26593
26594 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26595 remflag = true;
26596 }
26597 } else {
26598 if (b->metric) {
26599
26600
26601 frontlist->append(&checktet);
26602 formstarpolyhedron(pa, frontlist, ptlist, true);
26603 len = 0.0;
26604 for (j = 0; j < ptlist->len(); j++) {
26605 neipt = * (point *)(* ptlist)[j];
26606 len += distance(pa, neipt);
26607 }
26608 len /= ptlist->len();
26609
26610 remflag = len < pa[pointmtrindex];
26611 frontlist->clear();
26612 ptlist->clear();
26613 } else {
26614
26615
26616 remflag = true;
26617 j = pointmark(pa) - in->firstnumber;
26618 if (j < in->numberofpoints) {
26619 remflag = (in->pointmarkerlist[j] == 0);
26620 }
26621 }
26622 }
26623 if (remflag) break;
26624 }
26625 }
26626 }
26627 if (remflag) {
26628 findorg(&checktet, pa);
26629 assert(org(checktet) == pa);
26630 suppressvolpoint(&checktet, frontlist, misfrontlist, ptlist, flipque,
26631 false);
26632 }
26633 checktet.tet = tetrahedrontraverse();
26634 }
26635
26636 } while (unuverts > rmstein);
26637
26638
26639
26640 if (!coarseflag && (relverts > suprelverts)) {
26641 if (b->verbose) {
26642 printf(" Smoothing relocated points.\n");
26643 }
26644 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26645 tetrahedrons->traversalinit();
26646 checktet.tet = tetrahedrontraverse();
26647 while (checktet.tet != (tetrahedron *) NULL) {
26648 for (i = 0; i < 4; i++) {
26649 pa = (point) checktet.tet[4 + i];
26650 if (pointtype(pa) == FREEVOLVERTEX) {
26651 if (worklist[pointmark(pa)] == 0) {
26652 worklist[pointmark(pa)] = 1;
26653 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26654
26655 findorg(&checktet, pa);
26656 frontlist->append(&checktet);
26657 formstarpolyhedron(pa, frontlist, NULL, false);
26658 smoothpoint(pa, NULL, NULL, frontlist, false, NULL);
26659 frontlist->clear();
26660 }
26661 }
26662 }
26663 }
26664 checktet.tet = tetrahedrontraverse();
26665 }
26666 }
26667 delete [] worklist;
26668 }
26669
26670 if (b->verbose > 0) {
26671 if (!coarseflag) {
26672 printf(" %d points removed from boundary", unuverts - oldnum);
26673 if (expcavcount > 0) {
26674 printf(" (%d cavity corrections)", expcavcount);
26675 }
26676 printf("\n");
26677 if (relverts > 0) {
26678 printf(" %d points relocated (%d suppressed, %d collapsed).\n",
26679 relverts, suprelverts - collapverts, collapverts);
26680 if (smoothvolverts > 0) {
26681 printf(" %d points are smoothed.\n", smoothvolverts);
26682 }
26683 }
26684 if (unsupverts > 0) {
26685 printf(" !! %d points are unsuppressed.\n", unsupverts);
26686 }
26687 } else {
26688 printf(" %d points are removed.\n", unuverts - oldnum);
26689 }
26690 }
26691
26692
26693 delete frontlist;
26694 delete misfrontlist;
26695 delete spinshlist;
26696 delete newsegshlist;
26697 delete ptlist;
26698 delete conlist;
26699 delete flipque;
26700 delete viri;
26701 }
26702
26703
26704
26705
26706
26708
26709
26710
26711
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
26743
26744 long tetgenmesh::reconstructmesh()
26745 {
26746 tetrahedron **tetsperverlist;
26747 shellface **facesperverlist;
26748 triface tetloop, neightet, neineightet, spintet;
26749 face subloop, neighsh, neineighsh, subseg;
26750 face sface1, sface2;
26751 point *idx2verlist;
26752 point torg, tdest, tapex, toppo;
26753 point norg, ndest, napex;
26754 list *neighshlist, *markerlist;
26755 REAL sign, attrib, volume;
26756 REAL da1, da2;
26757 bool bondflag, insertsegflag;
26758 int *idx2tetlist;
26759 int *idx2facelist;
26760 int *worklist;
26761 int facetidx, marker;
26762 int iorg, idest, iapex, ioppo;
26763 int inorg, indest, inapex;
26764 int index, i, j;
26765
26766 if (!b->quiet) {
26767 printf("Reconstructing mesh.\n");
26768 }
26769
26770
26771 makeindex2pointmap(idx2verlist);
26772
26773
26774 for (i = 0; i < in->numberoftetrahedra; i++) {
26775
26776
26777 maketetrahedron(&tetloop);
26778 index = i * in->numberofcorners;
26779
26780 iorg = in->tetrahedronlist[index] - in->firstnumber;
26781 idest = in->tetrahedronlist[index + 1] - in->firstnumber;
26782 iapex = in->tetrahedronlist[index + 2] - in->firstnumber;
26783 ioppo = in->tetrahedronlist[index + 3] - in->firstnumber;
26784 torg = idx2verlist[iorg];
26785 tdest = idx2verlist[idest];
26786 tapex = idx2verlist[iapex];
26787 toppo = idx2verlist[ioppo];
26788 sign = orient3d(torg, tdest, tapex, toppo);
26789 if (sign > 0.0) {
26790 norg = torg; torg = tdest; tdest = norg;
26791 } else if (sign == 0.0) {
26792 if (!b->quiet) {
26793 printf("Warning: Tet %d is degenerate.\n", i + in->firstnumber);
26794 }
26795 }
26796 setorg(tetloop, torg);
26797 setdest(tetloop, tdest);
26798 setapex(tetloop, tapex);
26799 setoppo(tetloop, toppo);
26800
26801
26802 setpointtype(torg, FREEVOLVERTEX);
26803 setpointtype(tdest, FREEVOLVERTEX);
26804 setpointtype(tapex, FREEVOLVERTEX);
26805 setpointtype(toppo, FREEVOLVERTEX);
26806
26807 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
26808 index = i * in->numberoftetrahedronattributes;
26809 attrib = in->tetrahedronattributelist[index + j];
26810 setelemattribute(tetloop.tet, j, attrib);
26811 }
26812
26813
26814 if (b->varvolume) {
26815 if (in->tetrahedronvolumelist != (REAL *) NULL) {
26816 volume = in->tetrahedronvolumelist[i];
26817 } else {
26818 volume = -1.0;
26819 }
26820 setvolumebound(tetloop.tet, volume);
26821 }
26822 }
26823
26824
26825 hullsize = 0l;
26826
26827 maketetrahedronmap(idx2tetlist, tetsperverlist);
26828
26829 worklist = new int[points->items];
26830 for (i = 0; i < points->items; i++) worklist[i] = 0;
26831
26832
26833 tetrahedrons->traversalinit();
26834 tetloop.tet = tetrahedrontraverse();
26835 while (tetloop.tet != (tetrahedron *) NULL) {
26836
26837 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26838 sym(tetloop, neightet);
26839 if (neightet.tet != dummytet) continue;
26840 torg = org(tetloop);
26841 tdest = dest(tetloop);
26842 tapex = apex(tetloop);
26843 iorg = pointmark(torg) - in->firstnumber;
26844 idest = pointmark(tdest) - in->firstnumber;
26845 iapex = pointmark(tapex) - in->firstnumber;
26846 worklist[iorg] = 1;
26847 worklist[idest] = 1;
26848 worklist[iapex] = 1;
26849 bondflag = false;
26850
26851 for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26852 j++) {
26853 if (tetsperverlist[j] == tetloop.tet) continue;
26854 neightet.tet = tetsperverlist[j];
26855 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26856 sym(neightet, neineightet);
26857 if (neineightet.tet == dummytet) {
26858 norg = org(neightet);
26859 ndest = dest(neightet);
26860 napex = apex(neightet);
26861 inorg = pointmark(norg) - in->firstnumber;
26862 indest = pointmark(ndest) - in->firstnumber;
26863 inapex = pointmark(napex) - in->firstnumber;
26864 if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26865
26866 bond(tetloop, neightet);
26867 bondflag = true;
26868 break;
26869 }
26870 }
26871 }
26872 }
26873 if (!bondflag) {
26874 hullsize++;
26875
26876 dummytet[0] = encode(tetloop);
26877 if ((in->pointmarkerlist != (int *) NULL) && !b->coarse) {
26878
26879 if (in->pointmarkerlist[iorg] == 0) {
26880 in->pointmarkerlist[iorg] = 1;
26881 }
26882 if (in->pointmarkerlist[idest] == 0) {
26883 in->pointmarkerlist[idest] = 1;
26884 }
26885 if (in->pointmarkerlist[iapex] == 0) {
26886 in->pointmarkerlist[iapex] = 1;
26887 }
26888 }
26889 }
26890 worklist[iorg] = 0;
26891 worklist[idest] = 0;
26892 worklist[iapex] = 0;
26893 }
26894 tetloop.tet = tetrahedrontraverse();
26895 }
26896
26897
26898
26899
26900
26901
26902
26903 if (in->trifacelist != (int *) NULL) {
26904
26905 for (i = 0; i < in->numberoftrifaces; i++) {
26906 index = i * 3;
26907 iorg = in->trifacelist[index] - in->firstnumber;
26908 idest = in->trifacelist[index + 1] - in->firstnumber;
26909 iapex = in->trifacelist[index + 2] - in->firstnumber;
26910
26911 worklist[iorg] = 1;
26912 worklist[idest] = 1;
26913 worklist[iapex] = 1;
26914 bondflag = false;
26915
26916 for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26917 j++) {
26918 neightet.tet = tetsperverlist[j];
26919 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26920 norg = org(neightet);
26921 ndest = dest(neightet);
26922 napex = apex(neightet);
26923 inorg = pointmark(norg) - in->firstnumber;
26924 indest = pointmark(ndest) - in->firstnumber;
26925 inapex = pointmark(napex) - in->firstnumber;
26926 if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26927 bondflag = true;
26928 break;
26929 }
26930 }
26931 }
26932 if (bondflag) {
26933
26934 makeshellface(subfaces, &subloop);
26935 torg = idx2verlist[iorg];
26936 tdest = idx2verlist[idest];
26937 tapex = idx2verlist[iapex];
26938 setsorg(subloop, torg);
26939 setsdest(subloop, tdest);
26940 setsapex(subloop, tapex);
26941
26942
26943 setpointtype(torg, FREESUBVERTEX);
26944 setpointtype(tdest, FREESUBVERTEX);
26945 setpointtype(tapex, FREESUBVERTEX);
26946 if (in->trifacemarkerlist != (int *) NULL) {
26947 setshellmark(subloop, in->trifacemarkerlist[i]);
26948 }
26949 adjustedgering(neightet, CCW);
26950 findedge(&subloop, org(neightet), dest(neightet));
26951 tsbond(neightet, subloop);
26952 sym(neightet, neineightet);
26953 if (neineightet.tet != dummytet) {
26954 sesymself(subloop);
26955 tsbond(neineightet, subloop);
26956 }
26957 } else {
26958 if (!b->quiet) {
26959 printf("Warning: Subface %d is discarded.\n", i + in->firstnumber);
26960 }
26961 }
26962 worklist[iorg] = 0;
26963 worklist[idest] = 0;
26964 worklist[iapex] = 0;
26965 }
26966 }
26967
26968
26969 tetrahedrons->traversalinit();
26970 tetloop.tet = tetrahedrontraverse();
26971 while (tetloop.tet != (tetrahedron *) NULL) {
26972
26973 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26974 tspivot(tetloop, subloop);
26975 if (subloop.sh != dummysh) continue;
26976 bondflag = false;
26977 sym(tetloop, neightet);
26978 if (neightet.tet == dummytet) {
26979
26980 bondflag = true;
26981 } else {
26982
26983
26984 if (in->numberoftetrahedronattributes > 0) {
26985 if (elemattribute(neightet.tet,
26986 in->numberoftetrahedronattributes - 1) !=
26987 elemattribute(tetloop.tet,
26988 in->numberoftetrahedronattributes - 1)) {
26989 bondflag = true;
26990 }
26991 }
26992 }
26993 if (bondflag) {
26994 adjustedgering(tetloop, CCW);
26995 makeshellface(subfaces, &subloop);
26996 torg = org(tetloop);
26997 tdest = dest(tetloop);
26998 tapex = apex(tetloop);
26999 setsorg(subloop, torg);
27000 setsdest(subloop, tdest);
27001 setsapex(subloop, tapex);
27002
27003
27004 setpointtype(torg, FREESUBVERTEX);
27005 setpointtype(tdest, FREESUBVERTEX);
27006 setpointtype(tapex, FREESUBVERTEX);
27007 tsbond(tetloop, subloop);
27008 if (neightet.tet != dummytet) {
27009 sesymself(subloop);
27010 tsbond(neightet, subloop);
27011 }
27012 }
27013 }
27014 tetloop.tet = tetrahedrontraverse();
27015 }
27016
27017
27018
27019
27020 neighshlist = new list(sizeof(face), NULL);
27021
27022 makesubfacemap(idx2facelist, facesperverlist);
27023
27024
27025 subfaces->traversalinit();
27026 subloop.sh = shellfacetraverse(subfaces);
27027 while (subloop.sh != (shellface *) NULL) {
27028 for (i = 0; i < 3; i++) {
27029 spivot(subloop, neighsh);
27030 if (neighsh.sh == dummysh) {
27031
27032 torg = sorg(subloop);
27033 tdest = sdest(subloop);
27034 tapex = sapex(subloop);
27035 neighshlist->append(&subloop);
27036 iorg = pointmark(torg) - in->firstnumber;
27037
27038 for (j = idx2facelist[iorg]; j < idx2facelist[iorg + 1]; j++) {
27039 neighsh.sh = facesperverlist[j];
27040 if (neighsh.sh == subloop.sh) continue;
27041 neighsh.shver = 0;
27042 if (isfacehasedge(&neighsh, torg, tdest)) {
27043 findedge(&neighsh, torg, tdest);
27044
27045 if (neighshlist->len() < 2) {
27046 neighshlist->append(&neighsh);
27047 } else {
27048 for (index = 0; index < neighshlist->len() - 1; index++) {
27049 sface1 = * (face *)(* neighshlist)[index];
27050 sface2 = * (face *)(* neighshlist)[index + 1];
27051 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(neighsh));
27052 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
27053 if (da1 < da2) {
27054 break;
27055 }
27056 }
27057 neighshlist->insert(index + 1, &neighsh);
27058 }
27059 }
27060 }
27061
27062 if (neighshlist->len() > 1) {
27063 neighsh = * (face *)(* neighshlist)[0];
27064 for (j = 1; j <= neighshlist->len(); j++) {
27065 if (j < neighshlist->len()) {
27066 neineighsh = * (face *)(* neighshlist)[j];
27067 } else {
27068 neineighsh = * (face *)(* neighshlist)[0];
27069 }
27070 sbond1(neighsh, neineighsh);
27071 neighsh = neineighsh;
27072 }
27073 } else {
27074
27075 sbond(subloop, subloop);
27076 }
27077 neighshlist->clear();
27078 }
27079 senextself(subloop);
27080 }
27081 subloop.sh = shellfacetraverse(subfaces);
27082 }
27083
27084
27085 marker = 1;
27086 subfaces->traversalinit();
27087 subloop.sh = shellfacetraverse(subfaces);
27088 while (subloop.sh != (shellface *) NULL) {
27089 for (i = 0; i < 3; i++) {
27090 sspivot(subloop, subseg);
27091 if (subseg.sh == dummysh) {
27092
27093 torg = sorg(subloop);
27094 tdest = sdest(subloop);
27095 tapex = sapex(subloop);
27096 spivot(subloop, neighsh);
27097 spivot(neighsh, neineighsh);
27098 insertsegflag = false;
27099 if (subloop.sh == neighsh.sh || subloop.sh != neineighsh.sh) {
27100
27101
27102 insertsegflag = true;
27103 } else {
27104
27105 #ifdef SELF_CHECK
27106 assert(subloop.sh != neighsh.sh);
27107 #endif
27108 napex = sapex(neighsh);
27109 sign = orient3d(torg, tdest, tapex, napex);
27110 if (iscoplanar(torg, tdest, tapex, napex, sign, b->epsilon)) {
27111
27112
27113 insertsegflag = (shellmark(subloop) != shellmark(neighsh));
27114 } else {
27115
27116 insertsegflag = true;
27117 }
27118 }
27119 if (insertsegflag) {
27120
27121 makeshellface(subsegs, &subseg);
27122 setsorg(subseg, torg);
27123 setsdest(subseg, tdest);
27124
27125
27126 setpointtype(torg, NACUTEVERTEX);
27127 setpointtype(tdest, NACUTEVERTEX);
27128 setshellmark(subseg, marker);
27129 marker++;
27130
27131 neighsh = subloop;
27132 do {
27133 ssbond(neighsh, subseg);
27134 spivotself(neighsh);
27135 } while (neighsh.sh != subloop.sh);
27136 }
27137 }
27138 senextself(subloop);
27139 }
27140 subloop.sh = shellfacetraverse(subfaces);
27141 }
27142
27143 insegments = subsegs->items;
27144
27145
27146
27147 markerlist = new list((char*)"int");
27148
27149 subfaces->traversalinit();
27150 subloop.sh = shellfacetraverse(subfaces);
27151 while (subloop.sh != (shellface *) NULL) {
27152
27153 if (!sinfected(subloop)) {
27154
27155 marker = shellmark(subloop);
27156 markerlist->append(&marker);
27157 facetidx = markerlist->len();
27158 setshellmark(subloop, facetidx);
27159 sinfect(subloop);
27160 neighshlist->append(&subloop);
27161
27162 for (i = 0; i < neighshlist->len(); i++) {
27163 neighsh = * (face *) (* neighshlist)[i];
27164 for (j = 0; j < 3; j++) {
27165 sspivot(neighsh, subseg);
27166 if (subseg.sh == dummysh) {
27167 spivot(neighsh, neineighsh);
27168 if (!sinfected(neineighsh)) {
27169
27170 #ifdef SELF_CHECK
27171 assert(shellmark(neineighsh) == marker);
27172 #endif
27173 setshellmark(neineighsh, facetidx);
27174 sinfect(neineighsh);
27175 neighshlist->append(&neineighsh);
27176 }
27177 }
27178 senextself(neighsh);
27179 }
27180 }
27181 neighshlist->clear();
27182 }
27183 subloop.sh = shellfacetraverse(subfaces);
27184 }
27185
27186 subfaces->traversalinit();
27187 subloop.sh = shellfacetraverse(subfaces);
27188 while (subloop.sh != (shellface *) NULL) {
27189 #ifdef SELF_CHECK
27190 assert(sinfected(subloop));
27191 #endif
27192 suninfect(subloop);
27193 subloop.sh = shellfacetraverse(subfaces);
27194 }
27195
27196 in->numberoffacets = markerlist->len();
27197 in->facetmarkerlist = new int[in->numberoffacets];
27198 for (i = 0; i < in->numberoffacets; i++) {
27199 marker = * (int *) (* markerlist)[i];
27200 in->facetmarkerlist[i] = marker;
27201 }
27202
27203 facetabovepointarray = new point[in->numberoffacets + 1];
27204 for (i = 0; i < in->numberoffacets + 1; i++) {
27205 facetabovepointarray[i] = (point) NULL;
27206 }
27207
27208
27209 checksubfaces = 1;
27210
27211 nonconvex = 1;
27212
27213
27214 if (checkpbcs) {
27215 tetgenio::pbcgroup *pg;
27216 pbcdata *pd;
27217
27218 createsubpbcgrouptable();
27219
27220 for (i = 0; i < in->numberofpbcgroups; i++) {
27221 pg = &(in->pbcgrouplist[i]);
27222 pd = &(subpbcgrouptable[i]);
27223
27224 for (j = 0; j < 2; j++) {
27225 subfaces->traversalinit();
27226 subloop.sh = shellfacetraverse(subfaces);
27227 while (subloop.sh != (shellface *) NULL) {
27228 facetidx = shellmark(subloop);
27229 marker = in->facetmarkerlist[facetidx - 1];
27230 if (marker == pd->fmark[j]) {
27231 setshellpbcgroup(subloop, i);
27232 pd->ss[j] = subloop;
27233 }
27234 subloop.sh = shellfacetraverse(subfaces);
27235 }
27236 }
27237 if (pg->pointpairlist != (int *) NULL) {
27238
27239 for (j = 0; j < pg->numberofpointpairs; j++) {
27240 iorg = pg->pointpairlist[j * 2] - in->firstnumber;
27241 idest = pg->pointpairlist[j * 2 + 1] - in->firstnumber;
27242 torg = idx2verlist[iorg];
27243 tdest = idx2verlist[idest];
27244 setpoint2pbcpt(torg, tdest);
27245 setpoint2pbcpt(tdest, torg);
27246 }
27247 }
27248 }
27249
27250 createsegpbcgrouptable();
27251 }
27252
27253 delete markerlist;
27254 delete neighshlist;
27255 delete [] worklist;
27256 delete [] idx2tetlist;
27257 delete [] tetsperverlist;
27258 delete [] idx2facelist;
27259 delete [] facesperverlist;
27260 delete [] idx2verlist;
27261
27262 return hullsize;
27263 }
27264
27266
27267
27268
27270
27271 void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
27272 {
27273 queue *flipqueue;
27274 triface searchtet;
27275 face checksh, checkseg;
27276 point newpoint;
27277 enum locateresult loc;
27278 REAL *attr;
27279 bool insertflag;
27280 int covertices, outvertices;
27281 int index;
27282 int i, j;
27283
27284 if (!b->quiet) {
27285 printf("Insert additional points into mesh.\n");
27286 }
27287
27288 flipqueue = new queue(sizeof(badface));
27289 recenttet.tet = dummytet;
27290 covertices = outvertices = 0;
27291
27292 index = 0;
27293 for (i = 0; i < addio->numberofpoints; i++) {
27294
27295 makepoint(&newpoint);
27296 newpoint[0] = addio->pointlist[index++];
27297 newpoint[1] = addio->pointlist[index++];
27298 newpoint[2] = addio->pointlist[index++];
27299
27300 if ((addio->numberofpointattributes > 0) &&
27301 (in->numberofpointattributes > 0)) {
27302 attr = addio->pointattributelist + addio->numberofpointattributes * i;
27303 for (j = 0; j < in->numberofpointattributes; j++) {
27304 if (j < addio->numberofpointattributes) {
27305 newpoint[3 + j] = attr[j];
27306 }
27307 }
27308 }
27309
27310 searchtet = recenttet;
27311 loc = locate(newpoint, &searchtet);
27312 if (loc != ONVERTEX) {
27313 loc = adjustlocate(newpoint, &searchtet, loc, b->epsilon2);
27314 }
27315 if (loc == OUTSIDE) {
27316 loc = hullwalk(newpoint, &searchtet);
27317 if (loc == OUTSIDE) {
27318
27319 tetrahedrons->traversalinit();
27320 searchtet.tet = tetrahedrontraverse();
27321 while (searchtet.tet != (tetrahedron *) NULL) {
27322 loc = adjustlocate(newpoint, &searchtet, OUTSIDE, b->epsilon2);
27323 if (loc != OUTSIDE) break;
27324 searchtet.tet = tetrahedrontraverse();
27325 }
27326 }
27327 }
27328
27329 insertflag = true;
27330 switch (loc) {
27331 case INTETRAHEDRON:
27332 setpointtype(newpoint, FREEVOLVERTEX);
27333 splittetrahedron(newpoint, &searchtet, flipqueue);
27334 break;
27335 case ONFACE:
27336 tspivot(searchtet, checksh);
27337 if (checksh.sh != dummysh) {
27338
27339 if (b->nobisect) {
27340 insertflag = false;
27341 } else {
27342 setpointtype(newpoint, FREESUBVERTEX);
27343 }
27344 } else {
27345 setpointtype(newpoint, FREEVOLVERTEX);
27346 }
27347 if (insertflag) {
27348 splittetface(newpoint, &searchtet, flipqueue);
27349 }
27350 break;
27351 case ONEDGE:
27352 tsspivot(&searchtet, &checkseg);
27353 if (checkseg.sh != dummysh) {
27354 if (b->nobisect) {
27355 insertflag = false;
27356 } else {
27357 setpointtype(newpoint, FREESEGVERTEX);
27358 setpoint2sh(newpoint, sencode(checkseg));
27359 }
27360 } else {
27361 tspivot(searchtet, checksh);
27362 if (checksh.sh != dummysh) {
27363 if (b->nobisect) {
27364 insertflag = false;
27365 } else {
27366 setpointtype(newpoint, FREESUBVERTEX);
27367 }
27368 } else {
27369 setpointtype(newpoint, FREEVOLVERTEX);
27370 }
27371 }
27372 if (insertflag) {
27373 splittetedge(newpoint, &searchtet, flipqueue);
27374 }
27375 break;
27376 case ONVERTEX:
27377 insertflag = false;
27378 covertices++;
27379 break;
27380 case OUTSIDE:
27381 insertflag = false;
27382 outvertices++;
27383 break;
27384 }
27385
27386 recenttet = searchtet;
27387 if (!insertflag) {
27388 pointdealloc(newpoint);
27389 } else {
27390 flip(flipqueue, NULL);
27391 }
27392 }
27393
27394 if (b->verbose) {
27395 if (covertices > 0) {
27396 printf(" %d constrained points already exist.\n", covertices);
27397 }
27398 if (outvertices > 0) {
27399 printf(" %d constrained points lie outside the mesh.\n", outvertices);
27400 }
27401 printf(" %d constrained points have been inserted.\n",
27402 addio->numberofpoints - covertices - outvertices);
27403 }
27404
27405 delete flipqueue;
27406 }
27407
27409
27410
27411
27412
27413
27414
27416
27417 bool tetgenmesh::p1interpolatebgm(point pt, triface* bgmtet, long *scount)
27418 {
27419 point bgmpt[4];
27420 enum locateresult loc;
27421 REAL vol, volpt[4], weights[4];
27422 int i;
27423
27424 loc = bgm->preciselocate(pt, bgmtet, bgm->tetrahedrons->items);
27425 if (loc == OUTSIDE) {
27426 loc = bgm->hullwalk(pt, bgmtet);
27427 if (loc == OUTSIDE) {
27428
27429 if (b->verbose) {
27430 printf("Warning: Global point location.\n");
27431 }
27432 if (scount) (*scount)++;
27433 bgm->tetrahedrons->traversalinit();
27434 bgmtet->tet = bgm->tetrahedrontraverse();
27435 while (bgmtet->tet != (tetrahedron *) NULL) {
27436 loc = bgm->adjustlocate(pt, bgmtet, OUTSIDE, b->epsilon);
27437 if (loc != OUTSIDE) break;
27438 bgmtet->tet = bgm->tetrahedrontraverse();
27439 }
27440 }
27441 }
27442 if (loc != OUTSIDE) {
27443
27444 setpoint2bgmtet(pt, encode(*bgmtet));
27445
27446 for (i = 0; i < 4; i++) bgmpt[i] = (point) bgmtet->tet[4 + i];
27447
27448 vol = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], bgmpt[3]);
27449 volpt[0] = orient3d(pt, bgmpt[1], bgmpt[2], bgmpt[3]);
27450 volpt[1] = orient3d(bgmpt[0], pt, bgmpt[2], bgmpt[3]);
27451 volpt[2] = orient3d(bgmpt[0], bgmpt[1], pt, bgmpt[3]);
27452 volpt[3] = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], pt);
27453 for (i = 0; i < 4; i++) weights[i] = fabs(volpt[i] / vol);
27454
27455 for (i = 0; i < bgm->in->numberofpointmtrs; i++) {
27456 pt[pointmtrindex + i] = weights[0] * bgmpt[0][bgm->pointmtrindex + i]
27457 + weights[1] * bgmpt[1][bgm->pointmtrindex + i]
27458 + weights[2] * bgmpt[2][bgm->pointmtrindex + i]
27459 + weights[3] * bgmpt[3][bgm->pointmtrindex + i];
27460 }
27461 } else {
27462 setpoint2bgmtet(pt, (tetrahedron) NULL);
27463 }
27464 return loc != OUTSIDE;
27465 }
27466
27468
27469
27470
27471
27472
27473
27474
27475
27476
27477
27479
27480 void tetgenmesh::interpolatesizemap()
27481 {
27482 list *adjtetlist;
27483 triface tetloop, neightet, bgmtet;
27484 point searchpt;
27485 long scount;
27486 int *worklist;
27487 int sepcount;
27488 int i;
27489
27490 if (b->verbose) {
27491 printf(" Interpolating size map.\n");
27492 }
27493
27494 worklist = new int[points->items + 1];
27495 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
27496 sepcount = 0;
27497 scount = 0l;
27498
27499 tetrahedrons->traversalinit();
27500 tetloop.tet = tetrahedrontraverse();
27501 while (tetloop.tet != (tetrahedron *) NULL) {
27502 if (!infected(tetloop)) {
27503
27504 adjtetlist = new list(sizeof(triface), NULL, 1024);
27505 infect(tetloop);
27506
27507 for (i = 0; i < 4; i++) {
27508 searchpt = (point) tetloop.tet[4 + i];
27509
27510
27511 worklist[pointmark(searchpt)] = 1;
27512
27513 bgm->decode(point2bgmtet(searchpt), bgmtet);
27514 if (bgm->isdead(&bgmtet)) {
27515 bgmtet = bgm->recenttet;
27516 }
27517 if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27518 bgm->recenttet = bgmtet;
27519 }
27520 }
27521
27522 adjtetlist->append(&tetloop);
27523
27524 for (i = 0; i < adjtetlist->len(); i++) {
27525 tetloop = * (triface *)(* adjtetlist)[i];
27526 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27527 sym(tetloop, neightet);
27528 if ((neightet.tet != dummytet) && !infected(neightet)) {
27529
27530 searchpt = oppo(neightet);
27531 if (worklist[pointmark(searchpt)] == 0) {
27532 worklist[pointmark(searchpt)] = 1;
27533 decode(point2bgmtet(searchpt), bgmtet);
27534 if (bgm->isdead(&bgmtet)) {
27535 bgmtet = bgm->recenttet;
27536 }
27537 if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27538 bgm->recenttet = bgmtet;
27539 }
27540 }
27541 infect(neightet);
27542 adjtetlist->append(&neightet);
27543 }
27544 }
27545 }
27546
27547 sepcount++;
27548 delete adjtetlist;
27549 }
27550 tetloop.tet = tetrahedrontraverse();
27551 }
27552
27553
27554 tetrahedrons->traversalinit();
27555 tetloop.tet = tetrahedrontraverse();
27556 while (tetloop.tet != (tetrahedron *) NULL) {
27557 assert(infected(tetloop));
27558 uninfect(tetloop);
27559 tetloop.tet = tetrahedrontraverse();
27560 }
27561 delete [] worklist;
27562
27563 #ifdef SELF_CHECK
27564 if (b->verbose && scount > 0l) {
27565 printf(" %ld brute-force searches.\n", scount);
27566 }
27567 if (b->verbose && sepcount > 0) {
27568 printf(" %d separate domains.\n", sepcount);
27569 }
27570 #endif
27571 }
27572
27574
27575
27576
27577
27578
27579
27581
27582 void tetgenmesh::duplicatebgmesh()
27583 {
27584 triface tetloop, btetloop;
27585 triface symtet, bsymtet;
27586 face bhullsh, bneighsh;
27587 point *idx2bplist, *tetptbaklist;
27588 point ploop, bploop;
27589 int idx, i;
27590
27591 if (!b->quiet) {
27592 printf("Duplicating background mesh.\n");
27593 }
27594
27595
27596
27597
27598
27599
27600
27601 idx2bplist = new point[points->items + 1];
27602 idx = in->firstnumber;
27603 points->traversalinit();
27604 ploop = pointtraverse();
27605 while (ploop != (point) NULL) {
27606 bgm->makepoint(&bploop);
27607
27608 for (i = 0; i < 3 + in->numberofpointattributes; i++) {
27609 bploop[i] = ploop[i];
27610 }
27611
27612 for (i = 0; i < bgm->sizeoftensor; i++) {
27613 bploop[bgm->pointmtrindex + i] = ploop[pointmtrindex + i];
27614
27615 if (bploop[bgm->pointmtrindex + i] <= 0.0) {
27616 printf("Error: Point %d has non-positive size %g (-m option).\n",
27617 bgm->pointmark(bploop), bploop[bgm->pointmtrindex + i]);
27618 terminatetetgen(1);
27619 }
27620 }
27621
27622 idx2bplist[idx++] = bploop;
27623 ploop = pointtraverse();
27624 }
27625
27626
27627 tetptbaklist = new point[tetrahedrons->items + 1];
27628 idx = in->firstnumber;
27629 tetrahedrons->traversalinit();
27630 tetloop.tet = tetrahedrontraverse();
27631 while (tetloop.tet != (tetrahedron *) NULL) {
27632 bgm->maketetrahedron(&btetloop);
27633
27634 for (i = 0; i < 4; i++) {
27635 ploop = (point) tetloop.tet[4 + i];
27636 bploop = idx2bplist[pointmark(ploop)];
27637 btetloop.tet[4 + i] = (tetrahedron) bploop;
27638 }
27639
27640 tetptbaklist[idx++] = (point) tetloop.tet[4];
27641 tetloop.tet[4] = (tetrahedron) btetloop.tet;
27642 tetloop.tet = tetrahedrontraverse();
27643 }
27644
27645
27646
27647 idx = in->firstnumber;
27648 tetrahedrons->traversalinit();
27649 tetloop.tet = tetrahedrontraverse();
27650 while (tetloop.tet != (tetrahedron *) NULL) {
27651
27652 btetloop.tet = (tetrahedron *) tetloop.tet[4];
27653
27654 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27655 btetloop.loc = tetloop.loc;
27656 sym(tetloop, symtet);
27657 if ((symtet.tet != dummytet) && (symtet.tet > tetloop.tet)) {
27658
27659 bsymtet.tet = (tetrahedron *) symtet.tet[4];
27660 bsymtet.loc = symtet.loc;
27661 bgm->bond(btetloop, bsymtet);
27662 } else if (symtet.tet == dummytet) {
27663
27664 bgm->makeshellface(bgm->subfaces, &bhullsh);
27665 bgm->adjustedgering(btetloop, CCW);
27666 bgm->setsorg(bhullsh, bgm->org(btetloop));
27667 bgm->setsdest(bhullsh, bgm->dest(btetloop));
27668 bgm->setsapex(bhullsh, bgm->apex(btetloop));
27669 bgm->tsbond(btetloop, bhullsh);
27670
27671 bgm->dummytet[0] = bgm->encode(btetloop);
27672 }
27673 }
27674
27675 tetloop.tet[4] = (tetrahedron) tetptbaklist[idx++];
27676
27677 btetloop.loc = 0;
27678 for (i = 0; i < 4; i++) {
27679 ploop = (point) tetloop.tet[4 + i];
27680 setpoint2bgmtet(ploop, bgm->encode(btetloop));
27681 }
27682
27683 tetloop.tet = tetrahedrontraverse();
27684 }
27685
27686
27687 bgm->subfaces->traversalinit();
27688 bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27689 while (bhullsh.sh != (shellface *) NULL) {
27690 bhullsh.shver = 0;
27691 bgm->stpivot(bhullsh, btetloop);
27692 assert(btetloop.tet != bgm->dummytet);
27693 bgm->adjustedgering(btetloop, CCW);
27694 for (i = 0; i < 3; i++) {
27695 bgm->spivot(bhullsh, bneighsh);
27696 if (bneighsh.sh == bgm->dummysh) {
27697
27698 bsymtet = btetloop;
27699 while (bgm->fnextself(bsymtet));
27700 bgm->tspivot(bsymtet, bneighsh);
27701 bgm->findedge(&bneighsh, bgm->sdest(bhullsh), bgm->sorg(bhullsh));
27702 bgm->sbond(bhullsh, bneighsh);
27703 }
27704 bgm->enextself(btetloop);
27705 bgm->senextself(bhullsh);
27706 }
27707 bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27708 }
27709
27710 delete [] tetptbaklist;
27711 delete [] idx2bplist;
27712 }
27713
27714
27715
27716
27717
27719
27720
27721
27722
27723
27724
27725
27726
27727
27728
27729
27730
27731
27732
27733
27735
27736 void tetgenmesh::marksharpsegments(REAL sharpangle)
27737 {
27738 triface adjtet;
27739 face startsh, spinsh, neighsh;
27740 face segloop, prevseg, nextseg;
27741 point eorg, edest;
27742 REAL ang, smallang;
27743 bool issharp;
27744 int sharpsegcount;
27745
27746 if (b->verbose > 0) {
27747 printf(" Marking sharp segments.\n");
27748 }
27749
27750 smallang = sharpangle * PI / 180.;
27751 sharpsegcount = 0;
27752 eorg = edest = (point) NULL;
27753
27754
27755
27756 subsegs->traversalinit();
27757 segloop.sh = shellfacetraverse(subsegs);
27758 while (segloop.sh != (shellface *) NULL) {
27759 segloop.shver = 0;
27760 senext2(segloop, prevseg);
27761 spivotself(prevseg);
27762 if (prevseg.sh == dummysh) {
27763
27764 assert(shelltype(segloop) != SHARP);
27765 issharp = false;
27766 spivot(segloop, startsh);
27767 if (startsh.sh != dummysh) {
27768
27769 eorg = sorg(segloop);
27770 edest = sdest(segloop);
27771 spinsh = startsh;
27772 do {
27773 if (sorg(spinsh) != eorg) {
27774 sesymself(spinsh);
27775 }
27776
27777 stpivot(spinsh, adjtet);
27778 if (adjtet.tet != dummytet) {
27779
27780 spivot(spinsh, neighsh);
27781
27782 if (neighsh.sh != spinsh.sh) {
27783
27784 ang = facedihedral(eorg, edest, sapex(spinsh), sapex(neighsh));
27785
27786 if (!issharp) issharp = (ang < smallang);
27787
27788 minfacetdihed = minfacetdihed < ang ? minfacetdihed : ang;
27789 }
27790 }
27791
27792 spivotself(spinsh);
27793 } while (spinsh.sh != startsh.sh);
27794
27795
27796 spinsh = startsh;
27797 do {
27798 if (sorg(spinsh) != eorg) {
27799 sesymself(spinsh);
27800 }
27801
27802 neighsh = spinsh;
27803
27804
27805
27806
27807 ang = 0.0;
27808 do {
27809 ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27810 senext2self(neighsh);
27811 sspivot(neighsh, nextseg);
27812 if (nextseg.sh != dummysh) break;
27813
27814 spivotself(neighsh);
27815 assert(neighsh.sh != dummysh);
27816 if (sorg(neighsh) != eorg) {
27817 sesymself(neighsh);
27818 }
27819 } while (true);
27820
27821 if (!issharp) issharp = (ang < smallang);
27822
27823 minfaceang = minfaceang < ang ? minfaceang : ang;
27824
27825 spivotself(spinsh);
27826 } while (spinsh.sh != startsh.sh);
27827
27828 }
27829 if (issharp) {
27830 setshelltype(segloop, SHARP);
27831
27832 senext(segloop, nextseg);
27833 spivotself(nextseg);
27834 while (nextseg.sh != dummysh) {
27835 nextseg.shver = 0;
27836 setshelltype(nextseg, SHARP);
27837 senextself(nextseg);
27838 spivotself(nextseg);
27839 }
27840 sharpsegcount++;
27841 }
27842 }
27843 segloop.sh = shellfacetraverse(subsegs);
27844 }
27845
27846
27847
27848
27849 subsegs->traversalinit();
27850 segloop.sh = shellfacetraverse(subsegs);
27851 while (segloop.sh != (shellface *) NULL) {
27852
27853 segloop.shver = 0;
27854 senext(segloop, nextseg);
27855 spivotself(nextseg);
27856
27857 if (nextseg.sh == dummysh) {
27858
27859 issharp = (shelltype(segloop) == SHARP);
27860 spivot(segloop, startsh);
27861 if (startsh.sh != dummysh) {
27862
27863 eorg = sdest(segloop);
27864 spinsh = startsh;
27865 do {
27866 if (sorg(spinsh) != eorg) {
27867 sesymself(spinsh);
27868 }
27869
27870 neighsh = spinsh;
27871 ang = 0.0;
27872 do {
27873 ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27874 senext2self(neighsh);
27875 sspivot(neighsh, nextseg);
27876 if (nextseg.sh != dummysh) break;
27877
27878 spivotself(neighsh);
27879 assert(neighsh.sh != dummysh);
27880 if (sorg(neighsh) != eorg) {
27881 sesymself(neighsh);
27882 }
27883 } while (true);
27884
27885 if (!issharp) issharp = (ang < smallang);
27886
27887 minfaceang = minfaceang < ang ? minfaceang : ang;
27888
27889 spivotself(spinsh);
27890 } while (spinsh.sh != startsh.sh);
27891 }
27892 if (issharp) {
27893 setshelltype(segloop, SHARP);
27894
27895 senext2(segloop, prevseg);
27896 spivotself(prevseg);
27897 while (prevseg.sh != dummysh) {
27898 prevseg.shver = 0;
27899 setshelltype(prevseg, SHARP);
27900 senext2self(prevseg);
27901 spivotself(prevseg);
27902 }
27903 sharpsegcount++;
27904 }
27905 }
27906 segloop.sh = shellfacetraverse(subsegs);
27907 }
27908
27909 if ((b->verbose > 0) && (sharpsegcount > 0)) {
27910 printf(" %d sharp segments.\n", sharpsegcount);
27911 }
27912 }
27913
27915
27916
27917
27918
27919
27920
27921
27922
27923
27924
27925
27926
27927
27928
27929
27930
27931
27933
27934 void tetgenmesh::decidefeaturepointsizes()
27935 {
27936 list *tetlist, *verlist;
27937 shellface **segsperverlist;
27938 triface starttet;
27939 face shloop;
27940 face checkseg, prevseg, nextseg, testseg;
27941 point ploop, adjpt, e1, e2;
27942 REAL lfs_0, len, vol, maxlen, varlen;
27943 bool isfeature;
27944 int *idx2seglist;
27945 int featurecount;
27946 int idx, i, j;
27947
27948 maxlen = 0.0;
27949
27950 if (b->verbose > 0) {
27951 printf(" Deciding feature-point sizes.\n");
27952 }
27953
27954
27955 makesegmentmap(idx2seglist, segsperverlist);
27956
27957 tetlist = new list(sizeof(triface), NULL, 256);
27958 verlist = new list(sizeof(point *), NULL, 256);
27959
27960 if (b->fixedvolume) {
27961
27962
27963 maxlen = pow(6.0 * b->maxvolume, 1.0/3.0);
27964 }
27965
27966 if (!b->refine) {
27967
27968 featurecount = 0;
27969 points->traversalinit();
27970 ploop = pointtraverse();
27971 while (ploop != (point) NULL) {
27972 if (pointtype(ploop) == NACUTEVERTEX) {
27973 if (point2sh(ploop) != (shellface) NULL) {
27974 setpointtype(ploop, FREESEGVERTEX);
27975 featurecount++;
27976 }
27977 }
27978 ploop = pointtraverse();
27979 }
27980 #ifdef SELF_CHECK
27981 if ((b->verbose > 0) && (featurecount > 0)) {
27982 printf(" %d Steiner points correction.\n", featurecount);
27983 }
27984 #endif
27985 }
27986
27987
27988
27989
27990 featurecount = 0;
27991 points->traversalinit();
27992 ploop = pointtraverse();
27993 while (ploop != (point) NULL) {
27994 if (pointtype(ploop) != FREESEGVERTEX) {
27995
27996 isfeature = false;
27997 idx = pointmark(ploop) - in->firstnumber;
27998 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; i++) {
27999 checkseg.sh = segsperverlist[i];
28000 isfeature = (shelltype(checkseg) == SHARP);
28001 }
28002
28003 if (isfeature) {
28004
28005 sstpivot(&checkseg, &starttet);
28006
28007 tetlist->append(&starttet);
28008 formstarpolyhedron(ploop, tetlist, verlist, true);
28009
28010 if (ploop[pointmtrindex] == 0.0) {
28011
28012 lfs_0 = longest;
28013 for (i = 0; i < verlist->len(); i++) {
28014 adjpt = * (point *)(* verlist)[i];
28015 if (pointtype(adjpt) == FREESEGVERTEX) {
28016
28017 sdecode(point2sh(adjpt), checkseg);
28018 assert(checkseg.sh != dummysh);
28019 checkseg.shver = 0;
28020
28021 prevseg = checkseg;
28022 do {
28023 senext2(prevseg, testseg);
28024 spivotself(testseg);
28025 if (testseg.sh == dummysh) break;
28026 prevseg = testseg;
28027 prevseg.shver = 0;
28028 } while (true);
28029
28030 nextseg = checkseg;
28031 do {
28032 senext(nextseg, testseg);
28033 spivotself(testseg);
28034 if (testseg.sh == dummysh) break;
28035 nextseg = testseg;
28036 nextseg.shver = 0;
28037 } while (true);
28038 e1 = sorg(prevseg);
28039 e2 = sdest(nextseg);
28040
28041 if (ploop == e1) {
28042
28043 adjpt = e2;
28044 } else if (ploop == e2) {
28045
28046 adjpt = e1;
28047 }
28048 }
28049 len = distance(ploop, adjpt);
28050 if (lfs_0 > len) lfs_0 = len;
28051 }
28052 ploop[pointmtrindex] = lfs_0;
28053 }
28054 if (b->fixedvolume) {
28055
28056 if (ploop[pointmtrindex] > maxlen) {
28057 ploop[pointmtrindex] = maxlen;
28058 }
28059 }
28060 if (b->varvolume) {
28061
28062 for (i = 0; i < tetlist->len(); i++) {
28063 starttet = * (triface *)(* tetlist)[i];
28064 vol = volumebound(starttet.tet);
28065 if (vol > 0.0) {
28066 varlen = pow(6 * vol, 1.0/3.0);
28067 if (ploop[pointmtrindex] > varlen) {
28068 ploop[pointmtrindex] = varlen;
28069 }
28070 }
28071 }
28072 }
28073
28074 tetlist->clear();
28075 verlist->clear();
28076 featurecount++;
28077 } else {
28078
28079 ploop[pointmtrindex] = 0.0;
28080 }
28081 }
28082 ploop = pointtraverse();
28083 }
28084
28085 if (b->verbose > 0) {
28086 printf(" %d feature points.\n", featurecount);
28087 }
28088
28089 if (!b->refine) {
28090
28091
28092
28093 featurecount = 0;
28094 points->traversalinit();
28095 ploop = pointtraverse();
28096 while (ploop != (point) NULL) {
28097 if (pointtype(ploop) == FREESEGVERTEX) {
28098 if (ploop[pointmtrindex] == 0.0) {
28099 sdecode(point2sh(ploop), checkseg);
28100 assert(checkseg.sh != dummysh);
28101 if (shelltype(checkseg) == SHARP) {
28102 checkseg.shver = 0;
28103
28104 prevseg = checkseg;
28105 do {
28106 senext2(prevseg, testseg);
28107 spivotself(testseg);
28108 if (testseg.sh == dummysh) break;
28109 prevseg = testseg;
28110 prevseg.shver = 0;
28111 } while (true);
28112
28113 nextseg = checkseg;
28114 do {
28115 senext(nextseg, testseg);
28116 spivotself(testseg);
28117 if (testseg.sh == dummysh) break;
28118 nextseg = testseg;
28119 nextseg.shver = 0;
28120 } while (true);
28121 e1 = sorg(prevseg);
28122 e2 = sdest(nextseg);
28123 len = distance(e1, e2);
28124 lfs_0 = distance(e1, ploop);
28125
28126 if (b->nobisect == 0) {
28127 assert(lfs_0 < len);
28128 }
28129 ploop[pointmtrindex] = e1[pointmtrindex]
28130 + (lfs_0 / len) * (e2[pointmtrindex] - e1[pointmtrindex]);
28131 featurecount++;
28132 } else {
28133
28134 ploop[pointmtrindex] = 0.0;
28135 }
28136 }
28137 }
28138 ploop = pointtraverse();
28139 }
28140 if ((b->verbose > 0) && (featurecount > 0)) {
28141 printf(" %d Steiner feature points.\n", featurecount);
28142 }
28143 }
28144
28145 if (varconstraint) {
28146
28147 if (in->facetconstraintlist) {
28148
28149 subfaces->traversalinit();
28150 shloop.sh = shellfacetraverse(subfaces);
28151 while (shloop.sh != (shellface *) NULL) {
28152 varlen = areabound(shloop);
28153 if (varlen > 0.0) {
28154
28155 varlen = sqrt(varlen);
28156 for (j = 0; j < 3; j++) {
28157 ploop = (point) shloop.sh[3 + j];
28158 isfeature = false;
28159 idx = pointmark(ploop) - in->firstnumber;
28160 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28161 i++) {
28162 checkseg.sh = segsperverlist[i];
28163 isfeature = (shelltype(checkseg) == SHARP);
28164 }
28165 if (isfeature) {
28166 assert(ploop[pointmtrindex] > 0.0);
28167 if (ploop[pointmtrindex] > varlen) {
28168 ploop[pointmtrindex] = varlen;
28169 }
28170 }
28171 }
28172 }
28173 shloop.sh = shellfacetraverse(subfaces);
28174 }
28175 }
28176 if (in->segmentconstraintlist) {
28177
28178 subsegs->traversalinit();
28179 shloop.sh = shellfacetraverse(subsegs);
28180 while (shloop.sh != (shellface *) NULL) {
28181 varlen = areabound(shloop);
28182 if (varlen > 0.0) {
28183
28184 for (j = 0; j < 2; j++) {
28185 ploop = (point) shloop.sh[3 + j];
28186 isfeature = false;
28187 idx = pointmark(ploop) - in->firstnumber;
28188 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28189 i++) {
28190 checkseg.sh = segsperverlist[i];
28191 isfeature = (shelltype(checkseg) == SHARP);
28192 }
28193 if (isfeature) {
28194 assert(ploop[pointmtrindex] > 0.0);
28195 if (ploop[pointmtrindex] > varlen) {
28196 ploop[pointmtrindex] = varlen;
28197 }
28198 }
28199 }
28200 }
28201 shloop.sh = shellfacetraverse(subsegs);
28202 }
28203 }
28204 }
28205
28206 delete [] segsperverlist;
28207 delete [] idx2seglist;
28208 delete tetlist;
28209 delete verlist;
28210 }
28211
28213
28214
28215
28217
28218 void tetgenmesh::enqueueencsub(face* testsub, point encpt, int quenumber,
28219 REAL* cent)
28220 {
28221 badface *encsub;
28222 int i;
28223
28224 encsub = (badface *) badsubfaces->alloc();
28225 encsub->ss = *testsub;
28226 encsub->forg = sorg(*testsub);
28227 encsub->fdest = sdest(*testsub);
28228 encsub->fapex = sapex(*testsub);
28229 encsub->foppo = (point) encpt;
28230 for (i = 0; i < 3; i++) encsub->cent[i] = cent[i];
28231 encsub->nextitem = (badface *) NULL;
28232
28233
28234 setshell2badface(encsub->ss, encsub);
28235
28236 *subquetail[quenumber] = encsub;
28237
28238 subquetail[quenumber] = &encsub->nextitem;
28239 if (b->verbose > 2) {
28240 printf(" Queuing subface (%d, %d, %d) [%d].\n", pointmark(encsub->forg),
28241 pointmark(encsub->fdest), pointmark(encsub->fapex), quenumber);
28242 }
28243 }
28244
28246
28247
28248
28250
28251 tetgenmesh::badface* tetgenmesh::dequeueencsub(int* pquenumber)
28252 {
28253 badface *result;
28254 int quenumber;
28255
28256
28257 for (quenumber = 2; quenumber >= 0; quenumber--) {
28258 result = subquefront[quenumber];
28259 if (result != (badface *) NULL) {
28260
28261 subquefront[quenumber] = result->nextitem;
28262
28263 if (subquefront[quenumber] == (badface *) NULL) {
28264 subquetail[quenumber] = &subquefront[quenumber];
28265 }
28266 *pquenumber = quenumber;
28267 return result;
28268 }
28269 }
28270 return (badface *) NULL;
28271 }
28272
28274
28275
28276
28278
28279 void tetgenmesh::enqueuebadtet(triface* testtet, REAL ratio2, REAL* cent)
28280 {
28281 badface *newbadtet;
28282 int queuenumber;
28283 int i;
28284
28285
28286 newbadtet = (badface *) badtetrahedrons->alloc();
28287 newbadtet->tt = *testtet;
28288 newbadtet->key = ratio2;
28289 if (cent != NULL) {
28290 for (i = 0; i < 3; i++) newbadtet->cent[i] = cent[i];
28291 } else {
28292 for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
28293 }
28294 newbadtet->forg = org(*testtet);
28295 newbadtet->fdest = dest(*testtet);
28296 newbadtet->fapex = apex(*testtet);
28297 newbadtet->foppo = oppo(*testtet);
28298 newbadtet->nextitem = (badface *) NULL;
28299
28300 if (ratio2 > b->goodratio) {
28301
28302 queuenumber = (int) (64.0 - 64.0 / ratio2);
28303
28304 if ((queuenumber > 63) || (queuenumber < 0)) {
28305 queuenumber = 63;
28306 }
28307 } else {
28308
28309 queuenumber = 0;
28310 }
28311
28312
28313 if (tetquefront[queuenumber] == (badface *) NULL) {
28314
28315 if (queuenumber > firstnonemptyq) {
28316
28317 nextnonemptyq[queuenumber] = firstnonemptyq;
28318 firstnonemptyq = queuenumber;
28319 } else {
28320
28321 i = queuenumber + 1;
28322 while (tetquefront[i] == (badface *) NULL) {
28323 i++;
28324 }
28325
28326 nextnonemptyq[queuenumber] = nextnonemptyq[i];
28327 nextnonemptyq[i] = queuenumber;
28328 }
28329
28330 tetquefront[queuenumber] = newbadtet;
28331 } else {
28332
28333 tetquetail[queuenumber]->nextitem = newbadtet;
28334 }
28335
28336 tetquetail[queuenumber] = newbadtet;
28337
28338 if (b->verbose > 2) {
28339 printf(" Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
28340 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
28341 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
28342 sqrt(ratio2), queuenumber);
28343 }
28344 }
28345
28347
28348
28349
28351
28352 tetgenmesh::badface* tetgenmesh::topbadtetra()
28353 {
28354
28355
28356 recentq = firstnonemptyq;
28357
28358 if (firstnonemptyq < 0) {
28359 return (badface *) NULL;
28360 } else {
28361
28362 return tetquefront[firstnonemptyq];
28363 }
28364 }
28365
28366 void tetgenmesh::dequeuebadtet()
28367 {
28368 badface *deadbadtet;
28369 int i;
28370
28371
28372 if (recentq >= 0) {
28373
28374 deadbadtet = tetquefront[recentq];
28375
28376 tetquefront[recentq] = deadbadtet->nextitem;
28377
28378 if (deadbadtet == tetquetail[recentq]) {
28379
28380 if (firstnonemptyq == recentq) {
28381
28382 firstnonemptyq = nextnonemptyq[firstnonemptyq];
28383 } else {
28384
28385 i = recentq + 1;
28386 while (tetquefront[i] == (badface *) NULL) {
28387 i++;
28388 }
28389 nextnonemptyq[i] = nextnonemptyq[recentq];
28390 }
28391 }
28392
28393 badfacedealloc(badtetrahedrons, deadbadtet);
28394 }
28395 }
28396
28398
28399
28400
28401
28402
28403
28404
28405
28406
28407
28408
28409
28410
28412
28413 bool tetgenmesh::checkseg4encroach(face* testseg, point testpt, point* prefpt,
28414 bool enqflag)
28415 {
28416 badface *encsubseg;
28417 triface starttet, spintet;
28418 point eorg, edest, eapex, encpt;
28419 REAL cent[3], radius, dist, diff;
28420 REAL maxradius;
28421 bool enq;
28422 int hitbdry;
28423
28424 enq = false;
28425 eorg = sorg(*testseg);
28426 edest = sdest(*testseg);
28427 cent[0] = 0.5 * (eorg[0] + edest[0]);
28428 cent[1] = 0.5 * (eorg[1] + edest[1]);
28429 cent[2] = 0.5 * (eorg[2] + edest[2]);
28430 radius = distance(cent, eorg);
28431
28432 if (varconstraint && (areabound(*testseg) > 0.0)) {
28433 enq = (2.0 * radius) > areabound(*testseg);
28434 }
28435
28436 if (!enq) {
28437 maxradius = 0.0;
28438 if (testpt == (point) NULL) {
28439
28440 sstpivot(testseg, &starttet);
28441 eapex = apex(starttet);
28442 spintet = starttet;
28443 hitbdry = 0;
28444 do {
28445 dist = distance(cent, apex(spintet));
28446 diff = dist - radius;
28447 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28448 if (diff <= 0.0) {
28449
28450 enq = true;
28451 if (prefpt != (point *) NULL) {
28452
28453 encpt = apex(spintet);
28454 circumsphere(eorg, edest, encpt, NULL, NULL, &dist);
28455 if (dist > maxradius) {
28456
28457 *prefpt = encpt;
28458 maxradius = dist;
28459 }
28460 } else {
28461 break;
28462 }
28463 }
28464 if (!fnextself(spintet)) {
28465 hitbdry++;
28466 if (hitbdry < 2) {
28467 esym(starttet, spintet);
28468 if (!fnextself(spintet)) {
28469 hitbdry++;
28470 }
28471 }
28472 }
28473 } while (apex(spintet) != eapex && (hitbdry < 2));
28474 } else {
28475
28476 dist = distance(cent, testpt);
28477 diff = dist - radius;
28478 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28479 enq = (diff <= 0.0);
28480 }
28481 }
28482
28483 if (enq && enqflag) {
28484 if (b->verbose > 2) {
28485 printf(" Queuing encroaching subsegment (%d, %d).\n",
28486 pointmark(eorg), pointmark(edest));
28487 }
28488 encsubseg = (badface *) badsubsegs->alloc();
28489 encsubseg->ss = *testseg;
28490 encsubseg->forg = eorg;
28491 encsubseg->fdest = edest;
28492 encsubseg->foppo = (point) NULL;
28493
28494
28495 setshell2badface(encsubseg->ss, encsubseg);
28496 }
28497
28498 return enq;
28499 }
28500
28502
28503
28504
28505
28506
28507
28508
28509
28510
28511
28513
28514 bool tetgenmesh::checksub4encroach(face* testsub, point testpt, bool enqflag)
28515 {
28516 triface abuttet;
28517 point pa, pb, pc, encpt;
28518 REAL A[4][4], rhs[4], D;
28519 REAL cent[3], area;
28520 REAL radius, dist, diff;
28521 bool enq;
28522 int indx[4];
28523 int quenumber;
28524
28525 enq = false;
28526 radius = 0.0;
28527 encpt = (point) NULL;
28528
28529 pa = sorg(*testsub);
28530 pb = sdest(*testsub);
28531 pc = sapex(*testsub);
28532
28533
28534 A[0][0] = pb[0] - pa[0];
28535 A[0][1] = pb[1] - pa[1];
28536 A[0][2] = pb[2] - pa[2];
28537 A[1][0] = pc[0] - pa[0];
28538 A[1][1] = pc[1] - pa[1];
28539 A[1][2] = pc[2] - pa[2];
28540 cross(A[0], A[1], A[2]);
28541
28542 if (varconstraint && (areabound(*testsub) > 0.0)) {
28543
28544 area = 0.5 * sqrt(dot(A[2], A[2]));
28545 enq = area > areabound(*testsub);
28546 if (enq) {
28547 quenumber = 2;
28548 }
28549 }
28550
28551
28552 rhs[0] = 0.5 * dot(A[0], A[0]);
28553 rhs[1] = 0.5 * dot(A[1], A[1]);
28554 rhs[2] = 0.0;
28555
28556
28557 if (lu_decmp(A, 3, indx, &D, 0)) {
28558 lu_solve(A, 3, indx, rhs, 0);
28559 cent[0] = pa[0] + rhs[0];
28560 cent[1] = pa[1] + rhs[1];
28561 cent[2] = pa[2] + rhs[2];
28562 radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
28563 }
28564
28565 if (!enq) {
28566
28567 if (testpt == (point) NULL) {
28568 stpivot(*testsub, abuttet);
28569 if (abuttet.tet != dummytet) {
28570 dist = distance(cent, oppo(abuttet));
28571 diff = dist - radius;
28572 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28573 enq = (diff <= 0.0);
28574 if (enq) encpt = oppo(abuttet);
28575 }
28576 if (!enq) {
28577 sesymself(*testsub);
28578 stpivot(*testsub, abuttet);
28579 if (abuttet.tet != dummytet) {
28580 dist = distance(cent, oppo(abuttet));
28581 diff = dist - radius;
28582 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28583 enq = (diff <= 0.0);
28584 if (enq) encpt = oppo(abuttet);
28585 }
28586 }
28587 } else {
28588 dist = distance(cent, testpt);
28589 diff = dist - radius;
28590 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28591 enq = (diff <= 0.0);
28592 }
28593 if (enq) {
28594 quenumber = 0;
28595 }
28596 }
28597
28598 if (enq && enqflag) {
28599 enqueueencsub(testsub, encpt, quenumber, cent);
28600 }
28601
28602 return enq;
28603 }
28604
28606
28607
28608
28609
28610
28611
28612
28614
28615 bool tetgenmesh::checktet4badqual(triface* testtet, bool enqflag)
28616 {
28617 point pa, pb, pc, pd, pe1, pe2;
28618 REAL vda[3], vdb[3], vdc[3];
28619 REAL vab[3], vbc[3], vca[3];
28620 REAL N[4][3], A[4][4], rhs[4], D;
28621 REAL elen[6], circumcent[3];
28622 REAL bicent[3], offcent[3];
28623 REAL volume, L, cosd;
28624 REAL radius2, smlen2, ratio2;
28625 REAL dist, sdist, split;
28626 bool enq;
28627 int indx[4];
28628 int sidx, i, j;
28629
28630 pa = (point) testtet->tet[4];
28631 pb = (point) testtet->tet[5];
28632 pc = (point) testtet->tet[6];
28633 pd = (point) testtet->tet[7];
28634
28635
28636
28637 for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
28638 for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
28639 for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
28640
28641 for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
28642 for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i];
28643 for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i];
28644
28645
28646 lu_decmp(A, 3, indx, &D, 0);
28647
28648 volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
28649 if (volume < 0.0) volume = -volume;
28650
28651 rhs[0] = 0.5 * dot(vda, vda);
28652 rhs[1] = 0.5 * dot(vdb, vdb);
28653 rhs[2] = 0.5 * dot(vdc, vdc);
28654 lu_solve(A, 3, indx, rhs, 0);
28655
28656 for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
28657
28658 radius2 = dot(rhs, rhs);
28659
28660 elen[0] = dot(vda, vda);
28661 elen[1] = dot(vdb, vdb);
28662 elen[2] = dot(vdc, vdc);
28663 elen[3] = dot(vab, vab);
28664 elen[4] = dot(vbc, vbc);
28665 elen[5] = dot(vca, vca);
28666 smlen2 = elen[0]; sidx = 0;
28667 for (i = 1; i < 6; i++) {
28668 if (smlen2 > elen[i]) { smlen2 = elen[i]; sidx = i; }
28669 }
28670
28671 ratio2 = radius2 / smlen2;
28672
28673 enq = ratio2 > b->goodratio;
28674 if (!enq) {
28675
28676
28677
28678
28679
28680 for (j = 0; j < 3; j++) {
28681 for (i = 0; i < 3; i++) rhs[i] = 0.0;
28682 rhs[j] = 1.0;
28683 lu_solve(A, 3, indx, rhs, 0);
28684 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
28685 }
28686
28687 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
28688
28689 for (i = 0; i < 4; i++) {
28690 L = sqrt(dot(N[i], N[i]));
28691 if (L > 0.0) {
28692 for (j = 0; j < 3; j++) N[i][j] /= L;
28693 }
28694 }
28695
28696
28697 for (i = 1; i < 4 && !enq; i++) {
28698 cosd = -dot(N[0], N[i]);
28699 enq = cosd > cosmindihed;
28700 }
28701 if (!enq) {
28702 for (i = 2; i < 4 && !enq; i++) {
28703 cosd = -dot(N[1], N[i]);
28704 enq = cosd > cosmindihed;
28705 }
28706 if (!enq) {
28707 cosd = -dot(N[2], N[3]);
28708 enq = cosd > cosmindihed;
28709 }
28710 }
28711
28712 } else if (b->offcenter) {
28713
28714 switch (sidx) {
28715 case 0:
28716 pe1 = pd; pe2 = pa; break;
28717 case 1:
28718 pe1 = pd; pe2 = pb; break;
28719 case 2:
28720 pe1 = pd; pe2 = pc; break;
28721 case 3:
28722 pe1 = pa; pe2 = pb; break;
28723 case 4:
28724 pe1 = pb; pe2 = pc; break;
28725 case 5:
28726 pe1 = pc; pe2 = pa; break;
28727 default:
28728 pe1 = pe2 = (point) NULL;
28729 }
28730
28731 for (i = 0; i < 3; i++) bicent[i] = 0.5 * (pe1[i] + pe2[i]);
28732 dist = distance(bicent, circumcent);
28733
28734
28735 sdist = b->alpha3 * (b->minratio+sqrt(b->goodratio-0.25))* sqrt(smlen2);
28736 split = sdist / dist;
28737 if (split > 1.0) split = 1.0;
28738
28739 for (i = 0; i < 3; i++) {
28740 offcent[i] = bicent[i] + split * (circumcent[i] - bicent[i]);
28741 }
28742 }
28743
28744 if (!enq && (b->varvolume || b->fixedvolume)) {
28745
28746 enq = b->fixedvolume && (volume > b->maxvolume);
28747 if (!enq && b->varvolume) {
28748 enq = (volume > volumebound(testtet->tet)) &&
28749 (volumebound(testtet->tet) > 0.0);
28750 }
28751 }
28752
28753 if (!enq) {
28754
28755 if (b->metric) {
28756
28757 sdist = sqrt(radius2) / b->alpha1;
28758 for (i = 0; i < 4; i++) {
28759 pa = (point) testtet->tet[4 + i];
28760
28761 dist = pa[pointmtrindex];
28762 enq = ((dist < sdist) && (dist > 0.0));
28763 if (enq) break;
28764
28765
28766 }
28767
28768
28769 }
28770 }
28771
28772 if (enq && enqflag) {
28773 if (b->offcenter && (ratio2 > b->goodratio)) {
28774 for (i = 0; i < 3; i++) circumcent[i] = offcent[i];
28775 }
28776 enqueuebadtet(testtet, ratio2, circumcent);
28777 }
28778
28779 return enq;
28780 }
28781
28783
28784
28785
28786
28787
28788
28789
28790
28791
28792
28793
28794
28795
28796
28798
28799 bool tetgenmesh::acceptsegpt(point segpt, point refpt, face* splitseg)
28800 {
28801 point p[2];
28802 REAL L, lfs;
28803 int i, j;
28804
28805 if (b->nobisect == 1) {
28806
28807 triface spintet;
28808 point pc;
28809 sstpivot(splitseg, &spintet);
28810 assert(spintet.tet != dummytet);
28811 pc = apex(spintet);
28812 do {
28813 if (!fnextself(spintet)) {
28814
28815 return false;
28816 }
28817 } while (pc != apex(spintet));
28818 } else if (b->nobisect > 1) {
28819
28820 return false;
28821 }
28822
28823 p[0] = sorg(*splitseg);
28824 p[1] = sdest(*splitseg);
28825 if (varconstraint && (areabound(*splitseg) > 0)) {
28826 lfs = areabound(*splitseg);
28827 L = distance(p[0], p[1]);
28828 if (L > lfs) {
28829 return true;
28830 }
28831 }
28832
28833 j = 0;
28834 for (i = 0; i < 2; i++) {
28835
28836 if (p[i][pointmtrindex] > 0.0) {
28837 lfs = b->alpha2 * p[i][pointmtrindex];
28838 L = distance(p[i], segpt);
28839 if (L < lfs) j++;
28840 }
28841 }
28842 if (j == 0) return true;
28843
28844
28845 if (refpt != (point) NULL) {
28846 cdtenforcesegpts++;
28847 return true;
28848 }
28849
28850
28851 rejsegpts++;
28852 return false;
28853 }
28854
28856
28857
28858
28859
28860
28861
28862
28863
28864
28865
28866
28868
28869 bool tetgenmesh::acceptfacpt(point facpt, list* subceillist, list* verlist)
28870 {
28871 face *testsh;
28872 point p[2], ploop;
28873 REAL L, lfs;
28874 int idx, i, j;
28875
28876 if (b->nobisect == 1) {
28877
28878 triface testtet;
28879 testsh = (face *)(* subceillist)[0];
28880 stpivot(*testsh, testtet);
28881 if (testtet.tet != dummytet) {
28882 sesymself(*testsh);
28883 stpivot(*testsh, testtet);
28884 }
28885 if (testtet.tet == dummytet) return false;
28886 } else if (b->nobisect > 1) {
28887
28888 return false;
28889 }
28890
28891
28892 for (i = 0; i < subceillist->len(); i++) {
28893 testsh = (face *)(* subceillist)[i];
28894 p[0] = sorg(*testsh);
28895 p[1] = sdest(*testsh);
28896 for (j = 0; j < 2; j++) {
28897 idx = pointmark(p[j]);
28898 if (idx >= 0) {
28899 setpointmark(p[j], -idx - 1);
28900 verlist->append(&(p[j]));
28901 }
28902 }
28903 }
28904
28905 j = 0;
28906 for (i = 0; i < verlist->len(); i++) {
28907 ploop = * (point *)(* verlist)[i];
28908
28909 idx = pointmark(ploop);
28910 setpointmark(ploop, -(idx + 1));
28911
28912 if (ploop[pointmtrindex] > 0.0) {
28913 lfs = b->alpha2 * ploop[pointmtrindex];
28914 L = distance(ploop, facpt);
28915 if (L < lfs) j++;
28916 }
28917 }
28918 verlist->clear();
28919
28920 if (j == 0) return true;
28921
28922 rejsubpts++;
28923 return false;
28924 }
28925
28927
28928
28929
28930
28931
28932
28933
28934
28936
28937 bool tetgenmesh::acceptvolpt(point volpt, list* ceillist, list* verlist)
28938 {
28939 triface* testtet;
28940 point p[3], ploop;
28941 REAL L, lfs;
28942 int idx, i, j;
28943
28944
28945 for (i = 0; i < ceillist->len(); i++) {
28946 testtet = (triface *)(* ceillist)[i];
28947 p[0] = org(*testtet);
28948 p[1] = dest(*testtet);
28949 p[2] = apex(*testtet);
28950 for (j = 0; j < 3; j++) {
28951 idx = pointmark(p[j]);
28952 if (idx >= 0) {
28953 setpointmark(p[j], -idx - 1);
28954 verlist->append(&(p[j]));
28955 }
28956 }
28957 }
28958
28959 j = 0;
28960 for (i = 0; i < verlist->len(); i++) {
28961 ploop = * (point *)(* verlist)[i];
28962
28963 idx = pointmark(ploop);
28964 setpointmark(ploop, -(idx + 1));
28965
28966 if (ploop[pointmtrindex] > 0.0) {
28967 lfs = b->alpha2 * ploop[pointmtrindex];
28968 L = distance(ploop, volpt);
28969 if (L < lfs) j++;
28970 }
28971 }
28972 verlist->clear();
28973
28974 if (j == 0) return true;
28975
28976 rejtetpts++;
28977 return false;
28978 }
28979
28981
28982
28983
28985
28986 void tetgenmesh::getsplitpoint(point e1, point e2, point refpt, point newpt)
28987 {
28988 point ei, ej;
28989 REAL split, L, d1, d2, ps, rs;
28990 bool acutea, acuteb;
28991 int i;
28992
28993 if (refpt != (point) NULL) {
28994
28995 acutea = (pointtype(e1) == ACUTEVERTEX);
28996 acuteb = (pointtype(e2) == ACUTEVERTEX);
28997 if (acutea ^ acuteb) {
28998
28999 ei = acutea ? e1 : e2;
29000 ej = acutea ? e2 : e1;
29001 L = distance(ei, ej);
29002
29003 d1 = distance(ei, refpt);
29004 split = d1 / L;
29005 for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29006
29007 d2 = distance(refpt, newpt);
29008 if (d2 > (L - d1)) {
29009
29010 if ((d1 - d2) > (0.5 * d1)) {
29011 split = (d1 - d2) / L;
29012 } else {
29013 split = 0.5 * d1 / L;
29014 }
29015 for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29016 if (b->verbose > 1) {
29017 printf(" Found by rule-3:");
29018 }
29019 r3count++;
29020 } else {
29021 if (b->verbose > 1) {
29022 printf(" Found by rule-2:");
29023 }
29024 r2count++;
29025 }
29026 if (b->verbose > 1) {
29027 printf(" center %d, split = %.12g.\n", pointmark(ei), split);
29028 }
29029
29030 d1 = distance(ei, newpt);
29031 d2 = distance(newpt, refpt);
29032 ps = randgenerator(d2 * b->epsilon2 * 1e+2);
29033 rs = ps / d1;
29034
29035 for (i = 0; i < 3; i++) newpt[i] = ei[i] + (1.0+rs) * (newpt[i] - ei[i]);
29036 } else {
29037
29038 for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29039
29040 d1 = 0.5 * distance(e1, e2);
29041 ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29042 rs = ps / d1;
29043 for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29044 }
29045 } else {
29046
29047 for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29048
29049 d1 = 0.5 * distance(e1, e2);
29050 ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29051 rs = ps / d1;
29052 for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29053 }
29054 }
29055
29057
29058
29059
29060
29061
29062
29063
29064
29066
29067 void tetgenmesh::shepardinterpolate(point newpt, list *verlist)
29068 {
29069 point neipt;
29070 REAL *weights, sumweight;
29071 REAL vec[3];
29072 int i, j;
29073
29074 weights = new REAL[verlist->len()];
29075 sumweight = 0.0;
29076
29077
29078 for (i = 0; i < verlist->len(); i++) {
29079 neipt = * (point *)(* verlist)[i];
29080 for (j = 0; j < 3; j++) vec[j] = neipt[j] - newpt[j];
29081 weights[i] = 1.0 / dot(vec, vec);
29082 sumweight += weights[i];
29083 }
29084
29085 newpt[pointmtrindex] = 0.0;
29086 for (i = 0; i < verlist->len(); i++) {
29087 neipt = * (point *)(* verlist)[i];
29088 newpt[pointmtrindex] += (weights[i] * neipt[pointmtrindex]) / sumweight;
29089 }
29090
29091 delete [] weights;
29092 }
29093
29095
29096
29097
29098
29099
29100
29102
29103 void tetgenmesh::setnewpointsize(point newpt, point e1, point e2)
29104 {
29105 if (b->metric) {
29106
29107 triface bgmtet;
29108
29109 decode(point2bgmtet(e1), bgmtet);
29110 p1interpolatebgm(newpt, &bgmtet, NULL);
29111 } else {
29112 if (e2 != (point) NULL) {
29113
29114 REAL split, l, d;
29115 l = distance(e1, e2);
29116 d = distance(e1, newpt);
29117 split = d / l;
29118 #ifdef SELF_CHECK
29119
29120 assert(e1[pointmtrindex] > 0.0);
29121 assert(e2[pointmtrindex] > 0.0);
29122 #endif
29123 newpt[pointmtrindex] = (1.0 - split) * e1[pointmtrindex]
29124 + split * e2[pointmtrindex];
29125 }
29126 }
29127 }
29128
29130
29131
29132
29134
29135 void tetgenmesh::splitencseg(point newpt, face* splitseg, list* tetlist,
29136 list* sublist, list* verlist, queue* flipque, bool chkencsub, bool chkbadtet,
29137 bool optflag)
29138 {
29139 list *mytetlist;
29140 queue *myflipque;
29141 triface starttet;
29142 face startsh, spinsh, checksh;
29143 int i;
29144
29145 mytetlist = NULL;
29146 myflipque = NULL;
29147
29148 if (optflag) {
29149 mytetlist = new list(sizeof(triface), NULL, 1024);
29150 myflipque = new queue(sizeof(badface));
29151 tetlist = mytetlist;
29152 flipque = myflipque;
29153 }
29154
29155
29156 splitseg->shver = 0;
29157
29158 sstpivot(splitseg, &starttet);
29159 splittetedge(newpt, &starttet, flipque);
29160
29161 flip(flipque, NULL);
29162
29163 if (!optflag) {
29164
29165 for (i = 0; i < 2; i++) {
29166 if (!shell2badface(*splitseg)) {
29167 checkseg4encroach(splitseg, NULL, NULL, true);
29168 }
29169 if (i == 1) break;
29170 senextself(*splitseg);
29171 spivotself(*splitseg);
29172 #ifdef SELF_CHECK
29173 assert(splitseg->sh != (shellface *) NULL);
29174 #endif
29175 splitseg->shver = 0;
29176 }
29177
29178 if (chkencsub) {
29179 spivot(*splitseg, startsh);
29180 spinsh = startsh;
29181 do {
29182 sublist->append(&spinsh);
29183 formstarpolygon(newpt, sublist, verlist);
29184 for (i = 0; i < sublist->len(); i++) {
29185 checksh = * (face *)(* sublist)[i];
29186 if (!shell2badface(checksh)) {
29187 checksub4encroach(&checksh, NULL, true);
29188 }
29189 }
29190 sublist->clear();
29191 if (verlist) verlist->clear();
29192 spivotself(spinsh);
29193 } while (spinsh.sh != startsh.sh);
29194 }
29195 }
29196
29197
29198 sstpivot(splitseg, &starttet);
29199 tetlist->append(&starttet);
29200 formstarpolyhedron(newpt, tetlist, verlist, true);
29201
29202 if (!optflag) {
29203
29204 tallencsegs(newpt, 1, &tetlist);
29205 if (chkencsub) {
29206
29207 tallencsubs(newpt, 1, &tetlist);
29208 }
29209 if (chkbadtet) {
29210
29211 for (i = 0; i < tetlist->len(); i++) {
29212 starttet = * (triface *)(* tetlist)[i];
29213 checktet4badqual(&starttet, true);
29214 }
29215 }
29216 tetlist->clear();
29217 } else {
29218
29219 for (i = 0; i < tetlist->len(); i++) {
29220 starttet = * (triface *)(* tetlist)[i];
29221 checktet4opt(&starttet, true);
29222 }
29223 delete mytetlist;
29224 delete myflipque;
29225 }
29226 }
29227
29229
29230
29231
29232
29233
29234
29235
29236
29237
29238
29240
29241 bool tetgenmesh::tallencsegs(point testpt, int n, list **ceillists)
29242 {
29243 list *ceillist;
29244 triface ceiltet;
29245 face checkseg;
29246 long oldencnum;
29247 int i, j, k;
29248
29249
29250 oldencnum = badsubsegs->items;
29251
29252 if (ceillists != (list **) NULL) {
29253 for (k = 0; k < n; k++) {
29254 ceillist = ceillists[k];
29255
29256 for (i = 0; i < ceillist->len(); i++) {
29257 ceiltet = * (triface *)(* ceillist)[i];
29258 ceiltet.ver = 0;
29259 for (j = 0; j < 3; j++) {
29260 tsspivot(&ceiltet, &checkseg);
29261 if (checkseg.sh != dummysh) {
29262
29263 if (!shell2badface(checkseg)) {
29264 checkseg4encroach(&checkseg, testpt, NULL, true);
29265 }
29266 }
29267 enextself(ceiltet);
29268 }
29269 }
29270 }
29271 } else {
29272
29273 subsegs->traversalinit();
29274 checkseg.sh = shellfacetraverse(subsegs);
29275 while (checkseg.sh != (shellface *) NULL) {
29276
29277 if (!shell2badface(checkseg)) {
29278 checkseg4encroach(&checkseg, testpt, NULL, true);
29279 }
29280 checkseg.sh = shellfacetraverse(subsegs);
29281 }
29282 }
29283
29284 return (badsubsegs->items > oldencnum);
29285 }
29286
29288
29289
29290
29291
29292
29293
29294
29295
29296
29297
29299
29300 bool tetgenmesh::tallencsubs(point testpt, int n, list** ceillists)
29301 {
29302 list *ceillist;
29303 triface ceiltet;
29304 face checksh;
29305 long oldencnum;
29306 int i, k;
29307
29308
29309 oldencnum = badsubfaces->items;
29310
29311 if (ceillists != (list **) NULL) {
29312 for (k = 0; k < n; k++) {
29313 ceillist = ceillists[k];
29314
29315 for (i = 0; i < ceillist->len(); i++) {
29316 ceiltet = * (triface *)(* ceillist)[i];
29317 tspivot(ceiltet, checksh);
29318 if (checksh.sh != dummysh) {
29319
29320 if (!shell2badface(checksh)) {
29321 checksub4encroach(&checksh, testpt, true);
29322 }
29323 }
29324 }
29325 }
29326 } else {
29327
29328 subfaces->traversalinit();
29329 checksh.sh = shellfacetraverse(subfaces);
29330 while (checksh.sh != (shellface *) NULL) {
29331
29332 if (!shell2badface(checksh)) {
29333 checksub4encroach(&checksh, testpt, true);
29334 }
29335 checksh.sh = shellfacetraverse(subfaces);
29336 }
29337 }
29338
29339 return (badsubfaces->items > oldencnum);
29340 }
29341
29343
29344
29345
29347
29348 void tetgenmesh::tallbadtetrahedrons()
29349 {
29350 triface tetloop;
29351
29352 tetrahedrons->traversalinit();
29353 tetloop.tet = tetrahedrontraverse();
29354 while (tetloop.tet != (tetrahedron *) NULL) {
29355 checktet4badqual(&tetloop, true);
29356 tetloop.tet = tetrahedrontraverse();
29357 }
29358 }
29359
29361
29362
29363
29364
29365
29366
29367
29368
29369
29370
29371
29373
29374 void tetgenmesh::repairencsegs(bool chkencsub, bool chkbadtet)
29375 {
29376 list **tetlists, **ceillists;
29377 list **sublists, **subceillists;
29378 list *tetlist, *sublist;
29379 queue *flipque;
29380 badface *encloop;
29381 face splitseg, symsplitseg;
29382 point newpt, sympt, refpt;
29383 point e1, e2;
29384 enum locateresult symloc;
29385 int nmax, n, i, j;
29386
29387 ceillists = NULL;
29388 flipque = NULL;
29389 subceillists = NULL;
29390 sublist = NULL;
29391 sublists = NULL;
29392 tetlist = NULL;
29393 tetlists = NULL;
29394
29395 n = 0;
29396 nmax = 128;
29397 if (!b->fliprepair) {
29398 tetlists = new list*[nmax];
29399 ceillists = new list*[nmax];
29400 sublists = new list*[nmax];
29401 subceillists = new list*[nmax];
29402 } else {
29403 tetlist = new list(sizeof(triface), NULL, 1024);
29404 sublist = new list(sizeof(face), NULL, 256);
29405 flipque = new queue(sizeof(badface));
29406 }
29407
29408
29409
29410 while ((badsubsegs->items > 0) && (steinerleft != 0)) {
29411 badsubsegs->traversalinit();
29412 encloop = badfacetraverse(badsubsegs);
29413 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
29414
29415 splitseg = encloop->ss;
29416
29417 setshell2badface(splitseg, NULL);
29418 if ((sorg(splitseg) == encloop->forg) &&
29419 (sdest(splitseg) == encloop->fdest)) {
29420 if (b->verbose > 1) {
29421 printf(" Get an enc-seg (%d, %d)\n", pointmark(encloop->forg),
29422 pointmark(encloop->fdest));
29423 }
29424 refpt = (point) NULL;
29425 if (b->conformdel) {
29426
29427 checkseg4encroach(&splitseg, NULL, &refpt, false);
29428 }
29429
29430 makepoint(&newpt);
29431 getsplitpoint(encloop->forg, encloop->fdest, refpt, newpt);
29432 setpointtype(newpt, FREESEGVERTEX);
29433 setpoint2sh(newpt, sencode(splitseg));
29434
29435 if (acceptsegpt(newpt, refpt, &splitseg)) {
29436
29437 if (checkpbcs) {
29438
29439 i = shellmark(splitseg) - 1;
29440 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
29441 makepoint(&sympt);
29442 symloc = getsegpbcsympoint(newpt, &splitseg, sympt, &symsplitseg,
29443 segpglist[j]);
29444 if (symloc == ONEDGE) {
29445 if (symsplitseg.sh != splitseg.sh) {
29446
29447 setpointtype(sympt, FREESEGVERTEX);
29448 setpoint2sh(sympt, sencode(symsplitseg));
29449
29450 e1 = sorg(symsplitseg);
29451 if (shelltype(symsplitseg) == SHARP) {
29452 e2 = sdest(symsplitseg);
29453 } else {
29454 e2 = (point) NULL;
29455 }
29456 if (!b->fliprepair) {
29457
29458 formbowatcavity(sympt, &symsplitseg, NULL, &n, &nmax,
29459 sublists, subceillists, tetlists, ceillists);
29460
29461 if (trimbowatcavity(sympt, &symsplitseg, n, sublists,
29462 subceillists, tetlists, ceillists, -1.0)) {
29463 bowatinsertsite(sympt, &symsplitseg, n, sublists,
29464 subceillists, tetlists, ceillists, NULL, flipque,
29465 true, chkencsub, chkbadtet);
29466 setnewpointsize(sympt, e1, e2);
29467 if (steinerleft > 0) steinerleft--;
29468 } else {
29469
29470 pointdealloc(sympt);
29471 }
29472
29473 releasebowatcavity(&symsplitseg, n, sublists, subceillists,
29474 tetlists, ceillists);
29475 } else {
29476 splitencseg(sympt, &symsplitseg, tetlist, sublist, NULL,
29477 flipque, chkencsub, chkbadtet, false);
29478 setnewpointsize(sympt, e1, e2);
29479 if (steinerleft > 0) steinerleft--;
29480 }
29481 } else {
29482
29483
29484 pointdealloc(sympt);
29485 }
29486 } else if (symloc == ONVERTEX) {
29487
29488
29489 pointdealloc(sympt);
29490 } else {
29491
29492
29493 pointdealloc(sympt);
29494 }
29495 }
29496 }
29497
29498 e1 = sorg(splitseg);
29499 if (shelltype(splitseg) == SHARP) {
29500 e2 = sdest(splitseg);
29501 } else {
29502 e2 = (point) NULL;
29503 }
29504 if (!b->fliprepair) {
29505
29506 formbowatcavity(newpt, &splitseg, NULL, &n, &nmax, sublists,
29507 subceillists, tetlists, ceillists);
29508
29509 if (trimbowatcavity(newpt, &splitseg, n, sublists, subceillists,
29510 tetlists, ceillists, -1.0)) {
29511 bowatinsertsite(newpt, &splitseg, n, sublists, subceillists,
29512 tetlists, ceillists, NULL, flipque, true,
29513 chkencsub, chkbadtet);
29514 setnewpointsize(newpt, e1, e2);
29515 if (steinerleft > 0) steinerleft--;
29516 } else {
29517
29518 pointdealloc(newpt);
29519 }
29520
29521 releasebowatcavity(&splitseg, n, sublists, subceillists, tetlists,
29522 ceillists);
29523 } else {
29524 splitencseg(newpt, &splitseg, tetlist, sublist, NULL, flipque,
29525 chkencsub, chkbadtet, false);
29526 setnewpointsize(newpt, e1, e2);
29527 if (steinerleft > 0) steinerleft--;
29528 }
29529 } else {
29530
29531 pointdealloc(newpt);
29532 }
29533 }
29534 badfacedealloc(badsubsegs, encloop);
29535 encloop = badfacetraverse(badsubsegs);
29536 }
29537 }
29538
29539 if (!b->fliprepair) {
29540 delete [] tetlists;
29541 delete [] ceillists;
29542 delete [] sublists;
29543 delete [] subceillists;
29544 } else {
29545 delete tetlist;
29546 delete sublist;
29547 delete flipque;
29548 }
29549 }
29550
29552
29553
29554
29555
29556
29557
29558
29559
29560
29561
29563
29564 void tetgenmesh::repairencsubs(bool chkbadtet)
29565 {
29566 list *tetlists[2], *ceillists[2];
29567 list *sublist, *subceillist;
29568 list *verlist;
29569 badface *encloop;
29570 face splitsub, symsplitsub;
29571 point newpt, sympt, e1;
29572 enum locateresult loc, symloc;
29573 bool reject;
29574 long oldptnum;
29575 int quenumber, n, i;
29576
29577 quenumber = 0;
29578 n = 0;
29579 sublist = (list *) NULL;
29580 subceillist = (list *) NULL;
29581 verlist = new list(sizeof(point *), NULL, 256);
29582
29583
29584
29585 while ((badsubfaces->items > 0) && (steinerleft != 0)) {
29586
29587 encloop = dequeueencsub(&quenumber);
29588 splitsub = encloop->ss;
29589
29590 setshell2badface(splitsub, NULL);
29591
29592 if (!isdead(&splitsub)
29593 && (sorg(splitsub) == encloop->forg)
29594 && (sdest(splitsub) == encloop->fdest)
29595 && (sapex(splitsub) == encloop->fapex)) {
29596 if (b->verbose > 1) {
29597 printf(" Dequeuing ensub (%d, %d, %d) [%d].\n",
29598 pointmark(encloop->forg), pointmark(encloop->fdest),
29599 pointmark(encloop->fapex), quenumber);
29600 }
29601
29602 makepoint(&newpt);
29603 for (i = 0; i < 3; i++) newpt[i] = encloop->cent[i];
29604 setpointtype(newpt, FREESUBVERTEX);
29605 setpoint2sh(newpt, sencode(splitsub));
29606
29607 abovepoint = facetabovepointarray[shellmark(splitsub)];
29608 if (abovepoint == (point) NULL) {
29609 getfacetabovepoint(&splitsub);
29610 }
29611
29612
29613 loc = locatesub(newpt, &splitsub, 1, b->epsilon * 1e+2);
29614 if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29615
29616 formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29617 &subceillist, tetlists, ceillists);
29618
29619 reject = tallencsegs(newpt, 2, ceillists);
29620
29621 if (!reject) {
29622 reject = !acceptfacpt(newpt, subceillist, verlist);
29623 }
29624 if (!reject) {
29625
29626 reject = !trimbowatcavity(newpt, NULL, n, &sublist, &subceillist,
29627 tetlists, ceillists, -1.0);
29628 }
29629 if (!reject) {
29630
29631
29632
29633
29634 reject = !sinfected(encloop->ss);
29635 }
29636 if (!reject) {
29637 if (checkpbcs) {
29638 if (shellpbcgroup(splitsub) >= 0) {
29639
29640 makepoint(&sympt);
29641 symloc = getsubpbcsympoint(newpt,&splitsub,sympt,&symsplitsub);
29642 if (symloc != ONVERTEX) {
29643
29644 releasebowatcavity(NULL, 2, &sublist, &subceillist, tetlists,
29645 ceillists);
29646
29647 formbowatcavity(sympt, NULL, &symsplitsub, &n, NULL, &sublist,
29648 &subceillist, tetlists, ceillists);
29649 reject = tallencsegs(sympt, 2, ceillists);
29650 if (!reject) {
29651 reject = !acceptfacpt(sympt, subceillist, verlist);
29652 }
29653 if (!reject) {
29654 reject = !trimbowatcavity(sympt,NULL,n,&sublist,&subceillist,
29655 tetlists, ceillists, -1.0);
29656 }
29657 if (!reject) {
29658
29659 setpoint2pbcpt(newpt, sympt);
29660 setpoint2pbcpt(sympt, newpt);
29661 setpointtype(sympt, FREESUBVERTEX);
29662 setpoint2sh(sympt, sencode(symsplitsub));
29663
29664 e1 = sorg(symsplitsub);
29665 bowatinsertsite(sympt, NULL, n, &sublist, &subceillist,
29666 tetlists,ceillists,NULL,NULL,false,true,chkbadtet);
29667 setnewpointsize(sympt, e1, NULL);
29668 if (steinerleft > 0) steinerleft--;
29669
29670 releasebowatcavity(NULL, n, &sublist, &subceillist, tetlists,
29671 ceillists);
29672 } else {
29673
29674
29675
29676
29677 pointdealloc(sympt);
29678
29679 }
29680 } else {
29681
29682 pointdealloc(sympt);
29683
29684 reject = true;
29685 }
29686 }
29687 }
29688 }
29689 if (!reject) {
29690
29691 if (checkpbcs) {
29692 if (shellpbcgroup(splitsub) >= 0) {
29693
29694 formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29695 &subceillist, tetlists, ceillists);
29696 trimbowatcavity(newpt, NULL, n, &sublist, &subceillist, tetlists,
29697 ceillists, -1.0);
29698 }
29699 }
29700
29701 e1 = sorg(splitsub);
29702 bowatinsertsite(newpt, NULL, n, &sublist, &subceillist, tetlists,
29703 ceillists, NULL, NULL, true, true, chkbadtet);
29704 setnewpointsize(newpt, e1, NULL);
29705 if (steinerleft > 0) steinerleft--;
29706 } else {
29707
29708
29709
29710
29711
29712
29713 pointdealloc(newpt);
29714 }
29715
29716 releasebowatcavity(NULL,n,&sublist,&subceillist,tetlists,ceillists);
29717 if (reject) {
29718
29719 if (badsubsegs->items > 0) {
29720
29721 oldptnum = points->items;
29722 repairencsegs(true, chkbadtet);
29723 if (points->items > oldptnum) {
29724
29725 splitsub = encloop->ss;
29726 if (!isdead(&splitsub)) {
29727 if (!shell2badface(splitsub)) {
29728 checksub4encroach(&splitsub, NULL, true);
29729 }
29730 }
29731 }
29732 }
29733 }
29734 } else {
29735
29736
29737
29738
29739
29740
29741
29742
29743
29744 if (loc == ONVERTEX) {
29745 printf("Internal error in repairencsubs():\n");
29746 printf(" During repairing encroached subface (%d, %d, %d)\n",
29747 pointmark(encloop->forg), pointmark(encloop->fdest),
29748 pointmark(encloop->fapex));
29749 printf(" New point %d is coincident with an existing vertex %d\n",
29750 pointmark(newpt), pointmark(sorg(splitsub)));
29751 internalerror();
29752 }
29753
29754
29755
29756 pointdealloc(newpt);
29757 }
29758 } else {
29759 if (!isdead(&splitsub)) {
29760
29761 checksub4encroach(&splitsub, NULL, true);
29762 }
29763 }
29764
29765 badfacedealloc(badsubfaces, encloop);
29766 }
29767
29768 delete verlist;
29769 }
29770
29772
29773
29774
29775
29776
29777
29778
29779
29780
29782
29783 void tetgenmesh::repairbadtets()
29784 {
29785 list *tetlist, *ceillist;
29786 list *verlist;
29787 badface *badtet;
29788 triface starttet;
29789 point newpt, e1;
29790 enum locateresult loc;
29791 bool reject;
29792 long oldptnum;
29793 int i;
29794
29795 tetlist = new list(sizeof(triface), NULL, 1024);
29796 ceillist = new list(sizeof(triface), NULL, 1024);
29797 verlist = new list(sizeof(point *), NULL, 256);
29798
29799
29800
29801 while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
29802
29803 badtet = topbadtetra();
29804
29805
29806 if ((badtet != (badface *) NULL) && !isdead(&badtet->tt)
29807 && org(badtet->tt) == badtet->forg
29808 && dest(badtet->tt) == badtet->fdest
29809 && apex(badtet->tt) == badtet->fapex
29810 && oppo(badtet->tt) == badtet->foppo) {
29811 if (b->verbose > 1) {
29812 printf(" Dequeuing btet (%d, %d, %d, %d).\n",
29813 pointmark(badtet->forg), pointmark(badtet->fdest),
29814 pointmark(badtet->fapex), pointmark(badtet->foppo));
29815 }
29816
29817 makepoint(&newpt);
29818 for (i = 0; i < 3; i++) newpt[i] = badtet->cent[i];
29819 setpointtype(newpt, FREEVOLVERTEX);
29820
29821 starttet = badtet->tt;
29822 loc = preciselocate(newpt, &starttet, tetrahedrons->items);
29823 if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29824
29825 infect(starttet);
29826 tetlist->append(&starttet);
29827 formbowatcavityquad(newpt, tetlist, ceillist);
29828
29829 reject = tallencsegs(newpt, 1, &ceillist);
29830 if (!reject) {
29831
29832 reject = tallencsubs(newpt, 1, &ceillist);
29833 }
29834
29835
29836 if (!reject) {
29837 reject = !acceptvolpt(newpt, ceillist, verlist);
29838 }
29839 if (!reject) {
29840 reject = !trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist,
29841 &ceillist, -1.0);
29842 }
29843 if (!reject) {
29844
29845
29846
29847
29848 reject = !infected(badtet->tt);
29849 if (reject) outbowatcircumcount++;
29850 }
29851 if (!reject) {
29852
29853 e1 = org(starttet);
29854
29855 bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist,
29856 NULL, NULL, false, false, true);
29857 setnewpointsize(newpt, e1, NULL);
29858 if (steinerleft > 0) steinerleft--;
29859 } else {
29860
29861
29862
29863
29864
29865
29866 pointdealloc(newpt);
29867
29868 for (i = 0; i < tetlist->len(); i++) {
29869 starttet = * (triface *)(* tetlist)[i];
29870 uninfect(starttet);
29871 }
29872 }
29873 tetlist->clear();
29874 ceillist->clear();
29875
29876 if (reject) {
29877 oldptnum = points->items;
29878 if (badsubsegs->items > 0) {
29879 repairencsegs(true, true);
29880 }
29881 if (badsubfaces->items > 0) {
29882 repairencsubs(true);
29883 }
29884 if (points->items > oldptnum) {
29885
29886
29887 starttet = badtet->tt;
29888 if (!isdead(&starttet)) {
29889 checktet4badqual(&starttet, true);
29890 }
29891 }
29892 }
29893 } else {
29894
29895
29896
29897
29898
29899
29900
29901
29902
29903 if (loc == ONVERTEX) {
29904 printf("Internal error in repairbadtets():\n");
29905 printf(" During repairing bad tet (%d, %d, %d, %d)\n",
29906 pointmark(badtet->forg), pointmark(badtet->fdest),
29907 pointmark(badtet->fapex), pointmark(badtet->foppo));
29908 printf(" New point %d is coincident with an existing vertex %d\n",
29909 pointmark(newpt), pointmark(org(starttet)));
29910 internalerror();
29911 }
29912
29913
29914
29915
29916 pointdealloc(newpt);
29917 }
29918 }
29919
29920 dequeuebadtet();
29921 }
29922
29923 delete tetlist;
29924 delete ceillist;
29925 delete verlist;
29926 }
29927
29929
29930
29931
29933
29934 void tetgenmesh::enforcequality()
29935 {
29936 long total, vertcount;
29937 int i;
29938
29939 if (!b->quiet) {
29940 printf("Adding Steiner points to enforce quality.\n");
29941 }
29942
29943 total = vertcount = 0l;
29944 if (b->conformdel) {
29945 r2count = r3count = 0l;
29946 }
29947
29948
29949 if (b->conformdel && b->refine) {
29950 markacutevertices(65.0);
29951 }
29952
29953 if (!b->metric) {
29954
29955 marksharpsegments(65.0);
29956
29957 decidefeaturepointsizes();
29958 }
29959
29960
29961 badsubsegs = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29962
29963 tallencsegs(NULL, 0, NULL);
29964 if (b->verbose && badsubsegs->items > 0) {
29965 printf(" Splitting encroached subsegments.\n");
29966 }
29967 vertcount = points->items;
29968
29969 repairencsegs(false, false);
29970 if (b->verbose > 0) {
29971 printf(" %ld split points.\n", points->items - vertcount);
29972 }
29973 total += points->items - vertcount;
29974
29975
29976 badsubfaces = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
29977
29978 for (i = 0; i < 3; i++) subquefront[i] = (badface *) NULL;
29979 for (i = 0; i < 3; i++) subquetail[i] = &subquefront[i];
29980
29981 tallencsubs(NULL, 0, NULL);
29982 if (b->verbose && badsubfaces->items > 0) {
29983 printf(" Splitting encroached subfaces.\n");
29984 }
29985 vertcount = points->items;
29986
29987 repairencsubs(false);
29988 if (b->verbose > 0) {
29989 printf(" %ld split points.\n", points->items - vertcount);
29990 }
29991 total += points->items - vertcount;
29992
29993
29994
29995
29996 if ((b->minratio > 0.0) || b->varvolume || b->fixedvolume) {
29997
29998 badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
29999
30000 for (i = 0; i < 64; i++) tetquefront[i] = (badface *) NULL;
30001 firstnonemptyq = -1;
30002 recentq = -1;
30003
30004 cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30005 cosmindihed = cos(b->mindihedral * PI / 180.0);
30006 tallbadtetrahedrons();
30007 if (b->verbose && badtetrahedrons->items > 0) {
30008 printf(" Splitting bad tetrahedra.\n");
30009 }
30010 vertcount = points->items;
30011 repairbadtets();
30012 if (b->verbose > 0) {
30013 printf(" %ld refinement points.\n", points->items - vertcount);
30014 }
30015 total += points->items - vertcount;
30016 delete badtetrahedrons;
30017 }
30018
30019 if (b->verbose > 0) {
30020 printf(" Totally added %ld points.\n", total);
30021 }
30022
30023 delete badsubfaces;
30024 delete badsubsegs;
30025 }
30026
30027
30028
30029
30030
30031
30032
30033
30034
30035 void tetgenmesh::dumpbadtets()
30036 {
30037 FILE *fout;
30038 badface *remtet;
30039
30040
30041 printf(" Writing bad tets to file bad-dump.lua.\n");
30042 fout = fopen("bad-dump.lua", "w");
30043 fprintf(fout, "-- %ld remaining bad tets (> %g degree).\n",
30044 badtetrahedrons->items, b->maxdihedral);
30045 badtetrahedrons->traversalinit();
30046 remtet = badfacetraverse(badtetrahedrons);
30047 while (remtet != (badface *) NULL) {
30048 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30049 dest(remtet->tt) == remtet->fdest &&
30050 apex(remtet->tt) == remtet->fapex &&
30051 oppo(remtet->tt) == remtet->foppo) {
30052 fprintf(fout, "p:draw_tet(%d, %d, %d, %d) -- %g\n",
30053 pointmark(remtet->forg), pointmark(remtet->fdest),
30054 pointmark(remtet->fapex), pointmark(remtet->foppo),
30055 acos(remtet->key) * 180.0 / PI);
30056 }
30057 remtet = badfacetraverse(badtetrahedrons);
30058 }
30059 fclose(fout);
30060 }
30061
30063
30064
30065
30066
30067
30068
30069
30070
30071
30073
30074 bool tetgenmesh::checktet4ill(triface* testtet, bool enqflag)
30075 {
30076 badface *newbadtet;
30077 triface checktet;
30078 face checksh1, checksh2;
30079 face checkseg;
30080 bool illflag;
30081 int i;
30082
30083 illflag = false;
30084 for (testtet->loc = 0; testtet->loc < 4; testtet->loc++) {
30085 tspivot(*testtet, checksh1);
30086 if (checksh1.sh != dummysh) {
30087 testtet->ver = 0;
30088 findedge(&checksh1, org(*testtet), dest(*testtet));
30089 for (i = 0; i < 3; i++) {
30090 fnext(*testtet, checktet);
30091 tspivot(checktet, checksh2);
30092 if (checksh2.sh != dummysh) {
30093
30094 sspivot(checksh1, checkseg);
30095 if (checkseg.sh == dummysh) {
30096
30097
30098 enextfnextself(*testtet);
30099 enextself(*testtet);
30100 illflag = true;
30101 break;
30102 }
30103 }
30104 enextself(*testtet);
30105 senextself(checksh1);
30106 }
30107 }
30108 if (illflag) break;
30109 }
30110
30111 if (illflag && enqflag) {
30112
30113 newbadtet = (badface *) badtetrahedrons->alloc();
30114 newbadtet->tt = *testtet;
30115 newbadtet->key = -1.0;
30116 for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
30117 newbadtet->forg = org(*testtet);
30118 newbadtet->fdest = dest(*testtet);
30119 newbadtet->fapex = apex(*testtet);
30120 newbadtet->foppo = oppo(*testtet);
30121 newbadtet->nextitem = (badface *) NULL;
30122 if (b->verbose > 2) {
30123 printf(" Queueing illtet: (%d, %d, %d, %d).\n",
30124 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30125 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo));
30126 }
30127 }
30128
30129 return illflag;
30130 }
30131
30133
30134
30135
30136
30137
30138
30139
30140
30141
30142
30143
30144
30145
30146
30147
30149
30150 bool tetgenmesh::checktet4opt(triface* testtet, bool enqflag)
30151 {
30152 badface *newbadtet;
30153 point pa, pb, pc, pd;
30154 REAL N[4][3], len;
30155 REAL cosd;
30156 bool enq;
30157 int i, j;
30158
30159 cosd = 0.0;
30160 enq = false;
30161 pa = (point) testtet->tet[4];
30162 pb = (point) testtet->tet[5];
30163 pc = (point) testtet->tet[6];
30164 pd = (point) testtet->tet[7];
30165
30166 tetallnormal(pa, pb, pc, pd, N, NULL);
30167
30168 for (i = 0; i < 4; i++) {
30169 len = sqrt(dot(N[i], N[i]));
30170 if (len != 0.0) {
30171 for (j = 0; j < 3; j++) N[i][j] /= len;
30172 }
30173 }
30174
30175 for (i = 0; i < 6; i++) {
30176
30177 testtet->loc = 0;
30178 testtet->ver = 0;
30179 switch (i) {
30180 case 0:
30181 cosd = -dot(N[2], N[3]);
30182 break;
30183 case 1:
30184 enextfnextself(*testtet);
30185 enextself(*testtet);
30186 cosd = -dot(N[0], N[1]);
30187 break;
30188 case 2:
30189 enextfnextself(*testtet);
30190 enext2self(*testtet);
30191 cosd = -dot(N[0], N[2]);
30192 break;
30193 case 3:
30194 enextself(*testtet);
30195 cosd = -dot(N[0], N[3]);
30196 break;
30197 case 4:
30198 enext2fnextself(*testtet);
30199 enextself(*testtet);
30200 cosd = -dot(N[1], N[2]);
30201 break;
30202 case 5:
30203 enext2self(*testtet);
30204 cosd = -dot(N[1], N[3]);
30205 break;
30206 }
30207 if (cosd < cosmaxdihed) {
30208
30209 if (enqflag) {
30210
30211 newbadtet = (badface *) badtetrahedrons->alloc();
30212 newbadtet->tt = *testtet;
30213 newbadtet->key = cosd;
30214 for (j = 0; j < 3; j++) newbadtet->cent[j] = 0.0;
30215 newbadtet->forg = org(*testtet);
30216 newbadtet->fdest = dest(*testtet);
30217 newbadtet->fapex = apex(*testtet);
30218 newbadtet->foppo = oppo(*testtet);
30219 newbadtet->nextitem = (badface *) NULL;
30220 if (b->verbose > 2) {
30221 printf(" Queueing tet: (%d, %d, %d, %d), dihed %g (degree).\n",
30222 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30223 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
30224 acos(cosd) * 180.0 / PI);
30225 }
30226 }
30227 enq = true;
30228 }
30229 }
30230
30231 return enq;
30232 }
30233
30235
30236
30237
30238
30239
30240
30241
30242
30243
30244
30245
30246
30247
30248
30249
30250
30251
30252
30253
30254
30256
30257 bool tetgenmesh::removeedge(badface* remedge, bool optflag)
30258 {
30259 triface abcd, badc;
30260 triface baccasing, abdcasing;
30261 triface abtetlist[11];
30262 triface bftetlist[11];
30263 triface newtetlist[33];
30264 face checksh;
30265 enum fliptype fty;
30266 REAL key;
30267 bool remflag, subflag;
30268 int n, n1, m, i, j;
30269
30270
30271
30272 abcd = remedge->tt;
30273 adjustedgering(abcd, CCW);
30274 i = 0;
30275 do {
30276 sym(abcd, baccasing);
30277
30278 if (baccasing.tet == dummytet) {
30279 fnext(abcd, badc);
30280 sym(badc, abdcasing);
30281 if (abdcasing.tet == dummytet) {
30282
30283 if (removetetbypeeloff(&abcd)) {
30284 if (b->verbose > 1) {
30285 printf(" Stripped tet from the mesh.\n");
30286 }
30287 optcount[0]++;
30288 return true;
30289 }
30290 }
30291 }
30292
30293 enext2fnextself(abcd);
30294 enext2self(abcd);
30295 esymself(abcd);
30296 i++;
30297 } while (i < 2);
30298
30299
30300 subflag = false;
30301 abcd = remedge->tt;
30302 adjustedgering(abcd, CW);
30303 n = 0;
30304 abtetlist[n] = abcd;
30305 do {
30306
30307 if (n == 10) break;
30308
30309 tspivot(abtetlist[n], checksh);
30310 if (checksh.sh != dummysh) {
30311
30312
30313 subflag = true; break;
30314 }
30315
30316 fnext(abtetlist[n], abtetlist[n + 1]);
30317 n++;
30318 } while (apex(abtetlist[n]) != apex(abcd));
30319
30320 remflag = false;
30321 key = remedge->key;
30322
30323 if (subflag && optflag) {
30324 abcd = remedge->tt;
30325 adjustedgering(abcd, CCW);
30326
30327 for (j = 0; j < 2; j++) {
30328 if (j == 0) {
30329 enext2fnext(abcd, abtetlist[0]);
30330 } else {
30331 enextfnext(abcd, abtetlist[0]);
30332 }
30333 fty = categorizeface(abtetlist[0]);
30334 if (fty == T23) {
30335
30336 sym(abtetlist[0], abtetlist[1]);
30337 assert(abtetlist[1].tet != dummytet);
30338 n = 2;
30339 m = 3;
30340 remflag = removefacebyflip23(&key, abtetlist, newtetlist, NULL);
30341 } else if (fty == T22) {
30342
30343 n = 2;
30344 newtetlist[0] = abtetlist[0];
30345 adjustedgering(newtetlist[0], CW);
30346 fnext(newtetlist[0], newtetlist[1]);
30347 assert(newtetlist[1].tet != dummytet);
30348
30349 if (fnext(newtetlist[1], newtetlist[2])) {
30350 fnext(newtetlist[2], newtetlist[3]);
30351 assert(newtetlist[3].tet != dummytet);
30352 n = 4;
30353 }
30354 m = n;
30355 remflag = removeedgebyflip22(&key, n, newtetlist, NULL);
30356 }
30357
30358 if (remflag) {
30359 if (b->verbose > 1) {
30360 printf(" Done flip %d-to-%d. Qual: %g -> %g.\n", n, m,
30361 acos(remedge->key) / PI * 180.0, acos(key) / PI * 180.0);
30362 }
30363
30364 if (m == 3) {
30365 for (i = 0; i < n; i++) {
30366 tetrahedrondealloc(abtetlist[i].tet);
30367 }
30368 }
30369 for (i = 0; i < m; i++) {
30370 checktet4opt(&(newtetlist[i]), true);
30371 }
30372 optcount[1]++;
30373 return true;
30374 }
30375 }
30376
30377 return false;
30378 }
30379
30380
30381 if (n == 3) {
30382
30383 remflag = removeedgebyflip32(&key, abtetlist, newtetlist, NULL);
30384 } else if ((n == 4) || (n == 5) || (n == 6)) {
30385
30386 remflag = removeedgebytranNM(&key,n,abtetlist,newtetlist,NULL,NULL,NULL);
30387 } else {
30388 if (b->verbose > 1) {
30389 printf(" !! Unhandled case: n = %d.\n", n);
30390 }
30391 }
30392 if (remflag) {
30393 optcount[n]++;
30394
30395 for (i = 0; i < n; i++) {
30396 tetrahedrondealloc(abtetlist[i].tet);
30397 }
30398 m = (n - 2) * 2;
30399 if (b->verbose > 1) {
30400 printf(" Done flip %d-to-%d. ", n, m);
30401 if (optflag) {
30402 printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30403 acos(key) / PI * 180.0);
30404 }
30405 printf("\n");
30406 }
30407 }
30408
30409 if (!remflag && (key == remedge->key) && (n < 7)) {
30410
30411 n1 = 0;
30412 remflag = removeedgebycombNM(&key, n, abtetlist, &n1, bftetlist,
30413 newtetlist, NULL);
30414 if (remflag) {
30415 optcount[9]++;
30416
30417 for (i = 0; i < n; i++) {
30418 tetrahedrondealloc(abtetlist[i].tet);
30419 }
30420 for (i = 0; i < n1; i++) {
30421 if (!isdead(&(bftetlist[i]))) {
30422 tetrahedrondealloc(bftetlist[i].tet);
30423 }
30424 }
30425 m = ((n1 - 2) * 2 - 1) + (n - 3) * 2;
30426 if (b->verbose > 1) {
30427 printf(" Done flip %d-to-%d (n-1=%d, n1=%d). ", n+n1-2, m, n-1,n1);
30428 if (optflag) {
30429 printf("Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30430 acos(key) / PI * 180.0);
30431 }
30432 printf("\n");
30433 }
30434 }
30435 }
30436
30437 if (remflag) {
30438
30439 for (i = 0; i < m; i++) {
30440 if (optflag) {
30441 checktet4opt(&(newtetlist[i]), true);
30442 } else {
30443 checktet4ill(&(newtetlist[i]), true);
30444 }
30445 }
30446 }
30447
30448 return remflag;
30449 }
30450
30452
30453
30454
30455
30456
30457
30459
30460 bool tetgenmesh::smoothsliver(badface* remedge, list *starlist)
30461 {
30462 triface checktet;
30463 point smthpt;
30464 bool smthed;
30465 int idx, i, j;
30466
30467
30468 smthed = false;
30469 for (i = 0; i < 4 && !smthed; i++) {
30470 smthpt = (point) remedge->tt.tet[4 + i];
30471
30472 if (pointtype(smthpt) == FREEVOLVERTEX) {
30473
30474 idx = pointmark(smthpt) - in->firstnumber;
30475 if (!(idx < in->numberofpoints)) {
30476
30477 starlist->append(&(remedge->tt.tet));
30478 formstarpolyhedron(smthpt, starlist, NULL, false);
30479 smthed = smoothpoint(smthpt,NULL,NULL,starlist,false,&remedge->key);
30480
30481 if (smthed) {
30482 for (j = 0; j < starlist->len(); j++) {
30483 checktet = * (triface *)(* starlist)[j];
30484 checktet4opt(&checktet, true);
30485 }
30486 }
30487 starlist->clear();
30488 }
30489 }
30490 }
30491
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 return smthed;
30532 }
30533
30535
30536
30537
30538
30539
30540
30542
30543 bool tetgenmesh::splitsliver(badface *remedge, list *tetlist, list *ceillist)
30544 {
30545 triface starttet;
30546 face checkseg;
30547 point newpt, pt[4];
30548 bool remflag;
30549 int i;
30550
30551 starttet = remedge->tt;
30552
30553
30554 adjustedgering(starttet, CCW);
30555 enextfnextself(starttet);
30556 enextself(starttet);
30557 tsspivot(&starttet, &checkseg);
30558 if (b->nobisect == 0) {
30559 if (checkseg.sh != dummysh) {
30560
30561
30562 checkseg.shver = 0;
30563 pt[0] = sorg(checkseg);
30564 pt[1] = sdest(checkseg);
30565 makepoint(&newpt);
30566 getsplitpoint(pt[0], pt[1], NULL, newpt);
30567 setpointtype(newpt, FREESEGVERTEX);
30568 setpoint2sh(newpt, sencode(checkseg));
30569
30570 sstpivot(&checkseg, &starttet);
30571 splittetedge(newpt, &starttet, NULL);
30572
30573 sstpivot(&checkseg, &starttet);
30574 ceillist->append(&starttet);
30575 formstarpolyhedron(newpt, ceillist, NULL, true);
30576 setnewpointsize(newpt, pt[0], NULL);
30577 if (steinerleft > 0) steinerleft--;
30578
30579 smoothpoint(newpt, pt[0], pt[1], ceillist, false, NULL);
30580
30581 for (i = 0; i < ceillist->len(); i++) {
30582 starttet = * (triface *)(* ceillist)[i];
30583 checktet4opt(&starttet, true);
30584 }
30585 ceillist->clear();
30586 return true;
30587 }
30588 }
30589
30590
30591 for (i = 0; i < 4; i++) {
30592 pt[i] = (point) starttet.tet[4 + i];
30593 }
30594
30595 makepoint(&newpt);
30596 for (i = 0; i < 3; i++) {
30597 newpt[i] = 0.25 * (pt[0][i] + pt[1][i] + pt[2][i] + pt[3][i]);
30598 }
30599 setpointtype(newpt, FREEVOLVERTEX);
30600
30601
30602 remflag = false;
30603 infect(starttet);
30604 tetlist->append(&starttet);
30605 formbowatcavityquad(newpt, tetlist, ceillist);
30606 if (trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, -1.0)) {
30607
30608 if (smoothpoint( newpt, NULL, NULL, ceillist, false, &remedge->key)) {
30609
30610 bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, NULL,
30611 NULL, false, false, false);
30612 setnewpointsize(newpt, pt[0], NULL);
30613 if (steinerleft > 0) steinerleft--;
30614
30615 for (i = 0; i < ceillist->len(); i++) {
30616 starttet = * (triface *)(* ceillist)[i];
30617 checktet4opt(&starttet, true);
30618 }
30619 remflag = true;
30620 }
30621 }
30622
30623 if (!remflag) {
30624
30625 pointdealloc(newpt);
30626
30627 for (i = 0; i < tetlist->len(); i++) {
30628 starttet = * (triface *)(* tetlist)[i];
30629 uninfect(starttet);
30630 }
30631 }
30632 tetlist->clear();
30633 ceillist->clear();
30634
30635 return remflag;
30636 }
30637
30639
30640
30641
30643
30644 void tetgenmesh::tallslivers(bool optflag)
30645 {
30646 triface tetloop;
30647
30648 tetrahedrons->traversalinit();
30649 tetloop.tet = tetrahedrontraverse();
30650 while (tetloop.tet != (tetrahedron *) NULL) {
30651 if (optflag) {
30652 checktet4opt(&tetloop, true);
30653 } else {
30654 checktet4ill(&tetloop, true);
30655 }
30656 tetloop.tet = tetrahedrontraverse();
30657 }
30658 }
30659
30661
30662
30663
30664
30665
30666
30667
30668
30669
30670
30671
30673
30674 void tetgenmesh::optimizemesh(bool optflag)
30675 {
30676 list *splittetlist, *tetlist, *ceillist;
30677 badface *remtet, *lastentry;
30678 REAL maxdihed, objdihed, curdihed;
30679 long oldnum;
30680 int iter, i;
30681
30682 objdihed = 0.0;
30683
30684 if (!b->quiet) {
30685 if (optflag) {
30686 printf("Optimizing mesh.\n");
30687 } else {
30688 printf("Repairing mesh.\n");
30689 }
30690 }
30691
30692 #ifdef SELF_CHECK
30693 if (optflag && (b->verbose)) {
30694 printf(" level = %d.\n", b->optlevel);
30695 }
30696 #endif
30697
30698
30699 badtetrahedrons = new memorypool(sizeof(badface), ELEPERBLOCK, POINTER, 0);
30700 if (optflag) {
30701 cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30702 cosmindihed = cos(b->mindihedral * PI / 180.0);
30703
30704 maxdihed = b->maxdihedral / 180.0 * PI;
30705
30706 objdihed = b->maxdihedral + 5.0;
30707 if (objdihed < 170.0) objdihed = 170.0;
30708 objdihed = objdihed / 180.0 * PI;
30709 }
30710
30711 tallslivers(optflag);
30712
30713 optcount[0] = 0l;
30714 optcount[1] = 0l;
30715 optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l;
30716 optcount[9] = 0l;
30717
30718
30719 lastentry = (badface *) NULL;
30720
30721 while (badtetrahedrons->items > 0) {
30722 badtetrahedrons->traversalinit();
30723 remtet = badfacetraverse(badtetrahedrons);
30724 while (remtet != (badface *) NULL) {
30725
30726
30727 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30728 dest(remtet->tt) == remtet->fdest &&
30729 apex(remtet->tt) == remtet->fapex &&
30730 oppo(remtet->tt) == remtet->foppo) {
30731 if (b->verbose > 1) {
30732 printf(" Repair tet (%d, %d, %d, %d) %g (degree).\n",
30733 pointmark(remtet->forg), pointmark(remtet->fdest),
30734 pointmark(remtet->fapex), pointmark(remtet->foppo),
30735 acos(remtet->key) / PI * 180.0);
30736 }
30737 if (!removeedge(remtet, optflag)) {
30738
30739 if (lastentry != (badface *) NULL) {
30740 if (remtet == lastentry) break;
30741 } else {
30742
30743 lastentry = remtet;
30744 }
30745 } else {
30746
30747 lastentry = (badface *) NULL;
30748
30749 badfacedealloc(badtetrahedrons, remtet);
30750 }
30751 } else {
30752
30753 badfacedealloc(badtetrahedrons, remtet);
30754 }
30755 remtet = badfacetraverse(badtetrahedrons);
30756 }
30757
30758 if (remtet != (badface *) NULL) break;
30759 }
30760
30761 if (b->verbose) {
30762 if (optcount[0] > 0l) {
30763 printf(" %ld tets are peeled off.\n", optcount[0]);
30764 }
30765 if (optcount[1] > 0l) {
30766 printf(" %ld faces are flipped.\n", optcount[1]);
30767 }
30768 if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30769 optcount[9] > 0l) {
30770 printf(" %ld edges are flipped.\n", optcount[3] + optcount[4] +
30771 optcount[5] + optcount[6] + optcount[9]);
30772 }
30773
30774
30775
30776 }
30777
30778 if ((badtetrahedrons->items > 0l) && optflag && (b->optlevel > 2)) {
30779 splittetlist = new list(sizeof(badface), NULL, 256);
30780 tetlist = new list(sizeof(triface), NULL, 256);
30781 ceillist = new list(sizeof(triface), NULL, 256);
30782 oldnum = points->items;
30783 smoothsegverts = smoothvolverts = 0;
30784 optcount[1] = 0l;
30785 optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l;
30786 optcount[9] = 0l;
30787 iter = 0;
30788
30789 do {
30790
30791 badtetrahedrons->traversalinit();
30792 remtet = badfacetraverse(badtetrahedrons);
30793 while (remtet != (badface *) NULL) {
30794 splittetlist->append(remtet);
30795
30796 badfacedealloc(badtetrahedrons, remtet);
30797 remtet = badfacetraverse(badtetrahedrons);
30798 }
30799 for (i = 0; i < splittetlist->len(); i++) {
30800 remtet = (badface *)(* splittetlist)[i];
30801
30802
30803 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30804 dest(remtet->tt) == remtet->fdest &&
30805 apex(remtet->tt) == remtet->fapex &&
30806 oppo(remtet->tt) == remtet->foppo) {
30807
30808 curdihed = facedihedral(remtet->forg, remtet->fdest, remtet->fapex,
30809 remtet->foppo);
30810
30811 if (curdihed > PI) curdihed = 2 * PI - curdihed;
30812
30813 if (curdihed > objdihed) {
30814 remtet->key = cos(curdihed);
30815 if (b->verbose > 1) {
30816 printf(" Get sliver (%d, %d, %d, %d) %g (degree).\n",
30817 pointmark(remtet->forg), pointmark(remtet->fdest),
30818 pointmark(remtet->fapex), pointmark(remtet->foppo),
30819 acos(remtet->key) / PI * 180.0);
30820 }
30821 if (!removeedge(remtet, optflag)) {
30822 if (!smoothsliver(remtet, tetlist)) {
30823 splitsliver(remtet, tetlist, ceillist);
30824 }
30825 }
30826 }
30827 }
30828 }
30829 iter++;
30830 } while ((badtetrahedrons->items > 0l) && (iter < b->optpasses));
30831
30832 if (b->verbose) {
30833 printf(" %d passes.\n", iter);
30834 if ((points->items - oldnum) > 0l) {
30835 printf(" %ld points are inserted (%d on segment).\n",
30836 points->items - oldnum, smoothsegverts);
30837 }
30838 if (optcount[1] > 0l) {
30839 printf(" %ld faces are flipped.\n", optcount[1]);
30840 }
30841 if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30842 optcount[9] > 0l) {
30843 printf(" %ld edges are flipped.\n", optcount[3] + optcount[4] +
30844 optcount[5] + optcount[6] + optcount[9]);
30845 }
30846
30847
30848
30849 }
30850 delete tetlist;
30851 delete ceillist;
30852 delete splittetlist;
30853 }
30854
30855 delete badtetrahedrons;
30856 badtetrahedrons = (memorypool *) NULL;
30857 }
30858
30859
30860
30861
30862
30863
30864
30865
30866
30868
30869
30870
30871
30872
30873
30874
30875
30877
30878 void tetgenmesh::transfernodes()
30879 {
30880 point pointloop;
30881 REAL x, y, z;
30882 int coordindex;
30883 int attribindex;
30884 int mtrindex;
30885 int i, j;
30886
30887
30888 coordindex = 0;
30889 attribindex = 0;
30890 mtrindex = 0;
30891 for (i = 0; i < in->numberofpoints; i++) {
30892 makepoint(&pointloop);
30893
30894 x = pointloop[0] = in->pointlist[coordindex++];
30895 y = pointloop[1] = in->pointlist[coordindex++];
30896 z = pointloop[2] = in->pointlist[coordindex++];
30897
30898 for (j = 0; j < in->numberofpointattributes; j++) {
30899 pointloop[3 + j] = in->pointattributelist[attribindex++];
30900 }
30901
30902 for (j = 0; j < in->numberofpointmtrs; j++) {
30903 pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
30904 }
30905
30906 if (i == 0) {
30907 xmin = xmax = x;
30908 ymin = ymax = y;
30909 zmin = zmax = z;
30910 } else {
30911 xmin = (x < xmin) ? x : xmin;
30912 xmax = (x > xmax) ? x : xmax;
30913 ymin = (y < ymin) ? y : ymin;
30914 ymax = (y > ymax) ? y : ymax;
30915 zmin = (z < zmin) ? z : zmin;
30916 zmax = (z > zmax) ? z : zmax;
30917 }
30918 }
30919
30920 x = xmax - xmin;
30921 y = ymax - ymin;
30922 z = zmax - zmin;
30923 longest = sqrt(x * x + y * y + z * z);
30924 if (longest == 0.0) {
30925 printf("Error: The point set is trivial.\n");
30926 terminatetetgen(1);
30927 }
30928
30929 lengthlimit = longest * b->epsilon * 1e+2;
30930 }
30931
30933
30934
30935
30936
30937
30938
30939
30940
30941
30943
30944 void tetgenmesh::jettisonnodes()
30945 {
30946 point pointloop;
30947 bool jetflag;
30948 int oldidx, newidx;
30949 int remcount;
30950
30951 if (!b->quiet) {
30952 printf("Jettisoning redundants points.\n");
30953 }
30954
30955 points->traversalinit();
30956 pointloop = pointtraverse();
30957 oldidx = newidx = 0;
30958 remcount = 0;
30959 while (pointloop != (point) NULL) {
30960 jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) ||
30961 (pointtype(pointloop) == UNUSEDVERTEX);
30962 if (jetflag) {
30963
30964 pointdealloc(pointloop);
30965 remcount++;
30966 } else {
30967
30968 setpointmark(pointloop, newidx + in->firstnumber);
30969 if (in->pointmarkerlist != (int *) NULL) {
30970 if (oldidx < in->numberofpoints) {
30971
30972 in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
30973 }
30974 }
30975 newidx++;
30976 }
30977 oldidx++;
30978 if (oldidx == in->numberofpoints) {
30979
30980 in->numberofpoints -= remcount;
30981
30982 jettisoninverts = remcount;
30983 }
30984 pointloop = pointtraverse();
30985 }
30986 if (b->verbose) {
30987 printf(" %d duplicated vertices have been removed.\n", dupverts);
30988 printf(" %d unused vertices have been removed.\n", unuverts);
30989 }
30990 dupverts = 0;
30991 unuverts = 0;
30992
30993
30994
30995
30996 points->deaditemstack = (void *) NULL;
30997 }
30998
31000
31001
31002
31003
31004
31005
31006
31008
31009 void tetgenmesh::highorder()
31010 {
31011 triface tetloop, worktet;
31012 triface spintet, adjtet;
31013 point torg, tdest, tapex;
31014 point *extralist, *adjextralist;
31015 point newpoint;
31016 int hitbdry, ptmark;
31017 int i, j;
31018
31019 if (!b->quiet) {
31020 printf("Adding vertices for second-order tetrahedra.\n");
31021 }
31022
31023
31024 highordertable = new point[tetrahedrons->items * 6];
31025 if (highordertable == (point *) NULL) {
31026 printf("Error: Out of memory.\n");
31027 terminatetetgen(1);
31028 }
31029
31030
31031
31032
31033
31034
31035 points->deaditemstack = (void *) NULL;
31036
31037
31038
31039 i = 0;
31040 tetrahedrons->traversalinit();
31041 tetloop.tet = tetrahedrontraverse();
31042 while (tetloop.tet != (tetrahedron *) NULL) {
31043 tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
31044 for (j = 0; j < 6; j++) {
31045 highordertable[i + j] = (point) NULL;
31046 }
31047 i += 6;
31048 tetloop.tet = tetrahedrontraverse();
31049 }
31050
31051
31052
31053
31054
31055
31056 tetrahedrons->traversalinit();
31057 tetloop.tet = tetrahedrontraverse();
31058 while (tetloop.tet != (tetrahedron *) NULL) {
31059
31060 extralist = (point *) tetloop.tet[highorderindex];
31061 worktet.tet = tetloop.tet;
31062 for (i = 0; i < 6; i++) {
31063 if (extralist[i] == (point) NULL) {
31064
31065 worktet.loc = edge2locver[i][0];
31066 worktet.ver = edge2locver[i][1];
31067
31068 torg = org(worktet);
31069 tdest = dest(worktet);
31070
31071 newpoint = (point) points->alloc();
31072
31073 for (j = 0; j < 3 + in->numberofpointattributes; j++) {
31074 newpoint[j] = 0.5 * (torg[j] + tdest[j]);
31075 }
31076 ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
31077 setpointmark(newpoint, ptmark);
31078
31079 extralist[i] = newpoint;
31080
31081
31082 tapex = apex(worktet);
31083 spintet = worktet;
31084 hitbdry = 0;
31085 while (hitbdry < 2) {
31086 if (fnextself(spintet)) {
31087
31088 adjextralist = (point *) spintet.tet[highorderindex];
31089
31090 j = locver2edge[spintet.loc][spintet.ver];
31091
31092
31093 if (adjextralist[j] == (point) NULL) {
31094 adjextralist[j] = newpoint;
31095 }
31096 if (apex(spintet) == tapex) {
31097 break;
31098 }
31099 } else {
31100 hitbdry++;
31101 if (hitbdry < 2) {
31102 esym(worktet, spintet);
31103 }
31104 }
31105 }
31106 }
31107 }
31108 tetloop.tet = tetrahedrontraverse();
31109 }
31110 }
31111
31113
31114
31115
31116
31117
31118
31120
31121 void tetgenmesh::outnodes(tetgenio* out)
31122 {
31123 FILE *outfile;
31124 char outnodefilename[FILENAMESIZE];
31125 shellface subptr;
31126 triface adjtet;
31127 face subloop;
31128 point pointloop;
31129 point *extralist, ep[3];
31130 int nextras, bmark, shmark, marker;
31131 int coordindex, attribindex;
31132 int pointnumber, firstindex;
31133 int index, i;
31134
31135 if (out == (tetgenio *) NULL) {
31136 strcpy(outnodefilename, b->outfilename);
31137 strcat(outnodefilename, ".node");
31138 }
31139
31140 if (!b->quiet) {
31141 if (out == (tetgenio *) NULL) {
31142 printf("Writing %s.\n", outnodefilename);
31143 } else {
31144 printf("Writing nodes.\n");
31145 }
31146 }
31147
31148 nextras = in->numberofpointattributes;
31149 bmark = !b->nobound && in->pointmarkerlist;
31150
31151
31152 outfile = (FILE *) NULL;
31153 marker = coordindex = 0;
31154
31155 if (out == (tetgenio *) NULL) {
31156 outfile = fopen(outnodefilename, "w");
31157 if (outfile == (FILE *) NULL) {
31158 printf("File I/O Error: Cannot create file %s.\n", outnodefilename);
31159 terminatetetgen(1);
31160 }
31161
31162
31163 fprintf(outfile, "%ld %d %d %d\n", points->items, 3, nextras, bmark);
31164 } else {
31165
31166 out->pointlist = new REAL[points->items * 3];
31167 if (out->pointlist == (REAL *) NULL) {
31168 printf("Error: Out of memory.\n");
31169 terminatetetgen(1);
31170 }
31171
31172 if (nextras > 0) {
31173 out->pointattributelist = new REAL[points->items * nextras];
31174 if (out->pointattributelist == (REAL *) NULL) {
31175 printf("Error: Out of memory.\n");
31176 terminatetetgen(1);
31177 }
31178 }
31179
31180 if (bmark) {
31181 out->pointmarkerlist = new int[points->items];
31182 if (out->pointmarkerlist == (int *) NULL) {
31183 printf("Error: Out of memory.\n");
31184 terminatetetgen(1);
31185 }
31186 }
31187 out->numberofpoints = points->items;
31188 out->numberofpointattributes = nextras;
31189 coordindex = 0;
31190 attribindex = 0;
31191 }
31192
31193 if (bmark && (b->plc || b->refine)) {
31194
31195 points->traversalinit();
31196 pointloop = pointtraverse();
31197 while (pointloop != (point) NULL) {
31198 setpoint2tet(pointloop, (tetrahedron) NULL);
31199 pointloop = pointtraverse();
31200 }
31201
31202
31203 subfaces->traversalinit();
31204 subloop.sh = shellfacetraverse(subfaces);
31205 while (subloop.sh != (shellface *) NULL) {
31206 subloop.shver = 0;
31207
31208 for (i = 0; i < 3; i++) {
31209 pointloop = (point) subloop.sh[3 + i];
31210 setpoint2tet(pointloop, (tetrahedron) sencode(subloop));
31211 }
31212 if (b->order == 2) {
31213
31214 stpivot(subloop, adjtet);
31215 if (adjtet.tet == dummytet) {
31216 sesymself(subloop);
31217 stpivot(subloop, adjtet);
31218 }
31219 assert(adjtet.tet != dummytet);
31220 extralist = (point *) adjtet.tet[highorderindex];
31221 switch (adjtet.loc) {
31222 case 0:
31223 ep[0] = extralist[0];
31224 ep[1] = extralist[1];
31225 ep[2] = extralist[2];
31226 break;
31227 case 1:
31228 ep[0] = extralist[0];
31229 ep[1] = extralist[4];
31230 ep[2] = extralist[3];
31231 break;
31232 case 2:
31233 ep[0] = extralist[1];
31234 ep[1] = extralist[5];
31235 ep[2] = extralist[4];
31236 break;
31237 case 3:
31238 ep[0] = extralist[2];
31239 ep[1] = extralist[3];
31240 ep[2] = extralist[5];
31241 break;
31242 default: break;
31243 }
31244 for (i = 0; i < 3; i++) {
31245 setpoint2tet(ep[i], (tetrahedron) sencode(subloop));
31246 }
31247 }
31248 subloop.sh = shellfacetraverse(subfaces);
31249 }
31250 }
31251
31252
31253 firstindex = b->zeroindex ? 0 : in->firstnumber;
31254
31255 points->traversalinit();
31256 pointloop = pointtraverse();
31257 pointnumber = firstindex;
31258 index = 0;
31259 while (pointloop != (point) NULL) {
31260 if (bmark) {
31261
31262 marker = 0;
31263
31264 if (index < in->numberofpoints) {
31265
31266 marker = in->pointmarkerlist[index];
31267 }
31268
31269 if ((marker == 0) && (b->plc || b->refine)) {
31270 subptr = (shellface) point2tet(pointloop);
31271 if (subptr != (shellface) NULL) {
31272
31273 marker = 1;
31274 if (in->facetmarkerlist != (int *) NULL) {
31275
31276 sdecode(subptr, subloop);
31277 shmark = shellmark(subloop);
31278 marker = in->facetmarkerlist[shmark - 1];
31279 }
31280 }
31281 }
31282 }
31283 if (out == (tetgenio *) NULL) {
31284
31285 fprintf(outfile, "%4d %.17g %.17g %.17g", pointnumber,
31286 pointloop[0], pointloop[1], pointloop[2]);
31287 for (i = 0; i < nextras; i++) {
31288
31289 fprintf(outfile, " %.17g", pointloop[3 + i]);
31290 }
31291 if (bmark) {
31292
31293 fprintf(outfile, " %d", marker);
31294 }
31295 fprintf(outfile, "\n");
31296 } else {
31297
31298 out->pointlist[coordindex++] = pointloop[0];
31299 out->pointlist[coordindex++] = pointloop[1];
31300 out->pointlist[coordindex++] = pointloop[2];
31301
31302 for (i = 0; i < nextras; i++) {
31303
31304 out->pointattributelist[attribindex++] = pointloop[3 + i];
31305 }
31306 if (bmark) {
31307
31308 out->pointmarkerlist[index] = marker;
31309 }
31310 }
31311 pointloop = pointtraverse();
31312 pointnumber++;
31313 index++;
31314 }
31315
31316 if (out == (tetgenio *) NULL) {
31317 fprintf(outfile, "# Generated by %s\n", b->commandline);
31318 fclose(outfile);
31319 }
31320 }
31321
31323
31324
31325
31327
31328 void tetgenmesh::outmetrics(tetgenio* out)
31329 {
31330 FILE *outfile;
31331 char outmtrfilename[FILENAMESIZE];
31332 list *tetlist, *ptlist;
31333 triface tetloop;
31334 point ptloop, neipt;
31335 REAL lave, len;
31336 int mtrindex;
31337 int i;
31338
31339 lave = 0.0;
31340
31341 if (out == (tetgenio *) NULL) {
31342 strcpy(outmtrfilename, b->outfilename);
31343 strcat(outmtrfilename, ".mtr");
31344 }
31345
31346 if (!b->quiet) {
31347 if (out == (tetgenio *) NULL) {
31348 printf("Writing %s.\n", outmtrfilename);
31349 } else {
31350 printf("Writing metrics.\n");
31351 }
31352 }
31353
31354
31355 outfile = (FILE *) NULL;
31356 mtrindex = 0;
31357
31358 if (out == (tetgenio *) NULL) {
31359 outfile = fopen(outmtrfilename, "w");
31360 if (outfile == (FILE *) NULL) {
31361 printf("File I/O Error: Cannot create file %s.\n", outmtrfilename);
31362 terminatetetgen(1);
31363 }
31364
31365
31366 fprintf(outfile, "%ld %d\n", points->items, 1);
31367 } else {
31368
31369
31370 out->pointmtrlist = new REAL[points->items];
31371 if (out->pointmtrlist == (REAL *) NULL) {
31372 printf("Error: Out of memory.\n");
31373 terminatetetgen(1);
31374 }
31375 out->numberofpointmtrs = 1;
31376 mtrindex = 0;
31377 }
31378
31379
31380 points->traversalinit();
31381 ptloop = pointtraverse();
31382 while (ptloop != (point) NULL) {
31383 setpoint2tet(ptloop, (tetrahedron) NULL);
31384 ptloop = pointtraverse();
31385 }
31386
31387 tetrahedrons->traversalinit();
31388 tetloop.tet = tetrahedrontraverse();
31389 while (tetloop.tet != (tetrahedron *) NULL) {
31390 for (i = 0; i < 4; i++) {
31391 ptloop = (point) tetloop.tet[4 + i];
31392 setpoint2tet(ptloop, encode(tetloop));
31393 }
31394 tetloop.tet = tetrahedrontraverse();
31395 }
31396
31397 tetlist = new list(sizeof(triface), NULL, 256);
31398 ptlist = new list(sizeof(point *), NULL, 256);
31399
31400 points->traversalinit();
31401 ptloop = pointtraverse();
31402 while (ptloop != (point) NULL) {
31403 decode(point2tet(ptloop), tetloop);
31404 if (!isdead(&tetloop)) {
31405
31406 tetlist->append(&tetloop);
31407 formstarpolyhedron(ptloop, tetlist, ptlist, true);
31408
31409
31410 lave = 0.0;
31411 for (i = 0; i < ptlist->len(); i++) {
31412 neipt = * (point *)(* ptlist)[i];
31413 len = distance(ptloop, neipt);
31414
31415
31416 lave += len;
31417 }
31418 lave /= ptlist->len();
31419 }
31420 if (out == (tetgenio *) NULL) {
31421
31422
31423
31424 if (ptlist->len() > 0) {
31425
31426 fprintf(outfile, "%-16.8e ", lave);
31427 } else {
31428 fprintf(outfile, "0.0 ");
31429 }
31430 fprintf(outfile, "\n");
31431 } else {
31432
31433
31434
31435 if (ptlist->len() > 0) {
31436
31437
31438 out->pointmtrlist[mtrindex++] = lave;
31439 } else {
31440
31441
31442 out->pointmtrlist[mtrindex++] = 0.0;
31443 }
31444 }
31445 tetlist->clear();
31446 ptlist->clear();
31447 ptloop = pointtraverse();
31448 }
31449
31450 delete tetlist;
31451 delete ptlist;
31452
31453 if (out == (tetgenio *) NULL) {
31454 fprintf(outfile, "# Generated by %s\n", b->commandline);
31455 fclose(outfile);
31456 }
31457 }
31458
31460
31461
31462
31463
31465
31466 void tetgenmesh::outelements(tetgenio* out)
31467 {
31468 FILE *outfile;
31469 char outelefilename[FILENAMESIZE];
31470 tetrahedron* tptr;
31471 int *tlist;
31472 REAL *talist;
31473 int firstindex, shift;
31474 int pointindex;
31475 int attribindex;
31476 point p1, p2, p3, p4;
31477 point *extralist;
31478 int elementnumber;
31479 int eextras;
31480 int i;
31481
31482 if (out == (tetgenio *) NULL) {
31483 strcpy(outelefilename, b->outfilename);
31484 strcat(outelefilename, ".ele");
31485 }
31486
31487 if (!b->quiet) {
31488 if (out == (tetgenio *) NULL) {
31489 printf("Writing %s.\n", outelefilename);
31490 } else {
31491 printf("Writing elements.\n");
31492 }
31493 }
31494
31495
31496 outfile = (FILE *) NULL;
31497 tlist = (int *) NULL;
31498 talist = (double *) NULL;
31499 pointindex = attribindex = 0;
31500
31501 eextras = in->numberoftetrahedronattributes;
31502 if (out == (tetgenio *) NULL) {
31503 outfile = fopen(outelefilename, "w");
31504 if (outfile == (FILE *) NULL) {
31505 printf("File I/O Error: Cannot create file %s.\n", outelefilename);
31506 terminatetetgen(1);
31507 }
31508
31509 fprintf(outfile, "%ld %d %d\n", tetrahedrons->items,
31510 b->order == 1 ? 4 : 10, eextras);
31511 } else {
31512
31513 out->tetrahedronlist = new int[tetrahedrons->items *
31514 (b->order == 1 ? 4 : 10)];
31515 if (out->tetrahedronlist == (int *) NULL) {
31516 printf("Error: Out of memory.\n");
31517 terminatetetgen(1);
31518 }
31519
31520 if (eextras > 0) {
31521 out->tetrahedronattributelist = new REAL[tetrahedrons->items * eextras];
31522 if (out->tetrahedronattributelist == (REAL *) NULL) {
31523 printf("Error: Out of memory.\n");
31524 terminatetetgen(1);
31525 }
31526 }
31527 out->numberoftetrahedra = tetrahedrons->items;
31528 out->numberofcorners = b->order == 1 ? 4 : 10;
31529 out->numberoftetrahedronattributes = eextras;
31530 tlist = out->tetrahedronlist;
31531 talist = out->tetrahedronattributelist;
31532 pointindex = 0;
31533 attribindex = 0;
31534 }
31535
31536
31537 firstindex = b->zeroindex ? 0 : in->firstnumber;
31538 shift = 0;
31539 if ((in->firstnumber == 1) && (firstindex == 0)) {
31540 shift = 1;
31541 }
31542
31543 tetrahedrons->traversalinit();
31544 tptr = tetrahedrontraverse();
31545 elementnumber = firstindex;
31546 while (tptr != (tetrahedron *) NULL) {
31547 p1 = (point) tptr[4];
31548 p2 = (point) tptr[5];
31549 p3 = (point) tptr[6];
31550 p4 = (point) tptr[7];
31551 if (out == (tetgenio *) NULL) {
31552
31553 fprintf(outfile, "%5d %5d %5d %5d %5d", elementnumber,
31554 pointmark(p1) - shift, pointmark(p2) - shift,
31555 pointmark(p3) - shift, pointmark(p4) - shift);
31556 if (b->order == 2) {
31557 extralist = (point *) tptr[highorderindex];
31558
31559 fprintf(outfile, " %5d %5d %5d %5d %5d %5d",
31560 pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
31561 pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
31562 pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
31563 }
31564 for (i = 0; i < eextras; i++) {
31565 fprintf(outfile, " %.17g", elemattribute(tptr, i));
31566 }
31567 fprintf(outfile, "\n");
31568 } else {
31569 tlist[pointindex++] = pointmark(p1) - shift;
31570 tlist[pointindex++] = pointmark(p2) - shift;
31571 tlist[pointindex++] = pointmark(p3) - shift;
31572 tlist[pointindex++] = pointmark(p4) - shift;
31573 if (b->order == 2) {
31574 extralist = (point *) tptr[highorderindex];
31575 tlist[pointindex++] = pointmark(extralist[0]) - shift;
31576 tlist[pointindex++] = pointmark(extralist[1]) - shift;
31577 tlist[pointindex++] = pointmark(extralist[2]) - shift;
31578 tlist[pointindex++] = pointmark(extralist[3]) - shift;
31579 tlist[pointindex++] = pointmark(extralist[4]) - shift;
31580 tlist[pointindex++] = pointmark(extralist[5]) - shift;
31581 }
31582 for (i = 0; i < eextras; i++) {
31583 talist[attribindex++] = elemattribute(tptr, i);
31584 }
31585 }
31586 if (b->neighout) {
31587
31588 * (int *) (tptr + elemmarkerindex) = elementnumber;
31589 }
31590 tptr = tetrahedrontraverse();
31591 elementnumber++;
31592 }
31593 if (b->neighout) {
31594
31595 * (int *) (dummytet + elemmarkerindex) = -1;
31596 }
31597
31598 if (out == (tetgenio *) NULL) {
31599 fprintf(outfile, "# Generated by %s\n", b->commandline);
31600 fclose(outfile);
31601 }
31602 }
31603
31605
31606
31607
31608
31609
31610
31612
31613 void tetgenmesh::outfaces(tetgenio* out)
31614 {
31615 FILE *outfile;
31616 char facefilename[FILENAMESIZE];
31617 int *elist;
31618 int *emlist;
31619 int neigh1, neigh2;
31620 int index;
31621 triface tface, tsymface;
31622 face checkmark;
31623 point torg, tdest, tapex;
31624 long faces;
31625 int bmark, faceid, marker;
31626 int firstindex, shift;
31627 int facenumber;
31628
31629 neigh1 = 0;
31630 neigh2 = 0;
31631
31632 if (out == (tetgenio *) NULL) {
31633 strcpy(facefilename, b->outfilename);
31634 strcat(facefilename, ".face");
31635 }
31636
31637 if (!b->quiet) {
31638 if (out == (tetgenio *) NULL) {
31639 printf("Writing %s.\n", facefilename);
31640 } else {
31641 printf("Writing faces.\n");
31642 }
31643 }
31644
31645
31646 outfile = (FILE *) NULL;
31647 elist = (int *) NULL;
31648 emlist = (int *) NULL;
31649 index = marker = 0;
31650
31651 faces = (4l * tetrahedrons->items + hullsize) / 2l;
31652 bmark = !b->nobound && in->facetmarkerlist;
31653
31654 if (out == (tetgenio *) NULL) {
31655 outfile = fopen(facefilename, "w");
31656 if (outfile == (FILE *) NULL) {
31657 printf("File I/O Error: Cannot create file %s.\n", facefilename);
31658 terminatetetgen(1);
31659 }
31660 fprintf(outfile, "%ld %d\n", faces, bmark);
31661 } else {
31662
31663 out->trifacelist = new int[faces * 3];
31664 if (out->trifacelist == (int *) NULL) {
31665 printf("Error: Out of memory.\n");
31666 terminatetetgen(1);
31667 }
31668
31669 if (bmark) {
31670 out->trifacemarkerlist = new int[faces];
31671 if (out->trifacemarkerlist == (int *) NULL) {
31672 printf("Error: Out of memory.\n");
31673 terminatetetgen(1);
31674 }
31675 }
31676 if (b->neighout > 1) {
31677
31678 out->adjtetlist = new int[subfaces->items * 2];
31679 if (out->adjtetlist == (int *) NULL) {
31680 printf("Error: Out of memory.\n");
31681 terminatetetgen(1);
31682 }
31683 }
31684 out->numberoftrifaces = faces;
31685 elist = out->trifacelist;
31686 emlist = out->trifacemarkerlist;
31687 index = 0;
31688 }
31689
31690
31691 firstindex = b->zeroindex ? 0 : in->firstnumber;
31692 shift = 0;
31693 if ((in->firstnumber == 1) && (firstindex == 0)) {
31694 shift = 1;
31695 }
31696
31697 tetrahedrons->traversalinit();
31698 tface.tet = tetrahedrontraverse();
31699 facenumber = firstindex;
31700
31701
31702
31703
31704
31705
31706 while (tface.tet != (tetrahedron *) NULL) {
31707 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31708 sym(tface, tsymface);
31709 if ((tsymface.tet == dummytet) || (tface.tet < tsymface.tet)) {
31710 torg = org(tface);
31711 tdest = dest(tface);
31712 tapex = apex(tface);
31713 if (bmark) {
31714
31715
31716 if (b->useshelles) {
31717
31718 tspivot(tface, checkmark);
31719 if (checkmark.sh == dummysh) {
31720 marker = 0;
31721 } else {
31722 faceid = shellmark(checkmark) - 1;
31723 marker = in->facetmarkerlist[faceid];
31724 }
31725 } else {
31726
31727 marker = tsymface.tet != dummytet ? 1 : 0;
31728 }
31729 }
31730 if (b->neighout > 1) {
31731
31732 neigh1 = * (int *)(tface.tet + elemmarkerindex);
31733 if (tsymface.tet != dummytet) {
31734 neigh2 = * (int *)(tsymface.tet + elemmarkerindex);
31735 } else {
31736 neigh2 = -1;
31737 }
31738 }
31739 if (out == (tetgenio *) NULL) {
31740
31741 fprintf(outfile, "%5d %4d %4d %4d", facenumber,
31742 pointmark(torg) - shift, pointmark(tdest) - shift,
31743 pointmark(tapex) - shift);
31744 if (bmark) {
31745
31746 fprintf(outfile, " %d", marker);
31747 }
31748 if (b->neighout > 1) {
31749 fprintf(outfile, " %5d %5d", neigh1, neigh2);
31750 }
31751 fprintf(outfile, "\n");
31752 } else {
31753
31754 elist[index++] = pointmark(torg) - shift;
31755 elist[index++] = pointmark(tdest) - shift;
31756 elist[index++] = pointmark(tapex) - shift;
31757 if (bmark) {
31758 emlist[facenumber - in->firstnumber] = marker;
31759 }
31760 if (b->neighout > 1) {
31761 out->adjtetlist[(facenumber - in->firstnumber) * 2] = neigh1;
31762 out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
31763 }
31764 }
31765 facenumber++;
31766 }
31767 }
31768 tface.tet = tetrahedrontraverse();
31769 }
31770
31771 if (out == (tetgenio *) NULL) {
31772 fprintf(outfile, "# Generated by %s\n", b->commandline);
31773 fclose(outfile);
31774 }
31775 }
31776
31778
31779
31780
31781
31782
31783
31784
31785
31787
31788 void tetgenmesh::outhullfaces(tetgenio* out)
31789 {
31790 FILE *outfile;
31791 char facefilename[FILENAMESIZE];
31792 int *elist;
31793 int index;
31794 triface tface, tsymface;
31795 face checkmark;
31796 point torg, tdest, tapex;
31797 int firstindex, shift;
31798 int facenumber;
31799
31800 if (out == (tetgenio *) NULL) {
31801 strcpy(facefilename, b->outfilename);
31802 strcat(facefilename, ".face");
31803 }
31804
31805 if (!b->quiet) {
31806 if (out == (tetgenio *) NULL) {
31807 printf("Writing %s.\n", facefilename);
31808 } else {
31809 printf("Writing faces.\n");
31810 }
31811 }
31812
31813
31814 outfile = (FILE *) NULL;
31815 elist = (int *) NULL;
31816 index = 0;
31817
31818 if (out == (tetgenio *) NULL) {
31819 outfile = fopen(facefilename, "w");
31820 if (outfile == (FILE *) NULL) {
31821 printf("File I/O Error: Cannot create file %s.\n", facefilename);
31822 terminatetetgen(1);
31823 }
31824 fprintf(outfile, "%ld 0\n", hullsize);
31825 } else {
31826
31827 out->trifacelist = new int[hullsize * 3];
31828 if (out->trifacelist == (int *) NULL) {
31829 printf("Error: Out of memory.\n");
31830 terminatetetgen(1);
31831 }
31832 out->numberoftrifaces = hullsize;
31833 elist = out->trifacelist;
31834 index = 0;
31835 }
31836
31837
31838 firstindex = b->zeroindex ? 0 : in->firstnumber;
31839 shift = 0;
31840 if ((in->firstnumber == 1) && (firstindex == 0)) {
31841 shift = 1;
31842 }
31843
31844 tetrahedrons->traversalinit();
31845 tface.tet = tetrahedrontraverse();
31846 facenumber = firstindex;
31847
31848
31849
31850 while (tface.tet != (tetrahedron *) NULL) {
31851 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31852 sym(tface, tsymface);
31853 if (tsymface.tet == dummytet) {
31854 torg = org(tface);
31855 tdest = dest(tface);
31856 tapex = apex(tface);
31857 if (out == (tetgenio *) NULL) {
31858
31859 fprintf(outfile, "%5d %4d %4d %4d", facenumber,
31860 pointmark(torg) - shift, pointmark(tdest) - shift,
31861 pointmark(tapex) - shift);
31862 fprintf(outfile, "\n");
31863 } else {
31864
31865 elist[index++] = pointmark(torg) - shift;
31866 elist[index++] = pointmark(tdest) - shift;
31867 elist[index++] = pointmark(tapex) - shift;
31868 }
31869 facenumber++;
31870 }
31871 }
31872 tface.tet = tetrahedrontraverse();
31873 }
31874
31875 if (out == (tetgenio *) NULL) {
31876 fprintf(outfile, "# Generated by %s\n", b->commandline);
31877 fclose(outfile);
31878 }
31879 }
31880
31882
31883
31884
31885
31886
31887
31888
31889
31891
31892 void tetgenmesh::outsubfaces(tetgenio* out)
31893 {
31894 FILE *outfile;
31895 char facefilename[FILENAMESIZE];
31896 int *elist;
31897 int *emlist;
31898 int index, index1, index2;
31899 triface abuttingtet;
31900 face faceloop;
31901 point torg, tdest, tapex;
31902 int bmark, faceid, marker;
31903 int firstindex, shift;
31904 int neigh1, neigh2;
31905 int facenumber;
31906
31907 if (out == (tetgenio *) NULL) {
31908 strcpy(facefilename, b->outfilename);
31909 strcat(facefilename, ".face");
31910 }
31911
31912 if (!b->quiet) {
31913 if (out == (tetgenio *) NULL) {
31914 printf("Writing %s.\n", facefilename);
31915 } else {
31916 printf("Writing faces.\n");
31917 }
31918 }
31919
31920
31921 outfile = (FILE *) NULL;
31922 elist = (int *) NULL;
31923 emlist = (int *) NULL;
31924 index = index1 = index2 = 0;
31925 faceid = marker = 0;
31926 neigh1 = neigh2 = 0;
31927
31928 bmark = !b->nobound && in->facetmarkerlist;
31929
31930 if (out == (tetgenio *) NULL) {
31931 outfile = fopen(facefilename, "w");
31932 if (outfile == (FILE *) NULL) {
31933 printf("File I/O Error: Cannot create file %s.\n", facefilename);
31934 terminatetetgen(1);
31935 }
31936
31937 fprintf(outfile, "%ld %d\n", subfaces->items, bmark);
31938 } else {
31939
31940 out->trifacelist = new int[subfaces->items * 3];
31941 if (out->trifacelist == (int *) NULL) {
31942 printf("Error: Out of memory.\n");
31943 terminatetetgen(1);
31944 }
31945 if (bmark) {
31946
31947 out->trifacemarkerlist = new int[subfaces->items];
31948 if (out->trifacemarkerlist == (int *) NULL) {
31949 printf("Error: Out of memory.\n");
31950 terminatetetgen(1);
31951 }
31952 }
31953 if (b->neighout > 1) {
31954
31955 out->adjtetlist = new int[subfaces->items * 2];
31956 if (out->adjtetlist == (int *) NULL) {
31957 printf("Error: Out of memory.\n");
31958 terminatetetgen(1);
31959 }
31960 }
31961 out->numberoftrifaces = subfaces->items;
31962 elist = out->trifacelist;
31963 emlist = out->trifacemarkerlist;
31964 }
31965
31966
31967 firstindex = b->zeroindex ? 0 : in->firstnumber;
31968 shift = 0;
31969 if ((in->firstnumber == 1) && (firstindex == 0)) {
31970 shift = 1;
31971 }
31972
31973 subfaces->traversalinit();
31974 faceloop.sh = shellfacetraverse(subfaces);
31975 facenumber = firstindex;
31976 while (faceloop.sh != (shellface *) NULL) {
31977 stpivot(faceloop, abuttingtet);
31978 if (abuttingtet.tet == dummytet) {
31979 sesymself(faceloop);
31980 stpivot(faceloop, abuttingtet);
31981 }
31982 if (abuttingtet.tet != dummytet) {
31983
31984
31985
31986 adjustedgering(abuttingtet, CCW);
31987 torg = org(abuttingtet);
31988 tdest = dest(abuttingtet);
31989 tapex = apex(abuttingtet);
31990 } else {
31991
31992 torg = sorg(faceloop);
31993 tdest = sdest(faceloop);
31994 tapex = sapex(faceloop);
31995 }
31996 if (bmark) {
31997 faceid = shellmark(faceloop) - 1;
31998 marker = in->facetmarkerlist[faceid];
31999 }
32000 if (b->neighout > 1) {
32001
32002 neigh1 = -1;
32003 stpivot(faceloop, abuttingtet);
32004 if (abuttingtet.tet != dummytet) {
32005 neigh1 = * (int *)(abuttingtet.tet + elemmarkerindex);
32006 }
32007 neigh2 = -1;
32008 sesymself(faceloop);
32009 stpivot(faceloop, abuttingtet);
32010 if (abuttingtet.tet != dummytet) {
32011 neigh2 = * (int *)(abuttingtet.tet + elemmarkerindex);
32012 }
32013 }
32014 if (out == (tetgenio *) NULL) {
32015 fprintf(outfile, "%5d %4d %4d %4d", facenumber,
32016 pointmark(torg) - shift, pointmark(tdest) - shift,
32017 pointmark(tapex) - shift);
32018 if (bmark) {
32019 fprintf(outfile, " %d", marker);
32020 }
32021 if (b->neighout > 1) {
32022 fprintf(outfile, " %5d %5d", neigh1, neigh2);
32023 }
32024 fprintf(outfile, "\n");
32025 } else {
32026
32027 elist[index++] = pointmark(torg) - shift;
32028 elist[index++] = pointmark(tdest) - shift;
32029 elist[index++] = pointmark(tapex) - shift;
32030 if (bmark) {
32031 emlist[index1++] = marker;
32032 }
32033 if (b->neighout > 1) {
32034 out->adjtetlist[index2++] = neigh1;
32035 out->adjtetlist[index2++] = neigh2;
32036 }
32037 }
32038 facenumber++;
32039 faceloop.sh = shellfacetraverse(subfaces);
32040 }
32041
32042 if (out == (tetgenio *) NULL) {
32043 fprintf(outfile, "# Generated by %s\n", b->commandline);
32044 fclose(outfile);
32045 }
32046 }
32047
32049
32050
32051
32053
32054 void tetgenmesh::outedges(tetgenio* out)
32055 {
32056 FILE *outfile;
32057 char edgefilename[FILENAMESIZE];
32058 int *elist, *emlist;
32059 int index, index1;
32060 triface tetloop, worktet, spintet;
32061 face checksh;
32062 point torg, tdest;
32063 long faces, edges;
32064 int firstindex, shift;
32065 int edgenumber, faceid, marker;
32066 int hitbdry, i;
32067
32068 if (out == (tetgenio *) NULL) {
32069 strcpy(edgefilename, b->outfilename);
32070 strcat(edgefilename, ".edge");
32071 }
32072
32073 if (!b->quiet) {
32074 if (out == (tetgenio *) NULL) {
32075 printf("Writing %s.\n", edgefilename);
32076 } else {
32077 printf("Writing edges.\n");
32078 }
32079 }
32080
32081
32082 outfile = (FILE *) NULL;
32083 elist = (int *) NULL;
32084 emlist = (int *) NULL;
32085 index = index1 = 0;
32086 faceid = marker = 0;
32087
32088
32089 faces = (4l * tetrahedrons->items + hullsize) / 2l;
32090 edges = points->items + faces - tetrahedrons->items - 1l;
32091
32092 if (out == (tetgenio *) NULL) {
32093 outfile = fopen(edgefilename, "w");
32094 if (outfile == (FILE *) NULL) {
32095 printf("File I/O Error: Cannot create file %s.\n", edgefilename);
32096 terminatetetgen(1);
32097 }
32098
32099 fprintf(outfile, "%ld %d\n", edges, !b->nobound);
32100 } else {
32101
32102 out->edgelist = new int[edges * 2];
32103 if (out->edgelist == (int *) NULL) {
32104 printf("Error: Out of memory.\n");
32105 terminatetetgen(1);
32106 }
32107 if (!b->nobound) {
32108 out->edgemarkerlist = new int[edges];
32109 }
32110 out->numberofedges = edges;
32111 elist = out->edgelist;
32112 emlist = out->edgemarkerlist;
32113 }
32114
32115
32116 firstindex = b->zeroindex ? 0 : in->firstnumber;
32117 shift = 0;
32118 if ((in->firstnumber == 1) && (firstindex == 0)) {
32119 shift = 1;
32120 }
32121
32122 tetrahedrons->traversalinit();
32123 tetloop.tet = tetrahedrontraverse();
32124 edgenumber = firstindex;
32125 while (tetloop.tet != (tetrahedron *) NULL) {
32126
32127
32128
32129 worktet.tet = tetloop.tet;
32130 for (i = 0; i < 6; i++) {
32131 worktet.loc = edge2locver[i][0];
32132 worktet.ver = edge2locver[i][1];
32133 adjustedgering(worktet, CW);
32134 spintet = worktet;
32135 hitbdry = 0;
32136 while (hitbdry < 2) {
32137 if (fnextself(spintet)) {
32138 if (apex(spintet) == apex(worktet)) break;
32139 if (spintet.tet < worktet.tet) break;
32140 } else {
32141 hitbdry++;
32142 if (hitbdry < 2) {
32143 esym(worktet, spintet);
32144 fnextself(spintet);
32145 }
32146 }
32147 }
32148
32149 if (spintet.tet >= worktet.tet) {
32150 torg = org(worktet);
32151 tdest = dest(worktet);
32152 if (out == (tetgenio *) NULL) {
32153 fprintf(outfile, "%5d %4d %4d", edgenumber,
32154 pointmark(torg) - shift, pointmark(tdest) - shift);
32155 } else {
32156
32157 elist[index++] = pointmark(torg) - shift;
32158 elist[index++] = pointmark(tdest) - shift;
32159 }
32160 if (!b->nobound) {
32161 if (hitbdry > 0) {
32162
32163
32164
32165 if ((b->plc || b->refine) && in->facetmarkerlist) {
32166 tspivot(spintet, checksh);
32167 faceid = shellmark(checksh) - 1;
32168 marker = in->facetmarkerlist[faceid];
32169 } else {
32170 marker = 1;
32171 }
32172 } else {
32173 marker = 0;
32174 }
32175 if (out == (tetgenio *) NULL) {
32176 fprintf(outfile, " %d", marker);
32177 } else {
32178 emlist[index1++] = marker;
32179 }
32180 }
32181 if (out == (tetgenio *) NULL) {
32182 fprintf(outfile, "\n");
32183 }
32184 edgenumber++;
32185 }
32186 }
32187 tetloop.tet = tetrahedrontraverse();
32188 }
32189
32190 if (out == (tetgenio *) NULL) {
32191 fprintf(outfile, "# Generated by %s\n", b->commandline);
32192 fclose(outfile);
32193 }
32194 }
32195
32197
32198
32199
32201
32202 void tetgenmesh::outsubsegments(tetgenio* out)
32203 {
32204 FILE *outfile;
32205 char edgefilename[FILENAMESIZE];
32206 int *elist;
32207 int index;
32208 face edgeloop;
32209 point torg, tdest;
32210 int firstindex, shift;
32211 int edgenumber;
32212
32213 if (out == (tetgenio *) NULL) {
32214 strcpy(edgefilename, b->outfilename);
32215 strcat(edgefilename, ".edge");
32216 }
32217
32218 if (!b->quiet) {
32219 if (out == (tetgenio *) NULL) {
32220 printf("Writing %s.\n", edgefilename);
32221 } else {
32222 printf("Writing edges.\n");
32223 }
32224 }
32225
32226
32227 outfile = (FILE *) NULL;
32228 elist = (int *) NULL;
32229 index = 0;
32230
32231 if (out == (tetgenio *) NULL) {
32232 outfile = fopen(edgefilename, "w");
32233 if (outfile == (FILE *) NULL) {
32234 printf("File I/O Error: Cannot create file %s.\n", edgefilename);
32235 terminatetetgen(1);
32236 }
32237
32238 fprintf(outfile, "%ld\n", subsegs->items);
32239 } else {
32240
32241 out->edgelist = new int[subsegs->items * 2];
32242 if (out->edgelist == (int *) NULL) {
32243 printf("Error: Out of memory.\n");
32244 terminatetetgen(1);
32245 }
32246 out->numberofedges = subsegs->items;
32247 elist = out->edgelist;
32248 }
32249
32250
32251 firstindex = b->zeroindex ? 0 : in->firstnumber;
32252 shift = 0;
32253 if ((in->firstnumber == 1) && (firstindex == 0)) {
32254 shift = 1;
32255 }
32256
32257 subsegs->traversalinit();
32258 edgeloop.sh = shellfacetraverse(subsegs);
32259 edgenumber = firstindex;
32260 while (edgeloop.sh != (shellface *) NULL) {
32261 torg = sorg(edgeloop);
32262 tdest = sdest(edgeloop);
32263 if (out == (tetgenio *) NULL) {
32264 fprintf(outfile, "%5d %4d %4d\n", edgenumber,
32265 pointmark(torg) - shift, pointmark(tdest) - shift);
32266 } else {
32267
32268 elist[index++] = pointmark(torg) - shift;
32269 elist[index++] = pointmark(tdest) - shift;
32270 }
32271 edgenumber++;
32272 edgeloop.sh = shellfacetraverse(subsegs);
32273 }
32274
32275 if (out == (tetgenio *) NULL) {
32276 fprintf(outfile, "# Generated by %s\n", b->commandline);
32277 fclose(outfile);
32278 }
32279 }
32280
32282
32283
32284
32286
32287 void tetgenmesh::outneighbors(tetgenio* out)
32288 {
32289 FILE *outfile;
32290 char neighborfilename[FILENAMESIZE];
32291 int *nlist;
32292 int index;
32293 triface tetloop, tetsym;
32294 int neighbor1, neighbor2, neighbor3, neighbor4;
32295 int firstindex;
32296 int elementnumber;
32297
32298 if (out == (tetgenio *) NULL) {
32299 strcpy(neighborfilename, b->outfilename);
32300 strcat(neighborfilename, ".neigh");
32301 }
32302
32303 if (!b->quiet) {
32304 if (out == (tetgenio *) NULL) {
32305 printf("Writing %s.\n", neighborfilename);
32306 } else {
32307 printf("Writing neighbors.\n");
32308 }
32309 }
32310
32311
32312 outfile = (FILE *) NULL;
32313 nlist = (int *) NULL;
32314 index = 0;
32315
32316 if (out == (tetgenio *) NULL) {
32317 outfile = fopen(neighborfilename, "w");
32318 if (outfile == (FILE *) NULL) {
32319 printf("File I/O Error: Cannot create file %s.\n", neighborfilename);
32320 terminatetetgen(1);
32321 }
32322
32323 fprintf(outfile, "%ld %d\n", tetrahedrons->items, 4);
32324 } else {
32325
32326 out->neighborlist = new int[tetrahedrons->items * 4];
32327 if (out->neighborlist == (int *) NULL) {
32328 printf("Error: Out of memory.\n");
32329 terminatetetgen(1);
32330 }
32331 nlist = out->neighborlist;
32332 }
32333
32334
32335 firstindex = b->zeroindex ? 0 : in->firstnumber;
32336
32337 tetrahedrons->traversalinit();
32338 tetloop.tet = tetrahedrontraverse();
32339 elementnumber = firstindex;
32340 while (tetloop.tet != (tetrahedron *) NULL) {
32341 tetloop.loc = 2;
32342 sym(tetloop, tetsym);
32343 neighbor1 = * (int *) (tetsym.tet + elemmarkerindex);
32344 tetloop.loc = 3;
32345 sym(tetloop, tetsym);
32346 neighbor2 = * (int *) (tetsym.tet + elemmarkerindex);
32347 tetloop.loc = 1;
32348 sym(tetloop, tetsym);
32349 neighbor3 = * (int *) (tetsym.tet + elemmarkerindex);
32350 tetloop.loc = 0;
32351 sym(tetloop, tetsym);
32352 neighbor4 = * (int *) (tetsym.tet + elemmarkerindex);
32353 if (out == (tetgenio *) NULL) {
32354
32355 fprintf(outfile, "%4d %4d %4d %4d %4d\n", elementnumber,
32356 neighbor1, neighbor2, neighbor3, neighbor4);
32357 } else {
32358 nlist[index++] = neighbor1;
32359 nlist[index++] = neighbor2;
32360 nlist[index++] = neighbor3;
32361 nlist[index++] = neighbor4;
32362 }
32363 tetloop.tet = tetrahedrontraverse();
32364 elementnumber++;
32365 }
32366
32367 if (out == (tetgenio *) NULL) {
32368 fprintf(outfile, "# Generated by %s\n", b->commandline);
32369 fclose(outfile);
32370 }
32371 }
32372
32374
32375
32376
32377
32378
32379
32380
32381
32382
32383
32384
32385
32386
32387
32388
32390
32391 void tetgenmesh::outvoronoi(tetgenio* out)
32392 {
32393 FILE *outfile;
32394 char outfilename[FILENAMESIZE];
32395 tetgenio::voroedge *vedge;
32396 tetgenio::vorofacet *vfacet;
32397 list *tetlist, *ptlist;
32398 triface tetloop, worktet, spintet;
32399 point pt[4], ptloop, neipt;
32400 REAL ccent[3], infvec[3], vec1[3], vec2[3], L;
32401 long faces, edges;
32402 int *tetfaceindexarray, *tetedgeindexarray;
32403 int arraysize, *vertarray;
32404 int vpointcount, vedgecount, vfacecount, tcount;
32405 int index, shift;
32406 int end1, end2;
32407 int hitbdry, i, j, k;
32408
32409 vedge = NULL;
32410 vertarray = NULL;
32411 vfacet = NULL;
32412 k = 0;
32413
32414
32415 if (out == (tetgenio *) NULL) {
32416 strcpy(outfilename, b->outfilename);
32417 strcat(outfilename, ".v.node");
32418 }
32419
32420 if (!b->quiet) {
32421 if (out == (tetgenio *) NULL) {
32422 printf("Writing %s.\n", outfilename);
32423 } else {
32424 printf("Writing Voronoi vertices.\n");
32425 }
32426 }
32427
32428
32429 shift = (b->zeroindex ? 0 : in->firstnumber);
32430
32431 faces = (4l * tetrahedrons->items + hullsize) / 2l;
32432
32433 edges = points->items + faces - tetrahedrons->items - 1;
32434 outfile = (FILE *) NULL;
32435
32436 if (out == (tetgenio *) NULL) {
32437 outfile = fopen(outfilename, "w");
32438 if (outfile == (FILE *) NULL) {
32439 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32440 terminatetetgen(1);
32441 }
32442
32443 fprintf(outfile, "%ld 3 0 0\n", tetrahedrons->items);
32444 } else {
32445
32446 out->numberofvpoints = (int) tetrahedrons->items;
32447 out->vpointlist = new REAL[out->numberofvpoints * 3];
32448 if (out->vpointlist == (REAL *) NULL) {
32449 printf("Error: Out of memory.\n");
32450 terminatetetgen(1);
32451 }
32452 }
32453
32454
32455
32456
32457 tetrahedrons->traversalinit();
32458 tetloop.tet = tetrahedrontraverse();
32459 vpointcount = 0;
32460 index = 0;
32461 while (tetloop.tet != (tetrahedron *) NULL) {
32462
32463 for (i = 0; i < 4; i++) {
32464 pt[i] = (point) tetloop.tet[4 + i];
32465 setpoint2tet(pt[i], encode(tetloop));
32466 }
32467 circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
32468 if (out == (tetgenio *) NULL) {
32469 fprintf(outfile, "%4d %16.8e %16.8e %16.8e\n", vpointcount + shift,
32470 ccent[0], ccent[1], ccent[2]);
32471 } else {
32472 out->vpointlist[index++] = ccent[0];
32473 out->vpointlist[index++] = ccent[1];
32474 out->vpointlist[index++] = ccent[2];
32475 }
32476
32477 * (int *) (tetloop.tet + elemmarkerindex) = vpointcount;
32478 vpointcount++;
32479 tetloop.tet = tetrahedrontraverse();
32480 }
32481
32482 * (int *) (dummytet + elemmarkerindex) = -1;
32483
32484 if (out == (tetgenio *) NULL) {
32485 fprintf(outfile, "# Generated by %s\n", b->commandline);
32486 fclose(outfile);
32487 }
32488
32489
32490 if (out == (tetgenio *) NULL) {
32491 strcpy(outfilename, b->outfilename);
32492 strcat(outfilename, ".v.edge");
32493 }
32494
32495 if (!b->quiet) {
32496 if (out == (tetgenio *) NULL) {
32497 printf("Writing %s.\n", outfilename);
32498 } else {
32499 printf("Writing Voronoi edges.\n");
32500 }
32501 }
32502
32503 if (out == (tetgenio *) NULL) {
32504 outfile = fopen(outfilename, "w");
32505 if (outfile == (FILE *) NULL) {
32506 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32507 terminatetetgen(1);
32508 }
32509
32510 fprintf(outfile, "%ld 0\n", faces);
32511 } else {
32512
32513 out->numberofedges = (int) faces;
32514 out->vedgelist = new tetgenio::voroedge[out->numberofvedges];
32515 }
32516
32517
32518
32519
32520
32521
32522 tetfaceindexarray = new int[tetrahedrons->items * 4];
32523 tetrahedrons->traversalinit();
32524 tetloop.tet = tetrahedrontraverse();
32525 vedgecount = 0;
32526 index = 0;
32527 while (tetloop.tet != (tetrahedron *) NULL) {
32528
32529
32530
32531 end1 = * (int *) (tetloop.tet + elemmarkerindex);
32532 for (i = 0; i < 4; i++) {
32533 decode(tetloop.tet[i], worktet);
32534 if ((worktet.tet == dummytet) || (tetloop.tet < worktet.tet)) {
32535 if (out == (tetgenio *) NULL) {
32536 fprintf(outfile, "%4d %4d", vedgecount + shift, end1 + shift);
32537 } else {
32538 vedge = &(out->vedgelist[index++]);
32539 vedge->v1 = end1 + shift;
32540 }
32541 end2 = * (int *) (worktet.tet + elemmarkerindex);
32542
32543 if (end2 == -1) {
32544
32545 worktet.tet = tetloop.tet;
32546 worktet.loc = i;
32547 worktet.ver = 1;
32548 pt[0] = org(worktet);
32549 pt[1] = dest(worktet);
32550 pt[2] = apex(worktet);
32551 for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j];
32552 for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j];
32553 cross(vec1, vec2, infvec);
32554
32555 L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1]
32556 + infvec[2] * infvec[2]);
32557 if (L > 0) for (j = 0; j < 3; j++) infvec[j] /= L;
32558 if (out == (tetgenio *) NULL) {
32559 fprintf(outfile, " -1");
32560 fprintf(outfile, " %g %g %g\n", infvec[0], infvec[1], infvec[2]);
32561 } else {
32562 vedge->v2 = -1;
32563 vedge->vnormal[0] = infvec[0];
32564 vedge->vnormal[1] = infvec[1];
32565 vedge->vnormal[2] = infvec[2];
32566 }
32567 } else {
32568 if (out == (tetgenio *) NULL) {
32569 fprintf(outfile, " %4d\n", end2 + shift);
32570 } else {
32571 vedge->v2 = end2 + shift;
32572 vedge->vnormal[0] = 0.0;
32573 vedge->vnormal[1] = 0.0;
32574 vedge->vnormal[2] = 0.0;
32575 }
32576 }
32577
32578 tetfaceindexarray[end1 * 4 + i] = vedgecount;
32579 if (end2 != -1) {
32580 tetfaceindexarray[end2 * 4 + worktet.loc] = vedgecount;
32581 }
32582 vedgecount++;
32583 }
32584 }
32585 tetloop.tet = tetrahedrontraverse();
32586 }
32587
32588 if (out == (tetgenio *) NULL) {
32589 fprintf(outfile, "# Generated by %s\n", b->commandline);
32590 fclose(outfile);
32591 }
32592
32593
32594 if (out == (tetgenio *) NULL) {
32595 strcpy(outfilename, b->outfilename);
32596 strcat(outfilename, ".v.face");
32597 }
32598
32599 if (!b->quiet) {
32600 if (out == (tetgenio *) NULL) {
32601 printf("Writing %s.\n", outfilename);
32602 } else {
32603 printf("Writing Voronoi faces.\n");
32604 }
32605 }
32606
32607 if (out == (tetgenio *) NULL) {
32608 outfile = fopen(outfilename, "w");
32609 if (outfile == (FILE *) NULL) {
32610 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32611 terminatetetgen(1);
32612 }
32613
32614 fprintf(outfile, "%ld 0\n", edges);
32615 } else {
32616 out->numberofvfacets = edges;
32617 out->vfacetlist = new tetgenio::vorofacet[out->numberofvfacets];
32618 if (out->vfacetlist == (tetgenio::vorofacet *) NULL) {
32619 printf("Error: Out of memory.\n");
32620 terminatetetgen(1);
32621 }
32622 }
32623
32624
32625
32626
32627
32628
32629 tetedgeindexarray = new int[tetrahedrons->items * 6];
32630 tetrahedrons->traversalinit();
32631 tetloop.tet = tetrahedrontraverse();
32632 vfacecount = 0;
32633 while (tetloop.tet != (tetrahedron *) NULL) {
32634
32635
32636
32637 worktet = tetloop;
32638 for (i = 0; i < 6; i++) {
32639 worktet.loc = edge2locver[i][0];
32640 worktet.ver = edge2locver[i][1];
32641
32642 tcount = 1;
32643 adjustedgering(worktet, CW);
32644 spintet = worktet;
32645 hitbdry = 0;
32646 while (hitbdry < 2) {
32647 if (fnextself(spintet)) {
32648 if (apex(spintet) == apex(worktet)) break;
32649 if (spintet.tet < worktet.tet) break;
32650 tcount++;
32651 } else {
32652 hitbdry++;
32653 if (hitbdry < 2) {
32654 esym(worktet, spintet);
32655 fnextself(spintet);
32656 }
32657 }
32658 }
32659
32660 if (spintet.tet >= worktet.tet) {
32661
32662 pt[0] = org(worktet);
32663 pt[1] = dest(worktet);
32664 end1 = pointmark(pt[0]) - in->firstnumber;
32665 end2 = pointmark(pt[1]) - in->firstnumber;
32666 if (out == (tetgenio *) NULL) {
32667 fprintf(outfile, "%4d %4d %4d %-2d ", vfacecount + shift,
32668 end1 + shift, end2 + shift, tcount + (hitbdry > 0));
32669 } else {
32670 vfacet = &(out->vfacetlist[vfacecount]);
32671 vfacet->c1 = end1 + shift;
32672 vfacet->c2 = end2 + shift;
32673 vfacet->elist = new int[tcount + (hitbdry > 0) + 1];
32674 vfacet->elist[0] = tcount + (hitbdry > 0);
32675 index = 1;
32676 }
32677
32678 if (hitbdry > 0) {
32679
32680 vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32681 vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32682 if (out == (tetgenio *) NULL) {
32683 fprintf(outfile, " %d", vedgecount + shift);
32684 } else {
32685 vfacet->elist[index++] = vedgecount + shift;
32686 }
32687
32688 tetedgeindexarray[vpointcount * 6 +
32689 locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32690 esymself(spintet);
32691 fnextself(spintet);
32692 }
32693
32694 for (j = 0; j < tcount; j++) {
32695 vpointcount = * (int *) (spintet.tet + elemmarkerindex);
32696 vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32697 if (out == (tetgenio *) NULL) {
32698 fprintf(outfile, " %d", vedgecount + shift);
32699 } else {
32700 vfacet->elist[index++] = vedgecount + shift;
32701 }
32702
32703 tetedgeindexarray[vpointcount * 6 +
32704 locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32705 fnextself(spintet);
32706 }
32707 if (out == (tetgenio *) NULL) {
32708 fprintf(outfile, "\n");
32709 }
32710 vfacecount++;
32711 }
32712 }
32713 tetloop.tet = tetrahedrontraverse();
32714 }
32715
32716 if (out == (tetgenio *) NULL) {
32717 fprintf(outfile, "# Generated by %s\n", b->commandline);
32718 fclose(outfile);
32719 }
32720
32721
32722 if (out == (tetgenio *) NULL) {
32723 strcpy(outfilename, b->outfilename);
32724 strcat(outfilename, ".v.cell");
32725 }
32726
32727 if (!b->quiet) {
32728 if (out == (tetgenio *) NULL) {
32729 printf("Writing %s.\n", outfilename);
32730 } else {
32731 printf("Writing Voronoi cells.\n");
32732 }
32733 }
32734
32735 if (out == (tetgenio *) NULL) {
32736 outfile = fopen(outfilename, "w");
32737 if (outfile == (FILE *) NULL) {
32738 printf("File I/O Error: Cannot create file %s.\n", outfilename);
32739 terminatetetgen(1);
32740 }
32741
32742 fprintf(outfile, "%ld\n", points->items);
32743 } else {
32744 out->numberofvcells = points->items;
32745 out->vcelllist = new int*[out->numberofvcells];
32746 if (out->vcelllist == (int **) NULL) {
32747 printf("Error: Out of memory.\n");
32748 terminatetetgen(1);
32749 }
32750 }
32751
32752
32753 tetlist = new list(sizeof(triface), NULL, 256);
32754 ptlist = new list(sizeof(point *), NULL, 256);
32755 points->traversalinit();
32756 ptloop = pointtraverse();
32757 vpointcount = 0;
32758 while (ptloop != (point) NULL) {
32759 decode(point2tet(ptloop), tetloop);
32760
32761 if (!isdead(&tetloop)) {
32762
32763 tetlist->append(&tetloop);
32764 formstarpolyhedron(ptloop, tetlist, ptlist, true);
32765 tcount = ptlist->len();
32766 if (out == (tetgenio *) NULL) {
32767 fprintf(outfile, "%4d %-2d ", vpointcount + shift, tcount);
32768 } else {
32769 arraysize = tcount;
32770 vertarray = out->vcelllist[vpointcount];
32771 vertarray = new int[arraysize + 1];
32772 vertarray[0] = arraysize;
32773 index = 1;
32774 }
32775
32776 for (i = 0; i < ptlist->len(); i++) {
32777 neipt = * (point *)(* ptlist)[i];
32778
32779 for (j = 0; j < tetlist->len(); j++) {
32780 tetloop = * (triface *)(* tetlist)[j];
32781 for (k = 0; k < 6; k++) {
32782 tetloop.loc = edge2locver[k][0];
32783 tetloop.ver = edge2locver[k][1];
32784 if (org(tetloop) == ptloop) {
32785 if (dest(tetloop) == neipt) break;
32786 } else if (org(tetloop) == neipt) {
32787 if (dest(tetloop) == ptloop) break;
32788 }
32789 }
32790 if (k < 6) break;
32791 }
32792 assert(j < tetlist->len());
32793
32794 end1 = * (int *) (tetloop.tet + elemmarkerindex);
32795 vfacecount = tetedgeindexarray[end1 * 6 + k];
32796 if (out == (tetgenio *) NULL) {
32797 fprintf(outfile, " %d", vfacecount + shift);
32798 } else {
32799 vertarray[index++] = vfacecount + shift;
32800 }
32801 }
32802 if (out == (tetgenio *) NULL) {
32803 fprintf(outfile, "\n");
32804 }
32805 vpointcount++;
32806 }
32807 tetlist->clear();
32808 ptlist->clear();
32809 ptloop = pointtraverse();
32810 }
32811 delete tetlist;
32812 delete ptlist;
32813 delete [] tetfaceindexarray;
32814 delete [] tetedgeindexarray;
32815
32816 if (out == (tetgenio *) NULL) {
32817 fprintf(outfile, "# Generated by %s\n", b->commandline);
32818 fclose(outfile);
32819 }
32820 }
32821
32823
32824
32825
32827
32828 void tetgenmesh::outpbcnodes(tetgenio* out)
32829 {
32830 FILE *outfile;
32831 char pbcfilename[FILENAMESIZE];
32832 list *ptpairlist;
32833 tetgenio::pbcgroup *pgi, *pgo;
32834 pbcdata *pd;
32835 face faceloop;
32836 face checkseg, symseg;
32837 point *ptpair, pa, pb;
32838 enum locateresult loc;
32839 REAL sympt[3], d1, d2;
32840 int *worklist;
32841 int firstindex, shift;
32842 int index, idx;
32843 int i, j, k, l;
32844
32845 if (out == (tetgenio *) NULL) {
32846 strcpy(pbcfilename, b->outfilename);
32847 strcat(pbcfilename, ".pbc");
32848 }
32849
32850 if (!b->quiet) {
32851 if (out == (tetgenio *) NULL) {
32852 printf("Writing %s.\n", pbcfilename);
32853 } else {
32854 printf("Writing pbc nodes.\n");
32855 }
32856 }
32857
32858
32859 outfile = (FILE *) NULL;
32860 pgo = (tetgenio::pbcgroup *) NULL;
32861 index = 0;
32862
32863 if (out == (tetgenio *) NULL) {
32864 outfile = fopen(pbcfilename, "w");
32865 if (outfile == (FILE *) NULL) {
32866 printf("File I/O Error: Cannot create file %s.\n", pbcfilename);
32867 terminatetetgen(1);
32868 }
32869
32870 fprintf(outfile, "# number of PBCs.\n");
32871 fprintf(outfile, "%d\n\n", in->numberofpbcgroups);
32872 } else {
32873 out->numberofpbcgroups = in->numberofpbcgroups;
32874
32875 out->pbcgrouplist = new tetgenio::pbcgroup[in->numberofpbcgroups];
32876
32877 if (out->pbcgrouplist == (tetgenio::pbcgroup *) NULL) {
32878 printf("Error: Out of memory.\n");
32879 terminatetetgen(1);
32880 }
32881 }
32882
32883 ptpairlist = new list(2 * sizeof(point *), NULL, 256);
32884 worklist = new int[points->items + 1];
32885 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
32886
32887
32888 firstindex = b->zeroindex ? 0 : in->firstnumber;
32889 shift = 0;
32890 if ((in->firstnumber == 1) && (firstindex == 0)) {
32891 shift = 1;
32892 }
32893
32894 for (i = 0; i < in->numberofpbcgroups; i++) {
32895
32896 pgi = &(in->pbcgrouplist[i]);
32897 if (out == (tetgenio *) NULL) {
32898 fprintf(outfile, "# PBC %d\n", in->firstnumber + i);
32899
32900 fprintf(outfile, "%d %d\n", pgi->fmark1, pgi->fmark2);
32901
32902 fprintf(outfile, "[\n");
32903 for (j = 0; j < 4; j++) {
32904 fprintf(outfile, " %.12g %.12g %.12g %.12g\n", pgi->transmat[j][0],
32905 pgi->transmat[j][1], pgi->transmat[j][2], pgi->transmat[j][3]);
32906 }
32907 fprintf(outfile, "]\n");
32908 } else {
32909 pgo = &(out->pbcgrouplist[i]);
32910
32911 pgo->fmark1 = pgi->fmark1;
32912 pgo->fmark2 = pgi->fmark2;
32913 for (j = 0; j < 4; j++) {
32914 for (k = 0; k < 4; k++) pgo->transmat[j][k] = pgi->transmat[j][k];
32915 }
32916 }
32917
32918
32919 subfaces->traversalinit();
32920 faceloop.sh = shellfacetraverse(subfaces);
32921 while (faceloop.sh != (shellface *) NULL) {
32922 if (shellpbcgroup(faceloop) == i) {
32923
32924 idx = shellmark(faceloop) - 1;
32925 if (in->facetmarkerlist[idx] == pgi->fmark1) {
32926
32927 for (j = 0; j < 3; j++) {
32928 sspivot(faceloop, checkseg);
32929
32930 for (k = 0; k < 2; k++) {
32931 if (k == 0) pa = sorg(faceloop);
32932 else pa = sdest(faceloop);
32933 if (worklist[pointmark(pa)] == 0) {
32934 pb = (point) NULL;
32935 if (checkseg.sh != dummysh) {
32936
32937
32938 idx = shellmark(checkseg) - 1;
32939 for (l = idx2segpglist[idx]; l < idx2segpglist[idx + 1];
32940 l++) {
32941 pd = (pbcdata *)(* segpbcgrouptable)[segpglist[l]];
32942 if (((pd->fmark[0] == pgi->fmark1) &&
32943 (pd->fmark[1] == pgi->fmark2)) ||
32944 ((pd->fmark[0] == pgi->fmark2) &&
32945 (pd->fmark[1] == pgi->fmark1))) break;
32946 }
32947 #ifdef SELF_CHECK
32948 assert(l < idx2segpglist[idx + 1]);
32949 #endif
32950 loc = getsegpbcsympoint(pa, &checkseg, sympt, &symseg,
32951 segpglist[l]);
32952 if (loc != ONVERTEX) {
32953
32954
32955
32956 d1 = distance(sympt, sorg(symseg));
32957 d2 = distance(sympt, sdest(symseg));
32958 if (d1 > d2) sesymself(symseg);
32959 }
32960 pb = sorg(symseg);
32961 } else {
32962
32963 if (pointtype(pa) == FREESUBVERTEX) {
32964 pb = point2pbcpt(pa);
32965 }
32966 }
32967 if (pb != (point) NULL) {
32968
32969 ptpair = (point *) ptpairlist->append(NULL);
32970 ptpair[0] = pa;
32971 ptpair[1] = pb;
32972
32973 worklist[pointmark(pa)] = 1;
32974 }
32975 }
32976 }
32977
32978 senextself(faceloop);
32979 }
32980 }
32981 }
32982 faceloop.sh = shellfacetraverse(subfaces);
32983 }
32984
32985
32986 if (out == (tetgenio *) NULL) {
32987 fprintf(outfile, "%d\n", ptpairlist->len());
32988 } else {
32989 pgo->numberofpointpairs = ptpairlist->len();
32990 pgo->pointpairlist = new int[pgo->numberofpointpairs * 2];
32991 index = 0;
32992 }
32993 for (j = 0; j < ptpairlist->len(); j++) {
32994 ptpair = (point *)(* ptpairlist)[j];
32995 pa = ptpair[0];
32996 pb = ptpair[1];
32997 if (out == (tetgenio *) NULL) {
32998 fprintf(outfile, " %4d %4d\n", pointmark(pa) - shift,
32999 pointmark(pb) - shift);
33000 } else {
33001 pgo->pointpairlist[index++] = pointmark(pa) - shift;
33002 pgo->pointpairlist[index++] = pointmark(pb) - shift;
33003 }
33004
33005 worklist[pointmark(pa)] = 0;
33006 }
33007 if (out == (tetgenio *) NULL) {
33008 fprintf(outfile, "\n");
33009 }
33010 ptpairlist->clear();
33011 }
33012
33013 delete [] worklist;
33014 delete ptpairlist;
33015
33016 if (out == (tetgenio *) NULL) {
33017 fprintf(outfile, "# Generated by %s\n", b->commandline);
33018 fclose(outfile);
33019 }
33020 }
33021
33023
33024
33025
33026
33027
33028
33029
33030
33032
33033 void tetgenmesh::outsmesh(char* smfilename)
33034 {
33035 FILE *outfile;
33036 char nodfilename[FILENAMESIZE];
33037 char smefilename[FILENAMESIZE];
33038 face faceloop;
33039 point p1, p2, p3;
33040 int firstindex, shift;
33041 int bmark;
33042 int faceid, marker;
33043 int i;
33044
33045 if (smfilename != (char *) NULL && smfilename[0] != '\0') {
33046 strcpy(smefilename, smfilename);
33047 } else if (b->outfilename[0] != '\0') {
33048 strcpy(smefilename, b->outfilename);
33049 } else {
33050 strcpy(smefilename, "unnamed");
33051 }
33052 strcpy(nodfilename, smefilename);
33053 strcat(smefilename, ".smesh");
33054 strcat(nodfilename, ".node");
33055
33056 if (!b->quiet) {
33057 printf("Writing %s.\n", smefilename);
33058 }
33059 outfile = fopen(smefilename, "w");
33060 if (outfile == (FILE *) NULL) {
33061 printf("File I/O Error: Cannot create file %s.\n", smefilename);
33062 return;
33063 }
33064
33065
33066 firstindex = b->zeroindex ? 0 : in->firstnumber;
33067 shift = 0;
33068 if ((in->firstnumber == 1) && (firstindex == 0)) {
33069 shift = 1;
33070 }
33071
33072 fprintf(outfile, "# %s. TetGen's input file.\n", smefilename);
33073 fprintf(outfile, "\n# part 1: node list.\n");
33074 fprintf(outfile, "0 3 0 0 # nodes are found in %s.\n", nodfilename);
33075
33076 marker = 0;
33077 bmark = !b->nobound && in->facetmarkerlist;
33078
33079 fprintf(outfile, "\n# part 2: facet list.\n");
33080
33081 fprintf(outfile, "%ld %d\n", subfaces->items, bmark);
33082
33083 subfaces->traversalinit();
33084 faceloop.sh = shellfacetraverse(subfaces);
33085 while (faceloop.sh != (shellface *) NULL) {
33086 p1 = sorg(faceloop);
33087 p2 = sdest(faceloop);
33088 p3 = sapex(faceloop);
33089 if (bmark) {
33090 faceid = shellmark(faceloop) - 1;
33091 if (faceid >= 0) {
33092 marker = in->facetmarkerlist[faceid];
33093 } else {
33094 marker = 0;
33095 }
33096 }
33097 fprintf(outfile, "3 %4d %4d %4d", pointmark(p1) - shift,
33098 pointmark(p2) - shift, pointmark(p3) - shift);
33099 if (bmark) {
33100 fprintf(outfile, " %d", marker);
33101 }
33102 fprintf(outfile, "\n");
33103 faceloop.sh = shellfacetraverse(subfaces);
33104 }
33105
33106
33107 fprintf(outfile, "\n# part 3: hole list.\n");
33108 fprintf(outfile, "%d\n", in->numberofholes);
33109 for (i = 0; i < in->numberofholes; i++) {
33110 fprintf(outfile, "%d %g %g %g\n", i + in->firstnumber,
33111 in->holelist[i * 3], in->holelist[i * 3 + 1],
33112 in->holelist[i * 3 + 2]);
33113 }
33114
33115
33116 fprintf(outfile, "\n# part 4: region list.\n");
33117 fprintf(outfile, "%d\n", in->numberofregions);
33118 for (i = 0; i < in->numberofregions; i++) {
33119 fprintf(outfile, "%d %g %g %g %d %g\n", i + in->firstnumber,
33120 in->regionlist[i * 5], in->regionlist[i * 5 + 1],
33121 in->regionlist[i * 5 + 2], (int) in->regionlist[i * 5 + 3],
33122 in->regionlist[i * 5 + 4]);
33123 }
33124
33125 fprintf(outfile, "# Generated by %s\n", b->commandline);
33126 fclose(outfile);
33127 }
33128
33130
33131
33132
33133
33134
33135
33136
33137
33139
33140 void tetgenmesh::outmesh2medit(char* mfilename)
33141 {
33142 FILE *outfile;
33143 char mefilename[FILENAMESIZE];
33144 tetrahedron* tetptr;
33145 triface tface, tsymface;
33146 face segloop, checkmark;
33147 point ptloop, p1, p2, p3, p4;
33148 long faces;
33149 int pointnumber;
33150 int i;
33151
33152 if (mfilename != (char *) NULL && mfilename[0] != '\0') {
33153 strcpy(mefilename, mfilename);
33154 } else if (b->outfilename[0] != '\0') {
33155 strcpy(mefilename, b->outfilename);
33156 } else {
33157 strcpy(mefilename, "unnamed");
33158 }
33159 strcat(mefilename, ".mesh");
33160
33161 if (!b->quiet) {
33162 printf("Writing %s.\n", mefilename);
33163 }
33164 outfile = fopen(mefilename, "w");
33165 if (outfile == (FILE *) NULL) {
33166 printf("File I/O Error: Cannot create file %s.\n", mefilename);
33167 return;
33168 }
33169
33170 fprintf(outfile, "MeshVersionFormatted 1\n");
33171 fprintf(outfile, "\n");
33172 fprintf(outfile, "Dimension\n");
33173 fprintf(outfile, "3\n");
33174 fprintf(outfile, "\n");
33175
33176 fprintf(outfile, "\n# Set of mesh vertices\n");
33177 fprintf(outfile, "Vertices\n");
33178 fprintf(outfile, "%ld\n", points->items);
33179
33180 points->traversalinit();
33181 ptloop = pointtraverse();
33182 pointnumber = 1;
33183 while (ptloop != (point) NULL) {
33184
33185 fprintf(outfile, "%.17g %.17g %.17g", ptloop[0], ptloop[1], ptloop[2]);
33186 if (in->numberofpointattributes > 0) {
33187
33188 fprintf(outfile, " %.17g\n", ptloop[3]);
33189 } else {
33190 fprintf(outfile, " 0\n");
33191 }
33192 setpointmark(ptloop, pointnumber);
33193 ptloop = pointtraverse();
33194 pointnumber++;
33195 }
33196
33197
33198 faces = (4l * tetrahedrons->items + hullsize) / 2l;
33199
33200 fprintf(outfile, "\n# Set of Triangles\n");
33201 fprintf(outfile, "Triangles\n");
33202 fprintf(outfile, "%ld\n", faces);
33203
33204 tetrahedrons->traversalinit();
33205 tface.tet = tetrahedrontraverse();
33206
33207
33208
33209
33210
33211
33212 while (tface.tet != (tetrahedron *) NULL) {
33213 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33214 sym(tface, tsymface);
33215 if (tface.tet < tsymface.tet || tsymface.tet == dummytet) {
33216 p1 = org (tface);
33217 p2 = dest(tface);
33218 p3 = apex(tface);
33219 fprintf(outfile, "%5d %5d %5d",
33220 pointmark(p1), pointmark(p2), pointmark(p3));
33221 fprintf(outfile, " 0\n");
33222 }
33223 }
33224 tface.tet = tetrahedrontraverse();
33225 }
33226
33227 fprintf(outfile, "\n# Set of Tetrahedra\n");
33228 fprintf(outfile, "Tetrahedra\n");
33229 fprintf(outfile, "%ld\n", tetrahedrons->items);
33230
33231 tetrahedrons->traversalinit();
33232 tetptr = tetrahedrontraverse();
33233 while (tetptr != (tetrahedron *) NULL) {
33234 p1 = (point) tetptr[4];
33235 p2 = (point) tetptr[5];
33236 p3 = (point) tetptr[6];
33237 p4 = (point) tetptr[7];
33238 fprintf(outfile, "%5d %5d %5d %5d",
33239 pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33240 if (in->numberoftetrahedronattributes > 0) {
33241 fprintf(outfile, " %.17g", elemattribute(tetptr, 0));
33242 } else {
33243 fprintf(outfile, " 0");
33244 }
33245 fprintf(outfile, "\n");
33246 tetptr = tetrahedrontraverse();
33247 }
33248
33249 fprintf(outfile, "\nCorners\n");
33250 fprintf(outfile, "%d\n", in->numberofpoints);
33251
33252 for (i = 0; i < in->numberofpoints; i++) {
33253 fprintf(outfile, "%4d\n", i + 1);
33254 }
33255
33256 if (b->useshelles) {
33257 fprintf(outfile, "\nEdges\n");
33258 fprintf(outfile, "%ld\n", subsegs->items);
33259
33260 subsegs->traversalinit();
33261 segloop.sh = shellfacetraverse(subsegs);
33262 while (segloop.sh != (shellface *) NULL) {
33263 p1 = sorg(segloop);
33264 p2 = sdest(segloop);
33265 fprintf(outfile, "%5d %5d", pointmark(p1), pointmark(p2));
33266 fprintf(outfile, " 0\n");
33267 segloop.sh = shellfacetraverse(subsegs);
33268 }
33269 }
33270
33271 fprintf(outfile, "\nEnd\n");
33272 fclose(outfile);
33273 }
33274
33276
33277
33278
33279
33280
33281
33282
33283
33284
33286
33287 void tetgenmesh::outmesh2gid(char* gfilename)
33288 {
33289 FILE *outfile;
33290 char gidfilename[FILENAMESIZE];
33291 tetrahedron* tetptr;
33292 triface tface, tsymface;
33293 face sface;
33294 point ptloop, p1, p2, p3, p4;
33295 int pointnumber;
33296 int elementnumber;
33297
33298 if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33299 strcpy(gidfilename, gfilename);
33300 } else if (b->outfilename[0] != '\0') {
33301 strcpy(gidfilename, b->outfilename);
33302 } else {
33303 strcpy(gidfilename, "unnamed");
33304 }
33305 strcat(gidfilename, ".ele.msh");
33306
33307 if (!b->quiet) {
33308 printf("Writing %s.\n", gidfilename);
33309 }
33310 outfile = fopen(gidfilename, "w");
33311 if (outfile == (FILE *) NULL) {
33312 printf("File I/O Error: Cannot create file %s.\n", gidfilename);
33313 return;
33314 }
33315
33316 fprintf(outfile, "mesh dimension = 3 elemtype tetrahedron nnode = 4\n");
33317 fprintf(outfile, "coordinates\n");
33318
33319 points->traversalinit();
33320 ptloop = pointtraverse();
33321 pointnumber = 1;
33322 while (ptloop != (point) NULL) {
33323
33324 fprintf(outfile, "%4d %.17g %.17g %.17g", pointnumber,
33325 ptloop[0], ptloop[1], ptloop[2]);
33326 if (in->numberofpointattributes > 0) {
33327
33328 fprintf(outfile, " %.17g", ptloop[3]);
33329 }
33330 fprintf(outfile, "\n");
33331 setpointmark(ptloop, pointnumber);
33332 ptloop = pointtraverse();
33333 pointnumber++;
33334 }
33335
33336 fprintf(outfile, "end coordinates\n");
33337 fprintf(outfile, "elements\n");
33338
33339 tetrahedrons->traversalinit();
33340 tetptr = tetrahedrontraverse();
33341 elementnumber = 1;
33342 while (tetptr != (tetrahedron *) NULL) {
33343 p1 = (point) tetptr[4];
33344 p2 = (point) tetptr[5];
33345 p3 = (point) tetptr[6];
33346 p4 = (point) tetptr[7];
33347 fprintf(outfile, "%5d %5d %5d %5d %5d", elementnumber,
33348 pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33349 if (in->numberoftetrahedronattributes > 0) {
33350 fprintf(outfile, " %.17g", elemattribute(tetptr, 0));
33351 }
33352 fprintf(outfile, "\n");
33353 tetptr = tetrahedrontraverse();
33354 elementnumber++;
33355 }
33356
33357 fprintf(outfile, "end elements\n");
33358 fclose(outfile);
33359
33360 if (gfilename != (char *) NULL && gfilename[0] != '\0') {
33361 strcpy(gidfilename, gfilename);
33362 } else if (b->outfilename[0] != '\0') {
33363 strcpy(gidfilename, b->outfilename);
33364 } else {
33365 strcpy(gidfilename, "unnamed");
33366 }
33367 strcat(gidfilename, ".face.msh");
33368
33369 if (!b->quiet) {
33370 printf("Writing %s.\n", gidfilename);
33371 }
33372 outfile = fopen(gidfilename, "w");
33373 if (outfile == (FILE *) NULL) {
33374 printf("File I/O Error: Cannot create file %s.\n", gidfilename);
33375 return;
33376 }
33377
33378 fprintf(outfile, "mesh dimension = 3 elemtype triangle nnode = 3\n");
33379 fprintf(outfile, "coordinates\n");
33380
33381 points->traversalinit();
33382 ptloop = pointtraverse();
33383 pointnumber = 1;
33384 while (ptloop != (point) NULL) {
33385
33386 fprintf(outfile, "%4d %.17g %.17g %.17g", pointnumber,
33387 ptloop[0], ptloop[1], ptloop[2]);
33388 if (in->numberofpointattributes > 0) {
33389
33390 fprintf(outfile, " %.17g", ptloop[3]);
33391 }
33392 fprintf(outfile, "\n");
33393 setpointmark(ptloop, pointnumber);
33394 ptloop = pointtraverse();
33395 pointnumber++;
33396 }
33397
33398 fprintf(outfile, "end coordinates\n");
33399 fprintf(outfile, "elements\n");
33400
33401 tetrahedrons->traversalinit();
33402 tface.tet = tetrahedrontraverse();
33403 elementnumber = 1;
33404 while (tface.tet != (tetrahedron *) NULL) {
33405 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33406 sym(tface, tsymface);
33407 if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33408 p1 = org(tface);
33409 p2 = dest(tface);
33410 p3 = apex(tface);
33411 if (tsymface.tet == dummytet) {
33412
33413 fprintf(outfile, "%5d %d %d %d\n", elementnumber,
33414 pointmark(p1), pointmark(p2), pointmark(p3));
33415 elementnumber++;
33416 } else if (b->useshelles) {
33417
33418 tspivot(tface, sface);
33419 if (sface.sh != dummysh) {
33420 fprintf(outfile, "%5d %d %d %d\n", elementnumber,
33421 pointmark(p1), pointmark(p2), pointmark(p3));
33422 elementnumber++;
33423 }
33424 }
33425 }
33426 }
33427 tface.tet = tetrahedrontraverse();
33428 }
33429
33430 fprintf(outfile, "end elements\n");
33431 fclose(outfile);
33432 }
33433
33435
33436
33437
33438
33439
33440
33442
33443 void tetgenmesh::outmesh2off(char* ofilename)
33444 {
33445 FILE *outfile;
33446 char offfilename[FILENAMESIZE];
33447 triface tface, tsymface;
33448 point ptloop, p1, p2, p3;
33449 long faces;
33450 int shift;
33451
33452 if (ofilename != (char *) NULL && ofilename[0] != '\0') {
33453 strcpy(offfilename, ofilename);
33454 } else if (b->outfilename[0] != '\0') {
33455 strcpy(offfilename, b->outfilename);
33456 } else {
33457 strcpy(offfilename, "unnamed");
33458 }
33459 strcat(offfilename, ".off");
33460
33461 if (!b->quiet) {
33462 printf("Writing %s.\n", offfilename);
33463 }
33464 outfile = fopen(offfilename, "w");
33465 if (outfile == (FILE *) NULL) {
33466 printf("File I/O Error: Cannot create file %s.\n", offfilename);
33467 return;
33468 }
33469
33470
33471 faces = (4l * tetrahedrons->items + hullsize) / 2l;
33472
33473
33474 fprintf(outfile, "OFF\n%ld %ld %ld\n", points->items, faces, hullsize);
33475
33476
33477 points->traversalinit();
33478 ptloop = pointtraverse();
33479 while (ptloop != (point) NULL) {
33480 fprintf(outfile, " %.17g %.17g %.17g\n",ptloop[0], ptloop[1], ptloop[2]);
33481 ptloop = pointtraverse();
33482 }
33483
33484
33485 shift = in->firstnumber == 1 ? 1 : 0;
33486
33487 tetrahedrons->traversalinit();
33488 tface.tet = tetrahedrontraverse();
33489
33490
33491
33492
33493
33494
33495 while (tface.tet != (tetrahedron *) NULL) {
33496 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33497 sym(tface, tsymface);
33498 if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33499 p1 = org(tface);
33500 p2 = dest(tface);
33501 p3 = apex(tface);
33502
33503 fprintf(outfile, "3 %4d %4d %4d\n", pointmark(p1) - shift,
33504 pointmark(p2) - shift, pointmark(p3) - shift);
33505 }
33506 }
33507 tface.tet = tetrahedrontraverse();
33508 }
33509
33510 fprintf(outfile, "# Generated by %s\n", b->commandline);
33511 fclose(outfile);
33512 }
33513
33514
33515
33516
33517
33518
33519
33520
33521
33523
33524
33525
33527
33528 void tetgenmesh::internalerror()
33529 {
33530 printf(" Please report this bug to sihang@mail.berlios.de. Include the\n");
33531 printf(" message above, your input data set, and the exact command\n");
33532 printf(" line you used to run this program, thank you.\n");
33533 terminatetetgen(2);
33534 }
33535
33537
33538
33539
33541
33542 void tetgenmesh::checkmesh()
33543 {
33544 triface tetraloop;
33545 triface oppotet, oppooppotet;
33546 point tetorg, tetdest, tetapex, tetoppo;
33547 REAL oritest;
33548 int horrors;
33549
33550 if (!b->quiet) {
33551 printf(" Checking consistency of mesh...\n");
33552 }
33553
33554 horrors = 0;
33555
33556 tetrahedrons->traversalinit();
33557 tetraloop.tet = tetrahedrontraverse();
33558 while (tetraloop.tet != (tetrahedron *) NULL) {
33559
33560 for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33561 tetorg = org(tetraloop);
33562 tetdest = dest(tetraloop);
33563 tetapex = apex(tetraloop);
33564 tetoppo = oppo(tetraloop);
33565 if (tetraloop.loc == 0) {
33566 oritest = orient3d(tetorg, tetdest, tetapex, tetoppo);
33567 if (oritest >= 0.0) {
33568 printf(" !! !! %s ", oritest > 0.0 ? "Inverted" : "Degenerated");
33569 printtet(&tetraloop);
33570 printf(" orient3d = %.17g.\n", oritest);
33571 horrors++;
33572 }
33573 }
33574
33575 sym(tetraloop, oppotet);
33576 if (oppotet.tet != dummytet) {
33577
33578 sym(oppotet, oppooppotet);
33579 if ((tetraloop.tet != oppooppotet.tet)
33580 || (tetraloop.loc != oppooppotet.loc)) {
33581 printf(" !! !! Asymmetric tetra-tetra bond:\n");
33582 if (tetraloop.tet == oppooppotet.tet) {
33583 printf(" (Right tetrahedron, wrong orientation)\n");
33584 }
33585 printf(" First ");
33586 printtet(&tetraloop);
33587 printf(" Second (nonreciprocating) ");
33588 printtet(&oppotet);
33589 horrors++;
33590 }
33591 }
33592 }
33593 tetraloop.tet = tetrahedrontraverse();
33594 }
33595 if (horrors == 0) {
33596 if (!b->quiet) {
33597 printf(" In my studied opinion, the mesh appears to be consistent.\n");
33598 }
33599 } else if (horrors == 1) {
33600 printf(" !! !! !! !! Precisely one festering wound discovered.\n");
33601 } else {
33602 printf(" !! !! !! !! %d abominations witnessed.\n", horrors);
33603 }
33604 }
33605
33607
33608
33609
33611
33612 void tetgenmesh::checkshells()
33613 {
33614 triface oppotet, oppooppotet, testtet;
33615 face shloop, segloop, spin;
33616 face testsh, testseg, testshsh;
33617 point shorg, shdest, segorg, segdest;
33618 REAL checksign;
33619 bool same;
33620 int horrors;
33621 int i;
33622
33623 if (!b->quiet) {
33624 printf(" Checking consistency of the mesh boundary...\n");
33625 }
33626 horrors = 0;
33627
33628
33629 subfaces->traversalinit();
33630 shloop.sh = shellfacetraverse(subfaces);
33631 while (shloop.sh != (shellface *) NULL) {
33632
33633 shloop.shver = 0;
33634 stpivot(shloop, oppotet);
33635 if (oppotet.tet != dummytet) {
33636 tspivot(oppotet, testsh);
33637 if (testsh.sh != shloop.sh) {
33638 printf(" !! !! Wrong tetra-subface connection.\n");
33639 printf(" Tetra: ");
33640 printtet(&oppotet);
33641 printf(" Subface: ");
33642 printsh(&shloop);
33643 horrors++;
33644 }
33645 if (oppo(oppotet) != (point) NULL) {
33646 adjustedgering(oppotet, CCW);
33647 checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33648 oppo(oppotet));
33649 if (checksign >= 0.0) {
33650 printf(" !! !! Wrong subface orientation.\n");
33651 printf(" Subface: ");
33652 printsh(&shloop);
33653 horrors++;
33654 }
33655 }
33656 }
33657 sesymself(shloop);
33658 stpivot(shloop, oppooppotet);
33659 if (oppooppotet.tet != dummytet) {
33660 tspivot(oppooppotet, testsh);
33661 if (testsh.sh != shloop.sh) {
33662 printf(" !! !! Wrong tetra-subface connection.\n");
33663 printf(" Tetra: ");
33664 printtet(&oppooppotet);
33665 printf(" Subface: ");
33666 printsh(&shloop);
33667 horrors++;
33668 }
33669 if (oppotet.tet != dummytet) {
33670 sym(oppotet, testtet);
33671 if (testtet.tet != oppooppotet.tet) {
33672 printf(" !! !! Wrong tetra-subface-tetra connection.\n");
33673 printf(" Tetra 1: ");
33674 printtet(&oppotet);
33675 printf(" Subface: ");
33676 printsh(&shloop);
33677 printf(" Tetra 2: ");
33678 printtet(&oppooppotet);
33679 horrors++;
33680 }
33681 }
33682 if (oppo(oppooppotet) != (point) NULL) {
33683 adjustedgering(oppooppotet, CCW);
33684 checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33685 oppo(oppooppotet));
33686 if (checksign >= 0.0) {
33687 printf(" !! !! Wrong subface orientation.\n");
33688 printf(" Subface: ");
33689 printsh(&shloop);
33690 horrors++;
33691 }
33692 }
33693 }
33694
33695 shloop.shver = 0;
33696 for (i = 0; i < 3; i++) {
33697 shorg = sorg(shloop);
33698 shdest = sdest(shloop);
33699 sspivot(shloop, testseg);
33700 if (testseg.sh != dummysh) {
33701 segorg = sorg(testseg);
33702 segdest = sdest(testseg);
33703 same = ((shorg == segorg) && (shdest == segdest))
33704 || ((shorg == segdest) && (shdest == segorg));
33705 if (!same) {
33706 printf(" !! !! Wrong subface-subsegment connection.\n");
33707 printf(" Subface: ");
33708 printsh(&shloop);
33709 printf(" Subsegment: ");
33710 printsh(&testseg);
33711 horrors++;
33712 }
33713 }
33714 spivot(shloop, testsh);
33715 if (testsh.sh != dummysh) {
33716 segorg = sorg(testsh);
33717 segdest = sdest(testsh);
33718 same = ((shorg == segorg) && (shdest == segdest))
33719 || ((shorg == segdest) && (shdest == segorg));
33720 if (!same) {
33721 printf(" !! !! Wrong subface-subface connection.\n");
33722 printf(" Subface 1: ");
33723 printsh(&shloop);
33724 printf(" Subface 2: ");
33725 printsh(&testsh);
33726 horrors++;
33727 }
33728 spivot(testsh, testshsh);
33729 shorg = sorg(testshsh);
33730 shdest = sdest(testshsh);
33731 same = ((shorg == segorg) && (shdest == segdest))
33732 || ((shorg == segdest) && (shdest == segorg));
33733 if (!same) {
33734 printf(" !! !! Wrong subface-subface connection.\n");
33735 printf(" Subface 1: ");
33736 printsh(&testsh);
33737 printf(" Subface 2: ");
33738 printsh(&testshsh);
33739 horrors++;
33740 }
33741 if (testseg.sh == dummysh) {
33742 if (testshsh.sh != shloop.sh) {
33743 printf(" !! !! Wrong subface-subface connection.\n");
33744 printf(" Subface 1: ");
33745 printsh(&shloop);
33746 printf(" Subface 2: ");
33747 printsh(&testsh);
33748 horrors++;
33749 }
33750 }
33751 }
33752 senextself(shloop);
33753 }
33754 shloop.sh = shellfacetraverse(subfaces);
33755 }
33756
33757
33758 subsegs->traversalinit();
33759 segloop.sh = shellfacetraverse(subsegs);
33760 while (segloop.sh != (shellface *) NULL) {
33761 segorg = sorg(segloop);
33762 segdest = sdest(segloop);
33763 spivot(segloop, testsh);
33764 if (testsh.sh == dummysh) {
33765 printf(" !! !! Wrong subsegment-subface connection.\n");
33766 printf(" Subsegment: ");
33767 printsh(&segloop);
33768 horrors++;
33769 segloop.sh = shellfacetraverse(subsegs);
33770 continue;
33771 }
33772 shorg = sorg(testsh);
33773 shdest = sdest(testsh);
33774 same = ((shorg == segorg) && (shdest == segdest))
33775 || ((shorg == segdest) && (shdest == segorg));
33776 if (!same) {
33777 printf(" !! !! Wrong subsegment-subface connection.\n");
33778 printf(" Subsegment : ");
33779 printsh(&segloop);
33780 printf(" Subface : ");
33781 printsh(&testsh);
33782 horrors++;
33783 segloop.sh = shellfacetraverse(subsegs);
33784 continue;
33785 }
33786
33787 spin = testsh;
33788 i = 0;
33789 do {
33790 spivotself(spin);
33791 shorg = sorg(spin);
33792 shdest = sdest(spin);
33793 same = ((shorg == segorg) && (shdest == segdest))
33794 || ((shorg == segdest) && (shdest == segorg));
33795 if (!same) {
33796 printf(" !! !! Wrong subsegment-subface connection.\n");
33797 printf(" Subsegment : ");
33798 printsh(&segloop);
33799 printf(" Subface : ");
33800 printsh(&testsh);
33801 horrors++;
33802 break;
33803 }
33804 i++;
33805 } while (spin.sh != testsh.sh && i < 1000);
33806 if (i >= 1000) {
33807 printf(" !! !! Wrong subsegment-subface connection.\n");
33808 printf(" Subsegment : ");
33809 printsh(&segloop);
33810 horrors++;
33811 }
33812 segloop.sh = shellfacetraverse(subsegs);
33813 }
33814 if (horrors == 0) {
33815 if (!b->quiet) {
33816 printf(" Mesh boundaries connected correctly.\n");
33817 }
33818 } else {
33819 printf(" !! !! !! !! %d boundary connection viewed with horror.\n",
33820 horrors);
33821 return;
33822 }
33823 }
33824
33826
33827
33828
33829
33830
33832
33833 void tetgenmesh::checkdelaunay(REAL eps, queue* flipqueue)
33834 {
33835 triface tetraloop;
33836 triface oppotet;
33837 face opposhelle;
33838 point tetorg, tetdest, tetapex, tetoppo;
33839 point oppooppo;
33840 enum fliptype fc;
33841 REAL sign;
33842 int shouldbedelaunay;
33843 int horrors;
33844
33845 if (!b->quiet) {
33846 printf(" Checking Delaunay property of the mesh...\n");
33847 }
33848 horrors = 0;
33849
33850 tetrahedrons->traversalinit();
33851 tetraloop.tet = tetrahedrontraverse();
33852 while (tetraloop.tet != (tetrahedron *) NULL) {
33853
33854 for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33855 tetorg = org(tetraloop);
33856 tetdest = dest(tetraloop);
33857 tetapex = apex(tetraloop);
33858 tetoppo = oppo(tetraloop);
33859 sym(tetraloop, oppotet);
33860 oppooppo = oppo(oppotet);
33861
33862
33863 shouldbedelaunay = (oppotet.tet != dummytet)
33864 && (tetoppo != (point) NULL)
33865 && (oppooppo != (point) NULL)
33866 && (tetraloop.tet < oppotet.tet);
33867 if (checksubfaces && shouldbedelaunay) {
33868
33869
33870 tspivot(tetraloop, opposhelle);
33871 if (opposhelle.sh != dummysh){
33872 shouldbedelaunay = 0;
33873 }
33874 }
33875 if (shouldbedelaunay) {
33876 sign = insphere(tetdest, tetorg, tetapex, tetoppo, oppooppo);
33877 if ((sign > 0.0) && (eps > 0.0)) {
33878 if (iscospheric(tetdest, tetorg, tetapex, tetoppo, oppooppo, sign,
33879 eps)) sign = 0.0;
33880 }
33881 if (sign > 0.0) {
33882 if (flipqueue) {
33883 enqueueflipface(tetraloop, flipqueue);
33884 } else {
33885 printf(" !! Non-locally Delaunay face (%d, %d, %d) ",
33886 pointmark(tetorg), pointmark(tetdest), pointmark(tetapex));
33887 fc = categorizeface(tetraloop);
33888 switch (fc) {
33889 case T23: printf("\"T23\""); break;
33890 case T32: printf("\"T32\""); break;
33891 case T22: printf("\"T22\""); break;
33892 case T44: printf("\"T44\""); break;
33893 case N32: printf("\"N32\""); break;
33894 case N40: printf("\"N40\""); break;
33895 case FORBIDDENFACE:printf("\"FORBIDDENFACE\""); break;
33896 case FORBIDDENEDGE:printf("\"FORBIDDENEDGE\""); break;
33897 }
33898 printf("\n");
33899 }
33900 horrors++;
33901 }
33902 }
33903 }
33904 tetraloop.tet = tetrahedrontraverse();
33905 }
33906 if (flipqueue == (queue *) NULL) {
33907 if (horrors == 0) {
33908 if (!b->quiet) {
33909 printf(" The mesh is %s.\n",
33910 checksubfaces ? "constrained Delaunay" : "Delaunay");
33911 }
33912 } else {
33913 printf(" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
33914 }
33915 }
33916 }
33917
33919
33920
33921
33923
33924 void tetgenmesh::checkconforming()
33925 {
33926 face segloop, shloop;
33927 int encsubsegs, encsubfaces;
33928
33929 if (!b->quiet) {
33930 printf(" Checking conforming Delaunay property of mesh...\n");
33931 }
33932 encsubsegs = encsubfaces = 0;
33933
33934 subsegs->traversalinit();
33935 segloop.sh = shellfacetraverse(subsegs);
33936 while (segloop.sh != (shellface *) NULL) {
33937 if (checkseg4encroach(&segloop, NULL, NULL, false)) {
33938 printf(" !! !! Non-conforming subsegment: (%d, %d)\n",
33939 pointmark(sorg(segloop)), pointmark(sdest(segloop)));
33940 encsubsegs++;
33941 }
33942 segloop.sh = shellfacetraverse(subsegs);
33943 }
33944
33945 subfaces->traversalinit();
33946 shloop.sh = shellfacetraverse(subfaces);
33947 while (shloop.sh != (shellface *) NULL) {
33948 if (checksub4encroach(&shloop, NULL, false)) {
33949 printf(" !! !! Non-conforming subface: (%d, %d, %d)\n",
33950 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
33951 pointmark(sapex(shloop)));
33952 encsubfaces++;
33953 }
33954 shloop.sh = shellfacetraverse(subfaces);
33955 }
33956 if (encsubsegs == 0 && encsubfaces == 0) {
33957 if (!b->quiet) {
33958 printf(" The mesh is conforming Delaunay.\n");
33959 }
33960 } else {
33961 if (encsubsegs > 0) {
33962 printf(" !! !! %d subsegments are non-conforming.\n", encsubsegs);
33963 }
33964 if (encsubfaces > 0) {
33965 printf(" !! !! %d subfaces are non-conforming.\n", encsubfaces);
33966 }
33967 }
33968 }
33969
33971
33972
33973
33975
33976 #ifdef SELF_CHECK
33977
33978 void tetgenmesh::algorithmicstatistics()
33979 {
33980
33981
33982
33983
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 #endif // #ifdef SELF_CHECK
34019
34021
34022
34023
34025
34026 void tetgenmesh::qualitystatistics()
34027 {
34028 triface tetloop, neightet;
34029 point p[4];
34030 char sbuf[128];
34031 REAL radiusratiotable[12];
34032 REAL aspectratiotable[12];
34033 REAL A[4][4], rhs[4], D;
34034 REAL V[6][3], N[4][3], H[4];
34035 REAL edgelength[6], alldihed[6], faceangle[3];
34036 REAL shortest, longest;
34037 REAL smallestvolume, biggestvolume;
34038 REAL smallestdiangle, biggestdiangle;
34039 REAL smallestfaangle, biggestfaangle;
34040 REAL tetvol, minaltitude;
34041 REAL cirradius, minheightinv;
34042 REAL shortlen, longlen;
34043 REAL tetaspect, tetradius;
34044 REAL smalldiangle, bigdiangle;
34045 REAL smallfaangle, bigfaangle;
34046 int radiustable[12];
34047 int aspecttable[16];
34048 int dihedangletable[18];
34049 int faceangletable[18];
34050 int indx[4];
34051 int radiusindex;
34052 int aspectindex;
34053 int tendegree;
34054 int i, j;
34055
34056 smallfaangle = 0.0;
34057 bigfaangle = 0.0;
34058
34059 printf("Mesh quality statistics:\n\n");
34060
34061
34062 shortlen = longlen = 0.0;
34063 smalldiangle = bigdiangle = 0.0;
34064
34065 radiusratiotable[0] = 0.707; radiusratiotable[1] = 1.0;
34066 radiusratiotable[2] = 1.1; radiusratiotable[3] = 1.2;
34067 radiusratiotable[4] = 1.4; radiusratiotable[5] = 1.6;
34068 radiusratiotable[6] = 1.8; radiusratiotable[7] = 2.0;
34069 radiusratiotable[8] = 2.5; radiusratiotable[9] = 3.0;
34070 radiusratiotable[10] = 10.0; radiusratiotable[11] = 0.0;
34071
34072 aspectratiotable[0] = 1.5; aspectratiotable[1] = 2.0;
34073 aspectratiotable[2] = 2.5; aspectratiotable[3] = 3.0;
34074 aspectratiotable[4] = 4.0; aspectratiotable[5] = 6.0;
34075 aspectratiotable[6] = 10.0; aspectratiotable[7] = 15.0;
34076 aspectratiotable[8] = 25.0; aspectratiotable[9] = 50.0;
34077 aspectratiotable[10] = 100.0; aspectratiotable[11] = 0.0;
34078
34079 for (i = 0; i < 12; i++) radiustable[i] = 0;
34080 for (i = 0; i < 12; i++) aspecttable[i] = 0;
34081 for (i = 0; i < 18; i++) dihedangletable[i] = 0;
34082 for (i = 0; i < 18; i++) faceangletable[i] = 0;
34083
34084 minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
34085 minaltitude = minaltitude * minaltitude;
34086 shortest = minaltitude;
34087 longest = 0.0;
34088 smallestvolume = minaltitude;
34089 biggestvolume = 0.0;
34090 smallestdiangle = smallestfaangle = 180.0;
34091 biggestdiangle = biggestfaangle = 0.0;
34092
34093
34094 tetrahedrons->traversalinit();
34095 tetloop.tet = tetrahedrontraverse();
34096 while (tetloop.tet != (tetrahedron *) NULL) {
34097
34098
34099 for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i];
34100
34101 for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i];
34102 for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i];
34103 for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i];
34104 for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i];
34105 for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i];
34106 for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i];
34107
34108 for (j = 0; j < 3; j++) {
34109 for (i = 0; i < 3; i++) A[j][i] = V[j][i];
34110 }
34111
34112 lu_decmp(A, 3, indx, &D, 0);
34113
34114 tetvol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
34115
34116 for (j = 0; j < 3; j++) {
34117 for (i = 0; i < 3; i++) rhs[i] = 0.0;
34118 rhs[j] = 1.0;
34119 lu_solve(A, 3, indx, rhs, 0);
34120 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
34121 }
34122
34123 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
34124
34125 for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]);
34126 lu_solve(A, 3, indx, rhs, 0);
34127 cirradius = sqrt(dot(rhs, rhs));
34128
34129 for (i = 0; i < 4; i++) {
34130
34131 H[i] = sqrt(dot(N[i], N[i]));
34132 for (j = 0; j < 3; j++) N[i][j] /= H[i];
34133 }
34134
34135
34136
34137 minheightinv = H[0];
34138 for (i = 1; i < 3; i++) {
34139 if (H[i] > minheightinv) minheightinv = H[i];
34140 }
34141
34142 for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
34143
34144 j = 0;
34145 for (i = 1; i < 4; i++) {
34146 alldihed[j] = -dot(N[0], N[i]);
34147 if (alldihed[j] < -1.0) alldihed[j] = -1;
34148 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34149 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34150 j++;
34151 }
34152 for (i = 2; i < 4; i++) {
34153 alldihed[j] = -dot(N[1], N[i]);
34154 if (alldihed[j] < -1.0) alldihed[j] = -1;
34155 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34156 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34157 j++;
34158 }
34159 alldihed[j] = -dot(N[2], N[3]);
34160 if (alldihed[j] < -1.0) alldihed[j] = -1;
34161 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34162 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34163
34164
34165 for (i = 0; i < 6; i++) {
34166 if (i == 0) {
34167 shortlen = longlen = edgelength[i];
34168 } else {
34169 shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen;
34170 longlen = edgelength[i] > longlen ? edgelength[i] : longlen;
34171 }
34172 if (edgelength[i] > longest) {
34173 longest = edgelength[i];
34174 }
34175 if (edgelength[i] < shortest) {
34176 shortest = edgelength[i];
34177 }
34178 }
34179
34180
34181 if (tetvol < smallestvolume) {
34182 smallestvolume = tetvol;
34183 }
34184 if (tetvol > biggestvolume) {
34185 biggestvolume = tetvol;
34186 }
34187
34188
34189 for (i = 0; i < 6; i++) {
34190 if (i == 0) {
34191 smalldiangle = bigdiangle = alldihed[i];
34192 } else {
34193 smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle;
34194 bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle;
34195 }
34196 if (alldihed[i] < smallestdiangle) {
34197 smallestdiangle = alldihed[i];
34198 }
34199 if (alldihed[i] > biggestdiangle) {
34200 biggestdiangle = alldihed[i];
34201 }
34202 }
34203
34204 if (smalldiangle < 5.0) {
34205 tendegree = 0;
34206 } else if (smalldiangle >= 5.0 && smalldiangle < 10.0) {
34207 tendegree = 1;
34208 } else if (smalldiangle >= 80.0 && smalldiangle < 110.0) {
34209 tendegree = 9;
34210 } else {
34211 tendegree = (int) (smalldiangle / 10.);
34212 if (smalldiangle < 80.0) {
34213 tendegree++;
34214 } else {
34215 tendegree--;
34216 }
34217 }
34218 dihedangletable[tendegree]++;
34219 if (bigdiangle >= 80.0 && bigdiangle < 110.0) {
34220 tendegree = 9;
34221 } else if (bigdiangle >= 170.0 && bigdiangle < 175.0) {
34222 tendegree = 16;
34223 } else if (bigdiangle >= 175.0) {
34224 tendegree = 17;
34225 } else {
34226 tendegree = (int) (bigdiangle / 10.);
34227 if (bigdiangle < 80.0) {
34228 tendegree++;
34229 } else {
34230 tendegree--;
34231 }
34232 }
34233 dihedangletable[tendegree]++;
34234
34235
34236 tetloop.ver = 0;
34237 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
34238 sym(tetloop, neightet);
34239
34240 if ((neightet.tet == dummytet) || (tetloop.tet < neightet.tet)) {
34241 p[0] = org(tetloop);
34242 p[1] = dest(tetloop);
34243 p[2] = apex(tetloop);
34244 faceangle[0] = interiorangle(p[0], p[1], p[2], NULL);
34245 faceangle[1] = interiorangle(p[1], p[2], p[0], NULL);
34246 faceangle[2] = PI - (faceangle[0] + faceangle[1]);
34247
34248 for (i = 0; i < 3; i++) {
34249 faceangle[i] = (faceangle[i] * 180.0) / PI;
34250 }
34251
34252 for (i = 0; i < 3; i++) {
34253 if (i == 0) {
34254 smallfaangle = bigfaangle = faceangle[i];
34255 } else {
34256 smallfaangle = faceangle[i] < smallfaangle ?
34257 faceangle[i] : smallfaangle;
34258 bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle;
34259 }
34260 if (faceangle[i] < smallestfaangle) {
34261 smallestfaangle = faceangle[i];
34262 }
34263 if (faceangle[i] > biggestfaangle) {
34264 biggestfaangle = faceangle[i];
34265 }
34266 }
34267 tendegree = (int) (smallfaangle / 10.);
34268 faceangletable[tendegree]++;
34269 tendegree = (int) (bigfaangle / 10.);
34270 faceangletable[tendegree]++;
34271 }
34272 }
34273
34274
34275 tetradius = cirradius / sqrt(shortlen);
34276
34277 tetaspect = sqrt(longlen) * minheightinv;
34278 aspectindex = 0;
34279 while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) {
34280 aspectindex++;
34281 }
34282 aspecttable[aspectindex]++;
34283 radiusindex = 0;
34284 while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) {
34285 radiusindex++;
34286 }
34287 radiustable[radiusindex]++;
34288
34289 tetloop.tet = tetrahedrontraverse();
34290 }
34291
34292 shortest = sqrt(shortest);
34293 longest = sqrt(longest);
34294 minaltitude = sqrt(minaltitude);
34295
34296 printf(" Smallest volume: %16.5g | Largest volume: %16.5g\n",
34297 smallestvolume, biggestvolume);
34298 printf(" Shortest edge: %16.5g | Longest edge: %16.5g\n",
34299 shortest, longest);
34300 sprintf(sbuf, "%.17g", biggestfaangle);
34301 if (strlen(sbuf) > 8) {
34302 sbuf[8] = '\0';
34303 }
34304 printf(" Smallest facangle: %14.5g | Largest facangle: %s\n",
34305 smallestfaangle, sbuf);
34306 sprintf(sbuf, "%.17g", biggestdiangle);
34307 if (strlen(sbuf) > 8) {
34308 sbuf[8] = '\0';
34309 }
34310 printf(" Smallest dihedral: %14.5g | Largest dihedral: %s\n\n",
34311 smallestdiangle, sbuf);
34312
34313
34314
34315
34316
34317
34318
34319
34320
34321
34322
34323
34324
34325
34326
34327
34328
34329
34330
34331
34332 printf(" Aspect ratio histogram:\n");
34333 printf(" < %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
34334 aspectratiotable[0], aspecttable[0], aspectratiotable[5],
34335 aspectratiotable[6], aspecttable[6]);
34336 for (i = 1; i < 5; i++) {
34337 printf(" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
34338 aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i],
34339 aspectratiotable[i + 5], aspectratiotable[i + 6],
34340 aspecttable[i + 6]);
34341 }
34342 printf(" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
34343 aspectratiotable[4], aspectratiotable[5], aspecttable[5],
34344 aspectratiotable[10], aspecttable[11]);
34345 printf(" (A tetrahedron's aspect ratio is its longest edge length");
34346 printf(" divided by its\n");
34347 printf(" smallest side height)\n\n");
34348
34349 printf(" Face angle histogram:\n");
34350 for (i = 0; i < 9; i++) {
34351 printf(" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
34352 i * 10, i * 10 + 10, faceangletable[i],
34353 i * 10 + 90, i * 10 + 100, faceangletable[i + 9]);
34354 }
34355 if (minfaceang != PI) {
34356 printf(" Minimum input face angle is %g (degree).\n",
34357 minfaceang / PI * 180.0);
34358 }
34359 printf("\n");
34360
34361 printf(" Dihedral angle histogram:\n");
34362
34363 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34364 0, 5, dihedangletable[0], 80, 110, dihedangletable[9]);
34365 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34366 5, 10, dihedangletable[1], 110, 120, dihedangletable[10]);
34367
34368 for (i = 2; i < 7; i++) {
34369 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34370 (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i],
34371 (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]);
34372 }
34373
34374 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34375 60, 70, dihedangletable[7], 170, 175, dihedangletable[16]);
34376 printf(" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34377 70, 80, dihedangletable[8], 175, 180, dihedangletable[17]);
34378 if (minfacetdihed != PI) {
34379 printf(" Minimum input facet dihedral angle is %g (degree).\n",
34380 minfacetdihed / PI * 180.0);
34381 }
34382 printf("\n");
34383 }
34384
34386
34387
34388
34390
34391 void tetgenmesh::statistics()
34392 {
34393 printf("\nStatistics:\n\n");
34394 printf(" Input points: %d\n", in->numberofpoints + jettisoninverts);
34395 if (b->refine) {
34396 printf(" Input tetrahedra: %d\n", in->numberoftetrahedra);
34397 }
34398 if (b->plc) {
34399 printf(" Input facets: %d\n", in->numberoffacets);
34400 printf(" Input segments: %ld\n", insegments);
34401 printf(" Input holes: %d\n", in->numberofholes);
34402 printf(" Input regions: %d\n", in->numberofregions);
34403 }
34404
34405 printf("\n Mesh points: %ld\n", points->items);
34406 printf(" Mesh tetrahedra: %ld\n", tetrahedrons->items);
34407 if (b->plc || b->refine) {
34408 printf(" Mesh triangles: %ld\n", (4l*tetrahedrons->items+hullsize)/2l);
34409 }
34410 if (b->plc || b->refine) {
34411 printf(" Mesh subfaces: %ld\n", subfaces->items);
34412 printf(" Mesh subsegments: %ld\n\n", subsegs->items);
34413 } else {
34414 printf(" Convex hull triangles: %ld\n\n", hullsize);
34415 }
34416 if (b->verbose > 0) {
34417 qualitystatistics();
34418 unsigned long totalmeshbytes;
34419 printf("Memory allocation statistics:\n\n");
34420 printf(" Maximum number of vertices: %ld\n", points->maxitems);
34421 totalmeshbytes = points->maxitems * points->itembytes;
34422 printf(" Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems);
34423 totalmeshbytes += tetrahedrons->maxitems * tetrahedrons->itembytes;
34424 if (subfaces != (memorypool *) NULL) {
34425 printf(" Maximum number of subfaces: %ld\n", subfaces->maxitems);
34426 totalmeshbytes += subfaces->maxitems * subfaces->itembytes;
34427 }
34428 if (subsegs != (memorypool *) NULL) {
34429 printf(" Maximum number of segments: %ld\n", subsegs->maxitems);
34430 totalmeshbytes += subsegs->maxitems * subsegs->itembytes;
34431 }
34432 printf(" Approximate heap memory used by the mesh (K bytes): %g\n\n",
34433 (double) totalmeshbytes / 1024.0);
34434 #ifdef SELF_CHECK
34435 algorithmicstatistics();
34436 #endif
34437 }
34438 }
34439
34440
34441
34442
34443
34444
34445
34446
34447
34449
34450
34451
34453
34454 tetgenmesh::~tetgenmesh()
34455 {
34456 bgm = (tetgenmesh *) NULL;
34457 in = (tetgenio *) NULL;
34458 b = (tetgenbehavior *) NULL;
34459
34460 if (tetrahedrons != (memorypool *) NULL) {
34461 delete tetrahedrons;
34462 }
34463 if (subfaces != (memorypool *) NULL) {
34464 delete subfaces;
34465 }
34466 if (subsegs != (memorypool *) NULL) {
34467 delete subsegs;
34468 }
34469 if (points != (memorypool *) NULL) {
34470 delete points;
34471 }
34472 if (dummytetbase != (tetrahedron *) NULL) {
34473 delete [] dummytetbase;
34474 }
34475 if (dummyshbase != (shellface *) NULL) {
34476 delete [] dummyshbase;
34477 }
34478 if (facetabovepointarray != (point *) NULL) {
34479 delete [] facetabovepointarray;
34480 }
34481 if (highordertable != (point *) NULL) {
34482 delete [] highordertable;
34483 }
34484 if (subpbcgrouptable != (pbcdata *) NULL) {
34485 delete [] subpbcgrouptable;
34486 }
34487 if (segpbcgrouptable != (list *) NULL) {
34488 delete segpbcgrouptable;
34489 delete [] idx2segpglist;
34490 delete [] segpglist;
34491 }
34492 }
34493
34495
34496
34497
34499
34500 tetgenmesh::tetgenmesh()
34501 {
34502 bgm = (tetgenmesh *) NULL;
34503 in = (tetgenio *) NULL;
34504 b = (tetgenbehavior *) NULL;
34505
34506 tetrahedrons = (memorypool *) NULL;
34507 subfaces = (memorypool *) NULL;
34508 subsegs = (memorypool *) NULL;
34509 points = (memorypool *) NULL;
34510 badsubsegs = (memorypool *) NULL;
34511 badsubfaces = (memorypool *) NULL;
34512 badtetrahedrons = (memorypool *) NULL;
34513 flipstackers = (memorypool *) NULL;
34514
34515 dummytet = (tetrahedron *) NULL;
34516 dummytetbase = (tetrahedron *) NULL;
34517 dummysh = (shellface *) NULL;
34518 dummyshbase = (shellface *) NULL;
34519
34520 facetabovepointarray = (point *) NULL;
34521 abovepoint = (point) NULL;
34522 highordertable = (point *) NULL;
34523 subpbcgrouptable = (pbcdata *) NULL;
34524 segpbcgrouptable = (list *) NULL;
34525 idx2segpglist = (int *) NULL;
34526 segpglist = (int *) NULL;
34527
34528 xmax = xmin = ymax = ymin = zmax = zmin = 0.0;
34529 longest = 0.0;
34530 hullsize = 0l;
34531 insegments = 0l;
34532 pointmtrindex = 0;
34533 pointmarkindex = 0;
34534 point2simindex = 0;
34535 point2pbcptindex = 0;
34536 highorderindex = 0;
34537 elemattribindex = 0;
34538 volumeboundindex = 0;
34539 shmarkindex = 0;
34540 areaboundindex = 0;
34541 checksubfaces = 0;
34542 checksubsegs = 0;
34543 checkpbcs = 0;
34544 varconstraint = 0;
34545 nonconvex = 0;
34546 dupverts = 0;
34547 unuverts = 0;
34548 relverts = 0;
34549 suprelverts = 0;
34550 collapverts = 0;
34551 unsupverts = 0;
34552 jettisoninverts = 0;
34553 symbolic = 1;
34554 samples = 0l;
34555 randomseed = 1l;
34556 macheps = 0.0;
34557 minfaceang = minfacetdihed = PI;
34558 maxcavfaces = maxcavverts = 0;
34559 expcavcount = 0;
34560 abovecount = 0l;
34561 bowatvolcount = bowatsubcount = bowatsegcount = 0l;
34562 updvolcount = updsubcount = updsegcount = 0l;
34563 repairflipcount = 0l;
34564 outbowatcircumcount = 0l;
34565 failvolcount = failsubcount = failsegcount = 0l;
34566 r1count = r2count = r3count = 0l;
34567 cdtenforcesegpts = 0l;
34568 rejsegpts = rejsubpts = rejtetpts = 0l;
34569 flip23s = flip32s = flip22s = flip44s = 0l;
34570 tloctime = tfliptime = 0.0;
34571 }
34572
34573
34574
34575
34576
34577
34578
34579
34580
34582
34583
34584
34585
34586
34587
34588
34589
34590
34591
34592
34593
34594
34595
34596
34597
34598
34599
34600
34601
34602
34604
34605 void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
34606 tetgenio *addin, tetgenio *bgmin)
34607 {
34608 tetgenmesh m;
34609
34610 clock_t tv[14];
34611
34612 tv[0] = clock();
34613
34614 m.b = b;
34615 m.in = in;
34616 m.macheps = exactinit();
34617 m.steinerleft = b->steiner;
34618 if (b->metric) {
34619 m.bgm = new tetgenmesh();
34620 m.bgm->b = b;
34621 m.bgm->in = bgmin;
34622 m.bgm->macheps = exactinit();
34623 }
34624 m.initializepools();
34625 m.transfernodes();
34626
34627 tv[1] = clock();
34628
34629 if (b->refine) {
34630 m.reconstructmesh();
34631 } else {
34632 m.delaunizevertices();
34633 }
34634
34635 tv[2] = clock();
34636
34637 if (!b->quiet) {
34638 if (b->refine) {
34639 printf("Mesh reconstruction seconds:");
34640 } else {
34641 printf("Delaunay seconds:");
34642 }
34643 printf(" %g\n", (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
34644 }
34645
34646 if (b->metric) {
34647 if (bgmin != (tetgenio *) NULL) {
34648 m.bgm->initializepools();
34649 m.bgm->transfernodes();
34650 m.bgm->reconstructmesh();
34651 } else {
34652 m.bgm->in = in;
34653 m.bgm->initializepools();
34654 m.duplicatebgmesh();
34655 }
34656 }
34657
34658 tv[3] = clock();
34659
34660 if (!b->quiet) {
34661 if (b->metric) {
34662 printf("Background mesh reconstruct seconds: %g\n",
34663 (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
34664 }
34665 }
34666
34667 if (b->useshelles && !b->refine) {
34668 m.meshsurface();
34669 if (b->diagnose != 1) {
34670 m.markacutevertices(89.0);
34671 m.incrperturbvertices(b->epsilon);
34672 m.delaunizesegments();
34673 if (m.checkpbcs) {
34674 long oldnum;
34675 do {
34676 oldnum = m.points->items;
34677 m.incrperturbvertices(b->epsilon);
34678 if (m.points->items > oldnum) {
34679 oldnum = m.points->items;
34680 m.delaunizesegments();
34681 }
34682 } while (oldnum < m.points->items);
34683 }
34684 m.constrainedfacets();
34685 } else {
34686 m.detectinterfaces();
34687 }
34688 }
34689
34690 tv[4] = clock();
34691
34692 if (!b->quiet) {
34693 if (b->useshelles && !b->refine) {
34694 if (b->diagnose != 1) {
34695 printf("Segment and facet ");
34696 } else {
34697 printf("Intersection ");
34698 }
34699 printf("seconds: %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
34700 }
34701 }
34702
34703 if (b->plc && !(b->diagnose == 1)) {
34704 m.carveholes();
34705 }
34706
34707 tv[5] = clock();
34708
34709 if (!b->quiet) {
34710 if (b->plc && !(b->diagnose == 1)) {
34711 printf("Hole seconds: %g\n", (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
34712 }
34713 }
34714
34715 if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34716 m.optimizemesh(false);
34717 }
34718
34719 tv[6] = clock();
34720
34721 if (!b->quiet) {
34722 if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34723 printf("Repair seconds: %g\n", (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
34724 }
34725 }
34726
34727 if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34728 m.removesteiners(false);
34729 }
34730
34731 tv[7] = clock();
34732
34733 if (!b->quiet) {
34734 if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34735 printf("Steiner removal seconds: %g\n",
34736 (tv[7] - tv[6]) / (REAL) CLOCKS_PER_SEC);
34737 }
34738 }
34739
34740 if (b->insertaddpoints && (addin != (tetgenio *) NULL)) {
34741 if (addin->numberofpoints > 0) {
34742 m.insertconstrainedpoints(addin);
34743 }
34744 }
34745
34746 tv[8] = clock();
34747
34748 if (!b->quiet) {
34749 if ((b->plc || b->refine) && (b->insertaddpoints)) {
34750 printf("Constrained points seconds: %g\n",
34751 (tv[8] - tv[7]) / (REAL) CLOCKS_PER_SEC);
34752 }
34753 }
34754
34755 if (b->metric) {
34756 m.interpolatesizemap();
34757 }
34758
34759 tv[9] = clock();
34760
34761 if (!b->quiet) {
34762 if (b->metric) {
34763 printf("Size interpolating seconds: %g\n",
34764 (tv[9] - tv[8]) / (REAL) CLOCKS_PER_SEC);
34765 }
34766 }
34767
34768 if (b->coarse) {
34769 m.removesteiners(true);
34770 }
34771
34772 tv[10] = clock();
34773
34774 if (!b->quiet) {
34775 if (b->coarse) {
34776 printf("Mesh coarsening seconds: %g\n",
34777 (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
34778 }
34779 }
34780
34781 if (b->quality) {
34782 m.enforcequality();
34783 }
34784
34785 tv[11] = clock();
34786
34787 if (!b->quiet) {
34788 if (b->quality) {
34789 printf("Quality seconds: %g\n",
34790 (tv[11] - tv[10]) / (REAL) CLOCKS_PER_SEC);
34791 }
34792 }
34793
34794 if (b->quality && (b->optlevel > 0)) {
34795 m.optimizemesh(true);
34796 }
34797
34798 tv[12] = clock();
34799
34800 if (!b->quiet) {
34801 if (b->quality && (b->optlevel > 0)) {
34802 printf("Optimize seconds: %g\n",
34803 (tv[12] - tv[11]) / (REAL) CLOCKS_PER_SEC);
34804 }
34805 }
34806
34807 if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0)
34808 || (b->refine && (in->numberofcorners == 10)))) {
34809 m.jettisonnodes();
34810 }
34811
34812 if (b->order > 1) {
34813 m.highorder();
34814 }
34815
34816 if (!b->quiet) {
34817 printf("\n");
34818 }
34819
34820 if (out != (tetgenio *) NULL) {
34821 out->firstnumber = in->firstnumber;
34822 out->mesh_dim = in->mesh_dim;
34823 }
34824
34825 if (b->nonodewritten || b->noiterationnum) {
34826 if (!b->quiet) {
34827 printf("NOT writing a .node file.\n");
34828 }
34829 } else {
34830 if (b->diagnose == 1) {
34831 if (m.subfaces->items > 0l) {
34832 m.outnodes(out);
34833 }
34834 } else {
34835 m.outnodes(out);
34836 if (b->quality || b->metric) {
34837
34838 }
34839 }
34840 }
34841
34842 if (b->noelewritten) {
34843 if (!b->quiet) {
34844 printf("NOT writing an .ele file.\n");
34845 }
34846 } else {
34847 if (!(b->diagnose == 1)) {
34848 if (m.tetrahedrons->items > 0l) {
34849 m.outelements(out);
34850 }
34851 }
34852 }
34853
34854 if (b->nofacewritten) {
34855 if (!b->quiet) {
34856 printf("NOT writing an .face file.\n");
34857 }
34858 } else {
34859 if (b->facesout) {
34860 if (m.tetrahedrons->items > 0l) {
34861 m.outfaces(out);
34862 }
34863 } else {
34864 if (b->diagnose == 1) {
34865 if (m.subfaces->items > 0l) {
34866 m.outsubfaces(out);
34867 }
34868 } else if (b->plc || b->refine) {
34869 if (m.subfaces->items > 0l) {
34870 m.outsubfaces(out);
34871 }
34872 } else {
34873 if (m.tetrahedrons->items > 0l) {
34874 m.outhullfaces(out);
34875 }
34876 }
34877 }
34878 }
34879
34880 if (m.checkpbcs) {
34881 m.outpbcnodes(out);
34882 }
34883
34884 if (b->edgesout) {
34885 if (b->edgesout > 1) {
34886 m.outedges(out);
34887 } else {
34888 m.outsubsegments(out);
34889 }
34890 }
34891
34892 if (!out && b->plc &&
34893 ((b->object == tetgenbehavior::OFF) ||
34894 (b->object == tetgenbehavior::PLY) ||
34895 (b->object == tetgenbehavior::STL))) {
34896 m.outsmesh(b->outfilename);
34897 }
34898
34899 if (!out && b->meditview) {
34900 m.outmesh2medit(b->outfilename);
34901 }
34902
34903 if (!out && b->gidview) {
34904 m.outmesh2gid(b->outfilename);
34905 }
34906
34907 if (!out && b->geomview) {
34908 m.outmesh2off(b->outfilename);
34909 }
34910
34911 if (b->neighout) {
34912 m.outneighbors(out);
34913 }
34914
34915 if (b->voroout) {
34916 m.outvoronoi(out);
34917 }
34918
34919 tv[13] = clock();
34920
34921 if (!b->quiet) {
34922 printf("\nOutput seconds: %g\n",
34923 (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
34924 printf("Total running seconds: %g\n",
34925 (tv[13] - tv[0]) / (REAL) CLOCKS_PER_SEC);
34926 }
34927
34928 if (b->docheck) {
34929 m.checkmesh();
34930 if (m.checksubfaces) {
34931 m.checkshells();
34932 }
34933 if (b->docheck > 1) {
34934 m.checkdelaunay(0.0, NULL);
34935 if (b->docheck > 2) {
34936 if (b->quality || b->refine) {
34937 m.checkconforming();
34938 }
34939 }
34940 }
34941 }
34942
34943 if (!b->quiet) {
34944 m.statistics();
34945 }
34946
34947 if (b->metric) {
34948 delete m.bgm;
34949 }
34950 }
34951
34952 #ifndef TETLIBRARY
34953
34955
34956
34957
34959
34960 int main(int argc, char *argv[])
34961
34962 #else // with TETLIBRARY
34963
34965
34966
34967
34969
34970 void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
34971 tetgenio *addin, tetgenio *bgmin)
34972
34973 #endif // not TETLIBRARY
34974
34975 {
34976 tetgenbehavior b;
34977
34978 #ifndef TETLIBRARY
34979
34980 tetgenio in, addin, bgmin;
34981
34982 if (!b.parse_commandline(argc, argv)) {
34983 terminatetetgen(1);
34984 }
34985 if (b.refine) {
34986 if (!in.load_tetmesh(b.infilename)) {
34987 terminatetetgen(1);
34988 }
34989 } else {
34990 if (!in.load_plc(b.infilename, (int) b.object)) {
34991 terminatetetgen(1);
34992 }
34993 }
34994 if (b.insertaddpoints) {
34995 if (!addin.load_node(b.addinfilename)) {
34996 addin.numberofpoints = 0l;
34997 }
34998 }
34999 if (b.metric) {
35000 if (!bgmin.load_tetmesh(b.bgmeshfilename)) {
35001 bgmin.numberoftetrahedra = 0l;
35002 }
35003 }
35004
35005 if (bgmin.numberoftetrahedra > 0l) {
35006 tetrahedralize(&b, &in, NULL, &addin, &bgmin);
35007 } else {
35008 tetrahedralize(&b, &in, NULL, &addin, NULL);
35009 }
35010
35011 return 0;
35012
35013 #else // with TETLIBRARY
35014
35015 if (!b.parse_commandline(switches)) {
35016 terminatetetgen(1);
35017 }
35018 tetrahedralize(&b, in, out, addin, bgmin);
35019
35020 #endif // not TETLIBRARY
35021 }
35022
35023 }
35024
35025 #ifndef TETLIBRARY
35026
35027
35028 int main(int argc, char *argv[])
35029 {
35030 tetgen::main(argc, argv);
35031 }
35032 #endif // not TETLIBRARY