9 #define UNUSED_OPT(var) var=var 11 #define UNUSED_OPT(var) 58 void terminatetetgen(
int x)
64 #endif // #ifdef TETLIBRARY 84 void tetgenio::initialize()
90 pointlist = (REAL *) NULL;
91 pointattributelist = (REAL *) NULL;
92 pointmtrlist = (REAL *) NULL;
93 pointmarkerlist = (
int *) NULL;
95 numberofpointattributes = 0;
96 numberofpointmtrs = 0;
98 tetrahedronlist = (
int *) NULL;
99 tetrahedronattributelist = (REAL *) NULL;
100 tetrahedronvolumelist = (REAL *) NULL;
101 neighborlist = (
int *) NULL;
102 numberoftetrahedra = 0;
104 numberoftetrahedronattributes = 0;
106 trifacelist = (
int *) NULL;
107 adjtetlist = (
int *) NULL;
108 trifacemarkerlist = (
int *) NULL;
109 numberoftrifaces = 0;
111 facetlist = (facet *) NULL;
112 facetmarkerlist = (
int *) NULL;
115 edgelist = (
int *) NULL;
116 edgemarkerlist = (
int *) NULL;
119 holelist = (REAL *) NULL;
122 regionlist = (REAL *) NULL;
125 facetconstraintlist = (REAL *) NULL;
126 numberoffacetconstraints = 0;
127 segmentconstraintlist = (REAL *) NULL;
128 numberofsegmentconstraints = 0;
130 pbcgrouplist = (pbcgroup *) NULL;
131 numberofpbcgroups = 0;
133 vpointlist = (REAL *) NULL;
134 vedgelist = (voroedge *) NULL;
135 vfacetlist = (vorofacet *) NULL;
136 vcelllist = (
int **) NULL;
158 void tetgenio::deinitialize()
165 if (pointlist != (REAL *) NULL) {
168 if (pointattributelist != (REAL *) NULL) {
169 delete [] pointattributelist;
171 if (pointmtrlist != (REAL *) NULL) {
172 delete [] pointmtrlist;
174 if (pointmarkerlist != (
int *) NULL) {
175 delete [] pointmarkerlist;
178 if (tetrahedronlist != (
int *) NULL) {
179 delete [] tetrahedronlist;
181 if (tetrahedronattributelist != (REAL *) NULL) {
182 delete [] tetrahedronattributelist;
184 if (tetrahedronvolumelist != (REAL *) NULL) {
185 delete [] tetrahedronvolumelist;
187 if (neighborlist != (
int *) NULL) {
188 delete [] neighborlist;
191 if (trifacelist != (
int *) NULL) {
192 delete [] trifacelist;
194 if (adjtetlist != (
int *) NULL) {
195 delete [] adjtetlist;
197 if (trifacemarkerlist != (
int *) NULL) {
198 delete [] trifacemarkerlist;
201 if (edgelist != (
int *) NULL) {
204 if (edgemarkerlist != (
int *) NULL) {
205 delete [] edgemarkerlist;
208 if (facetlist != (facet *) NULL) {
209 for (i = 0; i < numberoffacets; i++) {
211 for (j = 0; j < f->numberofpolygons; j++) {
212 p = &f->polygonlist[j];
213 delete [] p->vertexlist;
215 delete [] f->polygonlist;
216 if (f->holelist != (REAL *) NULL) {
217 delete [] f->holelist;
222 if (facetmarkerlist != (
int *) NULL) {
223 delete [] facetmarkerlist;
226 if (holelist != (REAL *) NULL) {
229 if (regionlist != (REAL *) NULL) {
230 delete [] regionlist;
232 if (facetconstraintlist != (REAL *) NULL) {
233 delete [] facetconstraintlist;
235 if (segmentconstraintlist != (REAL *) NULL) {
236 delete [] segmentconstraintlist;
238 if (pbcgrouplist != (pbcgroup *) NULL) {
239 for (i = 0; i < numberofpbcgroups; i++) {
240 pg = &(pbcgrouplist[i]);
241 if (pg->pointpairlist != (
int *) NULL) {
242 delete [] pg->pointpairlist;
245 delete [] pbcgrouplist;
247 if (vpointlist != (REAL *) NULL) {
248 delete [] vpointlist;
250 if (vedgelist != (voroedge *) NULL) {
253 if (vfacetlist != (vorofacet *) NULL) {
254 for (i = 0; i < numberofvfacets; i++) {
255 delete [] vfacetlist[i].elist;
257 delete [] vfacetlist;
259 if (vcelllist != (
int **) NULL) {
260 for (i = 0; i < numberofvcells; i++) {
261 delete [] vcelllist[i];
282 bool tetgenio::load_node_call(FILE* infile,
int markers,
char* infilename)
284 char inputline[INPUTLINESIZE];
286 REAL x, y, z, attrib;
287 int firstnode, currentmarker;
288 int index, attribindex;
292 pointlist =
new REAL[numberofpoints * 3];
293 if (pointlist == (REAL *) NULL) {
294 printf(
"Error: Out of memory.\n");
297 if (numberofpointattributes > 0) {
298 pointattributelist =
new REAL[numberofpoints * numberofpointattributes];
299 if (pointattributelist == (REAL *) NULL) {
300 printf(
"Error: Out of memory.\n");
305 pointmarkerlist =
new int[numberofpoints];
306 if (pointmarkerlist == (
int *) NULL) {
307 printf(
"Error: Out of memory.\n");
315 for (i = 0; i < numberofpoints; i++) {
316 stringptr = readnumberline(inputline, infile, infilename);
319 firstnode = (int) strtol (stringptr, &stringptr, 0);
320 if ((firstnode == 0) || (firstnode == 1)) {
321 firstnumber = firstnode;
324 stringptr = findnextnumber(stringptr);
326 if (*stringptr ==
'\0') {
327 printf(
"Error: Point %d has no x coordinate.\n", firstnumber + i);
330 x = (REAL) strtod(stringptr, &stringptr);
331 stringptr = findnextnumber(stringptr);
332 if (*stringptr ==
'\0') {
333 printf(
"Error: Point %d has no y coordinate.\n", firstnumber + i);
336 y = (REAL) strtod(stringptr, &stringptr);
338 stringptr = findnextnumber(stringptr);
339 if (*stringptr ==
'\0') {
340 printf(
"Error: Point %d has no z coordinate.\n", firstnumber + i);
343 z = (REAL) strtod(stringptr, &stringptr);
347 pointlist[index++] = x;
348 pointlist[index++] = y;
349 pointlist[index++] = z;
351 for (j = 0; j < numberofpointattributes; j++) {
352 stringptr = findnextnumber(stringptr);
353 if (*stringptr ==
'\0') {
356 attrib = (REAL) strtod(stringptr, &stringptr);
358 pointattributelist[attribindex++] = attrib;
362 stringptr = findnextnumber(stringptr);
363 if (*stringptr ==
'\0') {
366 currentmarker = (int) strtol (stringptr, &stringptr, 0);
368 pointmarkerlist[i] = currentmarker;
371 if (i < numberofpoints) {
374 pointlist = (REAL *) NULL;
376 delete [] pointmarkerlist;
377 pointmarkerlist = (
int *) NULL;
379 if (numberofpointattributes > 0) {
380 delete [] pointattributelist;
381 pointattributelist = (REAL *) NULL;
398 bool tetgenio::load_node(
char* filename)
401 char innodefilename[FILENAMESIZE];
402 char inputline[INPUTLINESIZE];
408 strcpy(innodefilename, filename);
409 strcat(innodefilename,
".node");
412 infile = fopen(innodefilename,
"r");
413 if (infile == (FILE *) NULL) {
414 printf(
"File I/O Error: Cannot access file %s.\n", innodefilename);
417 printf(
"Opening %s.\n", innodefilename);
419 stringptr = readnumberline(inputline, infile, innodefilename);
421 stringptr = strstr(inputline,
"rbox");
422 if (stringptr == NULL) {
425 stringptr = inputline;
426 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
427 stringptr = findnextnumber(stringptr);
428 if (*stringptr ==
'\0') {
431 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
433 stringptr = findnextnumber(stringptr);
434 if (*stringptr ==
'\0') {
435 numberofpointattributes = 0;
437 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
439 stringptr = findnextnumber(stringptr);
440 if (*stringptr ==
'\0') {
443 markers = (int) strtol (stringptr, &stringptr, 0);
447 stringptr = inputline;
449 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
451 stringptr = readnumberline(inputline, infile, innodefilename);
452 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
462 if (numberofpoints < (mesh_dim + 1)) {
463 printf(
"Input error: TetGen needs at least %d points.\n", mesh_dim + 1);
469 if (!load_node_call(infile, markers, innodefilename)) {
488 bool tetgenio::load_pbc(
char* filename)
491 char pbcfilename[FILENAMESIZE];
492 char inputline[INPUTLINESIZE];
499 strcpy(pbcfilename, filename);
500 strcat(pbcfilename,
".pbc");
501 infile = fopen(pbcfilename,
"r");
502 if (infile != (FILE *) NULL) {
503 printf(
"Opening %s.\n", pbcfilename);
510 stringptr = readnumberline(inputline, infile, pbcfilename);
511 numberofpbcgroups = (int) strtol (stringptr, &stringptr, 0);
512 if (numberofpbcgroups == 0) {
518 pbcgrouplist =
new pbcgroup[numberofpbcgroups];
521 for (i = 0; i < numberofpbcgroups; i++) {
522 pg = &(pbcgrouplist[i]);
524 pg->numberofpointpairs = 0;
525 pg->pointpairlist = (
int *) NULL;
527 stringptr = readnumberline(inputline, infile, pbcfilename);
528 if (*stringptr ==
'\0')
break;
529 pg->fmark1 = (int) strtol(stringptr, &stringptr, 0);
530 stringptr = findnextnumber(stringptr);
531 if (*stringptr ==
'\0')
break;
532 pg->fmark2 = (int) strtol(stringptr, &stringptr, 0);
535 stringptr = readline(inputline, infile, NULL);
536 }
while ((*stringptr !=
'[') && (*stringptr !=
'\0'));
537 if (*stringptr ==
'\0')
break;
538 for (j = 0; j < 4; j++) {
539 for (k = 0; k < 4; k++) {
541 stringptr = findnextnumber(stringptr);
542 if (*stringptr ==
'\0') {
544 stringptr = readnumberline(inputline, infile, pbcfilename);
545 if (*stringptr ==
'\0')
break;
547 pg->transmat[j][k] = (REAL) strtod(stringptr, &stringptr);
553 stringptr = readnumberline(inputline, infile, pbcfilename);
554 if (*stringptr ==
'\0')
break;
555 pg->numberofpointpairs = (int) strtol(stringptr, &stringptr, 0);
556 if (pg->numberofpointpairs > 0) {
557 pg->pointpairlist =
new int[pg->numberofpointpairs * 2];
560 for (j = 0; j < pg->numberofpointpairs; j++) {
561 stringptr = readnumberline(inputline, infile, pbcfilename);
562 p1 = (int) strtol(stringptr, &stringptr, 0);
563 stringptr = findnextnumber(stringptr);
564 p2 = (int) strtol(stringptr, &stringptr, 0);
565 pg->pointpairlist[index++] = p1;
566 pg->pointpairlist[index++] = p2;
572 if (i < numberofpbcgroups) {
574 delete [] pbcgrouplist;
575 pbcgrouplist = (pbcgroup *) NULL;
576 numberofpbcgroups = 0;
591 bool tetgenio::load_var(
char* filename)
594 char varfilename[FILENAMESIZE];
595 char inputline[INPUTLINESIZE];
601 strcpy(varfilename, filename);
602 strcat(varfilename,
".var");
603 infile = fopen(varfilename,
"r");
604 if (infile != (FILE *) NULL) {
605 printf(
"Opening %s.\n", varfilename);
612 stringptr = readnumberline(inputline, infile, varfilename);
613 if (*stringptr !=
'\0') {
614 numberoffacetconstraints = (int) strtol (stringptr, &stringptr, 0);
616 numberoffacetconstraints = 0;
618 if (numberoffacetconstraints > 0) {
620 facetconstraintlist =
new REAL[numberoffacetconstraints * 2];
622 for (i = 0; i < numberoffacetconstraints; i++) {
623 stringptr = readnumberline(inputline, infile, varfilename);
624 stringptr = findnextnumber(stringptr);
625 if (*stringptr ==
'\0') {
626 printf(
"Error: facet constraint %d has no facet marker.\n",
630 facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
632 stringptr = findnextnumber(stringptr);
633 if (*stringptr ==
'\0') {
634 printf(
"Error: facet constraint %d has no maximum area bound.\n",
638 facetconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
641 if (i < numberoffacetconstraints) {
649 stringptr = readnumberline(inputline, infile, varfilename);
650 if (*stringptr !=
'\0') {
651 numberofsegmentconstraints = (int) strtol (stringptr, &stringptr, 0);
653 numberofsegmentconstraints = 0;
655 if (numberofsegmentconstraints > 0) {
657 segmentconstraintlist =
new REAL[numberofsegmentconstraints * 3];
659 for (i = 0; i < numberofsegmentconstraints; i++) {
660 stringptr = readnumberline(inputline, infile, varfilename);
661 stringptr = findnextnumber(stringptr);
662 if (*stringptr ==
'\0') {
663 printf(
"Error: segment constraint %d has no frist endpoint.\n",
667 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
669 stringptr = findnextnumber(stringptr);
670 if (*stringptr ==
'\0') {
671 printf(
"Error: segment constraint %d has no second endpoint.\n",
675 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
677 stringptr = findnextnumber(stringptr);
678 if (*stringptr ==
'\0') {
679 printf(
"Error: segment constraint %d has no maximum length bound.\n",
683 segmentconstraintlist[index++] = (REAL) strtod(stringptr, &stringptr);
686 if (i < numberofsegmentconstraints) {
706 bool tetgenio::load_mtr(
char* filename)
709 char mtrfilename[FILENAMESIZE];
710 char inputline[INPUTLINESIZE];
716 strcpy(mtrfilename, filename);
717 strcat(mtrfilename,
".mtr");
718 infile = fopen(mtrfilename,
"r");
719 if (infile != (FILE *) NULL) {
720 printf(
"Opening %s.\n", mtrfilename);
727 stringptr = readnumberline(inputline, infile, mtrfilename);
728 stringptr = findnextnumber(stringptr);
729 if (*stringptr !=
'\0') {
730 numberofpointmtrs = (int) strtol (stringptr, &stringptr, 0);
732 if (numberofpointmtrs == 0) {
734 numberofpointmtrs = 1;
738 pointmtrlist =
new REAL[numberofpoints * numberofpointmtrs];
739 if (pointmtrlist == (REAL *) NULL) {
740 printf(
"Error: Out of memory.\n");
744 for (i = 0; i < numberofpoints; i++) {
746 stringptr = readnumberline(inputline, infile, mtrfilename);
747 for (j = 0; j < numberofpointmtrs; j++) {
748 if (*stringptr ==
'\0') {
749 printf(
"Error: Metric %d is missing value #%d in %s.\n",
750 i + firstnumber, j + 1, mtrfilename);
753 mtr = (REAL) strtod(stringptr, &stringptr);
754 pointmtrlist[mtrindex++] = mtr;
755 stringptr = findnextnumber(stringptr);
773 bool tetgenio::load_poly(
char* filename)
775 FILE *infile, *polyfile;
776 char innodefilename[FILENAMESIZE];
777 char inpolyfilename[FILENAMESIZE];
778 char insmeshfilename[FILENAMESIZE];
779 char inputline[INPUTLINESIZE];
780 char *stringptr, *infilename;
781 int smesh, markers, currentmarker;
782 int readnodefile, index;
786 strcpy(innodefilename, filename);
787 strcpy(inpolyfilename, filename);
788 strcpy(insmeshfilename, filename);
789 strcat(innodefilename,
".node");
790 strcat(inpolyfilename,
".poly");
791 strcat(insmeshfilename,
".smesh");
796 polyfile = fopen(inpolyfilename,
"r");
797 if (polyfile == (FILE *) NULL) {
799 polyfile = fopen(insmeshfilename,
"r");
800 if (polyfile == (FILE *) NULL) {
801 printf(
"File I/O Error: Cannot access file %s and %s.\n",
802 inpolyfilename, insmeshfilename);
805 printf(
"Opening %s.\n", insmeshfilename);
809 printf(
"Opening %s.\n", inpolyfilename);
813 numberofpointattributes = 0;
817 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
818 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
819 stringptr = findnextnumber(stringptr);
820 if (*stringptr !=
'\0') {
821 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
823 stringptr = findnextnumber(stringptr);
824 if (*stringptr !=
'\0') {
825 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
827 stringptr = findnextnumber(stringptr);
828 if (*stringptr !=
'\0') {
829 markers = (int) strtol (stringptr, &stringptr, 0);
831 if (numberofpoints > 0) {
834 infilename = insmeshfilename;
836 infilename = inpolyfilename;
843 infilename = innodefilename;
848 printf(
"Opening %s.\n", innodefilename);
849 infile = fopen(innodefilename,
"r");
850 if (infile == (FILE *) NULL) {
851 printf(
"File I/O Error: Cannot access file %s.\n", innodefilename);
856 numberofpointattributes = 0;
860 stringptr = readnumberline(inputline, infile, innodefilename);
861 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
862 stringptr = findnextnumber(stringptr);
863 if (*stringptr !=
'\0') {
864 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
866 stringptr = findnextnumber(stringptr);
867 if (*stringptr !=
'\0') {
868 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
870 stringptr = findnextnumber(stringptr);
871 if (*stringptr !=
'\0') {
872 markers = (int) strtol (stringptr, &stringptr, 0);
876 if ((mesh_dim != 3) && (mesh_dim != 2)) {
877 printf(
"Input error: TetGen only works for 2D & 3D point sets.\n");
881 if (numberofpoints < (mesh_dim + 1)) {
882 printf(
"Input error: TetGen needs at least %d points.\n", mesh_dim + 1);
888 if (!load_node_call(infile, markers, infilename)) {
903 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
904 numberoffacets = (int) strtol (stringptr, &stringptr, 0);
905 if (numberoffacets <= 0) {
910 stringptr = findnextnumber(stringptr);
911 if (*stringptr ==
'\0') {
914 markers = (int) strtol (stringptr, &stringptr, 0);
918 facetlist =
new facet[numberoffacets];
920 facetmarkerlist =
new int[numberoffacets];
926 for (i = 1; i <= numberoffacets; i++) {
927 f = &(facetlist[i - 1]);
929 f->numberofholes = 0;
932 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
933 f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
934 stringptr = findnextnumber(stringptr);
935 if (*stringptr !=
'\0') {
936 f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
938 stringptr = findnextnumber(stringptr);
939 if (*stringptr !=
'\0') {
940 currentmarker = (int) strtol(stringptr, &stringptr, 0);
946 facetmarkerlist[i - 1] = currentmarker;
949 if (f->numberofpolygons <= 0) {
950 printf(
"Error: Wrong number of polygon in %d facet.\n", i);
954 f->polygonlist =
new polygon[f->numberofpolygons];
956 for (j = 1; j <= f->numberofpolygons; j++) {
957 p = &(f->polygonlist[j - 1]);
960 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
961 p->numberofvertices = (int) strtol(stringptr, &stringptr, 0);
962 if (p->numberofvertices < 1) {
963 printf(
"Error: Wrong polygon %d in facet %d\n", j, i);
967 p->vertexlist =
new int[p->numberofvertices];
969 for (k = 1; k <= p->numberofvertices; k++) {
970 stringptr = findnextnumber(stringptr);
971 if (*stringptr ==
'\0') {
974 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
975 if (*stringptr ==
'\0') {
976 printf(
"Error: Missing %d endpoints of polygon %d in facet %d",
977 p->numberofvertices - k, j, i);
981 p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
984 if (j <= f->numberofpolygons) {
989 delete [] f->polygonlist;
991 f->numberofpolygons = j - 1;
993 f->numberofholes = 0;
997 if (f->numberofholes > 0) {
999 f->holelist =
new REAL[f->numberofholes * 3];
1002 for (j = 1; j <= f->numberofholes; j++) {
1003 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
1004 for (k = 1; k <= 3; k++) {
1005 stringptr = findnextnumber(stringptr);
1006 if (*stringptr ==
'\0') {
1007 printf(
"Error: Hole %d in facet %d has no coordinates", j, i);
1010 f->holelist[index++] = (REAL) strtod (stringptr, &stringptr);
1017 if (j <= f->numberofholes) {
1023 if (i <= numberoffacets) {
1025 numberoffacets = i - 1;
1031 for (i = 1; i <= numberoffacets; i++) {
1032 f = &(facetlist[i - 1]);
1036 f->numberofpolygons = 1;
1037 f->polygonlist =
new polygon[f->numberofpolygons];
1038 p = &(f->polygonlist[0]);
1041 stringptr = readnumberline(inputline, polyfile, insmeshfilename);
1042 p->numberofvertices = (int) strtol (stringptr, &stringptr, 0);
1043 if (p->numberofvertices < 1) {
1044 printf(
"Error: Wrong number of vertex in facet %d\n", i);
1048 p->vertexlist =
new int[p->numberofvertices];
1049 for (k = 1; k <= p->numberofvertices; k++) {
1050 stringptr = findnextnumber(stringptr);
1051 if (*stringptr ==
'\0') {
1054 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
1055 if (*stringptr ==
'\0') {
1056 printf(
"Error: Missing %d endpoints in facet %d",
1057 p->numberofvertices - k, i);
1061 p->vertexlist[k - 1] = (int) strtol (stringptr, &stringptr, 0);
1063 if (k <= p->numberofvertices) {
1069 stringptr = findnextnumber(stringptr);
1070 if (*stringptr ==
'\0') {
1073 currentmarker = (int) strtol(stringptr, &stringptr, 0);
1075 facetmarkerlist[i - 1] = currentmarker;
1078 if (i <= numberoffacets) {
1080 numberoffacets = i - 1;
1087 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
1088 if (*stringptr !=
'\0') {
1089 numberofholes = (int) strtol (stringptr, &stringptr, 0);
1093 if (numberofholes > 0) {
1095 holelist =
new REAL[numberofholes * 3];
1096 for (i = 0; i < 3 * numberofholes; i += 3) {
1097 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
1098 stringptr = findnextnumber(stringptr);
1099 if (*stringptr ==
'\0') {
1100 printf(
"Error: Hole %d has no x coord.\n", firstnumber + (i / 3));
1103 holelist[i] = (REAL) strtod(stringptr, &stringptr);
1105 stringptr = findnextnumber(stringptr);
1106 if (*stringptr ==
'\0') {
1107 printf(
"Error: Hole %d has no y coord.\n", firstnumber + (i / 3));
1110 holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
1112 stringptr = findnextnumber(stringptr);
1113 if (*stringptr ==
'\0') {
1114 printf(
"Error: Hole %d has no z coord.\n", firstnumber + (i / 3));
1117 holelist[i + 2] = (REAL) strtod(stringptr, &stringptr);
1120 if (i < 3 * numberofholes) {
1129 stringptr = readnumberline(inputline, polyfile, NULL);
1130 if (stringptr != (
char *) NULL && *stringptr !=
'\0') {
1131 numberofregions = (int) strtol (stringptr, &stringptr, 0);
1133 numberofregions = 0;
1135 if (numberofregions > 0) {
1137 regionlist =
new REAL[numberofregions * 5];
1139 for (i = 0; i < numberofregions; i++) {
1140 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
1141 stringptr = findnextnumber(stringptr);
1142 if (*stringptr ==
'\0') {
1143 printf(
"Error: Region %d has no x coordinate.\n", firstnumber + i);
1146 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1148 stringptr = findnextnumber(stringptr);
1149 if (*stringptr ==
'\0') {
1150 printf(
"Error: Region %d has no y coordinate.\n", firstnumber + i);
1153 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1155 stringptr = findnextnumber(stringptr);
1156 if (*stringptr ==
'\0') {
1157 printf(
"Error: Region %d has no z coordinate.\n", firstnumber + i);
1160 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1162 stringptr = findnextnumber(stringptr);
1163 if (*stringptr ==
'\0') {
1164 printf(
"Error: Region %d has no region attrib.\n", firstnumber + i);
1167 regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
1169 stringptr = findnextnumber(stringptr);
1170 if (*stringptr ==
'\0') {
1171 regionlist[index] = regionlist[index - 1];
1173 regionlist[index] = (REAL) strtod(stringptr, &stringptr);
1177 if (i < numberofregions) {
1187 assert(mesh_dim == 2);
1191 facetlist =
new facet[numberoffacets];
1192 facetmarkerlist = (
int *) NULL;
1193 f = &(facetlist[0]);
1196 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
1198 f->numberofpolygons = (int) strtol (stringptr, &stringptr, 0);
1199 if (f->numberofpolygons > 0) {
1200 f->polygonlist =
new polygon[f->numberofpolygons];
1203 for (j = 0; j < f->numberofpolygons; j++) {
1204 p = &(f->polygonlist[j]);
1207 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
1208 stringptr = findnextnumber(stringptr);
1209 p->numberofvertices = 2;
1210 p->vertexlist =
new int[p->numberofvertices];
1211 p->vertexlist[0] = (int) strtol (stringptr, &stringptr, 0);
1212 stringptr = findnextnumber(stringptr);
1213 p->vertexlist[1] = (int) strtol (stringptr, &stringptr, 0);
1216 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
1217 f->numberofholes = (int) strtol (stringptr, &stringptr, 0);
1218 if (f->numberofholes > 0) {
1220 f->holelist =
new REAL[f->numberofholes * 3];
1222 for (j = 0; j < f->numberofholes; j++) {
1224 stringptr = readnumberline(inputline, polyfile, inpolyfilename);
1225 stringptr = findnextnumber(stringptr);
1226 f->holelist[j * 3] = (REAL) strtod (stringptr, &stringptr);
1227 stringptr = findnextnumber(stringptr);
1228 f->holelist[j * 3 + 1] = (REAL) strtod (stringptr, &stringptr);
1229 f->holelist[j * 3 + 2] = 0.0;
1263 bool tetgenio::load_off(
char* filename)
1267 tetgenio::polygon *p;
1268 char infilename[FILENAMESIZE];
1269 char buffer[INPUTLINESIZE];
1272 int nverts = 0, iverts = 0;
1273 int nfaces = 0, ifaces = 0;
1275 int line_count = 0, i;
1277 strncpy(infilename, filename, 1024 - 1);
1278 infilename[FILENAMESIZE - 1] =
'\0';
1279 if (infilename[0] ==
'\0') {
1280 printf(
"Error: No filename.\n");
1283 if (strcmp(&infilename[strlen(infilename) - 4],
".off") != 0) {
1284 strcat(infilename,
".off");
1287 if (!(fp = fopen(infilename,
"r"))) {
1288 printf(
"File I/O Error: Unable to open file %s\n", infilename);
1291 printf(
"Opening %s.\n", infilename);
1296 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1300 bufferp = strstr(bufferp,
"OFF");
1301 if (bufferp != NULL) {
1303 bufferp = findnextnumber(bufferp);
1304 if (*bufferp ==
'\0') {
1306 bufferp = readline(buffer, fp, &line_count);
1308 if ((sscanf(bufferp,
"%d%d%d", &nverts, &nfaces, &nedges) != 3)
1310 printf(
"Syntax error reading header on line %d in file %s\n",
1311 line_count, infilename);
1317 numberofpoints = nverts;
1318 pointlist =
new REAL[nverts * 3];
1321 numberoffacets = nfaces;
1322 facetlist =
new tetgenio::facet[nfaces];
1325 }
else if (iverts < nverts) {
1327 coord = &pointlist[iverts * 3];
1328 for (i = 0; i < 3; i++) {
1329 if (*bufferp ==
'\0') {
1330 printf(
"Syntax error reading vertex coords on line %d in file %s\n",
1331 line_count, infilename);
1335 coord[i] = (REAL) strtod(bufferp, &bufferp);
1336 bufferp = findnextnumber(bufferp);
1339 }
else if (ifaces < nfaces) {
1341 f = &facetlist[ifaces];
1344 f->numberofpolygons = 1;
1345 f->polygonlist =
new tetgenio::polygon[1];
1346 p = &f->polygonlist[0];
1349 p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
1350 if (p->numberofvertices == 0) {
1351 printf(
"Syntax error reading polygon on line %d in file %s\n",
1352 line_count, infilename);
1357 p->vertexlist =
new int[p->numberofvertices];
1358 for (i = 0; i < p->numberofvertices; i++) {
1359 bufferp = findnextnumber(bufferp);
1360 if (*bufferp ==
'\0') {
1361 printf(
"Syntax error reading polygon on line %d in file %s\n",
1362 line_count, infilename);
1366 p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
1371 printf(
"Found extra text starting at line %d in file %s\n", line_count,
1381 if (iverts != nverts) {
1382 printf(
"Expected %d vertices, but read only %d vertices in file %s\n",
1383 nverts, iverts, infilename);
1388 if (ifaces != nfaces) {
1389 printf(
"Expected %d faces, but read only %d faces in file %s\n",
1390 nfaces, ifaces, infilename);
1416 bool tetgenio::load_ply(
char* filename)
1420 tetgenio::polygon *p;
1421 char infilename[FILENAMESIZE];
1422 char buffer[INPUTLINESIZE];
1423 char *bufferp, *str;
1425 int endheader = 0, format = 0;
1426 int nverts = 0, iverts = 0;
1427 int nfaces = 0, ifaces = 0;
1428 int line_count = 0, i;
1430 strncpy(infilename, filename, FILENAMESIZE - 1);
1431 infilename[FILENAMESIZE - 1] =
'\0';
1432 if (infilename[0] ==
'\0') {
1433 printf(
"Error: No filename.\n");
1436 if (strcmp(&infilename[strlen(infilename) - 4],
".ply") != 0) {
1437 strcat(infilename,
".ply");
1440 if (!(fp = fopen(infilename,
"r"))) {
1441 printf(
"Error: Unable to open file %s\n", infilename);
1444 printf(
"Opening %s.\n", infilename);
1449 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1452 str = strstr(bufferp,
"end_header");
1454 if (!str) str = strstr(bufferp,
"End_header");
1455 if (!str) str = strstr(bufferp,
"End_Header");
1462 if (nverts == 0 || nfaces == 0) {
1464 str = strstr(bufferp,
"element");
1465 if (!str) str = strstr(bufferp,
"Element");
1467 bufferp = findnextfield(str);
1468 if (*bufferp ==
'\0') {
1469 printf(
"Syntax error reading element type on line%d in file %s\n",
1470 line_count, infilename);
1476 str = strstr(bufferp,
"vertex");
1477 if (!str) str = strstr(bufferp,
"Vertex");
1479 bufferp = findnextnumber(str);
1480 if (*bufferp ==
'\0') {
1481 printf(
"Syntax error reading vertex number on line");
1482 printf(
" %d in file %s\n", line_count, infilename);
1486 nverts = (int) strtol(bufferp, &bufferp, 0);
1489 numberofpoints = nverts;
1490 pointlist =
new REAL[nverts * 3];
1496 str = strstr(bufferp,
"face");
1497 if (!str) str = strstr(bufferp,
"Face");
1499 bufferp = findnextnumber(str);
1500 if (*bufferp ==
'\0') {
1501 printf(
"Syntax error reading face number on line");
1502 printf(
" %d in file %s\n", line_count, infilename);
1506 nfaces = (int) strtol(bufferp, &bufferp, 0);
1509 numberoffacets = nfaces;
1510 facetlist =
new tetgenio::facet[nfaces];
1518 str = strstr(bufferp,
"format");
1519 if (!str) str = strstr(bufferp,
"Format");
1522 bufferp = findnextfield(str);
1524 str = strstr(bufferp,
"ascii");
1525 if (!str) str = strstr(bufferp,
"ASCII");
1527 printf(
"This routine only reads ascii format of ply files.\n");
1528 printf(
"Hint: You can convert the binary to ascii format by\n");
1529 printf(
" using the provided ply tools:\n");
1530 printf(
" ply2ascii < %s > ascii_%s\n", infilename, infilename);
1536 }
else if (iverts < nverts) {
1538 coord = &pointlist[iverts * 3];
1539 for (i = 0; i < 3; i++) {
1540 if (*bufferp ==
'\0') {
1541 printf(
"Syntax error reading vertex coords on line %d in file %s\n",
1542 line_count, infilename);
1546 coord[i] = (REAL) strtod(bufferp, &bufferp);
1547 bufferp = findnextnumber(bufferp);
1550 }
else if (ifaces < nfaces) {
1552 f = &facetlist[ifaces];
1555 f->numberofpolygons = 1;
1556 f->polygonlist =
new tetgenio::polygon[1];
1557 p = &f->polygonlist[0];
1560 p->numberofvertices = (int) strtol(bufferp, &bufferp, 0);
1561 if (p->numberofvertices == 0) {
1562 printf(
"Syntax error reading polygon on line %d in file %s\n",
1563 line_count, infilename);
1568 p->vertexlist =
new int[p->numberofvertices];
1569 for (i = 0; i < p->numberofvertices; i++) {
1570 bufferp = findnextnumber(bufferp);
1571 if (*bufferp ==
'\0') {
1572 printf(
"Syntax error reading polygon on line %d in file %s\n",
1573 line_count, infilename);
1577 p->vertexlist[i] = (int) strtol(bufferp, &bufferp, 0);
1582 printf(
"Found extra text starting at line %d in file %s\n", line_count,
1592 if (iverts != nverts) {
1593 printf(
"Expected %d vertices, but read only %d vertices in file %s\n",
1594 nverts, iverts, infilename);
1599 if (ifaces != nfaces) {
1600 printf(
"Expected %d faces, but read only %d faces in file %s\n",
1601 nfaces, ifaces, infilename);
1626 bool tetgenio::load_stl(
char* filename)
1629 tetgenmesh::list *plist;
1631 tetgenio::polygon *p;
1632 char infilename[FILENAMESIZE];
1633 char buffer[INPUTLINESIZE];
1634 char *bufferp, *str;
1637 int nverts = 0, iverts = 0;
1639 int line_count = 0, i;
1641 strncpy(infilename, filename, FILENAMESIZE - 1);
1642 infilename[FILENAMESIZE - 1] =
'\0';
1643 if (infilename[0] ==
'\0') {
1644 printf(
"Error: No filename.\n");
1647 if (strcmp(&infilename[strlen(infilename) - 4],
".stl") != 0) {
1648 strcat(infilename,
".stl");
1651 if (!(fp = fopen(infilename,
"r"))) {
1652 printf(
"Error: Unable to open file %s\n", infilename);
1655 printf(
"Opening %s.\n", infilename);
1658 plist =
new tetgenmesh::list(
sizeof(
double) * 3, NULL, 1024);
1660 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1665 bufferp = strstr(bufferp,
"solid");
1666 if (bufferp != NULL) {
1673 bufferp = strstr(bufferp,
"endsolid");
1674 if (bufferp != NULL) {
1679 bufferp = strstr(bufferp,
"vertex");
1680 if (bufferp != NULL) {
1681 coord = (
double *) plist->append(NULL);
1682 for (i = 0; i < 3; i++) {
1683 bufferp = findnextnumber(bufferp);
1684 if (*bufferp ==
'\0') {
1685 printf(
"Syntax error reading vertex coords on line %d\n",
1691 coord[i] = (REAL) strtod(bufferp, &bufferp);
1699 nverts = plist->len();
1701 if (nverts == 0 || (nverts % 3 != 0)) {
1702 printf(
"Error: Wrong number of vertices in file %s.\n", infilename);
1706 numberofpoints = nverts;
1707 pointlist =
new REAL[nverts * 3];
1708 for (i = 0; i < nverts; i++) {
1709 coord = (
double *) (* plist)[i];
1711 pointlist[iverts] = (REAL) coord[0];
1712 pointlist[iverts + 1] = (REAL) coord[1];
1713 pointlist[iverts + 2] = (REAL) coord[2];
1716 nfaces = (int) (nverts / 3);
1717 numberoffacets = nfaces;
1718 facetlist =
new tetgenio::facet[nfaces];
1722 iverts = firstnumber;
1723 for (i = 0; i < nfaces; i++) {
1727 f->numberofpolygons = 1;
1728 f->polygonlist =
new tetgenio::polygon[1];
1729 p = &f->polygonlist[0];
1732 p->numberofvertices = 3;
1733 p->vertexlist =
new int[p->numberofvertices];
1734 p->vertexlist[0] = iverts;
1735 p->vertexlist[1] = iverts + 1;
1736 p->vertexlist[2] = iverts + 2;
1757 bool tetgenio::load_medit(
char* filename)
1760 tetgenio::facet *tmpflist, *f;
1761 tetgenio::polygon *p;
1762 char infilename[FILENAMESIZE];
1763 char buffer[INPUTLINESIZE];
1764 char *bufferp, *str;
1774 strncpy(infilename, filename, FILENAMESIZE - 1);
1775 infilename[FILENAMESIZE - 1] =
'\0';
1776 if (infilename[0] ==
'\0') {
1777 printf(
"Error: No filename.\n");
1780 if (strcmp(&infilename[strlen(infilename) - 5],
".mesh") != 0) {
1781 strcat(infilename,
".mesh");
1784 if (!(fp = fopen(infilename,
"r"))) {
1785 printf(
"Error: Unable to open file %s\n", infilename);
1788 printf(
"Opening %s.\n", infilename);
1793 while ((bufferp = readline(buffer, fp, &line_count)) != NULL) {
1794 if (*bufferp ==
'#')
continue;
1795 if (dimension == 0) {
1797 str = strstr(bufferp,
"Dimension");
1798 if (!str) str = strstr(bufferp,
"dimension");
1799 if (!str) str = strstr(bufferp,
"DIMENSION");
1802 bufferp = findnextnumber(str);
1803 if (*bufferp ==
'\0') {
1805 bufferp = readline(buffer, fp, &line_count);
1807 dimension = (int) strtol(bufferp, &bufferp, 0);
1808 if (dimension != 2 && dimension != 3) {
1809 printf(
"Unknown dimension in file on line %d in file %s\n",
1810 line_count, infilename);
1814 mesh_dim = dimension;
1819 str = strstr(bufferp,
"Vertices");
1820 if (!str) str = strstr(bufferp,
"vertices");
1821 if (!str) str = strstr(bufferp,
"VERTICES");
1824 bufferp = findnextnumber(str);
1825 if (*bufferp ==
'\0') {
1827 bufferp = readline(buffer, fp, &line_count);
1829 nverts = (int) strtol(bufferp, &bufferp, 0);
1832 numberofpoints = nverts;
1833 pointlist =
new REAL[nverts * 3];
1836 for (i = 0; i < nverts; i++) {
1837 bufferp = readline(buffer, fp, &line_count);
1838 if (bufferp == NULL) {
1839 printf(
"Unexpected end of file on line %d in file %s\n",
1840 line_count, infilename);
1845 coord = &pointlist[i * 3];
1846 for (j = 0; j < 3; j++) {
1847 if (*bufferp ==
'\0') {
1848 printf(
"Syntax error reading vertex coords on line");
1849 printf(
" %d in file %s\n", line_count, infilename);
1853 if ((j < 2) || (dimension == 3)) {
1854 coord[j] = (REAL) strtod(bufferp, &bufferp);
1856 assert((j == 2) && (dimension == 2));
1859 bufferp = findnextnumber(bufferp);
1868 str = strstr(bufferp,
"Triangles");
1869 if (!str) str = strstr(bufferp,
"triangles");
1870 if (!str) str = strstr(bufferp,
"TRIANGLES");
1874 str = strstr(bufferp,
"Quadrilaterals");
1875 if (!str) str = strstr(bufferp,
"quadrilaterals");
1876 if (!str) str = strstr(bufferp,
"QUADRILATERALS");
1881 if (corners == 3 || corners == 4) {
1883 bufferp = findnextnumber(str);
1884 if (*bufferp ==
'\0') {
1886 bufferp = readline(buffer, fp, &line_count);
1888 nfaces = strtol(bufferp, &bufferp, 0);
1891 if (numberoffacets > 0) {
1893 tmpflist =
new tetgenio::facet[numberoffacets + nfaces];
1894 tmpfmlist =
new int[numberoffacets + nfaces];
1896 for (i = 0; i < numberoffacets; i++) {
1900 tmpfmlist[i] = facetmarkerlist[i];
1903 delete [] facetlist;
1904 delete [] facetmarkerlist;
1906 facetlist = tmpflist;
1907 facetmarkerlist = tmpfmlist;
1910 facetlist =
new tetgenio::facet[nfaces];
1911 facetmarkerlist =
new int[nfaces];
1915 for (i = numberoffacets; i < numberoffacets + nfaces; i++) {
1916 bufferp = readline(buffer, fp, &line_count);
1917 if (bufferp == NULL) {
1918 printf(
"Unexpected end of file on line %d in file %s\n",
1919 line_count, infilename);
1926 f->numberofpolygons = 1;
1927 f->polygonlist =
new tetgenio::polygon[1];
1928 p = &f->polygonlist[0];
1930 p->numberofvertices = corners;
1932 p->vertexlist =
new int[p->numberofvertices];
1934 for (j = 0; j < corners; j++) {
1935 if (*bufferp ==
'\0') {
1936 printf(
"Syntax error reading face on line %d in file %s\n",
1937 line_count, infilename);
1941 p->vertexlist[j] = (int) strtol(bufferp, &bufferp, 0);
1942 if (firstnumber == 1) {
1944 if (p->vertexlist[j] == 0) {
1949 bufferp = findnextnumber(bufferp);
1952 facetmarkerlist[i] = 0;
1953 if (*bufferp !=
'\0') {
1954 facetmarkerlist[i] = (int) strtol(bufferp, &bufferp, 0);
1958 numberoffacets += nfaces;
1981 bool tetgenio::load_plc(
char* filename,
int object)
1983 enum tetgenbehavior::objecttype type;
1985 type = (
enum tetgenbehavior::objecttype)
object;
1987 case tetgenbehavior::NODES:
1988 return load_node(filename);
1989 case tetgenbehavior::POLY:
1990 return load_poly(filename);
1991 case tetgenbehavior::OFF:
1992 return load_off(filename);
1993 case tetgenbehavior::PLY:
1994 return load_ply(filename);
1995 case tetgenbehavior::STL:
1996 return load_stl(filename);
1997 case tetgenbehavior::MEDIT:
1998 return load_medit(filename);
2000 return load_poly(filename);
2014 bool tetgenio::load_tetmesh(
char* filename)
2017 char innodefilename[FILENAMESIZE];
2018 char inelefilename[FILENAMESIZE];
2019 char infacefilename[FILENAMESIZE];
2020 char inedgefilename[FILENAMESIZE];
2021 char involfilename[FILENAMESIZE];
2022 char inputline[INPUTLINESIZE];
2023 char *stringptr, *infilename;
2024 REAL attrib, volume;
2026 int markers, corner;
2027 int index, attribindex;
2033 strcpy(innodefilename, filename);
2034 strcpy(inelefilename, filename);
2035 strcpy(infacefilename, filename);
2036 strcpy(inedgefilename, filename);
2037 strcpy(involfilename, filename);
2038 strcat(innodefilename,
".node");
2039 strcat(inelefilename,
".ele");
2040 strcat(infacefilename,
".face");
2041 strcat(inedgefilename,
".edge");
2042 strcat(involfilename,
".vol");
2045 infilename = innodefilename;
2046 printf(
"Opening %s.\n", infilename);
2047 infile = fopen(infilename,
"r");
2048 if (infile == (FILE *) NULL) {
2049 printf(
"File I/O Error: Cannot access file %s.\n", infilename);
2053 stringptr = readnumberline(inputline, infile, infilename);
2055 stringptr = strstr(inputline,
"rbox");
2056 if (stringptr == NULL) {
2059 stringptr = inputline;
2060 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
2061 stringptr = findnextnumber(stringptr);
2062 if (*stringptr ==
'\0') {
2065 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
2067 stringptr = findnextnumber(stringptr);
2068 if (*stringptr ==
'\0') {
2069 numberofpointattributes = 0;
2071 numberofpointattributes = (int) strtol (stringptr, &stringptr, 0);
2073 stringptr = findnextnumber(stringptr);
2074 if (*stringptr ==
'\0') {
2077 markers = (int) strtol (stringptr, &stringptr, 0);
2081 stringptr = inputline;
2083 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
2085 stringptr = readnumberline(inputline, infile, infilename);
2086 numberofpoints = (int) strtol (stringptr, &stringptr, 0);
2092 if (!load_node_call(infile, markers, infilename)) {
2099 if (mesh_dim == 3) {
2100 infilename = inelefilename;
2101 infile = fopen(infilename,
"r");
2102 if (infile != (FILE *) NULL) {
2103 printf(
"Opening %s.\n", infilename);
2106 stringptr = readnumberline(inputline, infile, infilename);
2107 numberoftetrahedra = (int) strtol (stringptr, &stringptr, 0);
2108 stringptr = findnextnumber(stringptr);
2109 if (*stringptr ==
'\0') {
2110 numberofcorners = 4;
2112 numberofcorners = (int) strtol(stringptr, &stringptr, 0);
2114 stringptr = findnextnumber(stringptr);
2115 if (*stringptr ==
'\0') {
2116 numberoftetrahedronattributes = 0;
2118 numberoftetrahedronattributes = (int) strtol(stringptr, &stringptr, 0);
2120 if (numberofcorners != 4 && numberofcorners != 10) {
2121 printf(
"Error: Wrong number of corners %d (should be 4 or 10).\n",
2127 if (numberoftetrahedra > 0) {
2128 tetrahedronlist =
new int[numberoftetrahedra * numberofcorners];
2129 if (tetrahedronlist == (
int *) NULL) {
2130 printf(
"Error: Out of memory.\n");
2134 if (numberoftetrahedronattributes > 0) {
2135 tetrahedronattributelist =
new REAL[numberoftetrahedra *
2136 numberoftetrahedronattributes];
2137 if (tetrahedronattributelist == (REAL *) NULL) {
2138 printf(
"Error: Out of memory.\n");
2146 for (i = 0; i < numberoftetrahedra; i++) {
2148 stringptr = readnumberline(inputline, infile, infilename);
2149 for (j = 0; j < numberofcorners; j++) {
2150 stringptr = findnextnumber(stringptr);
2151 if (*stringptr ==
'\0') {
2152 printf(
"Error: Tetrahedron %d is missing vertex %d in %s.\n",
2153 i + firstnumber, j + 1, infilename);
2156 corner = (int) strtol(stringptr, &stringptr, 0);
2157 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
2158 printf(
"Error: Tetrahedron %d has an invalid vertex index.\n",
2162 tetrahedronlist[index++] = corner;
2165 for (j = 0; j < numberoftetrahedronattributes; j++) {
2166 stringptr = findnextnumber(stringptr);
2167 if (*stringptr ==
'\0') {
2170 attrib = (REAL) strtod(stringptr, &stringptr);
2172 tetrahedronattributelist[attribindex++] = attrib;
2180 if (mesh_dim == 3) {
2181 infilename = infacefilename;
2183 infilename = inelefilename;
2185 infile = fopen(infilename,
"r");
2186 if (infile != (FILE *) NULL) {
2187 printf(
"Opening %s.\n", infilename);
2189 stringptr = readnumberline(inputline, infile, infilename);
2190 numberoftrifaces = (int) strtol (stringptr, &stringptr, 0);
2191 stringptr = findnextnumber(stringptr);
2192 if (mesh_dim == 2) {
2194 stringptr = findnextnumber(stringptr);
2196 if (*stringptr ==
'\0') {
2199 markers = (int) strtol (stringptr, &stringptr, 0);
2201 if (numberoftrifaces > 0) {
2202 trifacelist =
new int[numberoftrifaces * 3];
2203 if (trifacelist == (
int *) NULL) {
2204 printf(
"Error: Out of memory.\n");
2208 trifacemarkerlist =
new int[numberoftrifaces * 3];
2209 if (trifacemarkerlist == (
int *) NULL) {
2210 printf(
"Error: Out of memory.\n");
2217 for (i = 0; i < numberoftrifaces; i++) {
2219 stringptr = readnumberline(inputline, infile, infilename);
2220 for (j = 0; j < 3; j++) {
2221 stringptr = findnextnumber(stringptr);
2222 if (*stringptr ==
'\0') {
2223 printf(
"Error: Face %d is missing vertex %d in %s.\n",
2224 i + firstnumber, j + 1, infilename);
2227 corner = (int) strtol(stringptr, &stringptr, 0);
2228 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
2229 printf(
"Error: Face %d has an invalid vertex index.\n",
2233 trifacelist[index++] = corner;
2237 stringptr = findnextnumber(stringptr);
2238 if (*stringptr ==
'\0') {
2241 attrib = (REAL) strtod(stringptr, &stringptr);
2243 trifacemarkerlist[i] = (int) attrib;
2250 infilename = inedgefilename;
2251 infile = fopen(infilename,
"r");
2252 if (infile != (FILE *) NULL) {
2253 printf(
"Opening %s.\n", infilename);
2255 stringptr = readnumberline(inputline, infile, infilename);
2256 numberofedges = (int) strtol (stringptr, &stringptr, 0);
2257 if (numberofedges > 0) {
2258 edgelist =
new int[numberofedges * 2];
2259 if (edgelist == (
int *) NULL) {
2260 printf(
"Error: Out of memory.\n");
2266 for (i = 0; i < numberofedges; i++) {
2268 stringptr = readnumberline(inputline, infile, infilename);
2269 for (j = 0; j < 2; j++) {
2270 stringptr = findnextnumber(stringptr);
2271 if (*stringptr ==
'\0') {
2272 printf(
"Error: Edge %d is missing vertex %d in %s.\n",
2273 i + firstnumber, j + 1, infilename);
2276 corner = (int) strtol(stringptr, &stringptr, 0);
2277 if (corner < firstnumber || corner >= numberofpoints + firstnumber) {
2278 printf(
"Error: Edge %d has an invalid vertex index.\n",
2282 edgelist[index++] = corner;
2289 infilename = involfilename;
2290 infile = fopen(infilename,
"r");
2291 if (infile != (FILE *) NULL) {
2292 printf(
"Opening %s.\n", infilename);
2294 stringptr = readnumberline(inputline, infile, infilename);
2295 volelements = (int) strtol (stringptr, &stringptr, 0);
2296 if (volelements != numberoftetrahedra) {
2297 printf(
"Warning: %s and %s disagree on number of tetrahedra.\n",
2298 inelefilename, involfilename);
2301 if (volelements > 0) {
2302 tetrahedronvolumelist =
new REAL[volelements];
2303 if (tetrahedronvolumelist == (REAL *) NULL) {
2304 printf(
"Error: Out of memory.\n");
2309 for (i = 0; i < volelements; i++) {
2310 stringptr = readnumberline(inputline, infile, infilename);
2311 stringptr = findnextnumber(stringptr);
2312 if (*stringptr ==
'\0') {
2315 volume = (REAL) strtod(stringptr, &stringptr);
2317 tetrahedronvolumelist[i] = volume;
2339 bool tetgenio::load_voronoi(
char* filename)
2342 char innodefilename[FILENAMESIZE];
2343 char inedgefilename[FILENAMESIZE];
2344 char inputline[INPUTLINESIZE];
2345 char *stringptr, *infilename;
2348 int firstnode, corner;
2353 strcpy(innodefilename, filename);
2354 strcpy(inedgefilename, filename);
2355 strcat(innodefilename,
".v.node");
2356 strcat(inedgefilename,
".v.edge");
2359 infilename = innodefilename;
2360 printf(
"Opening %s.\n", infilename);
2361 infile = fopen(infilename,
"r");
2362 if (infile == (FILE *) NULL) {
2363 printf(
"File I/O Error: Cannot access file %s.\n", infilename);
2367 stringptr = readnumberline(inputline, infile, infilename);
2369 stringptr = strstr(inputline,
"rbox");
2370 if (stringptr == NULL) {
2373 stringptr = inputline;
2374 numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
2375 stringptr = findnextnumber(stringptr);
2376 if (*stringptr ==
'\0') {
2379 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
2384 stringptr = inputline;
2386 mesh_dim = (int) strtol (stringptr, &stringptr, 0);
2388 stringptr = readnumberline(inputline, infile, infilename);
2389 numberofvpoints = (int) strtol (stringptr, &stringptr, 0);
2393 vpointlist =
new REAL[numberofvpoints * 3];
2394 if (vpointlist == (REAL *) NULL) {
2395 printf(
"Error: Out of memory.\n");
2400 for (i = 0; i < numberofvpoints; i++) {
2401 stringptr = readnumberline(inputline, infile, infilename);
2404 firstnode = (int) strtol (stringptr, &stringptr, 0);
2405 if ((firstnode == 0) || (firstnode == 1)) {
2406 firstnumber = firstnode;
2409 stringptr = findnextnumber(stringptr);
2411 if (*stringptr ==
'\0') {
2412 printf(
"Error: Point %d has no x coordinate.\n", firstnumber + i);
2415 x = (REAL) strtod(stringptr, &stringptr);
2416 stringptr = findnextnumber(stringptr);
2417 if (*stringptr ==
'\0') {
2418 printf(
"Error: Point %d has no y coordinate.\n", firstnumber + i);
2421 y = (REAL) strtod(stringptr, &stringptr);
2422 if (mesh_dim == 3) {
2423 stringptr = findnextnumber(stringptr);
2424 if (*stringptr ==
'\0') {
2425 printf(
"Error: Point %d has no z coordinate.\n", firstnumber + i);
2428 z = (REAL) strtod(stringptr, &stringptr);
2432 vpointlist[index++] = x;
2433 vpointlist[index++] = y;
2434 vpointlist[index++] = z;
2439 infilename = inedgefilename;
2440 infile = fopen(infilename,
"r");
2441 if (infile != (FILE *) NULL) {
2442 printf(
"Opening %s.\n", infilename);
2444 stringptr = readnumberline(inputline, infile, infilename);
2445 numberofvedges = (int) strtol (stringptr, &stringptr, 0);
2446 if (numberofvedges > 0) {
2447 vedgelist =
new voroedge[numberofvedges];
2451 for (i = 0; i < numberofvedges; i++) {
2453 stringptr = readnumberline(inputline, infile, infilename);
2454 vedge = &(vedgelist[i]);
2455 for (j = 0; j < 2; j++) {
2456 stringptr = findnextnumber(stringptr);
2457 if (*stringptr ==
'\0') {
2458 printf(
"Error: Edge %d is missing vertex %d in %s.\n",
2459 i + firstnumber, j + 1, infilename);
2462 corner = (int) strtol(stringptr, &stringptr, 0);
2463 j == 0 ? vedge->v1 = corner : vedge->v2 = corner;
2465 if (vedge->v2 < 0) {
2466 for (j = 0; j < mesh_dim; j++) {
2467 stringptr = findnextnumber(stringptr);
2468 if (*stringptr ==
'\0') {
2469 printf(
"Error: Edge %d is missing normal in %s.\n",
2470 i + firstnumber, infilename);
2473 vedge->vnormal[j] = (REAL) strtod(stringptr, &stringptr);
2475 if (mesh_dim == 2) {
2476 vedge->vnormal[2] = 0.0;
2479 vedge->vnormal[0] = 0.0;
2480 vedge->vnormal[1] = 0.0;
2481 vedge->vnormal[2] = 0.0;
2498 void tetgenio::save_nodes(
char* filename)
2501 char outnodefilename[FILENAMESIZE];
2502 char outmtrfilename[FILENAMESIZE];
2505 sprintf(outnodefilename,
"%s.node", filename);
2506 printf(
"Saving nodes to %s\n", outnodefilename);
2507 fout = fopen(outnodefilename,
"w");
2508 fprintf(fout,
"%d %d %d %d\n", numberofpoints, mesh_dim,
2509 numberofpointattributes, pointmarkerlist != NULL ? 1 : 0);
2510 for (i = 0; i < numberofpoints; i++) {
2511 if (mesh_dim == 2) {
2512 fprintf(fout,
"%d %.16g %.16g", i + firstnumber, pointlist[i * 2],
2513 pointlist[i * 2 + 1]);
2515 fprintf(fout,
"%d %.16g %.16g %.16g", i + firstnumber,
2516 pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
2518 for (j = 0; j < numberofpointattributes; j++) {
2519 fprintf(fout,
" %.16g",
2520 pointattributelist[i * numberofpointattributes + j]);
2522 if (pointmarkerlist != NULL) {
2523 fprintf(fout,
" %d", pointmarkerlist[i]);
2525 fprintf(fout,
"\n");
2530 if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
2531 sprintf(outmtrfilename,
"%s.mtr", filename);
2532 printf(
"Saving metrics to %s\n", outmtrfilename);
2533 fout = fopen(outmtrfilename,
"w");
2534 fprintf(fout,
"%d %d\n", numberofpoints, numberofpointmtrs);
2535 for (i = 0; i < numberofpoints; i++) {
2536 for (j = 0; j < numberofpointmtrs; j++) {
2537 fprintf(fout,
"%.16g ", pointmtrlist[i * numberofpointmtrs + j]);
2539 fprintf(fout,
"\n");
2553 void tetgenio::save_elements(
char* filename)
2556 char outelefilename[FILENAMESIZE];
2559 sprintf(outelefilename,
"%s.ele", filename);
2560 printf(
"Saving elements to %s\n", outelefilename);
2561 fout = fopen(outelefilename,
"w");
2562 fprintf(fout,
"%d %d %d\n", numberoftetrahedra, numberofcorners,
2563 numberoftetrahedronattributes);
2564 for (i = 0; i < numberoftetrahedra; i++) {
2565 fprintf(fout,
"%d", i + firstnumber);
2566 for (j = 0; j < numberofcorners; j++) {
2567 fprintf(fout,
" %5d", tetrahedronlist[i * numberofcorners + j]);
2569 for (j = 0; j < numberoftetrahedronattributes; j++) {
2570 fprintf(fout,
" %g",
2571 tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
2573 fprintf(fout,
"\n");
2587 void tetgenio::save_faces(
char* filename)
2590 char outfacefilename[FILENAMESIZE];
2593 sprintf(outfacefilename,
"%s.face", filename);
2594 printf(
"Saving faces to %s\n", outfacefilename);
2595 fout = fopen(outfacefilename,
"w");
2596 fprintf(fout,
"%d %d\n", numberoftrifaces,
2597 trifacemarkerlist != NULL ? 1 : 0);
2598 for (i = 0; i < numberoftrifaces; i++) {
2599 fprintf(fout,
"%d %5d %5d %5d", i + firstnumber, trifacelist[i * 3],
2600 trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
2601 if (trifacemarkerlist != NULL) {
2602 fprintf(fout,
" %d", trifacemarkerlist[i]);
2604 fprintf(fout,
"\n");
2618 void tetgenio::save_edges(
char* filename)
2621 char outedgefilename[FILENAMESIZE];
2624 sprintf(outedgefilename,
"%s.edge", filename);
2625 printf(
"Saving edges to %s\n", outedgefilename);
2626 fout = fopen(outedgefilename,
"w");
2627 fprintf(fout,
"%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
2628 for (i = 0; i < numberofedges; i++) {
2629 fprintf(fout,
"%d %4d %4d", i + firstnumber, edgelist[i * 2],
2630 edgelist[i * 2 + 1]);
2631 if (edgemarkerlist != NULL) {
2632 fprintf(fout,
" %d", edgemarkerlist[i]);
2634 fprintf(fout,
"\n");
2648 void tetgenio::save_neighbors(
char* filename)
2651 char outneighborfilename[FILENAMESIZE];
2654 sprintf(outneighborfilename,
"%s.neigh", filename);
2655 printf(
"Saving neighbors to %s\n", outneighborfilename);
2656 fout = fopen(outneighborfilename,
"w");
2657 fprintf(fout,
"%d %d\n", numberoftetrahedra, mesh_dim + 1);
2658 for (i = 0; i < numberoftetrahedra; i++) {
2659 if (mesh_dim == 2) {
2660 fprintf(fout,
"%d %5d %5d %5d", i + firstnumber, neighborlist[i * 3],
2661 neighborlist[i * 3 + 1], neighborlist[i * 3 + 2]);
2663 fprintf(fout,
"%d %5d %5d %5d %5d", i + firstnumber,
2664 neighborlist[i * 4], neighborlist[i * 4 + 1],
2665 neighborlist[i * 4 + 2], neighborlist[i * 4 + 3]);
2667 fprintf(fout,
"\n");
2683 void tetgenio::save_poly(
char* filename)
2688 char outpolyfilename[FILENAMESIZE];
2691 sprintf(outpolyfilename,
"%s.poly", filename);
2692 printf(
"Saving poly to %s\n", outpolyfilename);
2693 fout = fopen(outpolyfilename,
"w");
2698 fprintf(fout,
"%d %d %d %d\n", 0, mesh_dim, numberofpointattributes,
2699 pointmarkerlist != NULL ? 1 : 0);
2702 if (mesh_dim == 2) {
2704 fprintf(fout,
"%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
2705 for (i = 0; i < numberofedges; i++) {
2706 fprintf(fout,
"%d %4d %4d", i + firstnumber, edgelist[i * 2],
2707 edgelist[i * 2 + 1]);
2708 if (edgemarkerlist != NULL) {
2709 fprintf(fout,
" %d", edgemarkerlist[i]);
2711 fprintf(fout,
"\n");
2715 fprintf(fout,
"%d %d\n", numberoffacets, facetmarkerlist != NULL ? 1 : 0);
2716 for (i = 0; i < numberoffacets; i++) {
2717 f = &(facetlist[i]);
2718 fprintf(fout,
"%d %d %d # %d\n", f->numberofpolygons,f->numberofholes,
2719 facetmarkerlist != NULL ? facetmarkerlist[i] : 0, i + firstnumber);
2721 for (j = 0; j < f->numberofpolygons; j++) {
2722 p = &(f->polygonlist[j]);
2723 fprintf(fout,
"%d ", p->numberofvertices);
2724 for (k = 0; k < p->numberofvertices; k++) {
2725 if (((k + 1) % 10) == 0) {
2726 fprintf(fout,
"\n ");
2728 fprintf(fout,
" %d", p->vertexlist[k]);
2730 fprintf(fout,
"\n");
2733 for (j = 0; j < f->numberofholes; j++) {
2734 fprintf(fout,
"%d %.12g %.12g %.12g\n", j + firstnumber,
2735 f->holelist[j * 3], f->holelist[j * 3 + 1], f->holelist[j * 3 + 2]);
2741 fprintf(fout,
"%d\n", numberofholes);
2742 for (i = 0; i < numberofholes; i++) {
2744 fprintf(fout,
"%d %.12g %.12g", i + firstnumber, holelist[i * mesh_dim],
2745 holelist[i * mesh_dim + 1]);
2746 if (mesh_dim == 3) {
2748 fprintf(fout,
" %.12g", holelist[i * mesh_dim + 2]);
2750 fprintf(fout,
"\n");
2754 fprintf(fout,
"%d\n", numberofregions);
2755 for (i = 0; i < numberofregions; i++) {
2756 if (mesh_dim == 2) {
2759 fprintf(fout,
"%d %.12g %.12g %.12g %.12g\n", i + firstnumber,
2760 regionlist[i * 4], regionlist[i * 4 + 1],
2761 regionlist[i * 4 + 2], regionlist[i * 4 + 3]);
2765 fprintf(fout,
"%d %.12g %.12g %.12g %.12g %.12g\n", i + firstnumber,
2766 regionlist[i * 5], regionlist[i * 5 + 1],
2767 regionlist[i * 5 + 2], regionlist[i * 5 + 3],
2768 regionlist[i * 5 + 4]);
2787 char* tetgenio::readline(
char *
string, FILE *infile,
int *linenumber)
2793 result = fgets(
string, INPUTLINESIZE - 1, infile);
2794 if (linenumber) (*linenumber)++;
2795 if (result == (
char *) NULL) {
2796 return (
char *) NULL;
2799 while ((*result ==
' ') || (*result ==
'\t')) result++;
2801 }
while (*result ==
'\0');
2814 char* tetgenio::findnextfield(
char *
string)
2820 while ((*result !=
'\0') && (*result !=
' ') && (*result !=
'\t') &&
2821 (*result !=
',') && (*result !=
';')) {
2826 while ((*result ==
' ') || (*result ==
'\t') || (*result ==
',') ||
2842 char* tetgenio::readnumberline(
char *
string, FILE *infile,
char *infilename)
2848 result = fgets(
string, INPUTLINESIZE, infile);
2849 if (result == (
char *) NULL) {
2850 if (infilename != (
char *) NULL) {
2851 printf(
" Error: Unexpected end of file in %s.\n", infilename);
2858 while ((*result !=
'\0') && (*result !=
'#')
2859 && (*result !=
'.') && (*result !=
'+') && (*result !=
'-')
2860 && ((*result <
'0') || (*result >
'9'))) {
2864 }
while ((*result ==
'#') || (*result ==
'\0'));
2878 char* tetgenio::findnextnumber(
char *
string)
2884 while ((*result !=
'\0') && (*result !=
'#') && (*result !=
' ') &&
2885 (*result !=
'\t') && (*result !=
',')) {
2890 while ((*result !=
'\0') && (*result !=
'#')
2891 && (*result !=
'.') && (*result !=
'+') && (*result !=
'-')
2892 && ((*result <
'0') || (*result >
'9'))) {
2896 if (*result ==
'#') {
2906 static REAL PI = 3.14159265358979323846264338327950288419716939937510582;
2918 tetgenbehavior::tetgenbehavior()
2930 maxdihedral = 165.0;
2936 insertaddpoints = 0;
2973 commandline[0] =
'\0';
2974 infilename[0] =
'\0';
2975 outfilename[0] =
'\0';
2976 addinfilename[0] =
'\0';
2977 bgmeshfilename[0] =
'\0';
2986 void tetgenbehavior::versioninfo()
2988 printf(
"Version 1.4.2 (April 16, 2007).\n");
2990 printf(
"Copyright (C) 2002 - 2007\n");
2991 printf(
"Hang Si\n");
2992 printf(
"Mohrenstr. 39, 10117 Berlin, Germany\n");
2993 printf(
"si@wias-berlin.de\n");
3002 void tetgenbehavior::syntax()
3004 printf(
" tetgen [-prq_Ra_AiMYS_T_dzo_fenvgGOJBNEFICQVh] input_file\n");
3005 printf(
" -p Tetrahedralizes a piecewise linear complex (PLC).\n");
3006 printf(
" -r Reconstructs a previously generated mesh.\n");
3007 printf(
" -q Quality mesh generation (adding new mesh points to ");
3008 printf(
"improve mesh quality).\n");
3009 printf(
" -R Mesh coarsening (deleting redundant mesh points).\n");
3010 printf(
" -a Applies a maximum tetrahedron volume constraint.\n");
3011 printf(
" -A Assigns attributes to identify tetrahedra in different ");
3012 printf(
"regions.\n");
3013 printf(
" -i Inserts a list of additional points into mesh.\n");
3014 printf(
" -M Does not merge coplanar facets.\n");
3015 printf(
" -Y Suppresses boundary facets/segments splitting.\n");
3016 printf(
" -S Specifies maximum number of added points.\n");
3017 printf(
" -T Sets a tolerance for coplanar test (default 1e-8).\n");
3018 printf(
" -d Detects self-intersections of facets of the PLC.\n");
3019 printf(
" -z Numbers all output items starting from zero.\n");
3020 printf(
" -o2 Generates second-order subparametric elements.\n");
3021 printf(
" -f Outputs all faces to .face file.");
3023 printf(
" -e Outputs all edges to .edge file.\n");
3024 printf(
" -n Outputs tetrahedra neighbors to .neigh file.\n");
3025 printf(
" -v Outputs Voronoi diagram to files.\n");
3026 printf(
" -g Outputs mesh to .mesh file for viewing by Medit.\n");
3027 printf(
" -G Outputs mesh to .msh file for viewing by Gid.\n");
3028 printf(
" -O Outputs mesh to .off file for viewing by Geomview.\n");
3029 printf(
" -J No jettison of unused vertices from output .node file.\n");
3030 printf(
" -B Suppresses output of boundary information.\n");
3031 printf(
" -N Suppresses output of .node file.\n");
3032 printf(
" -E Suppresses output of .ele file.\n");
3033 printf(
" -F Suppresses output of .face file.\n");
3034 printf(
" -I Suppresses mesh iteration numbers.\n");
3035 printf(
" -C Checks the consistency of the final mesh.\n");
3036 printf(
" -Q Quiet: No terminal output except errors.\n");
3037 printf(
" -V Verbose: Detailed information, more terminal output.\n");
3038 printf(
" -h Help: A brief instruction for using TetGen.\n");
3047 void tetgenbehavior::usage()
3050 printf(
"A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
3051 printf(
"Triangulator\n");
3054 printf(
"What Can TetGen Do?\n");
3056 printf(
" TetGen generates exact Delaunay tetrahedralizations, exact\n");
3057 printf(
" constrained Delaunay tetrahedralizations, and quality ");
3058 printf(
"tetrahedral\n meshes. The latter are nicely graded and whose ");
3059 printf(
"tetrahedra have\n radius-edge ratio bounded, thus are suitable ");
3060 printf(
"for finite element and\n finite volume analysis.\n");
3062 printf(
"Command Line Syntax:\n");
3064 printf(
" Below is the command line syntax of TetGen with a list of ");
3066 printf(
" descriptions. Underscores indicate that numbers may optionally\n");
3067 printf(
" follow certain switches. Do not leave any space between a ");
3069 printf(
" and its numeric parameter. \'input_file\' contains input data\n");
3070 printf(
" depending on the switches you supplied which may be a ");
3071 printf(
" piecewise\n");
3072 printf(
" linear complex or a list of nodes. File formats and detailed\n");
3073 printf(
" description of command line switches are found in user's ");
3074 printf(
"manual.\n");
3078 printf(
"Examples of How to Use TetGen:\n");
3080 printf(
" \'tetgen object\' reads vertices from object.node, and writes ");
3081 printf(
"their\n Delaunay tetrahedralization to object.1.node and ");
3082 printf(
"object.1.ele.\n");
3084 printf(
" \'tetgen -p object\' reads a PLC from object.poly or object.");
3085 printf(
"smesh (and\n possibly object.node) and writes its constrained ");
3086 printf(
"Delaunay\n tetrahedralization to object.1.node, object.1.ele and ");
3087 printf(
"object.1.face.\n");
3089 printf(
" \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
3090 printf(
" object.smesh (and possibly object.node), generates a mesh ");
3091 printf(
"whose\n tetrahedra have radius-edge ratio smaller than 1.414 and ");
3092 printf(
"have volume\n of 0.1 or less, and writes the mesh to ");
3093 printf(
"object.1.node, object.1.ele\n and object.1.face.\n");
3095 printf(
"Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
3122 bool tetgenbehavior::parse_commandline(
int argc,
char **argv)
3129 char workstring[1024];
3135 commandline[0] =
'\0';
3138 strcpy(commandline, argv[0]);
3139 strcat(commandline,
" ");
3145 for (i = startindex; i < argc; i++) {
3147 strcat(commandline, argv[i]);
3148 strcat(commandline,
" ");
3149 if (startindex == 1) {
3151 if (argv[i][0] !=
'-') {
3152 strncpy(infilename, argv[i], 1024 - 1);
3153 infilename[1024 - 1] =
'\0';
3159 for (j = startindex; argv[i][j] !=
'\0'; j++) {
3160 if (argv[i][j] ==
'p') {
3162 }
else if (argv[i][j] ==
'r') {
3164 }
else if (argv[i][j] ==
'R') {
3166 }
else if (argv[i][j] ==
'q') {
3168 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3169 (argv[i][j + 1] ==
'.')) {
3171 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3172 (argv[i][j + 1] ==
'.')) {
3174 workstring[k] = argv[i][j];
3177 workstring[k] =
'\0';
3179 minratio = (REAL) strtod(workstring, (
char **) NULL);
3180 }
else if (quality == 2) {
3181 mindihedral = (REAL) strtod(workstring, (
char **) NULL);
3182 }
else if (quality == 3) {
3183 maxdihedral = (REAL) strtod(workstring, (
char **) NULL);
3184 }
else if (quality == 4) {
3185 alpha2 = (REAL) strtod(workstring, (
char **) NULL);
3186 }
else if (quality == 5) {
3187 alpha1 = (REAL) strtod(workstring, (
char **) NULL);
3190 }
else if (argv[i][j] ==
'm') {
3192 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3193 (argv[i][j + 1] ==
'.')) {
3195 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3196 (argv[i][j + 1] ==
'.')) {
3198 workstring[k] = argv[i][j];
3201 workstring[k] =
'\0';
3203 alpha1 = (REAL) strtod(workstring, (
char **) NULL);
3204 }
else if (metric == 2) {
3205 alpha2 = (REAL) strtod(workstring, (
char **) NULL);
3208 }
else if (argv[i][j] ==
'a') {
3209 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3210 (argv[i][j + 1] ==
'.')) {
3213 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3214 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3215 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3217 workstring[k] = argv[i][j];
3220 workstring[k] =
'\0';
3221 maxvolume = (REAL) strtod(workstring, (
char **) NULL);
3225 }
else if (argv[i][j] ==
'A') {
3227 }
else if (argv[i][j] ==
'i') {
3228 insertaddpoints = 1;
3229 }
else if (argv[i][j] ==
'd') {
3231 }
else if (argv[i][j] ==
'z') {
3233 }
else if (argv[i][j] ==
'f') {
3235 }
else if (argv[i][j] ==
'e') {
3237 }
else if (argv[i][j] ==
'n') {
3239 }
else if (argv[i][j] ==
'v') {
3241 }
else if (argv[i][j] ==
'g') {
3243 }
else if (argv[i][j] ==
'G') {
3245 }
else if (argv[i][j] ==
'O') {
3247 }
else if (argv[i][j] ==
'M') {
3249 }
else if (argv[i][j] ==
'Y') {
3251 }
else if (argv[i][j] ==
'J') {
3253 }
else if (argv[i][j] ==
'B') {
3255 }
else if (argv[i][j] ==
'N') {
3257 }
else if (argv[i][j] ==
'E') {
3259 }
else if (argv[i][j] ==
'F') {
3261 }
else if (argv[i][j] ==
'I') {
3263 }
else if (argv[i][j] ==
'o') {
3264 if (argv[i][j + 1] ==
'2') {
3268 }
else if (argv[i][j] ==
'S') {
3269 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3270 (argv[i][j + 1] ==
'.')) {
3272 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3273 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3274 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3276 workstring[k] = argv[i][j];
3279 workstring[k] =
'\0';
3280 steiner = (int) strtol(workstring, (
char **) NULL, 0);
3282 }
else if (argv[i][j] ==
's') {
3284 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3285 (argv[i][j + 1] ==
'.')) {
3287 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3288 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3289 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3291 workstring[k] = argv[i][j];
3294 workstring[k] =
'\0';
3296 optlevel = (int) strtol(workstring, (
char **) NULL, 0);
3297 }
else if (scount == 2) {
3298 optpasses = (int) strtol(workstring, (
char **) NULL, 0);
3301 }
else if (argv[i][j] ==
'D') {
3303 }
else if (argv[i][j] ==
'T') {
3304 if (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3305 (argv[i][j + 1] ==
'.')) {
3307 while (((argv[i][j + 1] >=
'0') && (argv[i][j + 1] <=
'9')) ||
3308 (argv[i][j + 1] ==
'.') || (argv[i][j + 1] ==
'e') ||
3309 (argv[i][j + 1] ==
'-') || (argv[i][j + 1] ==
'+')) {
3311 workstring[k] = argv[i][j];
3314 workstring[k] =
'\0';
3315 epsilon = (REAL) strtod(workstring, (
char **) NULL);
3317 }
else if (argv[i][j] ==
'C') {
3319 }
else if (argv[i][j] ==
'X') {
3321 }
else if (argv[i][j] ==
'Q') {
3323 }
else if (argv[i][j] ==
'V') {
3328 }
else if ((argv[i][j] ==
'h') || (argv[i][j] ==
'H') ||
3329 (argv[i][j] ==
'?')) {
3333 printf(
"Warning: Unknown switch -%c.\n", argv[i][j]);
3338 if (startindex == 0) {
3340 strcpy(infilename,
"tetgen-tmpfile");
3342 if (infilename[0] ==
'\0') {
3348 if (!strcmp(&infilename[strlen(infilename) - 5],
".node")) {
3349 infilename[strlen(infilename) - 5] =
'\0';
3351 }
else if (!strcmp(&infilename[strlen(infilename) - 5],
".poly")) {
3352 infilename[strlen(infilename) - 5] =
'\0';
3355 }
else if (!strcmp(&infilename[strlen(infilename) - 6],
".smesh")) {
3356 infilename[strlen(infilename) - 6] =
'\0';
3359 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".off")) {
3360 infilename[strlen(infilename) - 4] =
'\0';
3363 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".ply")) {
3364 infilename[strlen(infilename) - 4] =
'\0';
3367 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".stl")) {
3368 infilename[strlen(infilename) - 4] =
'\0';
3371 }
else if (!strcmp(&infilename[strlen(infilename) - 5],
".mesh")) {
3372 infilename[strlen(infilename) - 5] =
'\0';
3375 }
else if (!strcmp(&infilename[strlen(infilename) - 4],
".ele")) {
3376 infilename[strlen(infilename) - 4] =
'\0';
3381 plc = plc || diagnose;
3382 useshelles = plc || refine || coarse || quality;
3383 goodratio = minratio;
3384 goodratio *= goodratio;
3387 if (plc && refine) {
3388 printf(
"Error: Switch -r cannot use together with -p.\n");
3391 if (refine && (plc || noiterationnum)) {
3392 printf(
"Error: Switches %s cannot use together with -r.\n",
3396 if (diagnose && (quality || insertaddpoints || (order == 2) || neighout
3398 printf(
"Error: Switches %s cannot use together with -d.\n",
3399 "-q, -i, -o2, -n, and -C");
3405 if (!refine && !plc) {
3410 if (refine || !plc) {
3414 if (fixedvolume || varvolume) {
3420 goodangle = cos(minangle * PI / 180.0);
3421 goodangle *= goodangle;
3424 strcpy(workstring, infilename);
3426 while (workstring[j] !=
'\0') {
3427 if ((workstring[j] ==
'.') && (workstring[j + 1] !=
'\0')) {
3433 if (increment > 0) {
3436 if ((workstring[j] >=
'0') && (workstring[j] <=
'9')) {
3437 meshnumber = meshnumber * 10 + (int) (workstring[j] -
'0');
3442 }
while (workstring[j] !=
'\0');
3444 if (noiterationnum) {
3445 strcpy(outfilename, infilename);
3446 }
else if (increment == 0) {
3447 strcpy(outfilename, infilename);
3448 strcat(outfilename,
".1");
3450 workstring[increment] =
'%';
3451 workstring[increment + 1] =
'd';
3452 workstring[increment + 2] =
'\0';
3453 sprintf(outfilename, workstring, meshnumber + 1);
3456 strcpy(addinfilename, infilename);
3457 strcat(addinfilename,
".a");
3459 strcpy(bgmeshfilename, infilename);
3460 strcat(bgmeshfilename,
".b");
3483 int tetgenmesh::compare_2_ints(
const void* x,
const void* y) {
3484 if (* (
int *) x < * (
int *) y) {
3486 }
else if (* (
int *) x > * (
int *) y) {
3495 int tetgenmesh::compare_2_longs(
const void* x,
const void* y) {
3496 if (* (
long *) x < * (
long *) y) {
3498 }
else if (* (
long *) x > * (
long *) y) {
3506 int tetgenmesh::compare_2_unsignedlongs(
const void* x,
const void* y) {
3507 if (* (
unsigned long *) x < * (
unsigned long *) y) {
3509 }
else if (* (
unsigned long *) x > * (
unsigned long *) y) {
3531 void tetgenmesh::set_compfunc(
char* str,
int* itbytes, compfunc* pcomp)
3534 if (str[strlen(str) - 1] ==
'*') {
3535 *itbytes =
sizeof(
unsigned long);
3536 *pcomp = &compare_2_unsignedlongs;
3540 if (strcmp(str,
"int") == 0) {
3541 *itbytes =
sizeof(int);
3542 *pcomp = &compare_2_ints;
3543 }
else if (strcmp(str,
"long") == 0) {
3544 *itbytes =
sizeof(long);
3545 *pcomp = &compare_2_longs;
3546 }
else if (strcmp(str,
"unsigned long") == 0) {
3547 *itbytes =
sizeof(
unsigned long);
3548 *pcomp = &compare_2_unsignedlongs;
3551 printf(
"Error in set_compfunc(): unknown type %s.\n", str);
3566 void tetgenmesh::list::
3567 listinit(
int itbytes, compfunc pcomp,
int mitems,
int exsize)
3570 assert(itbytes > 0 && mitems > 0 && exsize > 0);
3572 itembytes = itbytes;
3575 expandsize = exsize;
3576 base = (
char *) malloc(maxitems * itembytes);
3577 if (base == (
char *) NULL) {
3578 printf(
"Error: Out of memory.\n");
3595 void* tetgenmesh::list::append(
void *appitem)
3598 if (items == maxitems) {
3599 char* newbase = (
char *) realloc(base, (maxitems + expandsize) *
3601 if (newbase == (
char *) NULL) {
3602 printf(
"Error: Out of memory.\n");
3606 maxitems += expandsize;
3608 if (appitem != (
void *) NULL) {
3609 memcpy(base + items * itembytes, appitem, itembytes);
3612 return (
void *) (base + (items - 1) * itembytes);
3626 void* tetgenmesh::list::insert(
int pos,
void* insitem)
3629 return append(insitem);
3632 if (items == maxitems) {
3633 char* newbase = (
char *) realloc(base, (maxitems + expandsize) *
3635 if (newbase == (
char *) NULL) {
3636 printf(
"Error: Out of memory.\n");
3640 maxitems += expandsize;
3643 memmove(base + (pos + 1) * itembytes,
3644 base + pos * itembytes,
3645 (items - pos) * itembytes);
3647 if (insitem != (
void *) NULL) {
3648 memcpy(base + pos * itembytes, insitem, itembytes);
3651 return (
void *) (base + pos * itembytes);
3665 void tetgenmesh::list::del(
int pos,
int order)
3668 if (pos >= 0 && pos < items - 1) {
3671 memmove(base + pos * itembytes,
3672 base + (pos + 1) * itembytes,
3673 (items - pos - 1) * itembytes);
3676 memcpy(base + pos * itembytes,
3677 base + (items - 1) * itembytes,
3696 int tetgenmesh::list::hasitem(
void* checkitem)
3700 for (i = 0; i < items; i++) {
3701 if (comp != (compfunc) NULL) {
3702 if ((* comp)((
void *)(base + i * itembytes), checkitem) == 0) {
3718 void tetgenmesh::list::sort()
3720 qsort((
void *) base, (
size_t) items, (
size_t) itembytes, comp);
3729 tetgenmesh::memorypool::memorypool()
3731 firstblock = nowblock = (
void **) NULL;
3732 nextitem = (
void *) NULL;
3733 deaditemstack = (
void *) NULL;
3734 pathblock = (
void **) NULL;
3735 pathitem = (
void *) NULL;
3736 itemwordtype = POINTER;
3738 itembytes = itemwords = 0;
3740 items = maxitems = 0l;
3741 unallocateditems = 0;
3745 tetgenmesh::memorypool::
3746 memorypool(
int bytecount,
int itemcount,
enum wordtype wtype,
int alignment)
3748 poolinit(bytecount, itemcount, wtype, alignment);
3757 tetgenmesh::memorypool::~memorypool()
3759 while (firstblock != (
void **) NULL) {
3760 nowblock = (
void **) *(firstblock);
3762 firstblock = nowblock;
3782 void tetgenmesh::memorypool::
3783 poolinit(
int bytecount,
int itemcount,
enum wordtype wtype,
int alignment)
3788 itemwordtype = wtype;
3789 wordsize = (itemwordtype == POINTER) ?
sizeof(
void *) :
sizeof(REAL);
3795 if (alignment > wordsize) {
3796 alignbytes = alignment;
3798 alignbytes = wordsize;
3800 if ((
int)
sizeof(
void *) > alignbytes) {
3801 alignbytes = (int)
sizeof(
void *);
3803 itemwords = ((bytecount + alignbytes - 1) / alignbytes)
3804 * (alignbytes / wordsize);
3805 itembytes = itemwords * wordsize;
3806 itemsperblock = itemcount;
3811 firstblock = (
void **) malloc(itemsperblock * itembytes +
sizeof(
void *)
3813 if (firstblock == (
void **) NULL) {
3814 printf(
"Error: Out of memory.\n");
3818 *(firstblock) = (
void *) NULL;
3832 void tetgenmesh::memorypool::restart()
3834 unsigned long alignptr;
3840 nowblock = firstblock;
3842 alignptr = (
unsigned long) (nowblock + 1);
3845 (alignptr + (
unsigned long) alignbytes -
3846 (alignptr % (
unsigned long) alignbytes));
3848 unallocateditems = itemsperblock;
3850 deaditemstack = (
void *) NULL;
3859 void* tetgenmesh::memorypool::alloc()
3863 unsigned long alignptr;
3867 if (deaditemstack != (
void *) NULL) {
3868 newitem = deaditemstack;
3869 deaditemstack = * (
void **) deaditemstack;
3872 if (unallocateditems == 0) {
3874 if (*nowblock == (
void *) NULL) {
3876 newblock = (
void **) malloc(itemsperblock * itembytes +
sizeof(
void *)
3878 if (newblock == (
void **) NULL) {
3879 printf(
"Error: Out of memory.\n");
3882 *nowblock = (
void *) newblock;
3884 *newblock = (
void *) NULL;
3887 nowblock = (
void **) *nowblock;
3890 alignptr = (
unsigned long) (nowblock + 1);
3893 (alignptr + (
unsigned long) alignbytes -
3894 (alignptr % (
unsigned long) alignbytes));
3896 unallocateditems = itemsperblock;
3901 if (itemwordtype == POINTER) {
3902 nextitem = (
void *) ((
void **) nextitem + itemwords);
3904 nextitem = (
void *) ((REAL *) nextitem + itemwords);
3921 void tetgenmesh::memorypool::dealloc(
void *dyingitem)
3924 *((
void **) dyingitem) = deaditemstack;
3925 deaditemstack = dyingitem;
3937 void tetgenmesh::memorypool::traversalinit()
3939 unsigned long alignptr;
3942 pathblock = firstblock;
3944 alignptr = (
unsigned long) (pathblock + 1);
3947 (alignptr + (
unsigned long) alignbytes -
3948 (alignptr % (
unsigned long) alignbytes));
3950 pathitemsleft = itemsperblock;
3965 void* tetgenmesh::memorypool::traverse()
3968 unsigned long alignptr;
3971 if (pathitem == nextitem) {
3972 return (
void *) NULL;
3975 if (pathitemsleft == 0) {
3977 pathblock = (
void **) *pathblock;
3979 alignptr = (
unsigned long) (pathblock + 1);
3982 (alignptr + (
unsigned long) alignbytes -
3983 (alignptr % (
unsigned long) alignbytes));
3985 pathitemsleft = itemsperblock;
3989 if (itemwordtype == POINTER) {
3990 pathitem = (
void *) ((
void **) pathitem + itemwords);
3992 pathitem = (
void *) ((REAL *) pathitem + itemwords);
4007 void tetgenmesh::link::linkinit(
int bytecount, compfunc pcomp,
int itemcount)
4010 assert(bytecount > 0 && itemcount > 0);
4013 linkitembytes = bytecount;
4021 poolinit(bytecount + 2 *
sizeof(
void **), itemcount + 2, POINTER, 0);
4024 head = (
void **) alloc();
4025 tail = (
void **) alloc();
4026 *head = (
void *) tail;
4029 *(tail + 1) = (
void *) head;
4030 nextlinkitem = *head;
4045 void tetgenmesh::link::clear()
4051 head = (
void **) alloc();
4052 tail = (
void **) alloc();
4053 *head = (
void *) tail;
4056 *(tail + 1) = (
void *) head;
4057 nextlinkitem = *head;
4073 bool tetgenmesh::link::move(
int numberofnodes)
4078 nownode = (
void **) nextlinkitem;
4079 if (numberofnodes > 0) {
4082 while ((i < numberofnodes) && *nownode) {
4083 nownode = (
void **) *nownode;
4086 if (*nownode == NULL)
return false;
4087 nextlinkitem = (
void *) nownode;
4088 curpos += numberofnodes;
4089 }
else if (numberofnodes < 0) {
4092 numberofnodes = -numberofnodes;
4093 while ((i < numberofnodes) && *(nownode + 1)) {
4094 nownode = (
void **) *(nownode + 1);
4097 if (*(nownode + 1) == NULL)
return false;
4098 nextlinkitem = (
void *) nownode;
4099 curpos -= numberofnodes;
4116 bool tetgenmesh::link::locate(
int pos)
4118 int headdist, taildist, curdist;
4119 int abscurdist, mindist;
4121 if (pos < 1 || pos > linkitems)
return false;
4124 taildist = linkitems - pos;
4125 curdist = pos - curpos;
4126 abscurdist = curdist >= 0 ? curdist : -curdist;
4128 if (headdist > taildist) {
4129 if (taildist > abscurdist) {
4133 mindist = -taildist;
4138 if (headdist > abscurdist) {
4147 return move(mindist);
4160 void* tetgenmesh::link::add(
void* newitem)
4162 void **newnode = tail;
4163 if (newitem != (
void *) NULL) {
4164 memcpy((
void *)(newnode + 2), newitem, linkitembytes);
4166 tail = (
void **) alloc();
4168 *newnode = (
void*) tail;
4169 *(tail + 1) = (
void*) newnode;
4171 return (
void *)(newnode + 2);
4186 void* tetgenmesh::link::insert(
int pos,
void* insitem)
4189 return add(insitem);
4192 void **nownode = (
void **) nextlinkitem;
4195 void **newnode = (
void **) alloc();
4196 if (insitem != (
void *) NULL) {
4197 memcpy((
void *)(newnode + 2), insitem, linkitembytes);
4200 *(
void **)(*(nownode + 1)) = (
void *) newnode;
4201 *newnode = (
void *) nownode;
4202 *(newnode + 1) = *(nownode + 1);
4203 *(nownode + 1) = (
void *) newnode;
4207 nextlinkitem = (
void *) newnode;
4208 return (
void *)(newnode + 2);
4220 void* tetgenmesh::link::deletenode(
void** deadnode)
4222 void **nextnode = (
void **) *deadnode;
4223 void **prevnode = (
void **) *(deadnode + 1);
4224 *prevnode = (
void *) nextnode;
4225 *(nextnode + 1) = (
void *) prevnode;
4227 dealloc((
void *) deadnode);
4230 nextlinkitem = (
void *) nextnode;
4231 return (
void *)(deadnode + 2);
4244 void* tetgenmesh::link::del(
int pos)
4246 if (!locate(pos) || (linkitems == 0)) {
4247 return (
void *) NULL;
4249 return deletenode((
void **) nextlinkitem);
4262 void* tetgenmesh::link::getitem()
4264 if (nextlinkitem == (
void *) tail)
return NULL;
4265 void **nownode = (
void **) nextlinkitem;
4266 nextlinkitem = *nownode;
4268 return (
void *)(nownode + 2);
4280 void* tetgenmesh::link::getnitem(
int pos)
4282 if (!locate(pos))
return NULL;
4283 return (
void *)((
void **) nextlinkitem + 2);
4296 int tetgenmesh::link::hasitem(
void* checkitem)
4302 pathitem = getitem();
4307 if ((* comp)(pathitem, checkitem) == 0) {
4311 pathitem = getitem();
4330 int tetgenmesh::plus1mod3[3] = {1, 2, 0};
4331 int tetgenmesh::minus1mod3[3] = {2, 0, 1};
4336 int tetgenmesh::ve[6] = { 2, 5, 4, 1, 0, 3 };
4341 int tetgenmesh::vo[6] = { 0, 1, 1, 2, 2, 0 };
4342 int tetgenmesh::vd[6] = { 1, 0, 2, 1, 0, 2 };
4343 int tetgenmesh::va[6] = { 2, 2, 0, 0, 1, 1 };
4350 int tetgenmesh::locver2org[4][6] = {
4356 int tetgenmesh::locver2dest[4][6] = {
4362 int tetgenmesh::locver2apex[4][6] = {
4371 int tetgenmesh::loc2oppo[4] = { 3, 2, 0, 1 };
4377 int tetgenmesh::locver2nextf[4][6][2] = {
4378 { {1, 5}, {-1, -1}, {2, 5}, {-1, -1}, {3, 5}, {-1, -1} },
4379 { {3, 3}, {-1, -1}, {2, 1}, {-1, -1}, {0, 1}, {-1, -1} },
4380 { {1, 3}, {-1, -1}, {3, 1}, {-1, -1}, {0, 3}, {-1, -1} },
4381 { {2, 3}, {-1, -1}, {1, 1}, {-1, -1}, {0, 5}, {-1, -1} }
4388 int tetgenmesh::locver2edge[4][6] = {
4395 int tetgenmesh::edge2locver[6][2] = {
4417 #define Orient(V) ((V) Div2) 4421 #define EdgeRing(V) ((V) Mod2) 4436 inline void tetgenmesh::decode(tetrahedron ptr, triface& t) {
4437 t.loc = (int) ((
unsigned long) (ptr) & (
unsigned long) 3l);
4438 t.tet = (tetrahedron *) ((
unsigned long) (ptr) & ~(
unsigned long) 7l);
4441 inline tetgenmesh::tetrahedron tetgenmesh::encode(triface& t) {
4442 return (tetrahedron) ((
unsigned long) t.tet | (
unsigned long) t.loc);
4447 inline void tetgenmesh::sym(triface& t1, triface& t2) {
4448 tetrahedron ptr = t1.tet[t1.loc];
4452 inline void tetgenmesh::symself(triface& t) {
4453 tetrahedron ptr = t.tet[t.loc];
4459 inline void tetgenmesh::bond(triface& t1, triface& t2) {
4460 t1.tet[t1.loc] = encode(t2);
4461 t2.tet[t2.loc] = encode(t1);
4469 inline void tetgenmesh::dissolve(triface& t) {
4470 t.tet[t.loc] = (tetrahedron) dummytet;
4476 inline tetgenmesh::point tetgenmesh::org(triface& t) {
4477 return (point) t.tet[locver2org[t.loc][t.ver] + 4];
4480 inline tetgenmesh::point tetgenmesh::dest(triface& t) {
4481 return (point) t.tet[locver2dest[t.loc][t.ver] + 4];
4484 inline tetgenmesh::point tetgenmesh::apex(triface& t) {
4485 return (point) t.tet[locver2apex[t.loc][t.ver] + 4];
4488 inline tetgenmesh::point tetgenmesh::oppo(triface& t) {
4489 return (point) t.tet[loc2oppo[t.loc] + 4];
4492 inline void tetgenmesh::setorg(triface& t, point pointptr) {
4493 t.tet[locver2org[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
4496 inline void tetgenmesh::setdest(triface& t, point pointptr) {
4497 t.tet[locver2dest[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
4500 inline void tetgenmesh::setapex(triface& t, point pointptr) {
4501 t.tet[locver2apex[t.loc][t.ver] + 4] = (tetrahedron) pointptr;
4504 inline void tetgenmesh::setoppo(triface& t, point pointptr) {
4505 t.tet[loc2oppo[t.loc] + 4] = (tetrahedron) pointptr;
4515 inline void tetgenmesh::esym(triface& t1, triface& t2) {
4518 t2.ver = t1.ver + (EdgeRing(t1.ver) ? -1 : 1);
4521 inline void tetgenmesh::esymself(triface& t) {
4522 t.ver += (EdgeRing(t.ver) ? -1 : 1);
4527 inline void tetgenmesh::enext(triface& t1, triface& t2) {
4530 t2.ver = ve[t1.ver];
4533 inline void tetgenmesh::enextself(triface& t) {
4539 inline void tetgenmesh::enext2(triface& t1, triface& t2) {
4542 t2.ver = ve[ve[t1.ver]];
4545 inline void tetgenmesh::enext2self(triface& t) {
4546 t.ver = ve[ve[t.ver]];
4553 inline bool tetgenmesh::fnext(triface& t1, triface& t2)
4556 t2.loc = locver2nextf[t1.loc][t1.ver][0];
4560 t2.ver = locver2nextf[t1.loc][t1.ver][1];
4565 if (t2.tet != dummytet) {
4571 for (i = 0; (i < 3) && (org(t2) != torg); i++) {
4577 t2.loc = locver2nextf[tloc][tver][0];
4578 t2.ver = locver2nextf[tloc][tver][1];
4581 return t2.tet != dummytet;
4584 inline bool tetgenmesh::fnextself(triface& t1)
4589 t2.loc = locver2nextf[t1.loc][t1.ver][0];
4593 t2.ver = locver2nextf[t1.loc][t1.ver][1];
4599 if (t2.tet != dummytet) {
4605 for (i = 0; (i < 3) && (org(t2) != torg); i++) {
4608 t1.loc = locver2nextf[t2.loc][t2.ver][0];
4609 t1.ver = locver2nextf[t2.loc][t2.ver][1];
4613 return t2.tet != dummytet;
4619 inline void tetgenmesh::enextfnext(triface& t1, triface& t2) {
4624 inline void tetgenmesh::enextfnextself(triface& t) {
4629 inline void tetgenmesh::enext2fnext(triface& t1, triface& t2) {
4634 inline void tetgenmesh::enext2fnextself(triface& t) {
4643 inline void tetgenmesh::infect(triface& t) {
4644 t.tet[0] = (tetrahedron) ((
unsigned long) t.tet[0] | (
unsigned long) 4l);
4647 inline void tetgenmesh::uninfect(triface& t) {
4648 t.tet[0] = (tetrahedron) ((
unsigned long) t.tet[0] & ~ (
unsigned long) 4l);
4653 inline bool tetgenmesh::infected(triface& t) {
4654 return (((
unsigned long) t.tet[0] & (
unsigned long) 4l) != 0);
4659 inline REAL tetgenmesh::elemattribute(tetrahedron* ptr,
int attnum) {
4660 return ((REAL *) (ptr))[elemattribindex + attnum];
4663 inline void tetgenmesh::
4664 setelemattribute(tetrahedron* ptr,
int attnum, REAL value){
4665 ((REAL *) (ptr))[elemattribindex + attnum] = value;
4670 inline REAL tetgenmesh::volumebound(tetrahedron* ptr) {
4671 return ((REAL *) (ptr))[volumeboundindex];
4674 inline void tetgenmesh::setvolumebound(tetrahedron* ptr, REAL value) {
4675 ((REAL *) (ptr))[volumeboundindex] = value;
4694 inline void tetgenmesh::sdecode(shellface sptr, face& s) {
4695 s.shver = (int) ((
unsigned long) (sptr) & (
unsigned long) 7l);
4696 s.sh = (shellface *) ((
unsigned long) (sptr) & ~ (
unsigned long) 7l);
4699 inline tetgenmesh::shellface tetgenmesh::sencode(face& s) {
4700 return (shellface) ((
unsigned long) s.sh | (
unsigned long) s.shver);
4706 inline void tetgenmesh::spivot(face& s1, face& s2) {
4707 shellface sptr = s1.sh[Orient(s1.shver)];
4711 inline void tetgenmesh::spivotself(face& s) {
4712 shellface sptr = s.sh[Orient(s.shver)];
4719 inline void tetgenmesh::sbond(face& s1, face& s2) {
4720 s1.sh[Orient(s1.shver)] = sencode(s2);
4721 s2.sh[Orient(s2.shver)] = sencode(s1);
4727 inline void tetgenmesh::sbond1(face& s1, face& s2) {
4728 s1.sh[Orient(s1.shver)] = sencode(s2);
4734 inline void tetgenmesh::sdissolve(face& s) {
4735 s.sh[Orient(s.shver)] = (shellface) dummysh;
4741 inline tetgenmesh::point tetgenmesh::sorg(face& s) {
4742 return (point) s.sh[3 + vo[s.shver]];
4745 inline tetgenmesh::point tetgenmesh::sdest(face& s) {
4746 return (point) s.sh[3 + vd[s.shver]];
4749 inline tetgenmesh::point tetgenmesh::sapex(face& s) {
4750 return (point) s.sh[3 + va[s.shver]];
4753 inline void tetgenmesh::setsorg(face& s, point pointptr) {
4754 s.sh[3 + vo[s.shver]] = (shellface) pointptr;
4757 inline void tetgenmesh::setsdest(face& s, point pointptr) {
4758 s.sh[3 + vd[s.shver]] = (shellface) pointptr;
4761 inline void tetgenmesh::setsapex(face& s, point pointptr) {
4762 s.sh[3 + va[s.shver]] = (shellface) pointptr;
4768 inline void tetgenmesh::sesym(face& s1, face& s2) {
4770 s2.shver = s1.shver + (EdgeRing(s1.shver) ? -1 : 1);
4773 inline void tetgenmesh::sesymself(face& s) {
4774 s.shver += (EdgeRing(s.shver) ? -1 : 1);
4777 inline void tetgenmesh::senext(face& s1, face& s2) {
4779 s2.shver = ve[s1.shver];
4782 inline void tetgenmesh::senextself(face& s) {
4783 s.shver = ve[s.shver];
4786 inline void tetgenmesh::senext2(face& s1, face& s2) {
4788 s2.shver = ve[ve[s1.shver]];
4791 inline void tetgenmesh::senext2self(face& s) {
4792 s.shver = ve[ve[s.shver]];
4797 inline void tetgenmesh::sfnext(face& s1, face& s2) {
4798 getnextsface(&s1, &s2);
4801 inline void tetgenmesh::sfnextself(face& s) {
4802 getnextsface(&s, NULL);
4808 inline tetgenmesh::badface* tetgenmesh::shell2badface(face& s) {
4809 return (badface*) s.sh[11];
4812 inline void tetgenmesh::setshell2badface(face& s, badface* value) {
4813 s.sh[11] = (shellface) value;
4818 inline REAL tetgenmesh::areabound(face& s) {
4819 return ((REAL *) (s.sh))[areaboundindex];
4822 inline void tetgenmesh::setareabound(face& s, REAL value) {
4823 ((REAL *) (s.sh))[areaboundindex] = value;
4829 inline int tetgenmesh::shellmark(face& s) {
4830 return ((
int *) (s.sh))[shmarkindex];
4833 inline void tetgenmesh::setshellmark(face& s,
int value) {
4834 ((
int *) (s.sh))[shmarkindex] = value;
4839 inline enum tetgenmesh::shestype tetgenmesh::shelltype(face& s) {
4840 return (
enum shestype) ((
int *) (s.sh))[shmarkindex + 1];
4843 inline void tetgenmesh::setshelltype(face& s,
enum shestype value) {
4844 ((
int *) (s.sh))[shmarkindex + 1] = (
int) value;
4849 inline int tetgenmesh::shellpbcgroup(face& s) {
4850 return ((
int *) (s.sh))[shmarkindex + 2];
4853 inline void tetgenmesh::setshellpbcgroup(face& s,
int value) {
4854 ((
int *) (s.sh))[shmarkindex + 2] = value;
4860 inline void tetgenmesh::sinfect(face& s) {
4861 s.sh[6] = (shellface) ((
unsigned long) s.sh[6] | (
unsigned long) 4l);
4864 inline void tetgenmesh::suninfect(face& s) {
4865 s.sh[6] = (shellface)((
unsigned long) s.sh[6] & ~(
unsigned long) 4l);
4870 inline bool tetgenmesh::sinfected(face& s) {
4871 return (((
unsigned long) s.sh[6] & (
unsigned long) 4l) != 0);
4884 inline void tetgenmesh::tspivot(triface& t, face& s) {
4885 shellface sptr = (shellface) t.tet[8 + t.loc];
4891 inline void tetgenmesh::stpivot(face& s, triface& t) {
4892 tetrahedron ptr = (tetrahedron) s.sh[6 + EdgeRing(s.shver)];
4898 inline void tetgenmesh::tsbond(triface& t, face& s) {
4899 t.tet[8 + t.loc] = (tetrahedron) sencode(s);
4900 s.sh[6 + EdgeRing(s.shver)] = (shellface) encode(t);
4905 inline void tetgenmesh::tsdissolve(triface& t) {
4906 t.tet[8 + t.loc] = (tetrahedron) dummysh;
4911 inline void tetgenmesh::stdissolve(face& s) {
4912 s.sh[6 + EdgeRing(s.shver)] = (shellface) dummytet;
4925 inline void tetgenmesh::sspivot(face& s, face& edge) {
4926 shellface sptr = (shellface) s.sh[8 + Orient(s.shver)];
4927 sdecode(sptr, edge);
4932 inline void tetgenmesh::ssbond(face& s, face& edge) {
4933 s.sh[8 + Orient(s.shver)] = sencode(edge);
4934 edge.sh[0] = sencode(s);
4939 inline void tetgenmesh::ssdissolve(face& s) {
4940 s.sh[8 + Orient(s.shver)] = (shellface) dummysh;
4951 inline void tetgenmesh::tsspivot1(triface& t, face& seg)
4953 shellface sptr = (shellface) t.tet[8 + locver2edge[t.loc][t.ver]];
4959 inline void tetgenmesh::tssbond1(triface& t, face& seg)
4961 t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) sencode(seg);
4964 inline void tetgenmesh::tssdissolve1(triface& t)
4966 t.tet[8 + locver2edge[t.loc][t.ver]] = (tetrahedron) dummysh;
4977 inline int tetgenmesh::pointmark(point pt) {
4978 return ((
int *) (pt))[pointmarkindex];
4981 inline void tetgenmesh::setpointmark(point pt,
int value) {
4982 ((
int *) (pt))[pointmarkindex] = value;
4987 inline enum tetgenmesh::verttype tetgenmesh::pointtype(point pt) {
4988 return (
enum verttype) ((
int *) (pt))[pointmarkindex + 1];
4991 inline void tetgenmesh::setpointtype(point pt,
enum verttype value) {
4992 ((
int *) (pt))[pointmarkindex + 1] = (
int) value;
4998 inline tetgenmesh::tetrahedron tetgenmesh::point2tet(point pt) {
4999 return ((tetrahedron *) (pt))[point2simindex];
5002 inline void tetgenmesh::setpoint2tet(point pt, tetrahedron value) {
5003 ((tetrahedron *) (pt))[point2simindex] = value;
5006 inline tetgenmesh::shellface tetgenmesh::point2sh(point pt) {
5007 return (shellface) ((tetrahedron *) (pt))[point2simindex + 1];
5010 inline void tetgenmesh::setpoint2sh(point pt, shellface value) {
5011 ((tetrahedron *) (pt))[point2simindex + 1] = (tetrahedron) value;
5014 inline tetgenmesh::point tetgenmesh::point2ppt(point pt) {
5015 return (point) ((tetrahedron *) (pt))[point2simindex + 2];
5018 inline void tetgenmesh::setpoint2ppt(point pt, point value) {
5019 ((tetrahedron *) (pt))[point2simindex + 2] = (tetrahedron) value;
5022 inline tetgenmesh::tetrahedron tetgenmesh::point2bgmtet(point pt) {
5023 return ((tetrahedron *) (pt))[point2simindex + 3];
5026 inline void tetgenmesh::setpoint2bgmtet(point pt, tetrahedron value) {
5027 ((tetrahedron *) (pt))[point2simindex + 3] = value;
5032 inline tetgenmesh::point tetgenmesh::point2pbcpt(point pt) {
5033 return (point) ((tetrahedron *) (pt))[point2pbcptindex];
5036 inline void tetgenmesh::setpoint2pbcpt(point pt, point value) {
5037 ((tetrahedron *) (pt))[point2pbcptindex] = (tetrahedron) value;
5052 inline void tetgenmesh::adjustedgering(triface& t,
int direction) {
5053 if (EdgeRing(t.ver) != direction) {
5058 inline void tetgenmesh::adjustedgering(face& s,
int direction) {
5059 if (EdgeRing(s.shver) != direction) {
5066 inline bool tetgenmesh::isdead(triface* t) {
5067 if (t->tet == (tetrahedron *) NULL)
return true;
5068 else return t->tet[4] == (tetrahedron) NULL;
5071 inline bool tetgenmesh::isdead(face* s) {
5072 if (s->sh == (shellface *) NULL)
return true;
5073 else return s->sh[3] == (shellface) NULL;
5079 inline bool tetgenmesh::isfacehaspoint(triface* t, point testpoint) {
5080 return ((org(*t) == testpoint) || (dest(*t) == testpoint) ||
5081 (apex(*t) == testpoint));
5084 inline bool tetgenmesh::isfacehaspoint(face* s, point testpoint) {
5085 return (s->sh[3] == (shellface) testpoint) ||
5086 (s->sh[4] == (shellface) testpoint) ||
5087 (s->sh[5] == (shellface) testpoint);
5093 inline bool tetgenmesh::isfacehasedge(face* s, point tend1, point tend2) {
5094 return (isfacehaspoint(s, tend1) && isfacehaspoint(s, tend2));
5099 inline bool tetgenmesh::issymexist(triface* t) {
5100 tetrahedron *ptr = (tetrahedron *)
5101 ((
unsigned long)(t->tet[t->loc]) & ~(
unsigned long)7l);
5102 return ptr != dummytet;
5115 void tetgenmesh::getnextsface(face* s1, face* s2)
5117 face neighsh, spinsh;
5120 sspivot(*s1, testseg);
5121 if (testseg.sh != dummysh) {
5123 if (sorg(testseg) == sorg(*s1)) {
5124 spivot(*s1, neighsh);
5130 }
while (spinsh.sh != s1->sh);
5133 spivot(*s1, neighsh);
5135 if (sorg(neighsh) != sorg(*s1)) {
5138 if (s2 != (face *) NULL) {
5161 void tetgenmesh::tsspivot(triface* checkedge, face* checkseg)
5168 spintet = *checkedge;
5169 tapex = apex(*checkedge);
5172 tspivot(spintet, parentsh);
5174 if ((parentsh.sh != dummysh) && (sapex(parentsh) != NULL)) {
5176 findedge(&parentsh, org(*checkedge), dest(*checkedge));
5177 sspivot(parentsh, *checkseg);
5178 if (checkseg->sh != dummysh) {
5180 if (sorg(*checkseg) != org(*checkedge)) {
5181 sesymself(*checkseg);
5186 if (!fnextself(spintet)) {
5189 esym(*checkedge, spintet);
5190 if (!fnextself(spintet)) {
5195 }
while ((apex(spintet) != tapex) && (hitbdry < 2));
5197 checkseg->sh = dummysh;
5211 void tetgenmesh::sstpivot(face* checkseg, triface* retedge)
5216 sdecode(checkseg->sh[0], parentsh);
5218 assert(parentsh.sh != dummysh);
5221 stpivot(parentsh, *retedge);
5222 if (retedge->tet == dummytet) {
5223 sesymself(parentsh);
5224 stpivot(parentsh, *retedge);
5226 assert(retedge->tet != dummytet);
5230 findedge(retedge, sorg(*checkseg), sdest(*checkseg));
5243 bool tetgenmesh::findorg(triface* tface, point dorg)
5245 if (org(*tface) == dorg) {
5248 if (dest(*tface) == dorg) {
5252 if (apex(*tface) == dorg) {
5256 if (oppo(*tface) == dorg) {
5258 adjustedgering(*tface, CCW);
5269 bool tetgenmesh::findorg(face* sface, point dorg)
5271 if (sorg(*sface) == dorg) {
5274 if (sdest(*sface) == dorg) {
5278 if (sapex(*sface) == dorg) {
5279 senext2self(*sface);
5297 void tetgenmesh::findedge(triface* tface, point eorg, point edest)
5301 for (i = 0; i < 3; i++) {
5302 if (org(*tface) == eorg) {
5303 if (dest(*tface) == edest) {
5308 if (org(*tface) == edest) {
5309 if (dest(*tface) == eorg) {
5319 printf(
"Internalerror in findedge(): Unable to find an edge in tet.\n");
5323 void tetgenmesh::findedge(face* sface, point eorg, point edest)
5327 for (i = 0; i < 3; i++) {
5328 if (sorg(*sface) == eorg) {
5329 if (sdest(*sface) == edest) {
5334 if (sorg(*sface) == edest) {
5335 if (sdest(*sface) == eorg) {
5344 printf(
"Internalerror in findedge(): Unable to find an edge in subface.\n");
5358 void tetgenmesh::findface(triface *fface, point forg, point fdest, point fapex)
5361 enum finddirectionresult collinear;
5364 if (!isdead(fface)) {
5366 if (org(*fface) == forg && dest(*fface) == fdest &&
5367 apex(*fface) == fapex)
return;
5370 if (!isdead(&recenttet)) *fface = recenttet;
5373 if (!isdead(fface)) {
5374 if (!findorg(fface, forg)) {
5376 preciselocate(forg, fface, tetrahedrons->items);
5379 if (org(*fface) == forg) {
5380 collinear = finddirection(fface, fdest, tetrahedrons->items);
5381 if (collinear == RIGHTCOLLINEAR) {
5383 }
else if (collinear == LEFTCOLLINEAR) {
5386 }
else if (collinear == TOPCOLLINEAR) {
5393 if ((org(*fface) == forg) && (dest(*fface) == fdest)) {
5398 if (apex(spintet) == fapex) {
5401 if (org(spintet) != org(*fface)) {
5407 if (!fnextself(spintet)) {
5410 esym(*fface, spintet);
5411 if (!fnextself(spintet)) {
5416 }
while (hitbdry < 2 && apex(spintet) != apex(*fface));
5421 if (isdead(fface) || (org(*fface) != forg) || (dest(*fface) != fdest) ||
5422 (apex(*fface) != fapex)) {
5426 if (b->verbose > 1) {
5427 printf(
"Warning in findface(): Perform a brute-force searching.\n");
5429 enum verttype forgty, fdestty, fapexty;
5431 forgty = pointtype(forg);
5432 fdestty = pointtype(fdest);
5433 fapexty = pointtype(fapex);
5434 setpointtype(forg, DEADVERTEX);
5435 setpointtype(fdest, DEADVERTEX);
5436 setpointtype(fapex, DEADVERTEX);
5437 tetrahedrons->traversalinit();
5438 fface->tet = tetrahedrontraverse();
5439 while (fface->tet != (tetrahedron *) NULL) {
5441 for (i = 0; i < 4; i++) {
5442 if (pointtype((point) fface->tet[4 + i]) == DEADVERTEX) share ++;
5446 if (pointtype((point) fface->tet[4]) != DEADVERTEX) {
5448 }
else if (pointtype((point) fface->tet[5]) != DEADVERTEX) {
5450 }
else if (pointtype((point) fface->tet[6]) != DEADVERTEX) {
5455 findedge(fface, forg, fdest);
5458 fface->tet = tetrahedrontraverse();
5460 setpointtype(forg, forgty);
5461 setpointtype(fdest, fdestty);
5462 setpointtype(fapex, fapexty);
5463 if (fface->tet == (tetrahedron *) NULL) {
5465 printf(
"Internal error: Fail to find the indicated face.\n");
5480 void tetgenmesh::getonextseg(face* s, face* lseg)
5482 face checksh, checkseg;
5489 senext2self(checksh);
5491 sspivot(checksh, checkseg);
5492 if (checkseg.sh != dummysh)
break;
5494 spivotself(checksh);
5497 assert(checksh.sh != s->sh);
5499 if (sorg(checksh) != forg) {
5502 assert(sorg(checksh) == forg);
5506 if (sorg(checkseg) != forg) sesymself(checkseg);
5520 void tetgenmesh::getseghasorg(face* sseg, point dorg)
5526 checkpt = sorg(nextseg);
5527 while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
5529 senext2self(nextseg);
5530 spivotself(nextseg);
5532 if (sdest(nextseg) != checkpt) sesymself(nextseg);
5533 checkpt = sorg(nextseg);
5535 if (checkpt == dorg) {
5540 checkpt = sdest(nextseg);
5541 while ((checkpt != dorg) && (pointtype(checkpt) == FREESEGVERTEX)) {
5543 senextself(nextseg);
5544 spivotself(nextseg);
5546 if (sorg(nextseg) != checkpt) sesymself(nextseg);
5547 checkpt = sdest(nextseg);
5549 if (checkpt == dorg) {
5550 sesym(nextseg, *sseg);
5554 printf(
"Internalerror in getseghasorg(): Unable to find the subseg.\n");
5564 tetgenmesh::point tetgenmesh::getsubsegfarorg(face* sseg)
5569 checkpt = sorg(*sseg);
5570 senext2(*sseg, prevseg);
5571 spivotself(prevseg);
5573 while (prevseg.sh != dummysh) {
5575 if (sdest(prevseg) != checkpt) sesymself(prevseg);
5576 checkpt = sorg(prevseg);
5577 senext2self(prevseg);
5578 spivotself(prevseg);
5589 tetgenmesh::point tetgenmesh::getsubsegfardest(face* sseg)
5594 checkpt = sdest(*sseg);
5595 senext(*sseg, nextseg);
5596 spivotself(nextseg);
5598 while (nextseg.sh != dummysh) {
5600 if (sorg(nextseg) != checkpt) sesymself(nextseg);
5601 checkpt = sdest(nextseg);
5602 senextself(nextseg);
5603 spivotself(nextseg);
5616 void tetgenmesh::printtet(triface* tface)
5618 triface tmpface, prtface;
5623 printf(
"Tetra x%lx with loc(%i) and ver(%i):",
5624 (
unsigned long)(tface->tet), tface->loc, tface->ver);
5625 if (infected(*tface)) {
5626 printf(
" (infected)");
5632 while(facecount < 4) {
5633 tmpface.loc = facecount;
5634 sym(tmpface, prtface);
5635 if(prtface.tet == dummytet) {
5636 printf(
" [%i] Outer space.\n", facecount);
5638 printf(
" [%i] x%lx loc(%i).", facecount,
5639 (
unsigned long)(prtface.tet), prtface.loc);
5640 if (infected(prtface)) {
5641 printf(
" (infected)");
5648 tmppt = org(*tface);
5649 if(tmppt == (point) NULL) {
5650 printf(
" Org [%i] NULL\n", locver2org[tface->loc][tface->ver]);
5652 printf(
" Org [%i] x%lx (%.12g,%.12g,%.12g) %d\n",
5653 locver2org[tface->loc][tface->ver], (
unsigned long)(tmppt),
5654 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
5656 tmppt = dest(*tface);
5657 if(tmppt == (point) NULL) {
5658 printf(
" Dest[%i] NULL\n", locver2dest[tface->loc][tface->ver]);
5660 printf(
" Dest[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
5661 locver2dest[tface->loc][tface->ver], (
unsigned long)(tmppt),
5662 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
5664 tmppt = apex(*tface);
5665 if(tmppt == (point) NULL) {
5666 printf(
" Apex[%i] NULL\n", locver2apex[tface->loc][tface->ver]);
5668 printf(
" Apex[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
5669 locver2apex[tface->loc][tface->ver], (
unsigned long)(tmppt),
5670 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
5672 tmppt = oppo(*tface);
5673 if(tmppt == (point) NULL) {
5674 printf(
" Oppo[%i] NULL\n", loc2oppo[tface->loc]);
5676 printf(
" Oppo[%i] x%lx (%.12g,%.12g,%.12g) %d\n",
5677 loc2oppo[tface->loc], (
unsigned long)(tmppt),
5678 tmppt[0], tmppt[1], tmppt[2], pointmark(tmppt));
5681 if (b->useshelles) {
5684 while(facecount < 6) {
5685 tmpface.loc = facecount;
5686 tspivot(tmpface, tmpsh);
5687 if(tmpsh.sh != dummysh) {
5688 printf(
" [%i] x%lx ID(%i) ", facecount,
5689 (
unsigned long)(tmpsh.sh), shellmark(tmpsh));
5690 if (sorg(tmpsh) == (point) NULL) {
5708 void tetgenmesh::printsh(face* sface)
5714 if (sapex(*sface) != NULL) {
5715 printf(
"subface x%lx, ver %d, mark %d:",
5716 (
unsigned long)(sface->sh), sface->shver, shellmark(*sface));
5718 printf(
"Subsegment x%lx, ver %d, mark %d:",
5719 (
unsigned long)(sface->sh), sface->shver, shellmark(*sface));
5721 if (sinfected(*sface)) {
5722 printf(
" (infected)");
5724 if (shell2badface(*sface)) {
5725 printf(
" (queued)");
5727 if (sapex(*sface) != NULL) {
5728 if (shelltype(*sface) == SHARP) {
5732 if (shelltype(*sface) == SHARP) {
5737 if (shellpbcgroup(*sface) >= 0) {
5738 printf(
" (pbc %d)", shellpbcgroup(*sface));
5743 sdecode(sface->sh[0], prtsh);
5744 if (prtsh.sh == dummysh) {
5745 printf(
" [0] = No shell\n");
5747 printf(
" [0] = x%lx %d\n", (
unsigned long)(prtsh.sh), prtsh.shver);
5749 sdecode(sface->sh[1], prtsh);
5750 if (prtsh.sh == dummysh) {
5751 printf(
" [1] = No shell\n");
5753 printf(
" [1] = x%lx %d\n", (
unsigned long)(prtsh.sh), prtsh.shver);
5755 sdecode(sface->sh[2], prtsh);
5756 if (prtsh.sh == dummysh) {
5757 printf(
" [2] = No shell\n");
5759 printf(
" [2] = x%lx %d\n", (
unsigned long)(prtsh.sh), prtsh.shver);
5762 printpoint = sorg(*sface);
5763 if (printpoint == (point) NULL)
5764 printf(
" Org [%d] = NULL\n", vo[sface->shver]);
5766 printf(
" Org [%d] = x%lx (%.12g,%.12g,%.12g) %d\n",
5767 vo[sface->shver], (
unsigned long)(printpoint), printpoint[0],
5768 printpoint[1], printpoint[2], pointmark(printpoint));
5769 printpoint = sdest(*sface);
5770 if (printpoint == (point) NULL)
5771 printf(
" Dest[%d] = NULL\n", vd[sface->shver]);
5773 printf(
" Dest[%d] = x%lx (%.12g,%.12g,%.12g) %d\n",
5774 vd[sface->shver], (
unsigned long)(printpoint), printpoint[0],
5775 printpoint[1], printpoint[2], pointmark(printpoint));
5777 if (sapex(*sface) != NULL) {
5778 printpoint = sapex(*sface);
5779 if (printpoint == (point) NULL)
5780 printf(
" Apex[%d] = NULL\n", va[sface->shver]);
5782 printf(
" Apex[%d] = x%lx (%.12g,%.12g,%.12g) %d\n",
5783 va[sface->shver], (
unsigned long)(printpoint), printpoint[0],
5784 printpoint[1], printpoint[2], pointmark(printpoint));
5786 decode(sface->sh[6], prttet);
5787 if (prttet.tet == dummytet) {
5788 printf(
" [6] = Outer space\n");
5790 printf(
" [6] = x%lx %d\n",
5791 (
unsigned long)(prttet.tet), prttet.loc);
5793 decode(sface->sh[7], prttet);
5794 if (prttet.tet == dummytet) {
5795 printf(
" [7] = Outer space\n");
5797 printf(
" [7] = x%lx %d\n",
5798 (
unsigned long)(prttet.tet), prttet.loc);
5801 sdecode(sface->sh[8], prtsh);
5802 if (prtsh.sh == dummysh) {
5803 printf(
" [8] = No subsegment\n");
5805 printf(
" [8] = x%lx %d\n",
5806 (
unsigned long)(prtsh.sh), prtsh.shver);
5808 sdecode(sface->sh[9], prtsh);
5809 if (prtsh.sh == dummysh) {
5810 printf(
" [9] = No subsegment\n");
5812 printf(
" [9] = x%lx %d\n",
5813 (
unsigned long)(prtsh.sh), prtsh.shver);
5815 sdecode(sface->sh[10], prtsh);
5816 if (prtsh.sh == dummysh) {
5817 printf(
" [10]= No subsegment\n");
5819 printf(
" [10]= x%lx %d\n",
5820 (
unsigned long)(prtsh.sh), prtsh.shver);
5848 void tetgenmesh::makepoint2tetmap()
5853 if (b->verbose > 0) {
5854 printf(
" Constructing mapping from points to tetrahedra.\n");
5858 points->traversalinit();
5859 pointptr = pointtraverse();
5860 while (pointptr != (point) NULL) {
5861 setpoint2tet(pointptr, (tetrahedron) NULL);
5862 pointptr = pointtraverse();
5865 tetrahedrons->traversalinit();
5866 tetloop.tet = tetrahedrontraverse();
5867 while (tetloop.tet != (tetrahedron *) NULL) {
5870 pointptr = org(tetloop);
5871 setpoint2tet(pointptr, encode(tetloop));
5872 pointptr = dest(tetloop);
5873 setpoint2tet(pointptr, encode(tetloop));
5874 pointptr = apex(tetloop);
5875 setpoint2tet(pointptr, encode(tetloop));
5876 pointptr = oppo(tetloop);
5877 setpoint2tet(pointptr, encode(tetloop));
5879 tetloop.tet = tetrahedrontraverse();
5894 void tetgenmesh::makeindex2pointmap(point*& idx2verlist)
5899 if (b->verbose > 0) {
5900 printf(
" Constructing mapping from indices to points.\n");
5903 idx2verlist =
new point[points->items];
5905 points->traversalinit();
5906 pointloop = pointtraverse();
5908 while (pointloop != (point) NULL) {
5909 idx2verlist[idx] = pointloop;
5911 pointloop = pointtraverse();
5933 void tetgenmesh::makesegmentmap(
int*& idx2seglist, shellface**& segsperverlist)
5938 if (b->verbose > 0) {
5939 printf(
" Constructing mapping from points to segments.\n");
5943 idx2seglist =
new int[points->items + 1];
5944 for (i = 0; i < points->items + 1; i++) idx2seglist[i] = 0;
5948 subsegs->traversalinit();
5949 shloop = shellfacetraverse(subsegs);
5950 while (shloop != (shellface *) NULL) {
5952 for (i = 0; i < 2; i++) {
5953 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
5956 shloop = shellfacetraverse(subsegs);
5962 for (i = 0; i < points->items; i++) {
5963 k = idx2seglist[i + 1];
5964 idx2seglist[i + 1] = idx2seglist[i] + j;
5968 segsperverlist =
new shellface*[idx2seglist[i]];
5970 subsegs->traversalinit();
5971 shloop = shellfacetraverse(subsegs);
5972 while (shloop != (shellface *) NULL) {
5973 for (i = 0; i < 2; i++) {
5974 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
5975 segsperverlist[idx2seglist[j]] = shloop;
5978 shloop = shellfacetraverse(subsegs);
5981 for (i = points->items - 1; i >= 0; i--) {
5982 idx2seglist[i + 1] = idx2seglist[i];
6006 makesubfacemap(
int*& idx2facelist, shellface**& facesperverlist)
6011 if (b->verbose > 0) {
6012 printf(
" Constructing mapping from points to subfaces.\n");
6016 idx2facelist =
new int[points->items + 1];
6017 for (i = 0; i < points->items + 1; i++) idx2facelist[i] = 0;
6021 subfaces->traversalinit();
6022 shloop = shellfacetraverse(subfaces);
6023 while (shloop != (shellface *) NULL) {
6025 for (i = 0; i < 3; i++) {
6026 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
6029 shloop = shellfacetraverse(subfaces);
6033 j = idx2facelist[0];
6034 idx2facelist[0] = 0;
6035 for (i = 0; i < points->items; i++) {
6036 k = idx2facelist[i + 1];
6037 idx2facelist[i + 1] = idx2facelist[i] + j;
6041 facesperverlist =
new shellface*[idx2facelist[i]];
6043 subfaces->traversalinit();
6044 shloop = shellfacetraverse(subfaces);
6045 while (shloop != (shellface *) NULL) {
6046 for (i = 0; i < 3; i++) {
6047 j = pointmark((point) shloop[3 + i]) - in->firstnumber;
6048 facesperverlist[idx2facelist[j]] = shloop;
6051 shloop = shellfacetraverse(subfaces);
6054 for (i = points->items - 1; i >= 0; i--) {
6055 idx2facelist[i + 1] = idx2facelist[i];
6057 idx2facelist[0] = 0;
6079 maketetrahedronmap(
int*& idx2tetlist, tetrahedron**& tetsperverlist)
6081 tetrahedron *tetloop;
6084 if (b->verbose > 0) {
6085 printf(
" Constructing mapping from points to tetrahedra.\n");
6089 idx2tetlist =
new int[points->items + 1];
6090 for (i = 0; i < points->items + 1; i++) idx2tetlist[i] = 0;
6094 tetrahedrons->traversalinit();
6095 tetloop = tetrahedrontraverse();
6096 while (tetloop != (tetrahedron *) NULL) {
6098 for (i = 0; i < 4; i++) {
6099 j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
6102 tetloop = tetrahedrontraverse();
6108 for (i = 0; i < points->items; i++) {
6109 k = idx2tetlist[i + 1];
6110 idx2tetlist[i + 1] = idx2tetlist[i] + j;
6114 tetsperverlist =
new tetrahedron*[idx2tetlist[i]];
6116 tetrahedrons->traversalinit();
6117 tetloop = tetrahedrontraverse();
6118 while (tetloop != (tetrahedron *) NULL) {
6119 for (i = 0; i < 4; i++) {
6120 j = pointmark((point) tetloop[4 + i]) - in->firstnumber;
6121 tetsperverlist[idx2tetlist[j]] = tetloop;
6124 tetloop = tetrahedrontraverse();
6127 for (i = points->items - 1; i >= 0; i--) {
6128 idx2tetlist[i + 1] = idx2tetlist[i];
6143 inline REAL tetgenmesh::dot(REAL* v1, REAL* v2)
6145 return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
6150 inline void tetgenmesh::cross(REAL* v1, REAL* v2, REAL* n)
6152 n[0] = v1[1] * v2[2] - v2[1] * v1[2];
6153 n[1] = -(v1[0] * v2[2] - v2[0] * v1[2]);
6154 n[2] = v1[0] * v2[1] - v2[0] * v1[1];
6158 static void initm44(REAL a00, REAL a01, REAL a02, REAL a03,
6159 REAL a10, REAL a11, REAL a12, REAL a13,
6160 REAL a20, REAL a21, REAL a22, REAL a23,
6161 REAL a30, REAL a31, REAL a32, REAL a33,
6164 M[0][0] = a00; M[0][1] = a01; M[0][2] = a02; M[0][3] = a03;
6165 M[1][0] = a10; M[1][1] = a11; M[1][2] = a12; M[1][3] = a13;
6166 M[2][0] = a20; M[2][1] = a21; M[2][2] = a22; M[2][3] = a23;
6167 M[3][0] = a30; M[3][1] = a31; M[3][2] = a32; M[3][3] = a33;
6171 static void m4xm4(REAL m1[4][4], REAL m2[4][4])
6176 for (i = 0; i < 4; i++) {
6177 for (j = 0; j < 4; j++) {
6178 tmp[j] = m1[i][0] * m2[0][j] + m1[i][1] * m2[1][j]
6179 + m1[i][2] * m2[2][j] + m1[i][3] * m2[3][j];
6181 for (j = 0; j < 4; j++)
6187 static void m4xv4(REAL v2[4], REAL m[4][4], REAL v1[4])
6189 v2[0] = m[0][0]*v1[0] + m[0][1]*v1[1] + m[0][2]*v1[2] + m[0][3]*v1[3];
6190 v2[1] = m[1][0]*v1[0] + m[1][1]*v1[1] + m[1][2]*v1[2] + m[1][3]*v1[3];
6191 v2[2] = m[2][0]*v1[0] + m[2][1]*v1[1] + m[2][2]*v1[2] + m[2][3]*v1[3];
6192 v2[3] = m[3][0]*v1[0] + m[3][1]*v1[1] + m[3][2]*v1[2] + m[3][3]*v1[3];
6219 bool tetgenmesh::lu_decmp(REAL lu[4][4],
int n,
int* ps, REAL* d,
int N)
6222 REAL pivot, biggest, mult, tempf;
6228 for (i = N; i < n + N; i++) {
6231 for (j = N; j < n + N; j++)
6232 if (biggest < (tempf = fabs(lu[i][j])))
6235 scales[i] = 1.0 / biggest;
6243 for (k = N; k < n + N - 1; k++) {
6246 for (i = k; i < n + N; i++) {
6247 if (biggest < (tempf = fabs(lu[ps[i]][k]) * scales[ps[i]])) {
6252 if (biggest == 0.0) {
6255 if (pivotindex != k) {
6257 ps[k] = ps[pivotindex];
6263 pivot = lu[ps[k]][k];
6264 for (i = k + 1; i < n + N; i++) {
6265 lu[ps[i]][k] = mult = lu[ps[i]][k] / pivot;
6267 for (j = k + 1; j < n + N; j++)
6268 lu[ps[i]][j] -= mult * lu[ps[k]][j];
6274 return lu[ps[n + N - 1]][n + N - 1] != 0.0;
6292 void tetgenmesh::lu_solve(REAL lu[4][4],
int n,
int* ps, REAL* b,
int N)
6297 for (i = N; i < n + N; i++) X[i] = 0.0;
6300 for (i = N; i < n + N; i++) {
6302 for (j = N; j < i + N; j++)
6303 dot += lu[ps[i]][j] * X[j];
6304 X[i] = b[ps[i]] - dot;
6308 for (i = n + N - 1; i >= N; i--) {
6310 for (j = i + 1; j < n + N; j++)
6311 dot += lu[ps[i]][j] * X[j];
6312 X[i] = (X[i] - dot) / lu[ps[i]][i];
6315 for (i = N; i < n + N; i++) b[i] = X[i];
6346 enum tetgenmesh::interresult tetgenmesh::edge_vert_col_inter(REAL* A, REAL* B,
6354 }
else if (P[i] > A[i]) {
6357 }
else if (P[i] > B[i]) {
6367 }
else if (A[i] > B[i]) {
6370 }
else if (P[i] > B[i]) {
6373 }
else if (P[i] > A[i]) {
6409 enum tetgenmesh::interresult tetgenmesh:: edge_edge_cop_inter(REAL* A, REAL* B,
6410 REAL* P, REAL* Q, REAL* R)
6412 REAL s1, s2, s3, s4;
6417 s1 = orient3d(A, B, R, P);
6418 s2 = orient3d(A, B, R, Q);
6419 if (s1 * s2 > 0.0) {
6423 s3 = orient3d(P, Q, R, A);
6424 s4 = orient3d(P, Q, R, B);
6425 if (s3 * s4 > 0.0) {
6434 enum interresult abp, abq;
6435 enum interresult pqa, pqb;
6439 abp = edge_vert_col_inter(A, B, P);
6440 if (abp == INTERSECT) {
6446 abq = edge_vert_col_inter(A, B, Q);
6447 if (abq == INTERSECT) {
6451 if (abp == SHAREVERTEX && abq == SHAREVERTEX) {
6455 pqa = edge_vert_col_inter(P, Q, A);
6456 if (pqa == INTERSECT) {
6460 pqb = edge_vert_col_inter(P, Q, B);
6461 if (pqb == INTERSECT) {
6465 if (abp == SHAREVERTEX || abq == SHAREVERTEX) {
6475 assert((abp == DISJOINT) && (abp == abq && abq == pqa && pqa == pqb));
6481 assert(abp == SHAREVERTEX || abp == DISJOINT);
6489 abq = edge_vert_col_inter(A, B, Q);
6491 assert(abq == SHAREVERTEX || abq == DISJOINT || abq == INTERSECT);
6503 pqa = edge_vert_col_inter(P, Q, A);
6506 assert(pqa != SHAREVERTEX);
6507 assert(pqa == INTERSECT || pqa == DISJOINT);
6516 pqb = edge_vert_col_inter(P, Q, B);
6519 assert(pqb != SHAREVERTEX);
6520 assert(pqb == INTERSECT || pqb == DISJOINT);
6558 enum tetgenmesh::interresult tetgenmesh::tri_vert_cop_inter(REAL* A, REAL* B,
6559 REAL* C, REAL* P, REAL* R)
6565 assert(R != (REAL *) NULL);
6569 s1 = orient3d(A, B, C, R);
6573 sign = s1 < 0.0 ? 1 : -1;
6576 s1 = orient3d(A, B, R, P) * sign;
6581 s2 = orient3d(B, C, R, P) * sign;
6586 s3 = orient3d(C, A, R, P) * sign;
6644 enum tetgenmesh::interresult tetgenmesh::tri_edge_cop_inter(REAL* A, REAL* B,
6645 REAL* C, REAL* P, REAL* Q, REAL* R)
6647 enum interresult abpq, bcpq, capq;
6648 enum interresult abcp, abcq;
6651 abpq = edge_edge_cop_inter(A, B, P, Q, R);
6652 if (abpq == INTERSECT || abpq == SHAREEDGE) {
6655 bcpq = edge_edge_cop_inter(B, C, P, Q, R);
6656 if (bcpq == INTERSECT || bcpq == SHAREEDGE) {
6659 capq = edge_edge_cop_inter(C, A, P, Q, R);
6660 if (capq == INTERSECT || capq == SHAREEDGE) {
6665 abcp = tri_vert_cop_inter(A, B, C, P, R);
6666 if (abcp == INTERSECT) {
6669 abcq = tri_vert_cop_inter(A, B, C, Q, R);
6670 if (abcq == INTERSECT) {
6676 if (abpq == SHAREVERTEX) {
6679 assert(abcp ^ abcq);
6683 if (bcpq == SHAREVERTEX) {
6686 assert(abcp ^ abcq);
6690 if (capq == SHAREVERTEX) {
6693 assert(abcp ^ abcq);
6716 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter_tail(REAL* A, REAL* B,
6717 REAL* C, REAL* P, REAL* Q, REAL s1, REAL s2)
6722 if (s1 * s2 > 0.0) {
6727 if (s1 * s2 < 0.0) {
6731 sign = s1 < 0.0 ? 1 : -1;
6732 s3 = orient3d(A, B, P, Q) * sign;
6737 s4 = orient3d(B, C, P, Q) * sign;
6742 s5 = orient3d(C, A, P, Q) * sign;
6788 if (s1 != 0.0 || s2 != 0.0) {
6795 return tri_vert_cop_inter(A, B, C, P, Q);
6801 return tri_vert_cop_inter(A, B, C, Q, P);
6808 REAL ax, ay, az, bx, by, bz;
6816 N[0] = ay * bz - by * az;
6817 N[1] = az * bx - bz * ax;
6818 N[2] = ax * by - bx * ay;
6821 assert((fabs(N[0]) + fabs(N[1]) + fabs(N[2])) > 0.0);
6831 if (R[0] == A[0] && R[1] == A[1] && R[2] == A[2]) {
6833 for (i = 0; i < 3; i++) {
6835 assert (R[i] == A[i]);
6840 N[i] += (j * macheps);
6842 N[i] -= (j * macheps);
6846 }
while (R[i] == A[i]);
6850 return tri_edge_cop_inter(A, B, C, P, Q, R);
6863 enum tetgenmesh::interresult tetgenmesh::tri_edge_inter(REAL* A, REAL* B,
6864 REAL* C, REAL* P, REAL* Q)
6869 s1 = orient3d(A, B, C, P);
6870 s2 = orient3d(A, B, C, Q);
6872 return tri_edge_inter_tail(A, B, C, P, Q, s1, s2);
6885 enum tetgenmesh::interresult tetgenmesh::tri_tri_inter(REAL* A, REAL* B,
6886 REAL* C, REAL* O, REAL* P, REAL* Q)
6891 s_o = orient3d(A, B, C, O);
6892 s_p = orient3d(A, B, C, P);
6893 s_q = orient3d(A, B, C, Q);
6894 if ((s_o * s_p > 0.0) && (s_o * s_q > 0.0)) {
6899 s_a = orient3d(O, P, Q, A);
6900 s_b = orient3d(O, P, Q, B);
6901 s_c = orient3d(O, P, Q, C);
6902 if ((s_a * s_b > 0.0) && (s_a * s_c > 0.0)) {
6907 enum interresult abcop, abcpq, abcqo;
6910 abcop = tri_edge_inter_tail(A, B, C, O, P, s_o, s_p);
6911 if (abcop == INTERSECT) {
6913 }
else if (abcop == SHAREEDGE) {
6916 abcpq = tri_edge_inter_tail(A, B, C, P, Q, s_p, s_q);
6917 if (abcpq == INTERSECT) {
6919 }
else if (abcpq == SHAREEDGE) {
6922 abcqo = tri_edge_inter_tail(A, B, C, Q, O, s_q, s_o);
6923 if (abcqo == INTERSECT) {
6925 }
else if (abcqo == SHAREEDGE) {
6928 if (shareedge == 3) {
6934 assert(shareedge == 0 || shareedge == 1);
6938 enum interresult opqab, opqbc, opqca;
6940 opqab = tri_edge_inter_tail(O, P, Q, A, B, s_a, s_b);
6941 if (opqab == INTERSECT) {
6944 opqbc = tri_edge_inter_tail(O, P, Q, B, C, s_b, s_c);
6945 if (opqbc == INTERSECT) {
6948 opqca = tri_edge_inter_tail(O, P, Q, C, A, s_c, s_a);
6949 if (opqca == INTERSECT) {
6955 if (abcop == SHAREEDGE) {
6957 assert(abcpq == SHAREVERTEX && abcqo == SHAREVERTEX);
6962 if (abcpq == SHAREEDGE) {
6964 assert(abcop == SHAREVERTEX && abcqo == SHAREVERTEX);
6969 if (abcqo == SHAREEDGE) {
6971 assert(abcop == SHAREVERTEX && abcpq == SHAREVERTEX);
6978 if (abcop == SHAREVERTEX) {
6980 if (abcpq == SHAREVERTEX) {
6983 assert(abcqo != SHAREVERTEX);
6988 assert(abcqo == SHAREVERTEX);
6993 if (abcpq == SHAREVERTEX) {
6996 assert(abcqo == SHAREVERTEX);
7018 REAL tetgenmesh::insphere_sos(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* pe,
7019 int ia,
int ib,
int ic,
int id,
int ie)
7023 det = insphere(pa, pb, pc, pd, pe);
7030 REAL sign, det_c, det_d;
7031 int idx[5], perm, tmp;
7034 p[0] = pa; idx[0] = ia;
7035 p[1] = pb; idx[1] = ib;
7036 p[2] = pc; idx[2] = ic;
7037 p[3] = pd; idx[3] = id;
7038 p[4] = pe; idx[4] = ie;
7043 for (i = 0; i < n - 1; i++) {
7044 for (j = 0; j < n - 1 - i; j++) {
7045 if (idx[j + 1] < idx[j]) {
7047 idx[j] = idx[j + 1];
7057 sign = (perm % 2 == 0) ? 1.0 : -1.0;
7058 det_c = orient3d(p[1], p[2], p[3], p[4]);
7060 return sign * det_c;
7062 det_d = orient3d(p[0], p[2], p[3], p[4]);
7063 return -sign * det_d;
7076 bool tetgenmesh::iscollinear(REAL* A, REAL* B, REAL* C, REAL eps)
7093 Lv = abx * abx + aby * aby + abz * abz;
7095 if (Lv < q)
return true;
7096 Lw = acx * acx + acy * acy + acz * acz;
7098 if (Lw < q)
return true;
7099 dd = abx * acx + aby * acy + abz * acz;
7101 d = (dd * dd) / (Lv * Lw);
7102 if (d > 1.0) d = 1.0;
7120 iscoplanar(REAL* k, REAL* l, REAL* m, REAL* n, REAL vol6, REAL eps)
7125 if (vol6 == 0.0)
return true;
7130 L = sqrt(x * x + y * y + z * z);
7134 L += sqrt(x * x + y * y + z * z);
7138 L += sqrt(x * x + y * y + z * z);
7142 L += sqrt(x * x + y * y + z * z);
7146 L += sqrt(x * x + y * y + z * z);
7150 L += sqrt(x * x + y * y + z * z);
7155 q = fabs(vol6) / (L * L * L);
7172 iscospheric(REAL* k, REAL* l, REAL* m, REAL* n, REAL* o, REAL vol24, REAL eps)
7178 L += distance(l, m);
7179 L += distance(m, k);
7180 L += distance(k, n);
7181 L += distance(l, n);
7182 L += distance(m, n);
7183 L += distance(k, o);
7184 L += distance(l, o);
7185 L += distance(m, o);
7186 L += distance(n, o);
7191 q = fabs(vol24) / (L * L * L * L);
7205 inline REAL tetgenmesh::distance(REAL* p1, REAL* p2)
7207 return sqrt((p2[0] - p1[0]) * (p2[0] - p1[0]) +
7208 (p2[1] - p1[1]) * (p2[1] - p1[1]) +
7209 (p2[2] - p1[2]) * (p2[2] - p1[2]));
7226 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2)
7231 v1[0] = e2[0] - e1[0];
7232 v1[1] = e2[1] - e1[1];
7233 v1[2] = e2[2] - e1[2];
7234 v2[0] = p[0] - e1[0];
7235 v2[1] = p[1] - e1[1];
7236 v2[2] = p[2] - e1[2];
7238 len = sqrt(dot(v1, v1));
7247 return sqrt(dot(v2, v2) - l_p * l_p);
7256 REAL tetgenmesh::shortdistance(REAL* p, REAL* e1, REAL* e2, REAL* e3)
7260 projpt2face(p, e1, e2, e3, prj);
7261 return distance(p, prj);
7277 REAL tetgenmesh::interiorangle(REAL* o, REAL* p1, REAL* p2, REAL* n)
7279 REAL v1[3], v2[3], np[3];
7280 REAL theta, costheta, lenlen;
7281 REAL ori, len1, len2;
7284 v1[0] = p1[0] - o[0];
7285 v1[1] = p1[1] - o[1];
7286 v1[2] = p1[2] - o[2];
7287 v2[0] = p2[0] - o[0];
7288 v2[1] = p2[1] - o[1];
7289 v2[2] = p2[2] - o[2];
7290 len1 = sqrt(dot(v1, v1));
7291 len2 = sqrt(dot(v2, v2));
7292 lenlen = len1 * len2;
7294 assert(lenlen != 0.0);
7296 costheta = dot(v1, v2) / lenlen;
7297 if (costheta > 1.0) {
7299 }
else if (costheta < -1.0) {
7302 theta = acos(costheta);
7305 np[0] = o[0] + n[0];
7306 np[1] = o[1] + n[1];
7307 np[2] = o[2] + n[2];
7309 ori = orient3d(p1, o, np, p2);
7311 theta = 2 * PI - theta;
7324 void tetgenmesh::projpt2edge(REAL* p, REAL* e1, REAL* e2, REAL* prj)
7329 v1[0] = e2[0] - e1[0];
7330 v1[1] = e2[1] - e1[1];
7331 v1[2] = e2[2] - e1[2];
7332 v2[0] = p[0] - e1[0];
7333 v2[1] = p[1] - e1[1];
7334 v2[2] = p[2] - e1[2];
7336 len = sqrt(dot(v1, v1));
7345 prj[0] = e1[0] + l_p * v1[0];
7346 prj[1] = e1[1] + l_p * v1[1];
7347 prj[2] = e1[2] + l_p * v1[2];
7356 void tetgenmesh::projpt2face(REAL* p, REAL* f1, REAL* f2, REAL* f3, REAL* prj)
7358 REAL fnormal[3], v1[3];
7362 facenormal(f1, f2, f3, fnormal, &len);
7370 v1[0] = p[0] - f1[0];
7371 v1[1] = p[1] - f1[1];
7372 v1[2] = p[2] - f1[2];
7374 dist = dot(fnormal, v1);
7377 prj[0] = p[0] - dist * fnormal[0];
7378 prj[1] = p[1] - dist * fnormal[1];
7379 prj[2] = p[2] - dist * fnormal[2];
7393 void tetgenmesh::facenormal(REAL* pa, REAL* pb, REAL* pc, REAL* n, REAL* nlen)
7397 v1[0] = pb[0] - pa[0];
7398 v1[1] = pb[1] - pa[1];
7399 v1[2] = pb[2] - pa[2];
7400 v2[0] = pc[0] - pa[0];
7401 v2[1] = pc[1] - pa[1];
7402 v2[2] = pc[2] - pa[2];
7405 if (nlen != (REAL *) NULL) {
7406 *nlen = sqrt(dot(n, n));
7426 void tetgenmesh::edgeorthonormal(REAL* e1, REAL* e2, REAL* op, REAL* n)
7428 REAL v1[3], v2[3], fn[3];
7432 v1[0] = e2[0] - e1[0];
7433 v1[1] = e2[1] - e1[1];
7434 v1[2] = e2[2] - e1[2];
7436 v2[0] = op[0] - e1[0];
7437 v2[1] = op[1] - e1[1];
7438 v2[2] = op[2] - e1[2];
7444 len = sqrt(dot(n, n));
7461 REAL tetgenmesh::facedihedral(REAL* pa, REAL* pb, REAL* pc1, REAL* pc2)
7468 facenormal(pa, pb, pc1, n1, &n1len);
7469 facenormal(pa, pb, pc2, n2, &n2len);
7470 costheta = dot(n1, n2) / (n1len * n2len);
7472 if (costheta > 1.0) {
7474 }
else if (costheta < -1.0) {
7477 theta = acos(costheta);
7478 ori = orient3d(pa, pb, pc1, pc2);
7480 theta = 2 * PI - theta;
7497 void tetgenmesh::tetalldihedral(point pa, point pb, point pc, point pd,
7498 REAL* cosdd, REAL* cosmaxd, REAL* cosmind)
7500 REAL N[4][3], cosd, len;
7507 tetallnormal(pa, pb, pc, pd, N, NULL);
7509 for (i = 0; i < 4; i++) {
7510 len = sqrt(dot(N[i], N[i]));
7512 for (j = 0; j < 3; j++) N[i][j] /= len;
7516 for (i = 0; i < 6; i++) {
7518 case 0: f1 = 2; f2 = 3;
break;
7519 case 1: f1 = 0; f2 = 3;
break;
7520 case 2: f1 = 1; f2 = 3;
break;
7521 case 3: f1 = 1; f2 = 2;
break;
7522 case 4: f1 = 2; f2 = 0;
break;
7523 case 5: f1 = 0; f2 = 1;
break;
7525 cosd = -dot(N[f1], N[f2]);
7526 if (cosdd) cosdd[i] = cosd;
7528 if (cosmaxd) *cosmaxd = cosd;
7529 if (cosmind) *cosmind = cosd;
7531 if (cosmaxd) *cosmaxd = cosd < *cosmaxd ? cosd : *cosmaxd;
7532 if (cosmind) *cosmind = cosd > *cosmind ? cosd : *cosmind;
7546 void tetgenmesh::tetallnormal(point pa, point pb, point pc, point pd,
7547 REAL N[4][3], REAL* volume)
7549 REAL A[4][4], rhs[4], D;
7554 for (i = 0; i < 3; i++) A[0][i] = pa[i] - pd[i];
7555 for (i = 0; i < 3; i++) A[1][i] = pb[i] - pd[i];
7556 for (i = 0; i < 3; i++) A[2][i] = pc[i] - pd[i];
7558 lu_decmp(A, 3, indx, &D, 0);
7559 if (volume != NULL) {
7561 *volume = fabs((A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2])) / 6.0;
7563 for (j = 0; j < 3; j++) {
7564 for (i = 0; i < 3; i++) rhs[i] = 0.0;
7566 lu_solve(A, 3, indx, rhs, 0);
7567 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
7570 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
7582 REAL tetgenmesh::tetaspectratio(point pa, point pb, point pc, point pd)
7584 REAL vda[3], vdb[3], vdc[3];
7585 REAL N[4][3], A[4][4], rhs[4], D;
7586 REAL H[4], volume, radius2, minheightinv;
7591 for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
7592 for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
7593 for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
7595 lu_decmp(A, 3, indx, &D, 0);
7597 volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
7599 if (volume == 0.0)
return 1.0e+200;
7602 rhs[0] = 0.5 * dot(vda, vda);
7603 rhs[1] = 0.5 * dot(vdb, vdb);
7604 rhs[2] = 0.5 * dot(vdc, vdc);
7605 lu_solve(A, 3, indx, rhs, 0);
7609 radius2 = dot(rhs, rhs);
7612 for (j = 0; j < 3; j++) {
7613 for (i = 0; i < 3; i++) rhs[i] = 0.0;
7615 lu_solve(A, 3, indx, rhs, 0);
7616 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
7619 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
7621 for (i = 0; i < 4; i++) {
7623 H[i] = sqrt(dot(N[i], N[i]));
7631 minheightinv = H[0];
7632 for (i = 1; i < 3; i++) {
7633 if (H[i] > minheightinv) minheightinv = H[i];
7636 return sqrt(radius2) * minheightinv;
7655 circumsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd, REAL* cent, REAL* radius)
7657 REAL A[4][4], rhs[4], D;
7661 A[0][0] = pb[0] - pa[0];
7662 A[0][1] = pb[1] - pa[1];
7663 A[0][2] = pb[2] - pa[2];
7664 A[1][0] = pc[0] - pa[0];
7665 A[1][1] = pc[1] - pa[1];
7666 A[1][2] = pc[2] - pa[2];
7668 A[2][0] = pd[0] - pa[0];
7669 A[2][1] = pd[1] - pa[1];
7670 A[2][2] = pd[2] - pa[2];
7672 cross(A[0], A[1], A[2]);
7676 rhs[0] = 0.5 * dot(A[0], A[0]);
7677 rhs[1] = 0.5 * dot(A[1], A[1]);
7679 rhs[2] = 0.5 * dot(A[2], A[2]);
7686 if (!lu_decmp(A, 3, indx, &D, 0)) {
7687 if (radius != (REAL *) NULL) *radius = 0.0;
7690 lu_solve(A, 3, indx, rhs, 0);
7691 if (cent != (REAL *) NULL) {
7692 cent[0] = pa[0] + rhs[0];
7693 cent[1] = pa[1] + rhs[1];
7694 cent[2] = pa[2] + rhs[2];
7696 if (radius != (REAL *) NULL) {
7697 *radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
7725 void tetgenmesh::inscribedsphere(REAL* pa, REAL* pb, REAL* pc, REAL* pd,
7726 REAL* cent, REAL* radius)
7733 tetallnormal(pa, pb, pc, pd, N, NULL);
7734 for (i = 0; i < 4; i++) {
7736 H[i] = sqrt(dot(N[i], N[i]));
7739 rd = 1.0 / (H[0] + H[1] + H[2] + H[3]);
7740 if (radius != (REAL*) NULL) *radius = rd;
7741 if (cent != (REAL*) NULL) {
7743 cent[0] = rd * (H[0] * pa[0] + H[1] * pb[0] + H[2] * pc[0] + H[3] * pd[0]);
7744 cent[1] = rd * (H[0] * pa[1] + H[1] * pb[1] + H[2] * pc[1] + H[3] * pd[1]);
7745 cent[2] = rd * (H[0] * pa[2] + H[1] * pb[2] + H[2] * pc[2] + H[3] * pd[2]);
7772 void tetgenmesh::rotatepoint(REAL* p, REAL rotangle, REAL* p1, REAL* p2)
7774 REAL T[4][4], pp0[4], p0t[4], p2t[4];
7775 REAL roty, rotx, alphaR, projlen;
7778 initm44(1, 0, 0, -p1[0],
7782 pp0[0] = p[0]; pp0[1] = p[1]; pp0[2] = p[2]; pp0[3] = 1.0;
7784 pp0[0] = p2[0]; pp0[1] = p2[1]; pp0[2] = p2[2]; pp0[3] = 1.0;
7790 projlen = sqrt(dx * dx + dz * dz);
7791 if (projlen <= (b->epsilon * 1e-2) * longest) {
7794 roty = acos(dz / projlen);
7800 initm44(cos(-roty), 0, sin(-roty), 0,
7802 -sin(-roty), 0, cos(-roty), 0,
7804 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
7806 pp0[0] = p2t[0]; pp0[1] = p2t[1]; pp0[2] = p2t[2]; pp0[3] = 1.0;
7812 projlen = sqrt(dy * dy + dz * dz);
7813 if (projlen <= (b->epsilon * 1e-2) * longest) {
7816 rotx = acos(dz / projlen);
7823 0, cos(rotx), -sin(rotx), 0,
7824 0, sin(rotx), cos(rotx), 0,
7826 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
7832 initm44(cos(alphaR), -sin(alphaR), 0, 0,
7833 sin(alphaR), cos(alphaR), 0, 0,
7836 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
7840 0, cos(-rotx), -sin(-rotx), 0,
7841 0, sin(-rotx), cos(-rotx), 0,
7843 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
7846 initm44(cos(roty), 0, sin(roty), 0,
7848 -sin(roty), 0, cos(roty), 0,
7850 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
7853 initm44(1, 0, 0, p1[0],
7857 pp0[0] = p0t[0]; pp0[1] = p0t[1]; pp0[2] = p0t[2]; pp0[3] = 1.0;
7878 void tetgenmesh::spherelineint(REAL* p1, REAL* p2, REAL* C, REAL R, REAL p[7])
7883 REAL a, b, c, mu, i ;
7885 x1 = p1[0]; y1 = p1[1]; z1 = p1[2];
7886 x2 = p2[0]; y2 = p2[1]; z2 = p2[2];
7887 x3 = C[0]; y3 = C[1]; z3 = C[2];
7890 a = (x2 - x1) * (x2 - x1)
7891 + (y2 - y1) * (y2 - y1)
7892 + (z2 - z1) * (z2 - z1);
7893 b = 2 * ( (x2 - x1) * (x1 - x3)
7894 + (y2 - y1) * (y1 - y3)
7895 + (z2 - z1) * (z1 - z3) ) ;
7896 c = (x3 * x3) + (y3 * y3) + (z3 * z3)
7897 + (x1 * x1) + (y1 * y1) + (z1 * z1)
7898 - 2 * (x3 * x1 + y3 * y1 + z3 * z1) - (r * r) ;
7899 i = b * b - 4 * a * c ;
7904 }
else if (i == 0.0) {
7908 p[1] = x1 + mu * (x2 - x1);
7909 p[2] = y1 + mu * (y2 - y1);
7910 p[3] = z1 + mu * (z2 - z1);
7915 mu = (-b + sqrt((b * b) - 4 * a * c)) / (2 * a);
7916 p[1] = x1 + mu * (x2 - x1);
7917 p[2] = y1 + mu * (y2 - y1);
7918 p[3] = z1 + mu * (z2 - z1);
7920 mu = (-b - sqrt((b * b) - 4 * a * c)) / (2 * a);
7921 p[4] = x1 + mu * (x2 - x1);
7922 p[5] = y1 + mu * (y2 - y1);
7923 p[6] = z1 + mu * (z2 - z1);
7947 void tetgenmesh::linelineint(REAL *p1,REAL *p2, REAL *p3, REAL *p4, REAL p[7])
7949 REAL p13[3], p43[3], p21[3];
7950 REAL d1343, d4321, d1321, d4343, d2121;
7954 p13[0] = p1[0] - p3[0];
7955 p13[1] = p1[1] - p3[1];
7956 p13[2] = p1[2] - p3[2];
7957 p43[0] = p4[0] - p3[0];
7958 p43[1] = p4[1] - p3[1];
7959 p43[2] = p4[2] - p3[2];
7960 if (p43[0] == 0.0 && p43[1] == 0.0 && p43[2] == 0.0) {
7965 p21[0] = p2[0] - p1[0];
7966 p21[1] = p2[1] - p1[1];
7967 p21[2] = p2[2] - p1[2];
7968 if (p21[0] == 0.0 && p21[1] == 0.0 && p21[2] == 0.0) {
7973 d1343 = p13[0] * p43[0] + p13[1] * p43[1] + p13[2] * p43[2];
7974 d4321 = p43[0] * p21[0] + p43[1] * p21[1] + p43[2] * p21[2];
7975 d1321 = p13[0] * p21[0] + p13[1] * p21[1] + p13[2] * p21[2];
7976 d4343 = p43[0] * p43[0] + p43[1] * p43[1] + p43[2] * p43[2];
7977 d2121 = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
7979 denom = d2121 * d4343 - d4321 * d4321;
7984 numer = d1343 * d4321 - d1321 * d4343;
7985 mua = numer / denom;
7986 mub = (d1343 + d4321 * mua) / d4343;
7989 p[1] = p1[0] + mua * p21[0];
7990 p[2] = p1[1] + mua * p21[1];
7991 p[3] = p1[2] + mua * p21[2];
7992 p[4] = p3[0] + mub * p43[0];
7993 p[5] = p3[1] + mub * p43[1];
7994 p[6] = p3[2] + mub * p43[2];
8020 void tetgenmesh::planelineint(REAL* pa, REAL* pb, REAL* pc, REAL* e1, REAL* e2,
8023 REAL n[3], det, det1;
8026 facenormal(pa, pb, pc, n, NULL);
8028 det = n[0] * (e2[0] - e1[0]) + n[1] * (e2[1] - e1[1])
8029 + n[2] * (e2[2] - e1[2]);
8032 det1 = n[0] * (pa[0] - e1[0]) + n[1] * (pa[1] - e1[1])
8033 + n[2] * (pa[2] - e1[2]);
8035 ip[0] = e1[0] + *u * (e2[0] - e1[0]);
8036 ip[1] = e1[1] + *u * (e2[1] - e1[1]);
8037 ip[2] = e1[2] + *u * (e2[2] - e1[2]);
8067 void tetgenmesh::dummyinit(
int tetwords,
int shwords)
8069 unsigned long alignptr;
8072 dummytetbase = (tetrahedron *)
new char[tetwords *
sizeof(tetrahedron)
8073 + tetrahedrons->alignbytes];
8075 alignptr = (
unsigned long) dummytetbase;
8076 dummytet = (tetrahedron *)
8077 (alignptr + (
unsigned long) tetrahedrons->alignbytes
8078 - (alignptr % (
unsigned long) tetrahedrons->alignbytes));
8083 dummytet[0] = (tetrahedron) dummytet;
8084 dummytet[1] = (tetrahedron) dummytet;
8085 dummytet[2] = (tetrahedron) dummytet;
8086 dummytet[3] = (tetrahedron) dummytet;
8088 dummytet[4] = (tetrahedron) NULL;
8089 dummytet[5] = (tetrahedron) NULL;
8090 dummytet[6] = (tetrahedron) NULL;
8091 dummytet[7] = (tetrahedron) NULL;
8093 if (b->useshelles) {
8097 dummyshbase = (shellface *)
new char[shwords *
sizeof(shellface)
8098 + subfaces->alignbytes];
8100 alignptr = (
unsigned long) dummyshbase;
8101 dummysh = (shellface *)
8102 (alignptr + (
unsigned long) subfaces->alignbytes
8103 - (alignptr % (
unsigned long) subfaces->alignbytes));
8108 dummysh[0] = (shellface) dummysh;
8109 dummysh[1] = (shellface) dummysh;
8110 dummysh[2] = (shellface) dummysh;
8112 dummysh[3] = (shellface) NULL;
8113 dummysh[4] = (shellface) NULL;
8114 dummysh[5] = (shellface) NULL;
8116 dummysh[6] = (shellface) dummytet;
8117 dummysh[7] = (shellface) dummytet;
8119 dummysh[8] = (shellface) dummysh;
8120 dummysh[9] = (shellface) dummysh;
8121 dummysh[10] = (shellface) dummysh;
8123 dummysh[11] = (shellface) NULL;
8126 dummytet[8 ] = (tetrahedron) dummysh;
8127 dummytet[9 ] = (tetrahedron) dummysh;
8128 dummytet[10] = (tetrahedron) dummysh;
8129 dummytet[11] = (tetrahedron) dummysh;
8151 void tetgenmesh::initializepools()
8153 enum wordtype wtype;
8154 int pointsize, elesize, shsize;
8157 if ((b->plc || b->refine) && (in->pbcgrouplist != NULL)) {
8161 if (in->segmentconstraintlist || in->facetconstraintlist) {
8167 pointmtrindex = 3 + in->numberofpointattributes;
8171 if (bgm != (tetgenmesh *) NULL) {
8173 sizeoftensor = (bgm->in != (tetgenio *) NULL) ?
8174 bgm->in->numberofpointmtrs : in->numberofpointmtrs;
8177 sizeoftensor = in->numberofpointmtrs;
8180 sizeoftensor = (sizeoftensor > 0) ? sizeoftensor : 1;
8183 sizeoftensor = b->quality ? 1 : 0;
8188 point2simindex = ((pointmtrindex + sizeoftensor) *
sizeof(REAL)
8189 +
sizeof(tetrahedron) - 1) /
sizeof(tetrahedron);
8190 if (b->plc || b->refine) {
8197 pointsize = (point2simindex + 4) *
sizeof(tetrahedron);
8199 pointsize = (point2simindex + 3) *
sizeof(tetrahedron);
8202 point2pbcptindex = (pointsize +
sizeof(tetrahedron) - 1)
8203 /
sizeof(tetrahedron);
8207 pointsize = (point2pbcptindex + 1) *
sizeof(tetrahedron);
8210 pointsize = point2simindex *
sizeof(tetrahedron);
8214 pointmarkindex = (pointsize +
sizeof(int) - 1) /
sizeof(int);
8218 pointsize = (pointmarkindex + 2) *
sizeof(
int);
8220 wtype = (
sizeof(REAL) >=
sizeof(tetrahedron)) ? FLOATINGPOINT : POINTER;
8222 points =
new memorypool(pointsize, VERPERBLOCK, wtype, 0);
8227 elesize = (8 + b->useshelles * 6) *
sizeof(tetrahedron);
8229 if (b->voroout && (b->useshelles == 0)) {
8230 elesize = (8 + 4) *
sizeof(tetrahedron);
8234 elemattribindex = (elesize +
sizeof(REAL) - 1) /
sizeof(REAL);
8238 volumeboundindex = elemattribindex + in->numberoftetrahedronattributes
8239 + (b->regionattrib > 0);
8243 elesize = (volumeboundindex + 1) *
sizeof(REAL);
8244 }
else if (in->numberoftetrahedronattributes + b->regionattrib > 0) {
8245 elesize = volumeboundindex *
sizeof(REAL);
8249 elemmarkerindex = (elesize +
sizeof(int) - 1) /
sizeof(int);
8250 if (b->neighout || b->voroout) {
8251 elesize = (elemmarkerindex + 1) *
sizeof(
int);
8255 highorderindex = (elesize +
sizeof(tetrahedron) - 1) /
sizeof(tetrahedron);
8256 if (b->order == 2) {
8257 elesize = (highorderindex + 1) *
sizeof(tetrahedron);
8260 tetrahedrons =
new memorypool(elesize, ELEPERBLOCK, POINTER, 8);
8262 if (b->useshelles) {
8266 shsize = 12 *
sizeof(shellface);
8269 areaboundindex = (shsize +
sizeof(REAL) - 1) /
sizeof(REAL);
8272 if (b->quality && varconstraint) {
8273 shsize = (areaboundindex + 1) *
sizeof(REAL);
8275 shsize = areaboundindex *
sizeof(REAL);
8279 shmarkindex = (shsize +
sizeof(int) - 1) /
sizeof(int);
8282 shsize = (shmarkindex + 2 + checkpbcs) *
sizeof(
int);
8286 subfaces =
new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
8289 subsegs =
new memorypool(shsize, SUBPERBLOCK, POINTER, 8);
8291 dummyinit(tetrahedrons->itemwords, subfaces->itemwords);
8294 dummyinit(tetrahedrons->itemwords, 0);
8304 void tetgenmesh::tetrahedrondealloc(tetrahedron *dyingtetrahedron)
8308 dyingtetrahedron[4] = (tetrahedron) NULL;
8309 dyingtetrahedron[5] = (tetrahedron) NULL;
8310 dyingtetrahedron[6] = (tetrahedron) NULL;
8311 dyingtetrahedron[7] = (tetrahedron) NULL;
8312 tetrahedrons->dealloc((
void *) dyingtetrahedron);
8321 tetgenmesh::tetrahedron* tetgenmesh::tetrahedrontraverse()
8323 tetrahedron *newtetrahedron;
8326 newtetrahedron = (tetrahedron *) tetrahedrons->traverse();
8327 if (newtetrahedron == (tetrahedron *) NULL) {
8328 return (tetrahedron *) NULL;
8330 }
while (newtetrahedron[7] == (tetrahedron) NULL);
8331 return newtetrahedron;
8341 void tetgenmesh::shellfacedealloc(
memorypool *pool, shellface *dyingsh)
8345 dyingsh[3] = (shellface) NULL;
8346 dyingsh[4] = (shellface) NULL;
8347 dyingsh[5] = (shellface) NULL;
8348 pool->dealloc((
void *) dyingsh);
8358 tetgenmesh::shellface* tetgenmesh::shellfacetraverse(
memorypool *pool)
8360 shellface *newshellface;
8363 newshellface = (shellface *) pool->traverse();
8364 if (newshellface == (shellface *) NULL) {
8365 return (shellface *) NULL;
8367 }
while (newshellface[3] == (shellface) NULL);
8368 return newshellface;
8377 void tetgenmesh::badfacedealloc(
memorypool *pool, badface *dying)
8381 dying->forg = (point) NULL;
8382 pool->dealloc((
void *) dying);
8391 tetgenmesh::badface* tetgenmesh::badfacetraverse(
memorypool *pool)
8396 newsh = (badface *) pool->traverse();
8397 if (newsh == (badface *) NULL) {
8398 return (badface *) NULL;
8400 }
while (newsh->forg == (point) NULL);
8410 void tetgenmesh::pointdealloc(point dyingpoint)
8414 setpointtype(dyingpoint, DEADVERTEX);
8415 points->dealloc((
void *) dyingpoint);
8424 tetgenmesh::point tetgenmesh::pointtraverse()
8429 newpoint = (point) points->traverse();
8430 if (newpoint == (point) NULL) {
8431 return (point) NULL;
8433 }
while (pointtype(newpoint) == DEADVERTEX);
8443 void tetgenmesh::maketetrahedron(triface *newtet)
8445 newtet->tet = (tetrahedron *) tetrahedrons->alloc();
8447 newtet->tet[0] = (tetrahedron) dummytet;
8448 newtet->tet[1] = (tetrahedron) dummytet;
8449 newtet->tet[2] = (tetrahedron) dummytet;
8450 newtet->tet[3] = (tetrahedron) dummytet;
8452 newtet->tet[4] = (tetrahedron) NULL;
8453 newtet->tet[5] = (tetrahedron) NULL;
8454 newtet->tet[6] = (tetrahedron) NULL;
8455 newtet->tet[7] = (tetrahedron) NULL;
8457 if (b->useshelles) {
8458 newtet->tet[8 ] = (tetrahedron) dummysh;
8459 newtet->tet[9 ] = (tetrahedron) dummysh;
8460 newtet->tet[10] = (tetrahedron) dummysh;
8461 newtet->tet[11] = (tetrahedron) dummysh;
8462 newtet->tet[12] = (tetrahedron) dummysh;
8463 newtet->tet[13] = (tetrahedron) dummysh;
8465 for (
int i = 0; i < in->numberoftetrahedronattributes; i++) {
8466 setelemattribute(newtet->tet, i, 0.0);
8469 setvolumebound(newtet->tet, -1.0);
8483 void tetgenmesh::makeshellface(
memorypool *pool, face *newface)
8485 newface->sh = (shellface *) pool->alloc();
8487 newface->sh[0] = (shellface) dummysh;
8488 newface->sh[1] = (shellface) dummysh;
8489 newface->sh[2] = (shellface) dummysh;
8491 newface->sh[3] = (shellface) NULL;
8492 newface->sh[4] = (shellface) NULL;
8493 newface->sh[5] = (shellface) NULL;
8495 newface->sh[6] = (shellface) dummytet;
8496 newface->sh[7] = (shellface) dummytet;
8499 newface->sh [8] = (shellface) dummysh;
8500 newface->sh [9] = (shellface) dummysh;
8501 newface->sh[10] = (shellface) dummysh;
8503 newface->sh[11] = (shellface) NULL;
8504 if (b->quality && varconstraint) {
8506 setareabound(*newface, 0.0);
8509 setshellmark(*newface, 0);
8511 setshelltype(*newface, NSHARP);
8514 setshellpbcgroup(*newface, -1);
8526 void tetgenmesh::makepoint(point* pnewpoint)
8530 *pnewpoint = (point) points->alloc();
8532 (*pnewpoint)[0] = 0.0;
8533 (*pnewpoint)[1] = 0.0;
8534 (*pnewpoint)[2] = 0.0;
8536 for (i = 0; i < in->numberofpointattributes; i++) {
8537 (*pnewpoint)[3 + i] = 0.0;
8540 for (i = 0; i < sizeoftensor; i++) {
8541 (*pnewpoint)[pointmtrindex + i] = 0.0;
8543 if (b->plc || b->refine) {
8545 setpoint2tet(*pnewpoint, NULL);
8546 setpoint2sh(*pnewpoint, NULL);
8547 setpoint2ppt(*pnewpoint, NULL);
8549 setpoint2bgmtet(*pnewpoint, NULL);
8553 setpoint2pbcpt(*pnewpoint, NULL);
8557 ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
8558 setpointmark(*pnewpoint, ptmark);
8560 setpointtype(*pnewpoint, UNUSEDVERTEX);
8577 unsigned long tetgenmesh::randomnation(
unsigned int choices)
8579 unsigned long newrandom;
8581 if (choices >= 714025l) {
8582 newrandom = (randomseed * 1366l + 150889l) % 714025l;
8583 randomseed = (newrandom * 1366l + 150889l) % 714025l;
8584 newrandom = newrandom * (choices / 714025l) + randomseed;
8585 if (newrandom >= choices) {
8586 return newrandom - choices;
8591 randomseed = (randomseed * 1366l + 150889l) % 714025l;
8592 return randomseed % choices;
8605 REAL tetgenmesh::distance2(tetrahedron* tetptr, point p)
8607 point p1, p2, p3, p4;
8610 p1 = (point) tetptr[4];
8611 p2 = (point) tetptr[5];
8612 p3 = (point) tetptr[6];
8613 p4 = (point) tetptr[7];
8615 dx = p[0] - 0.25 * (p1[0] + p2[0] + p3[0] + p4[0]);
8616 dy = p[1] - 0.25 * (p1[1] + p2[1] + p3[1] + p4[1]);
8617 dz = p[2] - 0.25 * (p1[2] + p2[2] + p3[2] + p4[2]);
8619 return dx * dx + dy * dy + dz * dz;
8652 enum tetgenmesh::locateresult tetgenmesh::preciselocate(point searchpt,
8653 triface* searchtet,
long maxtetnumber)
8655 triface backtracetet;
8656 triface walkthroface;
8657 point forg, fdest, fapex, toppo;
8658 REAL ori1, ori2, ori3, ori4;
8662 if (isdead(searchtet)) searchtet->tet = dummytet;
8663 if (searchtet->tet == dummytet) {
8665 symself(*searchtet);
8671 if (isdead(searchtet)) {
8672 printf(
"Warning: Point location failed.\n");
8679 for (searchtet->loc = 0; searchtet->loc < 4; searchtet->loc++) {
8680 forg = org(*searchtet);
8681 fdest = dest(*searchtet);
8682 fapex = apex(*searchtet);
8683 ori1 = orient3d(forg, fdest, fapex, searchpt);
8684 if (ori1 < 0.0)
break;
8687 assert(searchtet->loc < 4);
8692 while ((maxtetnumber > 0l) && (tetnumber <= maxtetnumber)) {
8694 if (searchtet->tet == dummytet) {
8695 *searchtet = backtracetet;
8699 walkthroface.tet = (tetrahedron *) NULL;
8703 toppo = oppo(*searchtet);
8706 for (side = 0; side < 3; side++) {
8707 forg = org(*searchtet);
8708 fdest = dest(*searchtet);
8709 ori2 = orient3d(forg, fdest, toppo, searchpt);
8713 fapex = apex(*searchtet);
8714 ori3 = orient3d(fdest, fapex, toppo, searchpt);
8717 enextself(*searchtet);
8718 fnext(*searchtet, walkthroface);
8721 ori4 = orient3d(fapex, forg, toppo, searchpt);
8724 enext2self(*searchtet);
8725 fnext(*searchtet, walkthroface);
8738 fnextself(*searchtet);
8742 enext2self(*searchtet);
8746 enextself(*searchtet);
8752 enext2self(*searchtet);
8757 }
else if (ori2 < 0.0) {
8759 fnext(*searchtet, walkthroface);
8763 enextself(*searchtet);
8767 return INTETRAHEDRON;
8771 assert(walkthroface.tet != (tetrahedron *) NULL);
8776 backtracetet = walkthroface;
8777 sym(walkthroface, *searchtet);
8809 enum tetgenmesh::locateresult tetgenmesh::locate(point searchpt,
8812 tetrahedron *firsttet, *tetptr;
8814 long sampleblocks, samplesperblock, samplenum;
8815 long tetblocks, i, j;
8816 unsigned long alignptr;
8817 REAL searchdist, dist;
8820 if (isdead(searchtet)) {
8821 searchtet->tet = dummytet;
8823 if (searchtet->tet == dummytet) {
8826 symself(*searchtet);
8831 if (isdead(searchtet)) {
8832 printf(
"Warning: Point location failed.\n");
8837 searchdist = distance2(searchtet->tet, searchpt);
8841 if (!isdead(&recenttet) && (recenttet.tet != searchtet->tet)) {
8842 dist = distance2(recenttet.tet, searchpt);
8843 if (dist < searchdist) {
8844 *searchtet = recenttet;
8853 while (SAMPLEFACTOR * samples * samples * samples * samples <
8854 tetrahedrons->items) {
8858 tetblocks = (tetrahedrons->maxitems + ELEPERBLOCK - 1) / ELEPERBLOCK;
8860 samplesperblock = 1 + (samples / tetblocks);
8861 sampleblocks = samples / samplesperblock;
8862 sampleblock = tetrahedrons->firstblock;
8863 for (i = 0; i < sampleblocks; i++) {
8864 alignptr = (
unsigned long) (sampleblock + 1);
8865 firsttet = (tetrahedron *)
8866 (alignptr + (
unsigned long) tetrahedrons->alignbytes
8867 - (alignptr % (
unsigned long) tetrahedrons->alignbytes));
8868 for (j = 0; j < samplesperblock; j++) {
8869 if (i == tetblocks - 1) {
8871 samplenum = randomnation((
int)
8872 (tetrahedrons->maxitems - (i * ELEPERBLOCK)));
8874 samplenum = randomnation(ELEPERBLOCK);
8876 tetptr = (tetrahedron *)
8877 (firsttet + (samplenum * tetrahedrons->itemwords));
8878 if (tetptr[4] != (tetrahedron) NULL) {
8879 dist = distance2(tetptr, searchpt);
8880 if (dist < searchdist) {
8881 searchtet->tet = tetptr;
8886 sampleblock = (
void **) *sampleblock;
8890 return preciselocate(searchpt, searchtet, tetrahedrons->items);
8916 enum tetgenmesh::locateresult tetgenmesh::adjustlocate(point searchpt,
8917 triface* searchtet,
enum locateresult precise, REAL epspp)
8919 point torg, tdest, tapex, toppo;
8920 REAL s1, s2, s3, s4;
8927 adjustedgering(*searchtet, CCW);
8928 torg = org(*searchtet);
8929 tdest = dest(*searchtet);
8930 tapex = apex(*searchtet);
8931 toppo = oppo(*searchtet);
8945 s2 = orient3d(torg, tdest, toppo, searchpt);
8948 s1 = orient3d(tdest, torg, tapex, searchpt);
8949 s2 = orient3d(torg, tdest, toppo, searchpt);
8953 if (iscoplanar(tdest, torg, tapex, searchpt, s1, epspp)) {
8962 if (iscoplanar(torg, tdest, toppo, searchpt, s2, epspp)) {
8967 fnextself(*searchtet);
8971 s3 = orient3d(tdest, tapex, toppo, searchpt);
8973 if (iscoplanar(tdest, tapex, toppo, searchpt, s3, epspp)) {
8978 enextfnextself(*searchtet);
8982 s4 = orient3d(tapex, torg, toppo, searchpt);
8984 if (iscoplanar(tapex, torg, toppo, searchpt, s4, epspp)) {
8989 enext2fnextself(*searchtet);
8998 enextself(*searchtet);
9011 enext2self(*searchtet);
9015 enextself(*searchtet);
9020 enext2self(*searchtet);
9027 fnextself(*searchtet);
9031 enext2self(*searchtet);
9035 enextself(*searchtet);
9040 enext2self(*searchtet);
9047 enextfnextself(*searchtet);
9050 enextself(*searchtet);
9057 enext2fnextself(*searchtet);
9063 return INTETRAHEDRON;
9072 enum tetgenmesh::locateresult tetgenmesh::hullwalk(point searchpt,
9076 triface travtet, neightet;
9078 enum locateresult loc;
9082 travtetlist =
new list(
sizeof(triface), NULL, 256);
9085 travtetlist->append(&travtet);
9088 for (i = 0; i < travtetlist->len(); i++) {
9089 travtet = * (triface *)(* travtetlist)[i];
9093 for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
9097 ori = orient3d(pa, pb, pc, searchpt);
9098 if (ori > 0.0)
break;
9101 if (travtet.loc == 4) {
9102 hulltet->tet = travtet.tet;
9103 loc = adjustlocate(searchpt, hulltet, INTETRAHEDRON, b->epsilon);
9104 assert(loc != OUTSIDE);
9107 sym(travtet, neightet);
9108 if (neightet.tet == dummytet) {
9110 loc = adjustlocate(searchpt, &travtet, OUTSIDE, b->epsilon);
9112 if (loc == OUTSIDE) {
9114 for (travtet.loc = 0; travtet.loc < 4; travtet.loc++) {
9115 sym(travtet, neightet);
9116 if ((neightet.tet != dummytet) && !infected(neightet)) {
9119 travtetlist->append(&neightet);
9124 if (loc != OUTSIDE)
break;
9128 for (i = 0; i < travtetlist->len(); i++) {
9129 travtet = * (triface *)(* travtetlist)[i];
9161 enum tetgenmesh::locateresult tetgenmesh::locatesub(point searchpt,
9162 face* searchsh,
int stopatseg, REAL epspp)
9164 face backtracksh, spinsh, checkedge;
9165 point forg, fdest, fapex;
9166 REAL orgori, destori;
9170 if (searchsh->sh == dummysh) {
9171 searchsh->shver = 0;
9172 spivotself(*searchsh);
9174 assert(searchsh->sh != dummysh);
9178 adjustedgering(*searchsh, CCW);
9179 forg = sorg(*searchsh);
9180 fdest = sdest(*searchsh);
9181 fapex = sapex(*searchsh);
9182 ori = orient3d(forg, fdest, fapex, abovepoint);
9183 sign = ori > 0.0 ? -1 : 1;
9188 for (i = 0; i < 3; i++) {
9189 forg = sorg(*searchsh);
9190 fdest = sdest(*searchsh);
9191 ori = orient3d(forg, fdest, abovepoint, searchpt) * sign;
9192 if (ori > 0.0)
break;
9193 senextself(*searchsh);
9200 fapex = sapex(*searchsh);
9202 if (fapex[0] == searchpt[0] && fapex[1] == searchpt[1] &&
9203 fapex[2] == searchpt[2]) {
9204 senext2self(*searchsh);
9209 destori = orient3d(forg, fapex, abovepoint, searchpt) * sign;
9211 if (iscoplanar(forg, fapex, abovepoint, searchpt, destori, epspp)) {
9217 orgori = orient3d(fapex, fdest, abovepoint, searchpt) * sign;
9219 if (iscoplanar(fapex, fdest, abovepoint, searchpt, orgori, epspp)) {
9223 if (destori > 0.0) {
9230 if (destori == 0.0) {
9231 senext2self(*searchsh);
9234 if (orgori == 0.0) {
9235 senextself(*searchsh);
9244 senext2(*searchsh, backtracksh);
9247 senext(*searchsh, backtracksh);
9251 sspivot(backtracksh, checkedge);
9252 if (checkedge.sh != dummysh) {
9255 *searchsh = backtracksh;
9260 spinsh = backtracksh;
9263 if (spinsh.sh == backtracksh.sh) {
9268 if (shellmark(spinsh) == shellmark(backtracksh)) {
9274 ori = orient3d(forg, fdest, sapex(backtracksh), sapex(spinsh));
9275 if (iscoplanar(forg, fdest, sapex(backtracksh), sapex(spinsh), ori,
9281 }
while (spinsh.sh != backtracksh.sh);
9283 spivot(backtracksh, *searchsh);
9286 if ((searchsh->sh == dummysh) || (searchsh->sh == backtracksh.sh)) {
9288 *searchsh = backtracksh;
9292 if (sorg(*searchsh) != forg) sesymself(*searchsh);
9294 assert((sorg(*searchsh) == forg) && (sdest(*searchsh) == fdest));
9323 enum tetgenmesh::locateresult tetgenmesh::
9324 adjustlocatesub(point searchpt, face* searchsh,
enum locateresult precise,
9330 pa = sorg(*searchsh);
9331 pb = sdest(*searchsh);
9332 pc = sapex(*searchsh);
9334 if (precise == ONEDGE) {
9337 s1 = iscollinear(pa, pb, searchpt, epspp);
9339 s2 = iscollinear(pb, pc, searchpt, epspp);
9340 s3 = iscollinear(pc, pa, searchpt, epspp);
9347 senextself(*searchsh);
9359 senext2self(*searchsh);
9363 senextself(*searchsh);
9368 senext2self(*searchsh);
9390 enum tetgenmesh::locateresult tetgenmesh::
9391 locateseg(point searchpt, face* searchseg)
9401 searchseg->shver = 0;
9402 pa = sorg(*searchseg);
9403 pb = sdest(*searchseg);
9405 dx = fabs(pb[0] - pa[0]);
9406 dy = fabs(pb[1] - pa[1]);
9407 dz = fabs(pb[2] - pa[2]);
9421 if (pa[i] < pb[i]) {
9422 if (searchpt[i] < pa[i]) {
9424 }
else if (searchpt[i] > pa[i]) {
9425 if (searchpt[i] < pb[i]) {
9427 }
else if (searchpt[i] > pb[i]) {
9431 assert(searchpt[i] == pb[i]);
9433 sesymself(*searchseg);
9438 assert(searchpt[i] == pa[i]);
9442 }
else if (pa[i] > pb[i]) {
9443 if (searchpt[i] < pb[i]) {
9445 }
else if (searchpt[i] > pb[i]) {
9446 if (searchpt[i] < pa[i]) {
9448 }
else if (searchpt[i] > pa[i]) {
9452 assert(searchpt[i] == pa[i]);
9458 assert(searchpt[i] == pb[i]);
9460 sesymself(*searchseg);
9464 backtraceseg = *searchseg;
9466 senext2self(*searchseg);
9468 senextself(*searchseg);
9470 spivotself(*searchseg);
9471 if (searchseg->sh == dummysh) {
9472 *searchseg = backtraceseg;
9490 enum tetgenmesh::locateresult tetgenmesh::
9491 adjustlocateseg(point searchpt, face* searchseg,
enum locateresult precise,
9497 pa = sorg(*searchseg);
9498 pb = sdest(*searchseg);
9499 L = distance(pa, pb);
9502 d = distance(pa, searchpt);
9508 d = distance(pb, searchpt);
9511 sesymself(*searchseg);
9590 enum tetgenmesh::fliptype tetgenmesh::categorizeface(triface& horiz)
9592 triface symhoriz, casing;
9593 face checksh, checkseg;
9594 face cassh1, cassh2;
9595 point pa, pb, pc, pd, pe, pf, pg;
9596 point abdoppo, bcdoppo, cadoppo;
9597 REAL ori1, ori2, ori3;
9600 sym(horiz, symhoriz);
9601 if (symhoriz.tet == dummytet) {
9606 adjustedgering(horiz, CCW);
9607 findedge(&symhoriz, dest(horiz), org(horiz));
9612 pe = oppo(symhoriz);
9616 abdoppo = bcdoppo = cadoppo = (point) NULL;
9618 fnext(horiz, casing);
9620 if (casing.tet != dummytet) {
9621 abdoppo = oppo(casing);
9622 if (abdoppo == pe) adjtet++;
9624 enextfnext(horiz, casing);
9626 if (casing.tet != dummytet) {
9627 bcdoppo = oppo(casing);
9628 if (bcdoppo == pe) adjtet++;
9630 enext2fnext(horiz, casing);
9632 if (casing.tet != dummytet) {
9633 cadoppo = oppo(casing);
9634 if (cadoppo == pe) adjtet++;
9639 ori1 = orient3d(pa, pb, pd, pe);
9640 if (checksubfaces && ori1 != 0.0) {
9642 fnext(horiz, casing);
9643 tspivot(casing, cassh1);
9644 fnext(symhoriz, casing);
9645 tspivot(casing, cassh2);
9646 if ((cassh1.sh != dummysh) && (cassh2.sh != dummysh)) {
9648 findedge(&cassh1, pa, pb);
9649 sspivot(cassh1, checkseg);
9650 if (checkseg.sh == dummysh) {
9660 if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
9665 if (iscoplanar(pa, pb, pd, pe, ori1, b->epsilon)) ori1 = 0.0;
9673 fnext(horiz, casing);
9675 assert(casing.tet != dummytet);
9676 fnext(symhoriz, casing);
9678 assert(casing.tet != dummytet);
9681 if (checksubfaces) {
9683 tsspivot(&horiz, &checkseg);
9684 if (checkseg.sh != dummysh) {
9685 return FORBIDDENEDGE;
9690 ori2 = orient3d(pb, pc, pd, pe);
9691 if (checksubfaces && ori2 != 0.0) {
9693 enextfnext(horiz, casing);
9694 tspivot(casing, cassh1);
9695 enext2fnext(symhoriz, casing);
9696 tspivot(casing, cassh2);
9697 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
9699 findedge(&cassh1, pb, pc);
9700 sspivot(cassh1, checkseg);
9701 if (checkseg.sh == dummysh) {
9706 if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
9711 if (iscoplanar(pb, pc, pd, pe, ori2, b->epsilon)) ori2 = 0.0;
9719 enextfnext(horiz, casing);
9721 assert(casing.tet != dummytet);
9722 enext2fnext(symhoriz, casing);
9724 assert(casing.tet != dummytet);
9728 if (checksubfaces) {
9730 tsspivot(&horiz, &checkseg);
9731 if (checkseg.sh != dummysh) {
9732 return FORBIDDENEDGE;
9737 ori3 = orient3d(pc, pa, pd, pe);
9738 if (checksubfaces && ori3 != 0.0) {
9740 enext2fnext(horiz, casing);
9741 tspivot(casing, cassh1);
9742 enextfnext(symhoriz, casing);
9743 tspivot(casing, cassh2);
9744 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
9746 findedge(&cassh1, pc, pa);
9747 sspivot(cassh1, checkseg);
9748 if (checkseg.sh == dummysh) {
9756 if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon * 1e+2)) ori3 = 0.0;
9761 if (iscoplanar(pc, pa, pd, pe, ori3, b->epsilon)) ori3 = 0.0;
9769 enext2fnext(horiz, casing);
9771 assert(casing.tet != dummytet);
9772 enextfnext(symhoriz, casing);
9774 assert(casing.tet != dummytet);
9778 if (checksubfaces) {
9780 tsspivot(&horiz, &checkseg);
9781 if (checkseg.sh != dummysh) {
9782 return FORBIDDENEDGE;
9789 if (ori2 * ori3 == 0.0) {
9796 }
else if (ori2 == 0.0) {
9798 if (ori1 * ori3 == 0.0) {
9807 enext2self(symhoriz);
9808 }
else if (ori3 == 0.0) {
9810 if (ori1 * ori2 == 0.0) {
9819 enextself(symhoriz);
9822 if (checksubfaces) {
9823 tspivot(horiz, checksh);
9824 if (checksh.sh != dummysh) {
9826 return FORBIDDENFACE;
9832 if (checksubfaces) {
9833 tsspivot(&horiz, &checkseg);
9834 if (checkseg.sh != dummysh) {
9836 return FORBIDDENEDGE;
9838 tspivot(horiz, checksh);
9839 if (checksh.sh != dummysh) {
9841 return FORBIDDENFACE;
9848 pf = pg = (point) NULL;
9849 fnext(horiz, casing);
9851 if (casing.tet != dummytet) {
9854 fnext(symhoriz, casing);
9856 if (casing.tet != dummytet) {
9861 if (checksubfaces) {
9867 ori1 = orient3d(pc, pd, pe, pa);
9868 if (ori1 <= 0)
return N40;
9869 ori1 = orient3d(pd, pc, pe, pb);
9870 if (ori1 <= 0)
return N40;
9871 if (pf != (point) NULL) {
9872 ori1 = orient3d(pd, pf, pe, pa);
9873 if (ori1 <= 0)
return N40;
9874 ori1 = orient3d(pf, pd, pe, pb);
9875 if (ori1 <= 0)
return N40;
9878 if (pf == (point) NULL) {
9884 assert(pf != (point) NULL);
9892 }
else if (adjtet == 1) {
9895 if (bcdoppo == pe) {
9898 enext2self(symhoriz);
9902 }
else if (cadoppo == pe) {
9905 enextself(symhoriz);
9912 assert(abdoppo == pe);
9916 ori1 = orient3d(pc, pd, pe, pa);
9917 if (checksubfaces && ori1 != 0.0) {
9919 enext2fnext(horiz, casing);
9920 tspivot(casing, cassh1);
9921 enextfnext(symhoriz, casing);
9922 tspivot(casing, cassh2);
9923 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
9925 findedge(&cassh1, pc, pa);
9926 sspivot(cassh1, checkseg);
9927 if (checkseg.sh == dummysh) {
9936 if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon * 1e+2)) ori1 = 0.0;
9940 if (iscoplanar(pc, pd, pe, pa, ori1, b->epsilon)) ori1 = 0.0;
9947 ori2 = orient3d(pd, pc, pe, pb);
9948 if (checksubfaces && ori2 != 0.0) {
9950 enextfnext(horiz, casing);
9951 tspivot(casing, cassh1);
9952 enext2fnext(symhoriz, casing);
9953 tspivot(casing, cassh2);
9954 if (cassh1.sh != dummysh && cassh2.sh != dummysh) {
9956 findedge(&cassh1, pb, pc);
9957 sspivot(cassh1, checkseg);
9958 if (checkseg.sh == dummysh) {
9967 if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon * 1e+2)) ori2 = 0.0;
9971 if (iscoplanar(pd, pc, pe, pb, ori2, b->epsilon)) ori2 = 0.0;
9979 if (checksubfaces) {
9982 tsspivot(&horiz, &checkseg);
9983 if (checkseg.sh != dummysh) {
9985 return FORBIDDENEDGE;
9991 fnext(horiz, casing);
9992 tspivot(casing, cassh1);
9993 fnext(symhoriz, casing);
9994 tspivot(casing, cassh2);
9995 if (cassh1.sh != dummysh || cassh2.sh != dummysh) {
9998 printf(
"Warning: A tetrahedron spans two subfaces of a facet.\n");
10023 void tetgenmesh::enqueueflipface(triface& checkface, queue* flipqueue)
10028 sym(checkface, symface);
10029 if (symface.tet != dummytet) {
10030 queface = (badface *) flipqueue->push((
void *) NULL);
10031 queface->tt = checkface;
10032 queface->foppo = oppo(symface);
10036 void tetgenmesh::enqueueflipedge(face& checkedge, queue* flipqueue)
10040 queface = (badface *) flipqueue->push((
void *) NULL);
10041 queface->ss = checkedge;
10042 queface->forg = sorg(checkedge);
10043 queface->fdest = sdest(checkedge);
10062 void tetgenmesh::flip23(triface* flipface, queue* flipqueue)
10064 triface abcd, bace;
10065 triface oldabd, oldbcd, oldcad;
10066 triface abdcasing, bcdcasing, cadcasing;
10067 triface oldbae, oldcbe, oldace;
10068 triface baecasing, cbecasing, acecasing;
10070 face abdsh, bcdsh, cadsh;
10071 face baesh, cbesh, acesh;
10072 face abseg, bcseg, caseg;
10073 face adseg, bdseg, cdseg;
10074 face aeseg, beseg, ceseg;
10075 triface edab, edbc, edca;
10076 point pa, pb, pc, pd, pe;
10077 REAL attrib, volume;
10081 adjustedgering(abcd, CCW);
10090 for (i = 0; (i < 3) && (org(bace) != pb); i++) {
10095 if (b->verbose > 2) {
10096 printf(
" Do T23 on face (%d, %d, %d) %d, %d.\n", pointmark(pa),
10097 pointmark(pb), pointmark(pc), pointmark(pd), pointmark(pe));
10102 fnext(abcd, oldabd);
10103 enextfnext(abcd, oldbcd);
10104 enext2fnext(abcd, oldcad);
10105 fnext(bace, oldbae);
10106 enext2fnext(bace, oldcbe);
10107 enextfnext(bace, oldace);
10108 sym(oldabd, abdcasing);
10109 sym(oldbcd, bcdcasing);
10110 sym(oldcad, cadcasing);
10111 sym(oldbae, baecasing);
10112 sym(oldcbe, cbecasing);
10113 sym(oldace, acecasing);
10114 if (checksubfaces) {
10115 tspivot(oldabd, abdsh);
10116 tspivot(oldbcd, bcdsh);
10117 tspivot(oldcad, cadsh);
10118 tspivot(oldbae, baesh);
10119 tspivot(oldcbe, cbesh);
10120 tspivot(oldace, acesh);
10121 }
else if (checksubsegs) {
10122 tsspivot1(abcd, abseg);
10123 enext(abcd, worktet);
10124 tsspivot1(worktet, bcseg);
10125 enext2(abcd, worktet);
10126 tsspivot1(worktet, caseg);
10127 enext2(oldabd, worktet);
10128 tsspivot1(worktet, adseg);
10129 enext2(oldbcd, worktet);
10130 tsspivot1(worktet, bdseg);
10131 enext2(oldcad, worktet);
10132 tsspivot1(worktet, cdseg);
10133 enext(oldbae, worktet);
10134 tsspivot1(worktet, aeseg);
10135 enext(oldcbe, worktet);
10136 tsspivot1(worktet, beseg);
10137 enext(oldace, worktet);
10138 tsspivot1(worktet, ceseg);
10142 edab.tet = abcd.tet;
10147 edbc.tet = bace.tet;
10152 maketetrahedron(&edca);
10158 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
10159 attrib = elemattribute(abcd.tet, i);
10160 setelemattribute(edca.tet, i, attrib);
10165 if (b->varvolume && !b->refine) {
10166 volume = volumebound(abcd.tet);
10167 setvolumebound(edca.tet, volume);
10171 for (i = 0; i < 4; i ++) {
10172 edab.tet[i] = (tetrahedron) dummytet;
10174 for (i = 0; i < 4; i ++) {
10175 edbc.tet[i] = (tetrahedron) dummytet;
10189 bond(edab, abdcasing);
10191 bond(edab, baecasing);
10193 bond(edbc, bcdcasing);
10195 bond(edbc, cbecasing);
10197 bond(edca, cadcasing);
10199 bond(edca, acecasing);
10201 if (checksubfaces) {
10203 for (i = 0; i < 4; i ++) {
10209 if (abdsh.sh != dummysh) {
10211 tsbond(edab, abdsh);
10213 if (baesh.sh != dummysh) {
10215 tsbond(edab, baesh);
10217 if (bcdsh.sh != dummysh) {
10219 tsbond(edbc, bcdsh);
10221 if (cbesh.sh != dummysh) {
10223 tsbond(edbc, cbesh);
10225 if (cadsh.sh != dummysh) {
10227 tsbond(edca, cadsh);
10229 if (acesh.sh != dummysh) {
10231 tsbond(edca, acesh);
10233 }
else if (checksubsegs) {
10234 for (i = 0; i < 6; i++) {
10235 edab.tet[8 + i] = (tetrahedron) dummysh;
10237 for (i = 0; i < 6; i++) {
10238 edbc.tet[8 + i] = (tetrahedron) dummysh;
10240 edab.loc = edab.ver = 0;
10241 edbc.loc = edab.ver = 0;
10242 edca.loc = edab.ver = 0;
10244 enext(edab, worktet);
10245 tssbond1(worktet, adseg);
10246 enext2(edab, worktet);
10247 tssbond1(worktet, aeseg);
10248 fnext(edab, worktet);
10249 enextself(worktet);
10250 tssbond1(worktet, bdseg);
10251 enextself(worktet);
10252 tssbond1(worktet, beseg);
10253 enextfnext(edab, worktet);
10254 enextself(worktet);
10255 tssbond1(worktet, abseg);
10257 enext(edbc, worktet);
10258 tssbond1(worktet, bdseg);
10259 enext2(edbc, worktet);
10260 tssbond1(worktet, beseg);
10261 fnext(edbc, worktet);
10262 enextself(worktet);
10263 tssbond1(worktet, cdseg);
10264 enextself(worktet);
10265 tssbond1(worktet, ceseg);
10266 enextfnext(edbc, worktet);
10267 enextself(worktet);
10268 tssbond1(worktet, bcseg);
10270 enext(edca, worktet);
10271 tssbond1(worktet, cdseg);
10272 enext2(edca, worktet);
10273 tssbond1(worktet, ceseg);
10274 fnext(edca, worktet);
10275 enextself(worktet);
10276 tssbond1(worktet, adseg);
10277 enextself(worktet);
10278 tssbond1(worktet, aeseg);
10279 enextfnext(edca, worktet);
10280 enextself(worktet);
10281 tssbond1(worktet, caseg);
10287 if (b->verbose > 3) {
10288 printf(
" Updating edab ");
10290 printf(
" Updating edbc ");
10292 printf(
" Creating edca ");
10296 if (flipqueue != (queue *) NULL) {
10297 enextfnext(edab, abdcasing);
10298 enqueueflipface(abdcasing, flipqueue);
10299 enext2fnext(edab, baecasing);
10300 enqueueflipface(baecasing, flipqueue);
10301 enextfnext(edbc, bcdcasing);
10302 enqueueflipface(bcdcasing, flipqueue);
10303 enext2fnext(edbc, cbecasing);
10304 enqueueflipface(cbecasing, flipqueue);
10305 enextfnext(edca, cadcasing);
10306 enqueueflipface(cadcasing, flipqueue);
10307 enext2fnext(edca, acecasing);
10308 enqueueflipface(acecasing, flipqueue);
10334 void tetgenmesh::flip32(triface* flipface, queue* flipqueue)
10336 triface edab, edbc, edca;
10337 triface oldabd, oldbcd, oldcad;
10338 triface abdcasing, bcdcasing, cadcasing;
10339 triface oldbae, oldcbe, oldace;
10340 triface baecasing, cbecasing, acecasing;
10342 face abdsh, bcdsh, cadsh;
10343 face baesh, cbesh, acesh;
10344 face abseg, bcseg, caseg;
10345 face adseg, bdseg, cdseg;
10346 face aeseg, beseg, ceseg;
10347 triface abcd, bace;
10348 point pa, pb, pc, pd, pe;
10352 adjustedgering(edab, CCW);
10360 for (i = 0; (i < 3) && (org(edbc) != pe); i++) {
10367 for (i = 0; (i < 3) && (org(edca) != pe); i++) {
10371 if (b->verbose > 2) {
10372 printf(
" Do T32 on edge (%d, %d) %d, %d, %d.\n", pointmark(pe),
10373 pointmark(pd), pointmark(pa), pointmark(pb), pointmark(pc));
10378 enextfnext(edab, oldabd);
10379 enext2fnext(edab, oldbae);
10380 enextfnext(edbc, oldbcd);
10381 enext2fnext(edbc, oldcbe);
10382 enextfnext(edca, oldcad);
10383 enext2fnext(edca, oldace);
10384 sym(oldabd, abdcasing);
10385 sym(oldbcd, bcdcasing);
10386 sym(oldcad, cadcasing);
10387 sym(oldbae, baecasing);
10388 sym(oldcbe, cbecasing);
10389 sym(oldace, acecasing);
10390 if (checksubfaces) {
10391 tspivot(oldabd, abdsh);
10392 tspivot(oldbcd, bcdsh);
10393 tspivot(oldcad, cadsh);
10394 tspivot(oldbae, baesh);
10395 tspivot(oldcbe, cbesh);
10396 tspivot(oldace, acesh);
10397 }
else if (checksubsegs) {
10398 enext(edab, worktet);
10399 tsspivot1(worktet, adseg);
10400 enext2(edab, worktet);
10401 tsspivot1(worktet, aeseg);
10402 enext(edbc, worktet);
10403 tsspivot1(worktet, bdseg);
10404 enext2(edbc, worktet);
10405 tsspivot1(worktet, beseg);
10406 enext(edca, worktet);
10407 tsspivot1(worktet, cdseg);
10408 enext2(edca, worktet);
10409 tsspivot1(worktet, ceseg);
10410 enextfnext(edab, worktet);
10411 enextself(worktet);
10412 tsspivot1(worktet, abseg);
10413 enextfnext(edbc, worktet);
10414 enextself(worktet);
10415 tsspivot1(worktet, bcseg);
10416 enextfnext(edca, worktet);
10417 enextself(worktet);
10418 tsspivot1(worktet, caseg);
10422 abcd.tet = edab.tet;
10427 bace.tet = edbc.tet;
10433 tetrahedrondealloc(edca.tet);
10436 for (i = 0; i < 4; i ++) {
10437 abcd.tet[i] = (tetrahedron) dummytet;
10439 for (i = 0; i < 4; i ++) {
10440 bace.tet[i] = (tetrahedron) dummytet;
10448 bond(abcd, abdcasing);
10450 bond(abcd, bcdcasing);
10452 bond(abcd, cadcasing);
10454 bond(bace, baecasing);
10456 bond(bace, cbecasing);
10458 bond(bace, acecasing);
10459 if (checksubfaces) {
10461 for (i = 0; i < 4; i ++) {
10462 abcd.tet[8 + i] = (tetrahedron) dummysh;
10464 for (i = 0; i < 4; i ++) {
10465 bace.tet[8 + i] = (tetrahedron) dummysh;
10467 if (abdsh.sh != dummysh) {
10469 tsbond(abcd, abdsh);
10471 if (bcdsh.sh != dummysh) {
10473 tsbond(abcd, bcdsh);
10475 if (cadsh.sh != dummysh) {
10477 tsbond(abcd, cadsh);
10479 if (baesh.sh != dummysh) {
10481 tsbond(bace, baesh);
10483 if (cbesh.sh != dummysh) {
10485 tsbond(bace, cbesh);
10487 if (acesh.sh != dummysh) {
10489 tsbond(bace, acesh);
10491 }
else if (checksubsegs) {
10492 for (i = 0; i < 6; i++) {
10493 abcd.tet[8 + i] = (tetrahedron) dummysh;
10495 for (i = 0; i < 6; i++) {
10496 bace.tet[8 + i] = (tetrahedron) dummysh;
10498 abcd.loc = abcd.ver = 0;
10499 bace.loc = bace.ver = 0;
10500 tssbond1(abcd, abseg);
10501 enext(abcd, worktet);
10502 tssbond1(worktet, bcseg);
10503 enext2(abcd, worktet);
10504 tssbond1(worktet, caseg);
10505 fnext(abcd, worktet);
10506 enext2self(worktet);
10507 tssbond1(worktet, adseg);
10508 enextfnext(abcd, worktet);
10509 enext2self(worktet);
10510 tssbond1(worktet, bdseg);
10511 enext2fnext(abcd, worktet);
10512 enext2self(worktet);
10513 tssbond1(worktet, cdseg);
10514 tssbond1(bace, abseg);
10515 enext2(bace, worktet);
10516 tssbond1(worktet, bcseg);
10517 enext(bace, worktet);
10518 tssbond1(worktet, caseg);
10519 fnext(bace, worktet);
10520 enextself(worktet);
10521 tssbond1(worktet, aeseg);
10522 enext2fnext(bace, worktet);
10523 enextself(worktet);
10524 tssbond1(worktet, beseg);
10525 enextfnext(bace, worktet);
10526 enextself(worktet);
10527 tssbond1(worktet, ceseg);
10532 if (b->verbose > 3) {
10533 printf(
" Updating abcd ");
10535 printf(
" Updating bace ");
10537 printf(
" Deleting edca ");
10541 if (flipqueue != (queue *) NULL) {
10542 fnext(abcd, abdcasing);
10543 enqueueflipface(abdcasing, flipqueue);
10544 fnext(bace, baecasing);
10545 enqueueflipface(baecasing, flipqueue);
10546 enextfnext(abcd, bcdcasing);
10547 enqueueflipface(bcdcasing, flipqueue);
10548 enextfnext(bace, cbecasing);
10549 enqueueflipface(cbecasing, flipqueue);
10550 enext2fnext(abcd, cadcasing);
10551 enqueueflipface(cadcasing, flipqueue);
10552 enext2fnext(bace, acecasing);
10553 enqueueflipface(acecasing, flipqueue);
10588 void tetgenmesh::flip22(triface* flipface, queue* flipqueue)
10590 triface abce, bade;
10591 triface oldbce, oldcae, oldade, olddbe;
10592 triface bcecasing, caecasing, adecasing, dbecasing;
10593 face bcesh, caesh, adesh, dbesh;
10594 triface bacf, abdf;
10595 triface oldacf, oldcbf, oldbdf, olddaf;
10596 triface acfcasing, cbfcasing, bdfcasing, dafcasing;
10598 face acfsh, cbfsh, bdfsh, dafsh;
10600 face adseg, dbseg, bcseg, caseg;
10601 face aeseg, deseg, beseg, ceseg;
10602 face afseg, dfseg, bfseg, cfseg;
10603 point pa, pb, pc, pd;
10609 adjustedgering(*flipface, CCW);
10610 fnext(*flipface, abce);
10612 adjustedgering(*flipface, CW);
10613 fnext(*flipface, bade);
10615 assert(bade.tet != dummytet);
10624 assert(oppo(abce) == pe);
10627 mirrorflag = bacf.tet != dummytet;
10631 for (i = 0; (i < 3) && (org(bacf) != pb); i++) {
10636 assert(abdf.tet != dummytet);
10640 for (i = 0; (i < 3) && (org(abdf) != pa); i++) {
10646 assert(oppo(abdf) == pf);
10650 if (b->verbose > 2) {
10651 printf(
" Do %s on edge (%d, %d).\n", mirrorflag ?
"T44" :
"T22",
10652 pointmark(pa), pointmark(pb));
10654 mirrorflag ? flip44s++ : flip22s++;
10657 enextfnext(abce, oldbce);
10658 enext2fnext(abce, oldcae);
10659 enextfnext(bade, oldade);
10660 enext2fnext(bade, olddbe);
10661 sym(oldbce, bcecasing);
10662 sym(oldcae, caecasing);
10663 sym(oldade, adecasing);
10664 sym(olddbe, dbecasing);
10665 if (checksubfaces) {
10666 tspivot(oldbce, bcesh);
10667 tspivot(oldcae, caesh);
10668 tspivot(oldade, adesh);
10669 tspivot(olddbe, dbesh);
10670 tspivot(abce, abc);
10671 tspivot(bade, bad);
10672 }
else if (checksubsegs) {
10674 enext(bade, worktet);
10675 tsspivot1(worktet, adseg);
10676 enext2(bade, worktet);
10677 tsspivot1(worktet, dbseg);
10678 enext(abce, worktet);
10679 tsspivot1(worktet, bcseg);
10680 enext2(abce, worktet);
10681 tsspivot1(worktet, caseg);
10683 fnext(bade, worktet);
10684 enextself(worktet);
10685 tsspivot1(worktet, aeseg);
10686 enextfnext(bade, worktet);
10687 enextself(worktet);
10688 tsspivot1(worktet, deseg);
10689 enext2fnext(bade, worktet);
10690 enextself(worktet);
10691 tsspivot1(worktet, beseg);
10692 enextfnext(abce, worktet);
10693 enextself(worktet);
10694 tsspivot1(worktet, ceseg);
10697 enextfnext(bacf, oldacf);
10698 enext2fnext(bacf, oldcbf);
10699 enextfnext(abdf, oldbdf);
10700 enext2fnext(abdf, olddaf);
10701 sym(oldacf, acfcasing);
10702 sym(oldcbf, cbfcasing);
10703 sym(oldbdf, bdfcasing);
10704 sym(olddaf, dafcasing);
10705 if (checksubfaces) {
10706 tspivot(oldacf, acfsh);
10707 tspivot(oldcbf, cbfsh);
10708 tspivot(oldbdf, bdfsh);
10709 tspivot(olddaf, dafsh);
10710 }
else if (checksubsegs) {
10712 fnext(abdf, worktet);
10713 enext2self(worktet);
10714 tsspivot1(worktet, afseg);
10715 enext2fnext(abdf, worktet);
10716 enext2self(worktet);
10717 tsspivot1(worktet, dfseg);
10718 enextfnext(abdf, worktet);
10719 enext2self(worktet);
10720 tsspivot1(worktet, bfseg);
10721 enextfnext(bacf, worktet);
10722 enextself(worktet);
10723 tsspivot1(worktet, cfseg);
10728 bond(oldbce, caecasing);
10729 bond(oldcae, adecasing);
10730 bond(oldade, dbecasing);
10731 bond(olddbe, bcecasing);
10732 if (checksubfaces) {
10734 if (caesh.sh == dummysh) {
10735 tsdissolve(oldbce);
10737 tsbond(oldbce, caesh);
10739 if (adesh.sh == dummysh) {
10740 tsdissolve(oldcae);
10742 tsbond(oldcae, adesh);
10744 if (dbesh.sh == dummysh) {
10745 tsdissolve(oldade);
10747 tsbond(oldade, dbesh);
10749 if (bcesh.sh == dummysh) {
10750 tsdissolve(olddbe);
10752 tsbond(olddbe, bcesh);
10754 }
else if (checksubsegs) {
10756 enext(abce, worktet);
10757 if (caseg.sh == dummysh) {
10758 tssdissolve1(worktet);
10760 tssbond1(worktet, caseg);
10762 enext2(abce, worktet);
10763 if (adseg.sh == dummysh) {
10764 tssdissolve1(worktet);
10766 tssbond1(worktet, adseg);
10768 fnext(abce, worktet);
10769 enextself(worktet);
10770 if (ceseg.sh == dummysh) {
10771 tssdissolve1(worktet);
10773 tssbond1(worktet, ceseg);
10775 enextfnext(abce, worktet);
10776 enextself(worktet);
10777 if (aeseg.sh == dummysh) {
10778 tssdissolve1(worktet);
10780 tssbond1(worktet, aeseg);
10782 enext2fnext(abce, worktet);
10783 enextself(worktet);
10784 if (deseg.sh == dummysh) {
10785 tssdissolve1(worktet);
10787 tssbond1(worktet, deseg);
10790 enext(bade, worktet);
10791 if (dbseg.sh == dummysh) {
10792 tssdissolve1(worktet);
10794 tssbond1(worktet, dbseg);
10796 enext2(bade, worktet);
10797 if (bcseg.sh == dummysh) {
10798 tssdissolve1(worktet);
10800 tssbond1(worktet, bcseg);
10802 fnext(bade, worktet);
10803 enextself(worktet);
10804 if (deseg.sh == dummysh) {
10805 tssdissolve1(worktet);
10807 tssbond1(worktet, deseg);
10809 enextfnext(bade, worktet);
10810 enextself(worktet);
10811 if (beseg.sh == dummysh) {
10812 tssdissolve1(worktet);
10814 tssbond1(worktet, beseg);
10816 enext2fnext(bade, worktet);
10817 enextself(worktet);
10818 if (ceseg.sh == dummysh) {
10819 tssdissolve1(worktet);
10821 tssbond1(worktet, ceseg);
10826 bond(oldcbf, acfcasing);
10827 bond(oldacf, dafcasing);
10828 bond(olddaf, bdfcasing);
10829 bond(oldbdf, cbfcasing);
10830 if (checksubfaces) {
10832 if (acfsh.sh == dummysh) {
10833 tsdissolve(oldcbf);
10835 tsbond(oldcbf, acfsh);
10837 if (dafsh.sh == dummysh) {
10838 tsdissolve(oldacf);
10840 tsbond(oldacf, dafsh);
10842 if (bdfsh.sh == dummysh) {
10843 tsdissolve(olddaf);
10845 tsbond(olddaf, bdfsh);
10847 if (cbfsh.sh == dummysh) {
10848 tsdissolve(oldbdf);
10850 tsbond(oldbdf, cbfsh);
10852 }
else if (checksubsegs) {
10854 enext2(bacf, worktet);
10855 if (caseg.sh == dummysh) {
10856 tssdissolve1(worktet);
10858 tssbond1(worktet, caseg);
10860 enext(bacf, worktet);
10861 if (adseg.sh == dummysh) {
10862 tssdissolve1(worktet);
10864 tssbond1(worktet, adseg);
10866 fnext(bacf, worktet);
10867 enext2self(worktet);
10868 if (cfseg.sh == dummysh) {
10869 tssdissolve1(worktet);
10871 tssbond1(worktet, cfseg);
10873 enext2fnext(bacf, worktet);
10874 enext2self(worktet);
10875 if (afseg.sh == dummysh) {
10876 tssdissolve1(worktet);
10878 tssbond1(worktet, afseg);
10880 enextfnext(bacf, worktet);
10881 enext2self(worktet);
10882 if (dfseg.sh == dummysh) {
10883 tssdissolve1(worktet);
10885 tssbond1(worktet, dfseg);
10888 enext2(abdf, worktet);
10889 if (dbseg.sh == dummysh) {
10890 tssdissolve1(worktet);
10892 tssbond1(worktet, dbseg);
10894 enext(abdf, worktet);
10895 if (bcseg.sh == dummysh) {
10896 tssdissolve1(worktet);
10898 tssbond1(worktet, bcseg);
10900 fnext(abdf, worktet);
10901 enext2self(worktet);
10902 if (dfseg.sh == dummysh) {
10903 tssdissolve1(worktet);
10905 tssbond1(worktet, dfseg);
10907 enext2fnext(abdf, worktet);
10908 enext2self(worktet);
10909 if (bfseg.sh == dummysh) {
10910 tssdissolve1(worktet);
10912 tssbond1(worktet, bfseg);
10914 enextfnext(abdf, worktet);
10915 enext2self(worktet);
10916 if (cfseg.sh == dummysh) {
10917 tssdissolve1(worktet);
10919 tssbond1(worktet, cfseg);
10941 if (checksubfaces && abc.sh != dummysh) {
10943 assert(bad.sh != dummysh);
10947 findedge(&abc, pa, pb);
10949 flip22sub(&abc, NULL);
10952 if (b->verbose > 3) {
10953 printf(
" Updating abce ");
10955 printf(
" Updating bade ");
10958 printf(
" Updating bacf ");
10960 printf(
" Updating abdf ");
10965 if (flipqueue != (queue *) NULL) {
10966 enextfnext(abce, bcecasing);
10967 enqueueflipface(bcecasing, flipqueue);
10968 enext2fnext(abce, caecasing);
10969 enqueueflipface(caecasing, flipqueue);
10970 enextfnext(bade, adecasing);
10971 enqueueflipface(adecasing, flipqueue);
10972 enext2fnext(bade, dbecasing);
10973 enqueueflipface(dbecasing, flipqueue);
10975 enextfnext(bacf, acfcasing);
10976 enqueueflipface(acfcasing, flipqueue);
10977 enext2fnext(bacf, cbfcasing);
10978 enqueueflipface(cbfcasing, flipqueue);
10979 enextfnext(abdf, bdfcasing);
10980 enqueueflipface(bdfcasing, flipqueue);
10981 enext2fnext(abdf, dafcasing);
10982 enqueueflipface(dafcasing, flipqueue);
10989 enqueueflipface(abce, flipqueue);
10990 enqueueflipface(bade, flipqueue);
11024 void tetgenmesh::flip22sub(face* flipedge, queue* flipqueue)
11027 face oldbc, oldca, oldad, olddb;
11028 face bccasin, bccasout, cacasin, cacasout;
11029 face adcasin, adcasout, dbcasin, dbcasout;
11030 face bc, ca, ad, db;
11032 point pa, pb, pc, pd;
11036 if (sorg(bad) != sdest(abc)) {
11044 if (b->verbose > 2) {
11045 printf(
" Flip sub edge (%d, %d).\n", pointmark(pa), pointmark(pb));
11049 senext(abc, oldbc);
11050 senext2(abc, oldca);
11051 senext(bad, oldad);
11052 senext2(bad, olddb);
11056 spivot(oldbc, bccasout);
11057 sspivot(oldbc, bc);
11058 if (bc.sh != dummysh) {
11060 if (bccasout.sh != dummysh) {
11061 if (oldbc.sh != bccasout.sh) {
11066 spivotself(spinsh);
11067 }
while (spinsh.sh != oldbc.sh);
11069 bccasout.sh = dummysh;
11074 spivot(oldca, cacasout);
11075 sspivot(oldca, ca);
11076 if (ca.sh != dummysh) {
11078 if (cacasout.sh != dummysh) {
11079 if (oldca.sh != cacasout.sh) {
11084 spivotself(spinsh);
11085 }
while (spinsh.sh != oldca.sh);
11087 cacasout.sh = dummysh;
11092 spivot(oldad, adcasout);
11093 sspivot(oldad, ad);
11094 if (ad.sh != dummysh) {
11096 if (adcasout.sh != dummysh) {
11097 if (oldad.sh != adcasout.sh) {
11102 spivotself(spinsh);
11103 }
while (spinsh.sh != oldad.sh);
11105 adcasout.sh = dummysh;
11110 spivot(olddb, dbcasout);
11111 sspivot(olddb, db);
11112 if (db.sh != dummysh) {
11114 if (dbcasout.sh != dummysh) {
11115 if (olddb.sh != dbcasout.sh) {
11120 spivotself(spinsh);
11121 }
while (spinsh.sh != olddb.sh);
11123 dbcasout.sh = dummysh;
11130 if (ca.sh != dummysh) {
11131 if (cacasout.sh != dummysh) {
11132 sbond1(cacasin, oldbc);
11133 sbond1(oldbc, cacasout);
11136 sbond(oldbc, oldbc);
11138 dummysh[0] = sencode(oldbc);
11142 sbond(oldbc, cacasout);
11144 if (ad.sh != dummysh) {
11145 if (adcasout.sh != dummysh) {
11146 sbond1(adcasin, oldca);
11147 sbond1(oldca, adcasout);
11150 sbond(oldca, oldca);
11152 dummysh[0] = sencode(oldca);
11156 sbond(oldca, adcasout);
11158 if (db.sh != dummysh) {
11159 if (dbcasout.sh != dummysh) {
11160 sbond1(dbcasin, oldad);
11161 sbond1(oldad, dbcasout);
11164 sbond(oldad, oldad);
11166 dummysh[0] = sencode(oldad);
11170 sbond(oldad, dbcasout);
11172 if (bc.sh != dummysh) {
11173 if (bccasout.sh != dummysh) {
11174 sbond1(bccasin, olddb);
11175 sbond1(olddb, bccasout);
11178 sbond(olddb, olddb);
11180 dummysh[0] = sencode(olddb);
11184 sbond(olddb, bccasout);
11195 if (flipqueue != (queue *) NULL) {
11196 enqueueflipedge(bccasout, flipqueue);
11197 enqueueflipedge(cacasout, flipqueue);
11198 enqueueflipedge(adcasout, flipqueue);
11199 enqueueflipedge(dbcasout, flipqueue);
11220 long tetgenmesh::flip(queue* flipqueue, badface **plastflip)
11222 badface *qface, *newflip;
11223 triface flipface, symface;
11224 point pa, pb, pc, pd, pe;
11226 REAL sign, bakepsilon;
11228 int epscount, fcount;
11229 int ia, ib, ic, id, ie;
11231 if (b->verbose > 1) {
11232 printf(
" Do flipface queue: %ld faces.\n", flipqueue->len());
11235 flipcount = flip23s + flip32s + flip22s + flip44s;
11236 if (checksubfaces) {
11241 if (plastflip != (badface **) NULL) {
11243 flipstackers->restart();
11244 *plastflip = (badface *) NULL;
11248 while (!flipqueue->empty()) {
11249 qface = (badface *) flipqueue->pop();
11250 flipface = qface->tt;
11251 if (isdead(&flipface))
continue;
11252 sym(flipface, symface);
11254 if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11256 adjustedgering(flipface, CW);
11257 pa = org(flipface);
11258 pb = dest(flipface);
11259 pc = apex(flipface);
11260 pd = oppo(flipface);
11261 pe = oppo(symface);
11263 ia = pointmark(pa);
11264 ib = pointmark(pb);
11265 ic = pointmark(pc);
11266 id = pointmark(pd);
11267 ie = pointmark(pe);
11268 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic,
id, ie);
11269 assert(sign != 0.0);
11271 sign = insphere(pa, pb, pc, pd, pe);
11278 if (checksubfaces) {
11280 bakepsilon = b->epsilon;
11282 while (epscount < 32) {
11283 fc = categorizeface(flipface);
11285 b->epsilon *= 1e-1;
11291 b->epsilon = bakepsilon;
11292 if (epscount >= 32) {
11293 if (b->verbose > 0) {
11294 printf(
"Warning: Can't flip a degenerate tetrahedron.\n");
11299 fc = categorizeface(flipface);
11308 flip22(&flipface, flipqueue);
11311 flip23(&flipface, flipqueue);
11314 flip32(&flipface, flipqueue);
11319 case FORBIDDENFACE:
11321 case FORBIDDENEDGE:
11328 if (plastflip != (badface **) NULL) {
11329 if ((fc == T44) || (fc == T22) || (fc == T23) || (fc == T32)) {
11331 newflip = (badface *) flipstackers->alloc();
11332 newflip->tt = flipface;
11333 newflip->key = (REAL) fc;
11334 newflip->forg = org(flipface);
11335 newflip->fdest = dest(flipface);
11336 newflip->fapex = apex(flipface);
11337 newflip->previtem = *plastflip;
11338 *plastflip = newflip;
11344 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11345 if (b->verbose > 1) {
11346 printf(
" %ld flips.\n", flipcount);
11358 long tetgenmesh::lawson(list *misseglist, queue* flipqueue)
11360 badface *qface, *misseg;
11361 triface flipface, symface;
11362 triface starttet, spintet;
11363 face checksh, checkseg;
11364 point pa, pb, pc, pd, pe;
11368 int ia, ib, ic, id, ie;
11371 if (b->verbose > 1) {
11372 printf(
" Do flipface queue: %ld faces.\n", flipqueue->len());
11374 flipcount = flip23s + flip32s + flip22s + flip44s;
11379 while (!flipqueue->empty()) {
11380 qface = (badface *) flipqueue->pop();
11381 flipface = qface->tt;
11383 if (!isdead(&flipface)) {
11384 sym(flipface, symface);
11386 if ((symface.tet != dummytet) && (oppo(symface) == qface->foppo)) {
11388 pa = org(flipface);
11389 pb = dest(flipface);
11390 pc = apex(flipface);
11391 pd = oppo(flipface);
11392 pe = oppo(symface);
11394 ia = pointmark(pa);
11395 ib = pointmark(pb);
11396 ic = pointmark(pc);
11397 id = pointmark(pd);
11398 ie = pointmark(pe);
11399 sign = insphere_sos(pb, pa, pc, pd, pe, ib, ia, ic,
id, ie);
11401 sign = insphere(pb, pa, pc, pd, pe);
11404 for (i = 0; i < 3; i++) {
11405 ori = orient3d(pa, pb, pd, pe);
11412 enextself(flipface);
11419 if (checksubfaces) {
11420 tspivot(flipface, checksh);
11421 if (checksh.sh != dummysh) {
11426 flip23(&flipface, flipqueue);
11427 }
else if (ori < 0.0) {
11429 fnext(flipface, symface);
11431 if (oppo(symface) == pe) {
11433 if (checksubfaces) {
11434 tsspivot(&flipface, &checkseg);
11435 if (checkseg.sh != dummysh) {
11439 }
else if (checksubsegs) {
11440 tsspivot1(flipface, checkseg);
11441 if (checkseg.sh != dummysh) {
11442 if (b->verbose > 2) {
11443 printf(
" Queuing missing segment (%d, %d).\n",
11444 pointmark(org(flipface)), pointmark(dest(flipface)));
11446 misseg = (badface *) misseglist->append(NULL);
11447 misseg->ss = checkseg;
11448 misseg->forg = sorg(checkseg);
11449 misseg->fdest = sdest(checkseg);
11451 starttet = flipface;
11452 adjustedgering(starttet, CCW);
11453 fnextself(starttet);
11454 spintet = starttet;
11457 tssdissolve1(spintet);
11458 if (!fnextself(spintet)) {
11461 esym(starttet, spintet);
11462 if (!fnextself(spintet)) {
11467 }
while ((apex(spintet) != apex(starttet)) && (hitbdry < 2));
11470 flip32(&flipface, flipqueue);
11474 fnext(flipface, symface);
11475 if (fnextself(symface)) {
11477 fnextself(symface);
11478 if (apex(symface) == pe) {
11479 if (checksubfaces) {
11480 tsspivot(&flipface, &checkseg);
11481 if (checkseg.sh != dummysh) {
11485 }
else if (checksubsegs) {
11486 tsspivot1(flipface, checkseg);
11487 if (checkseg.sh != dummysh) {
11488 if (b->verbose > 2) {
11489 printf(
" Queuing missing segment (%d, %d).\n",
11490 pointmark(org(flipface)), pointmark(dest(flipface)));
11492 misseg = (badface *) misseglist->append(NULL);
11493 misseg->ss = checkseg;
11494 misseg->forg = sorg(checkseg);
11495 misseg->fdest = sdest(checkseg);
11497 starttet = flipface;
11498 adjustedgering(starttet, CCW);
11499 fnextself(starttet);
11500 spintet = starttet;
11503 tssdissolve1(spintet);
11504 if (!fnextself(spintet)) {
11507 esym(starttet, spintet);
11508 if (!fnextself(spintet)) {
11513 }
while ((apex(spintet) != apex(starttet)) &&
11517 flip22(&flipface, flipqueue);
11521 esym(flipface, symface);
11522 fnextself(symface);
11524 if (symface.tet == dummytet) {
11525 if (checksubfaces) {
11526 tsspivot(&flipface, &checkseg);
11527 if (checkseg.sh != dummysh) {
11531 }
else if (checksubsegs) {
11532 tsspivot1(flipface, checkseg);
11533 if (checkseg.sh != dummysh) {
11534 if (b->verbose > 2) {
11535 printf(
" Queuing missing segment (%d, %d).\n",
11536 pointmark(org(flipface)), pointmark(dest(flipface)));
11538 misseg = (badface *) misseglist->append(NULL);
11539 misseg->ss = checkseg;
11540 misseg->forg = sorg(checkseg);
11541 misseg->fdest = sdest(checkseg);
11543 starttet = flipface;
11544 adjustedgering(starttet, CCW);
11545 fnextself(starttet);
11546 spintet = starttet;
11549 tssdissolve1(spintet);
11550 if (!fnextself(spintet)) {
11553 esym(starttet, spintet);
11554 if (!fnextself(spintet)) {
11559 }
while ((apex(spintet) != apex(starttet)) &&
11563 flip22(&flipface, flipqueue);
11572 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
11573 if (b->verbose > 1) {
11574 printf(
" %ld flips.\n", flipcount);
11589 void tetgenmesh::undoflip(badface *lastflip)
11593 while (lastflip != (badface *) NULL) {
11595 findface(&lastflip->tt, lastflip->forg, lastflip->fdest, lastflip->fapex);
11596 fc = (
enum fliptype) (
int) lastflip->key;
11600 flip32(&lastflip->tt, NULL);
11604 flip23(&lastflip->tt, NULL);
11609 flip22(&lastflip->tt, NULL);
11615 lastflip = lastflip->previtem;
11629 long tetgenmesh::flipsub(queue* flipqueue)
11632 face flipedge, symedge;
11634 point pa, pb, pc, pd;
11635 REAL vab[3], vac[3], vad[3];
11636 REAL dot1, dot2, lac, lad;
11641 if (b->verbose > 1) {
11642 printf(
" Start do edge queue: %ld edges.\n", flipqueue->len());
11647 while (!flipqueue->empty()) {
11648 qedge = (badface *) flipqueue->pop();
11649 flipedge = qedge->ss;
11650 if (flipedge.sh == dummysh)
continue;
11651 if ((sorg(flipedge) != qedge->forg) ||
11652 (sdest(flipedge) != qedge->fdest))
continue;
11653 sspivot(flipedge, checkseg);
11654 if (checkseg.sh != dummysh)
continue;
11655 spivot(flipedge, symedge);
11656 if (symedge.sh == dummysh)
continue;
11657 pa = sorg(flipedge);
11658 pb = sdest(flipedge);
11659 pc = sapex(flipedge);
11660 pd = sapex(symedge);
11663 for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
11664 for (i = 0; i < 3; i++) vac[i] = pc[i] - pa[i];
11665 for (i = 0; i < 3; i++) vad[i] = pd[i] - pa[i];
11666 dot1 = dot(vac, vab);
11667 dot2 = dot(vad, vab);
11670 lac = dot(vac, vac);
11671 lad = dot(vad, vad);
11672 if (lad * dot1 <= lac * dot2) {
11674 abovepoint = facetabovepointarray[shellmark(flipedge)];
11675 if (abovepoint == (point) NULL) {
11676 getfacetabovepoint(&flipedge);
11678 sign = insphere(pa, pb, pc, abovepoint, pd);
11679 ori = orient3d(pa, pb, pc, abovepoint);
11682 abovepoint = facetabovepointarray[shellmark(symedge)];
11683 if (abovepoint == (point) NULL) {
11684 getfacetabovepoint(&symedge);
11686 sign = insphere(pa, pb, pd, abovepoint, pc);
11687 ori = orient3d(pa, pb, pd, abovepoint);
11690 sign = ori > 0.0 ? sign : -sign;
11693 flip22sub(&flipedge, flipqueue);
11698 if (b->verbose > 1) {
11699 printf(
" Total %d flips.\n", edgeflips);
11721 bool tetgenmesh::removetetbypeeloff(triface *striptet)
11723 triface abcd, badc;
11724 triface dcacasing, cdbcasing;
11730 adjustedgering(abcd, CCW);
11732 enextfnext(abcd, cdbcasing);
11733 enext2fnext(abcd, dcacasing);
11734 symself(cdbcasing);
11735 symself(dcacasing);
11738 if ((cdbcasing.tet == dummytet) || (dcacasing.tet == dummytet)) {
11744 if (checksubfaces) {
11748 tspivot(abcd, abc);
11749 tspivot(badc, bad);
11750 if (abc.sh != dummysh) {
11751 assert(bad.sh != dummysh);
11752 findedge(&abc, org(abcd), dest(abcd));
11753 findedge(&bad, org(badc), dest(badc));
11755 sspivot(abc, abseg);
11756 if (abseg.sh != dummysh) {
11758 if ((b->optlevel > 3) && (b->nobisect == 0)) {
11762 ang = facedihedral(org(abcd), dest(abcd), apex(abcd), oppo(abcd));
11763 ang = ang * 180.0 / PI;
11764 if ((ang + 9.0) > b->maxdihedral) {
11765 if (b->verbose > 1) {
11766 printf(
" Remove a segment during peeling.\n");
11768 face prevseg, nextseg;
11773 senext(abseg, nextseg);
11774 spivotself(nextseg);
11775 if (nextseg.sh != dummysh) {
11776 ssdissolve(nextseg);
11778 senext2(abseg, prevseg);
11779 spivotself(prevseg);
11780 if (prevseg.sh != dummysh) {
11781 ssdissolve(prevseg);
11783 shellfacedealloc(subsegs, abseg.sh);
11793 flip22sub(&abc, NULL);
11795 tsbond(cdbcasing, bad);
11796 tsbond(dcacasing, abc);
11801 dissolve(cdbcasing);
11802 dissolve(dcacasing);
11804 tetrahedrondealloc(abcd.tet);
11824 bool tetgenmesh::removeedgebyflip22(REAL *key,
int n, triface *abtetlist,
11827 point pa, pb, pc, pd, pe, pf;
11828 REAL cosmaxd, d1, d2, d3;
11832 pf = apex(abtetlist[2]);
11834 adjustedgering(abtetlist[0], CW);
11835 pa = org(abtetlist[0]);
11836 pb = dest(abtetlist[0]);
11837 pe = apex(abtetlist[0]);
11838 pc = oppo(abtetlist[0]);
11839 pd = apex(abtetlist[1]);
11841 pf = apex(abtetlist[2]);
11843 if (key && (*key > -1.0)) {
11844 tetalldihedral(pc, pd, pe, pa, NULL, &d1, NULL);
11845 tetalldihedral(pd, pc, pe, pb, NULL, &d2, NULL);
11846 cosmaxd = d1 < d2 ? d1 : d2;
11848 tetalldihedral(pd, pc, pf, pa, NULL, &d1, NULL);
11849 tetalldihedral(pc, pd, pf, pb, NULL, &d2, NULL);
11850 d3 = d1 < d2 ? d1 : d2;
11851 cosmaxd = cosmaxd < d3 ? cosmaxd : d3;
11853 doflip = (*key < cosmaxd);
11857 flip22(&abtetlist[0], NULL);
11859 if (key) *key = cosmaxd;
11884 bool tetgenmesh::removefacebyflip23(REAL *key, triface *abctetlist,
11885 triface *newtetlist, queue *flipque)
11887 triface edab, edbc, edca;
11888 triface newfront, oldfront, adjfront;
11890 point pa, pb, pc, pd, pe;
11891 REAL ori, cosmaxd, d1, d2, d3;
11892 REAL attrib, volume;
11898 adjustedgering(abctetlist[0], CCW);
11899 pa = org(abctetlist[0]);
11900 pb = dest(abctetlist[0]);
11901 pc = apex(abctetlist[0]);
11902 pd = oppo(abctetlist[0]);
11903 pe = oppo(abctetlist[1]);
11906 ori = orient3d(pe, pd, pa, pb);
11908 ori = orient3d(pe, pd, pb, pc);
11910 ori = orient3d(pe, pd, pc, pa);
11913 doflip = (ori < 0.0);
11914 if (doflip && (key != (REAL *) NULL)) {
11917 tetalldihedral(pe, pd, pa, pb, NULL, &d1, NULL);
11918 tetalldihedral(pe, pd, pb, pc, NULL, &d2, NULL);
11919 tetalldihedral(pe, pd, pc, pa, NULL, &d3, NULL);
11920 cosmaxd = d1 < d2 ? d1 : d2;
11921 cosmaxd = cosmaxd < d3 ? cosmaxd : d3;
11922 doflip = (*key < cosmaxd);
11930 maketetrahedron(&edab);
11935 maketetrahedron(&edbc);
11940 maketetrahedron(&edca);
11946 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
11947 attrib = elemattribute(abctetlist[0].tet, i);
11948 setelemattribute(edab.tet, i, attrib);
11949 setelemattribute(edbc.tet, i, attrib);
11950 setelemattribute(edca.tet, i, attrib);
11953 if (b->varvolume && !b->refine) {
11954 volume = volumebound(abctetlist[0].tet);
11955 setvolumebound(edab.tet, volume);
11956 setvolumebound(edbc.tet, volume);
11957 setvolumebound(edca.tet, volume);
11960 newtetlist[0] = edab;
11961 newtetlist[1] = edbc;
11962 newtetlist[2] = edca;
11964 for (i = 0; i < 3; i++) {
11965 fnext(newtetlist[i], newfront);
11966 bond(newfront, newtetlist[(i + 1) % 3]);
11969 for (i = 0; i < 3; i++) {
11970 fnext(abctetlist[0], oldfront);
11971 sym(oldfront, adjfront);
11972 enextfnext(newtetlist[i], newfront);
11973 bond(newfront, adjfront);
11974 if (checksubfaces) {
11975 tspivot(oldfront, checksh);
11976 if (checksh.sh != dummysh) {
11977 tsbond(newfront, checksh);
11980 if (flipque != (queue *) NULL) {
11981 enqueueflipface(newfront, flipque);
11983 enextself(abctetlist[0]);
11985 findedge(&(abctetlist[1]), pb, pa);
11986 for (i = 0; i < 3; i++) {
11987 fnext(abctetlist[1], oldfront);
11988 sym(oldfront, adjfront);
11989 enext2fnext(newtetlist[i], newfront);
11990 bond(newfront, adjfront);
11991 if (checksubfaces) {
11992 tspivot(oldfront, checksh);
11993 if (checksh.sh != dummysh) {
11994 tsbond(newfront, checksh);
11997 if (flipque != (queue *) NULL) {
11998 enqueueflipface(newfront, flipque);
12000 enext2self(abctetlist[1]);
12007 if (key != (REAL *) NULL) *key = cosmaxd;
12036 bool tetgenmesh::removeedgebyflip32(REAL *key, triface *abtetlist,
12037 triface *newtetlist, queue *flipque)
12039 triface dcea, cdeb;
12040 triface newfront, oldfront, adjfront;
12042 point pa, pb, pc, pd, pe;
12043 REAL ori, cosmaxd, d1, d2;
12044 REAL attrib, volume;
12048 pa = org(abtetlist[0]);
12049 pb = dest(abtetlist[0]);
12050 pc = apex(abtetlist[0]);
12051 pd = apex(abtetlist[1]);
12052 pe = apex(abtetlist[2]);
12054 ori = orient3d(pd, pc, pe, pa);
12056 ori = orient3d(pc, pd, pe, pb);
12058 doflip = (ori < 0.0);
12061 if (doflip && (key != (REAL *) NULL)) {
12064 tetalldihedral(pd, pc, pe, pa, NULL, &d1, NULL);
12065 tetalldihedral(pc, pd, pe, pb, NULL, &d2, NULL);
12066 cosmaxd = d1 < d2 ? d1 : d2;
12067 doflip = (*key < cosmaxd);
12075 maketetrahedron(&dcea);
12080 maketetrahedron(&cdeb);
12086 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12087 attrib = elemattribute(abtetlist[0].tet, i);
12088 setelemattribute(dcea.tet, i, attrib);
12089 setelemattribute(cdeb.tet, i, attrib);
12092 if (b->varvolume && !b->refine) {
12093 volume = volumebound(abtetlist[0].tet);
12094 setvolumebound(dcea.tet, volume);
12095 setvolumebound(cdeb.tet, volume);
12098 newtetlist[0] = dcea;
12099 newtetlist[1] = cdeb;
12103 for (i = 0; i < 3; i++) {
12104 fnext(dcea, newfront);
12105 esym(abtetlist[(i + 1) % 3], oldfront);
12106 enextfnextself(oldfront);
12108 sym(oldfront, adjfront);
12109 bond(newfront, adjfront);
12110 if (checksubfaces) {
12111 tspivot(oldfront, checksh);
12112 if (checksh.sh != dummysh) {
12113 tsbond(newfront, checksh);
12116 if (flipque != (queue *) NULL) {
12117 enqueueflipface(newfront, flipque);
12121 for (i = 0; i < 3; i++) {
12122 fnext(cdeb, newfront);
12123 esym(abtetlist[(i + 1) % 3], oldfront);
12124 enext2fnextself(oldfront);
12126 sym(oldfront, adjfront);
12127 bond(newfront, adjfront);
12128 if (checksubfaces) {
12129 tspivot(oldfront, checksh);
12130 if (checksh.sh != dummysh) {
12131 tsbond(newfront, checksh);
12134 if (flipque != (queue *) NULL) {
12135 enqueueflipface(newfront, flipque);
12190 bool tetgenmesh::removeedgebytranNM(REAL *key,
int n, triface *abtetlist,
12191 triface *newtetlist, point e1, point e2, queue *flipque)
12193 triface tmpabtetlist[9];
12194 triface newfront, oldfront, adjfront;
12196 point pa, pb, p[10];
12197 REAL ori, cosmaxd, d1, d2;
12199 REAL attrib, volume;
12200 bool doflip, copflag, success;
12207 pa = org(abtetlist[0]);
12208 pb = dest(abtetlist[0]);
12213 for (i = 0; i < n; i++) {
12215 for (j = 0; j < n; j++) {
12216 p[j] = apex(abtetlist[(i + j) % n]);
12219 if ((e1 != (point) NULL) && (e2 != (point) NULL)) {
12221 if (!(((p[1] == e1) && (p[n - 1] == e2)) ||
12222 ((p[1] == e2) && (p[n - 1] == e1))))
continue;
12230 ori = orient3d(pa, pb, p[1], p[n - 1]);
12231 copflag = (ori == 0.0);
12234 ori = orient3d(pb, p[0], p[1], p[n - 1]);
12236 ori = orient3d(p[0], pa, p[1], p[n - 1]);
12242 copflag ? flip44s++ : flip23s++;
12244 if (key != (REAL *) NULL) {
12249 tetalldihedral(p[n - 1], p[1], p[0], pa, NULL, &d1, NULL);
12250 tetalldihedral(p[1], p[n - 1], p[0], pb, NULL, &d2, NULL);
12251 cosmaxd = d1 < d2 ? d1 : d2;
12252 doflip = *key < cosmaxd;
12256 tmpkey = key != NULL ? *key : -1.0;
12258 maketetrahedron(&(newtetlist[0]));
12259 setorg(newtetlist[0], p[n - 1]);
12260 setdest(newtetlist[0], p[1]);
12261 setapex(newtetlist[0], p[0]);
12262 setoppo(newtetlist[0], pa);
12263 maketetrahedron(&(newtetlist[1]));
12264 setorg(newtetlist[1], p[1]);
12265 setdest(newtetlist[1], p[n - 1]);
12266 setapex(newtetlist[1], p[0]);
12267 setoppo(newtetlist[1], pb);
12269 maketetrahedron(&(tmpabtetlist[0]));
12270 setorg(tmpabtetlist[0], pa);
12271 setdest(tmpabtetlist[0], pb);
12272 setapex(tmpabtetlist[0], p[n - 1]);
12273 setoppo(tmpabtetlist[0], p[1]);
12274 for (j = 1; j < n - 1; j++) {
12275 maketetrahedron(&(tmpabtetlist[j]));
12276 setorg(tmpabtetlist[j], pa);
12277 setdest(tmpabtetlist[j], pb);
12278 setapex(tmpabtetlist[j], p[j]);
12279 setoppo(tmpabtetlist[j], p[j + 1]);
12282 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12283 attrib = elemattribute(abtetlist[0].tet, j);
12284 setelemattribute(newtetlist[0].tet, j, attrib);
12285 setelemattribute(newtetlist[1].tet, j, attrib);
12286 for (k = 0; k < n - 1; k++) {
12287 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12291 if (b->varvolume && !b->refine) {
12292 volume = volumebound(abtetlist[0].tet);
12293 setvolumebound(newtetlist[0].tet, volume);
12294 setvolumebound(newtetlist[1].tet, volume);
12295 for (k = 0; k < n - 1; k++) {
12296 setvolumebound(tmpabtetlist[k].tet, volume);
12300 bond(newtetlist[0], newtetlist[1]);
12301 fnext(newtetlist[0], newfront);
12302 enext2fnext(tmpabtetlist[0], adjfront);
12303 bond(newfront, adjfront);
12304 fnext(newtetlist[1], newfront);
12305 enextfnext(tmpabtetlist[0], adjfront);
12306 bond(newfront, adjfront);
12308 for (j = 0; j < n - 1; j++) {
12309 fnext(tmpabtetlist[j], newfront);
12310 bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]);
12318 for (j = 0; j < n; j++) {
12320 oldfront = abtetlist[(i + j) % n];
12321 esymself(oldfront);
12322 enextfnextself(oldfront);
12324 sym(oldfront, adjfront);
12327 enext2fnext(newtetlist[0], newfront);
12328 }
else if (j == 1) {
12329 enextfnext(newtetlist[0], newfront);
12331 enext2fnext(tmpabtetlist[j - 1], newfront);
12333 bond(newfront, adjfront);
12334 if (checksubfaces) {
12335 tspivot(oldfront, checksh);
12336 if (checksh.sh != dummysh) {
12337 tsbond(newfront, checksh);
12340 if (flipque != (queue *) NULL) {
12342 if (j < 2) enqueueflipface(newfront, flipque);
12345 for (j = 0; j < n; j++) {
12347 oldfront = abtetlist[(i + j) % n];
12348 esymself(oldfront);
12349 enext2fnextself(oldfront);
12351 sym(oldfront, adjfront);
12354 enextfnext(newtetlist[1], newfront);
12355 }
else if (j == 1) {
12356 enext2fnext(newtetlist[1], newfront);
12358 enextfnext(tmpabtetlist[j - 1], newfront);
12360 bond(newfront, adjfront);
12361 if (checksubfaces) {
12362 tspivot(oldfront, checksh);
12363 if (checksh.sh != dummysh) {
12364 tsbond(newfront, checksh);
12367 if (flipque != (queue *) NULL) {
12369 if (j < 2) enqueueflipface(newfront, flipque);
12374 for (j = 0; j < n - 1; j++) {
12375 fnextself(tmpabtetlist[j]);
12378 success = removeedgebytranNM(&tmpkey, n-1, tmpabtetlist,
12379 &(newtetlist[2]), NULL, NULL, flipque);
12381 success = removeedgebyflip32(&tmpkey, tmpabtetlist,
12382 &(newtetlist[2]), flipque);
12385 for (j = 0; j < n - 1; j++) {
12386 tetrahedrondealloc(tmpabtetlist[j].tet);
12395 if (key != (REAL *) NULL) {
12396 *key = (tmpkey < cosmaxd ? tmpkey : cosmaxd);
12401 for (j = 0; j < n; j++) {
12402 oldfront = abtetlist[(i + j) % n];
12403 esymself(oldfront);
12404 enextfnextself(oldfront);
12405 sym(oldfront, adjfront);
12406 bond(oldfront, adjfront);
12407 if (checksubfaces) {
12408 tspivot(oldfront, checksh);
12409 if (checksh.sh != dummysh) {
12410 tsbond(oldfront, checksh);
12414 for (j = 0; j < n; j++) {
12415 oldfront = abtetlist[(i + j) % n];
12416 esymself(oldfront);
12417 enext2fnextself(oldfront);
12418 sym(oldfront, adjfront);
12419 bond(oldfront, adjfront);
12420 if (checksubfaces) {
12421 tspivot(oldfront, checksh);
12422 if (checksh.sh != dummysh) {
12423 tsbond(oldfront, checksh);
12428 tetrahedrondealloc(newtetlist[0].tet);
12429 tetrahedrondealloc(newtetlist[1].tet);
12432 if (key && (tmpkey < *key)) {
12486 bool tetgenmesh::removeedgebycombNM(REAL *key,
int n, triface *abtetlist,
12487 int *n1, triface *bftetlist, triface *newtetlist, queue *flipque)
12489 triface tmpabtetlist[11];
12490 triface newfront, oldfront, adjfront;
12492 point pa, pb, p[10];
12493 REAL ori, tmpkey, tmpkey2;
12494 REAL attrib, volume;
12495 bool doflip, success;
12507 pa = org(abtetlist[0]);
12508 pb = dest(abtetlist[0]);
12510 for (i = 0; i < n; i++) {
12512 for (j = 0; j < n; j++) {
12513 p[j] = apex(abtetlist[(i + j) % n]);
12516 ori = orient3d(pb, p[0], p[1], p[n - 1]);
12517 if ((ori > 0) && (key != (REAL *) NULL)) {
12521 tetalldihedral(pb, p[0], p[n - 1], p[1], NULL, &tmpkey, NULL);
12522 if (tmpkey < *key) ori = 0.0;
12526 bftetlist[0] = abtetlist[i];
12527 enextself(bftetlist[0]);
12528 adjustedgering(bftetlist[0], CW);
12529 assert(apex(bftetlist[0]) == pa);
12535 if (*n1 == 10)
break;
12536 if (checksubfaces) {
12538 tspivot(bftetlist[*n1], checksh);
12539 if (checksh.sh != dummysh) {
12540 doflip =
false;
break;
12544 fnext(bftetlist[*n1], bftetlist[(*n1) + 1]);
12546 }
while (apex(bftetlist[*n1]) != pa);
12551 if (key != (REAL *) NULL) tmpkey = *key;
12555 success = removeedgebyflip32(&tmpkey,bftetlist,newtetlist,flipque);
12557 }
else if ((*n1 > 3) && (*n1 < 7)) {
12559 success = removeedgebytranNM(&tmpkey, *n1, bftetlist, newtetlist,
12560 p[1], p[n - 1], flipque);
12562 m = ((*n1) - 2) * 2;
12564 if (b->verbose > 1) {
12565 printf(
" !! Unhandled case: n1 = %d.\n", *n1);
12574 setpointmark(pa, -pointmark(pa) - 1);
12575 setpointmark(pb, -pointmark(pb) - 1);
12577 for (j = 0; j < m; j++) {
12578 tmpabtetlist[0] = newtetlist[j];
12581 for (k = 0; k < 4; k++) {
12582 if (pointmark((point)(tmpabtetlist[0].tet[4+k])) < 0) count++;
12586 for (tmpabtetlist[0].loc = 0; tmpabtetlist[0].loc < 4;
12587 tmpabtetlist[0].loc++) {
12588 if ((oppo(tmpabtetlist[0]) != pa) &&
12589 (oppo(tmpabtetlist[0]) != pb))
break;
12592 assert(tmpabtetlist[0].loc < 4);
12593 findedge(&(tmpabtetlist[0]), pa, pb);
12599 newtetlist[j] = newtetlist[m - 1];
12600 setpointmark(pa, -(pointmark(pa) + 1));
12601 setpointmark(pb, -(pointmark(pb) + 1));
12603 adjustedgering(tmpabtetlist[0], CCW);
12604 if (org(tmpabtetlist[0]) != pa) {
12605 fnextself(tmpabtetlist[0]);
12606 esymself(tmpabtetlist[0]);
12610 assert(org(tmpabtetlist[0]) == pa);
12611 assert(dest(tmpabtetlist[0]) == pb);
12612 assert(apex(tmpabtetlist[0]) == p[n - 1]);
12613 assert(oppo(tmpabtetlist[0]) == p[1]);
12614 #endif // SELF_CHECK 12616 for (j = 1; j < n - 1; j++) {
12617 maketetrahedron(&(tmpabtetlist[j]));
12618 setorg(tmpabtetlist[j], pa);
12619 setdest(tmpabtetlist[j], pb);
12620 setapex(tmpabtetlist[j], p[j]);
12621 setoppo(tmpabtetlist[j], p[j + 1]);
12624 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
12625 attrib = elemattribute(abtetlist[0].tet, j);
12626 for (k = 0; k < n - 1; k++) {
12627 setelemattribute(tmpabtetlist[k].tet, j, attrib);
12631 if (b->varvolume && !b->refine) {
12632 volume = volumebound(abtetlist[0].tet);
12633 for (k = 0; k < n - 1; k++) {
12634 setvolumebound(tmpabtetlist[k].tet, volume);
12638 for (j = 0; j < n - 1; j++) {
12639 fnext(tmpabtetlist[j], newfront);
12640 bond(newfront, tmpabtetlist[(j + 1) % (n - 1)]);
12648 for (j = 2; j < n; j++) {
12650 oldfront = abtetlist[(i + j) % n];
12651 esymself(oldfront);
12652 enextfnextself(oldfront);
12654 sym(oldfront, adjfront);
12657 enext2fnext(tmpabtetlist[j - 1], newfront);
12658 bond(newfront, adjfront);
12659 if (checksubfaces) {
12660 tspivot(oldfront, checksh);
12661 if (checksh.sh != dummysh) {
12662 tsbond(newfront, checksh);
12666 for (j = 2; j < n; j++) {
12668 oldfront = abtetlist[(i + j) % n];
12669 esymself(oldfront);
12670 enext2fnextself(oldfront);
12672 sym(oldfront, adjfront);
12675 enextfnext(tmpabtetlist[j - 1], newfront);
12676 bond(newfront, adjfront);
12677 if (checksubfaces) {
12678 tspivot(oldfront, checksh);
12679 if (checksh.sh != dummysh) {
12680 tsbond(newfront, checksh);
12686 for (j = 0; j < n - 1; j++) {
12687 fnextself(tmpabtetlist[j]);
12690 if (key) tmpkey2 = *key;
12691 if ((n - 1) == 3) {
12692 success = removeedgebyflip32(&tmpkey2, tmpabtetlist,
12693 &(newtetlist[m - 1]), flipque);
12695 success = removeedgebytranNM(&tmpkey2, n - 1, tmpabtetlist,
12696 &(newtetlist[m - 1]), NULL, NULL, flipque);
12699 for (j = 0; j < n - 1; j++) {
12700 tetrahedrondealloc(tmpabtetlist[j].tet);
12709 if (key != (REAL *) NULL) {
12710 *key = tmpkey2 < tmpkey ? tmpkey2 : tmpkey;
12715 for (j = 0; j < n; j++) {
12716 oldfront = abtetlist[(i + j) % n];
12717 esymself(oldfront);
12718 enextfnextself(oldfront);
12719 sym(oldfront, adjfront);
12720 bond(oldfront, adjfront);
12721 if (checksubfaces) {
12722 tspivot(oldfront, checksh);
12723 if (checksh.sh != dummysh) {
12724 tsbond(oldfront, checksh);
12728 for (j = 0; j < n; j++) {
12729 oldfront = abtetlist[(i + j) % n];
12730 esymself(oldfront);
12731 enext2fnextself(oldfront);
12732 sym(oldfront, adjfront);
12733 bond(oldfront, adjfront);
12734 if (checksubfaces) {
12735 tspivot(oldfront, checksh);
12736 if (checksh.sh != dummysh) {
12737 tsbond(oldfront, checksh);
12742 for (j = 0; j < *n1; j++) {
12743 oldfront = bftetlist[j];
12744 esymself(oldfront);
12745 enextfnextself(oldfront);
12746 sym(oldfront, adjfront);
12747 bond(oldfront, adjfront);
12748 if (checksubfaces) {
12749 tspivot(oldfront, checksh);
12750 if (checksh.sh != dummysh) {
12751 tsbond(oldfront, checksh);
12755 for (j = 0; j < *n1; j++) {
12756 oldfront = bftetlist[j];
12757 esymself(oldfront);
12758 enext2fnextself(oldfront);
12759 sym(oldfront, adjfront);
12760 bond(oldfront, adjfront);
12761 if (checksubfaces) {
12762 tspivot(oldfront, checksh);
12763 if (checksh.sh != dummysh) {
12764 tsbond(oldfront, checksh);
12770 for (j = 0; j < m - 1; j++) {
12771 tetrahedrondealloc(newtetlist[j].tet);
12779 for (i = 0; i < n; i++) newtetlist[i] = abtetlist[i];
12780 for (i = 0; i < n; i++) {
12781 oldfront = newtetlist[n - i - 1];
12782 esymself(oldfront);
12783 fnextself(oldfront);
12784 abtetlist[i] = oldfront;
12787 }
while (twice < 2);
12808 void tetgenmesh::splittetrahedron(point newpoint, triface* splittet,
12811 triface oldabd, oldbcd, oldcad;
12812 triface abdcasing, bcdcasing, cadcasing;
12813 face abdsh, bcdsh, cadsh;
12814 triface abcv, badv, cbdv, acdv;
12816 face abseg, bcseg, caseg;
12817 face adseg, bdseg, cdseg;
12818 point pa, pb, pc, pd;
12819 REAL attrib, volume;
12830 if (b->verbose > 1) {
12831 printf(
" Inserting point %d in tetrahedron (%d, %d, %d, %d).\n",
12832 pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc),
12836 fnext(abcv, oldabd);
12837 enextfnext(abcv, oldbcd);
12838 enext2fnext(abcv, oldcad);
12839 sym(oldabd, abdcasing);
12840 sym(oldbcd, bcdcasing);
12841 sym(oldcad, cadcasing);
12842 maketetrahedron(&badv);
12843 maketetrahedron(&cbdv);
12844 maketetrahedron(&acdv);
12850 setoppo(badv, newpoint);
12855 setoppo(cbdv, newpoint);
12860 setoppo(acdv, newpoint);
12862 setoppo(abcv, newpoint);
12865 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
12866 attrib = elemattribute(abcv.tet, i);
12867 setelemattribute(badv.tet, i, attrib);
12868 setelemattribute(cbdv.tet, i, attrib);
12869 setelemattribute(acdv.tet, i, attrib);
12872 if (b->varvolume) {
12873 volume = volumebound(abcv.tet);
12874 setvolumebound(badv.tet, volume);
12875 setvolumebound(cbdv.tet, volume);
12876 setvolumebound(acdv.tet, volume);
12880 bond(badv, abdcasing);
12881 bond(cbdv, bcdcasing);
12882 bond(acdv, cadcasing);
12884 if (checksubfaces) {
12885 tspivot(oldabd, abdsh);
12886 if (abdsh.sh != dummysh) {
12887 tsdissolve(oldabd);
12888 tsbond(badv, abdsh);
12890 tspivot(oldbcd, bcdsh);
12891 if (bcdsh.sh != dummysh) {
12892 tsdissolve(oldbcd);
12893 tsbond(cbdv, bcdsh);
12895 tspivot(oldcad, cadsh);
12896 if (cadsh.sh != dummysh) {
12897 tsdissolve(oldcad);
12898 tsbond(acdv, cadsh);
12900 }
else if (checksubsegs) {
12901 tsspivot1(abcv, abseg);
12902 if (abseg.sh != dummysh) {
12903 tssbond1(badv, abseg);
12905 enext(abcv, worktet);
12906 tsspivot1(worktet, bcseg);
12907 if (bcseg.sh != dummysh) {
12908 tssbond1(cbdv, bcseg);
12910 enext2(abcv, worktet);
12911 tsspivot1(worktet, caseg);
12912 if (caseg.sh != dummysh) {
12913 tssbond1(acdv, caseg);
12915 fnext(abcv, worktet);
12916 enext2self(worktet);
12917 tsspivot1(worktet, adseg);
12918 if (adseg.sh != dummysh) {
12919 tssdissolve1(worktet);
12920 enext(badv, worktet);
12921 tssbond1(worktet, adseg);
12922 enext2(acdv, worktet);
12923 tssbond1(worktet, adseg);
12925 enextfnext(abcv, worktet);
12926 enext2self(worktet);
12927 tsspivot1(worktet, bdseg);
12928 if (bdseg.sh != dummysh) {
12929 tssdissolve1(worktet);
12930 enext(cbdv, worktet);
12931 tssbond1(worktet, bdseg);
12932 enext2(badv, worktet);
12933 tssbond1(worktet, bdseg);
12935 enext2fnext(abcv, worktet);
12936 enext2self(worktet);
12937 tsspivot1(worktet, cdseg);
12938 if (cdseg.sh != dummysh) {
12939 tssdissolve1(worktet);
12940 enext(acdv, worktet);
12941 tssbond1(worktet, cdseg);
12942 enext2(cbdv, worktet);
12943 tssbond1(worktet, cdseg);
12956 bond(badv, oldabd);
12958 bond(cbdv, oldbcd);
12960 bond(acdv, oldcad);
12965 if (b->verbose > 3) {
12966 printf(
" Updating abcv ");
12968 printf(
" Creating badv ");
12970 printf(
" Creating cbdv ");
12972 printf(
" Creating acdv ");
12976 if (flipqueue != (queue *) NULL) {
12977 enqueueflipface(abcv, flipqueue);
12978 enqueueflipface(badv, flipqueue);
12979 enqueueflipface(cbdv, flipqueue);
12980 enqueueflipface(acdv, flipqueue);
13004 void tetgenmesh::unsplittetrahedron(triface* splittet)
13006 triface abcv, badv, cbdv, acdv;
13007 triface oldabv, oldbcv, oldcav;
13008 triface badcasing, cbdcasing, acdcasing;
13009 face badsh, cbdsh, acdsh;
13012 adjustedgering(abcv, CCW);
13013 fnext(abcv, oldabv);
13014 fnext(oldabv, badv);
13016 enextfnext(abcv, oldbcv);
13017 fnext(oldbcv, cbdv);
13019 enext2fnext(abcv, oldcav);
13020 fnext(oldcav, acdv);
13023 if (b->verbose > 1) {
13024 printf(
" Removing point %d in tetrahedron (%d, %d, %d, %d).\n",
13025 pointmark(oppo(abcv)), pointmark(org(abcv)), pointmark(dest(abcv)),
13026 pointmark(apex(abcv)), pointmark(apex(badv)));
13029 sym(badv, badcasing);
13030 tspivot(badv, badsh);
13031 sym(cbdv, cbdcasing);
13032 tspivot(cbdv, cbdsh);
13033 sym(acdv, acdcasing);
13034 tspivot(acdv, acdsh);
13037 setoppo(abcv, apex(badv));
13038 bond(oldabv, badcasing);
13039 if (badsh.sh != dummysh) {
13040 tsbond(oldabv, badsh);
13042 bond(oldbcv, cbdcasing);
13043 if (cbdsh.sh != dummysh) {
13044 tsbond(oldbcv, cbdsh);
13046 bond(oldcav, acdcasing);
13047 if (acdsh.sh != dummysh) {
13048 tsbond(oldcav, acdsh);
13052 tetrahedrondealloc(badv.tet);
13053 tetrahedrondealloc(cbdv.tet);
13054 tetrahedrondealloc(acdv.tet);
13078 void tetgenmesh::splittetface(point newpoint, triface* splittet,
13081 triface abcd, bace;
13082 triface oldbcd, oldcad, oldace, oldcbe;
13083 triface bcdcasing, cadcasing, acecasing, cbecasing;
13084 face abcsh, bcdsh, cadsh, acesh, cbesh;
13085 triface abvd, bcvd, cavd, bave, cbve, acve;
13088 face adseg, bdseg, cdseg;
13089 face aeseg, beseg, ceseg;
13090 point pa, pb, pc, pd, pe;
13091 REAL attrib, volume;
13097 adjustedgering(abcd, CCW);
13104 mirrorflag = issymexist(&abcd);
13108 findedge(&bace, dest(abcd), org(abcd));
13111 if (checksubfaces) {
13113 tspivot(abcd, abcsh);
13114 if (abcsh.sh != dummysh) {
13116 findedge(&abcsh, org(abcd), dest(abcd));
13120 if (b->verbose > 1) {
13121 printf(
" Inserting point %d on face (%d, %d, %d).\n", pointmark(newpoint),
13122 pointmark(pa), pointmark(pb), pointmark(pc));
13126 enextfnext(abcd, oldbcd);
13127 enext2fnext(abcd, oldcad);
13128 sym(oldbcd, bcdcasing);
13129 sym(oldcad, cadcasing);
13131 maketetrahedron(&bcvd);
13132 maketetrahedron(&cavd);
13135 enextfnext(bace, oldace);
13136 enext2fnext(bace, oldcbe);
13137 sym(oldace, acecasing);
13138 sym(oldcbe, cbecasing);
13140 maketetrahedron(&acve);
13141 maketetrahedron(&cbve);
13149 setapex(abvd, newpoint);
13152 setapex(bcvd, newpoint);
13156 setapex(cavd, newpoint);
13159 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13160 attrib = elemattribute(abvd.tet, i);
13161 setelemattribute(bcvd.tet, i, attrib);
13162 setelemattribute(cavd.tet, i, attrib);
13164 if (b->varvolume) {
13166 volume = volumebound(abvd.tet);
13167 setvolumebound(bcvd.tet, volume);
13168 setvolumebound(cavd.tet, volume);
13172 setapex(bave, newpoint);
13175 setapex(acve, newpoint);
13179 setapex(cbve, newpoint);
13182 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
13183 attrib = elemattribute(bave.tet, i);
13184 setelemattribute(acve.tet, i, attrib);
13185 setelemattribute(cbve.tet, i, attrib);
13187 if (b->varvolume) {
13189 volume = volumebound(bave.tet);
13190 setvolumebound(acve.tet, volume);
13191 setvolumebound(cbve.tet, volume);
13197 bond(bcvd, bcdcasing);
13199 bond(cavd, cadcasing);
13201 bond(bcvd, oldbcd);
13203 bond(cavd, oldcad);
13209 bond(acve, acecasing);
13211 bond(cbve, cbecasing);
13213 bond(acve, oldace);
13215 bond(cbve, oldcbe);
13229 if (checksubfaces) {
13230 tspivot(oldbcd, bcdsh);
13231 if (bcdsh.sh != dummysh) {
13232 tsdissolve(oldbcd);
13234 tsbond(bcvd, bcdsh);
13236 tspivot(oldcad, cadsh);
13237 if (cadsh.sh != dummysh) {
13238 tsdissolve(oldcad);
13240 tsbond(cavd, cadsh);
13243 tspivot(oldace, acesh);
13244 if (acesh.sh != dummysh) {
13245 tsdissolve(oldace);
13247 tsbond(acve, acesh);
13249 tspivot(oldcbe, cbesh);
13250 if (cbesh.sh != dummysh) {
13251 tsdissolve(oldcbe);
13253 tsbond(cbve, cbesh);
13257 if (abcsh.sh != dummysh) {
13259 splitsubface(newpoint, &abcsh, (queue *) NULL);
13261 }
else if (checksubsegs) {
13263 bcvd.loc = bcvd.ver = 0;
13264 cavd.loc = cavd.ver = 0;
13267 cbve.loc = cbve.ver = 0;
13268 acve.loc = acve.ver = 0;
13270 enext(abvd, worktet);
13271 tsspivot1(worktet, bcseg);
13272 if (bcseg.sh != dummysh) {
13273 tssdissolve1(worktet);
13274 tssbond1(bcvd, bcseg);
13276 enext2(bave, worktet);
13277 tssdissolve1(worktet);
13278 tssbond1(cbve, bcseg);
13281 enext2(abvd, worktet);
13282 tsspivot1(worktet, caseg);
13283 if (caseg.sh != dummysh) {
13284 tssdissolve1(worktet);
13285 tssbond1(cavd, caseg);
13287 enext(bave, worktet);
13288 tssdissolve1(worktet);
13289 tssbond1(acve, caseg);
13292 fnext(abvd, worktet);
13293 enext2self(worktet);
13294 tsspivot1(worktet, adseg);
13295 if (adseg.sh != dummysh) {
13296 fnext(cavd, worktet);
13297 enextself(worktet);
13298 tssbond1(worktet, adseg);
13300 fnext(abvd, worktet);
13301 enextself(worktet);
13302 tsspivot1(worktet, bdseg);
13303 if (bdseg.sh != dummysh) {
13304 fnext(bcvd, worktet);
13305 enext2self(worktet);
13306 tssbond1(worktet, bdseg);
13308 enextfnext(abvd, worktet);
13309 enextself(worktet);
13310 tsspivot1(worktet, cdseg);
13311 if (cdseg.sh != dummysh) {
13312 tssdissolve1(worktet);
13313 fnext(bcvd, worktet);
13314 enextself(worktet);
13315 tssbond1(worktet, cdseg);
13316 fnext(cavd, worktet);
13317 enext2self(worktet);
13318 tssbond1(worktet, cdseg);
13321 fnext(bave, worktet);
13322 enextself(worktet);
13323 tsspivot1(worktet, aeseg);
13324 if (aeseg.sh != dummysh) {
13325 fnext(acve, worktet);
13326 enext2self(worktet);
13327 tssbond1(worktet, aeseg);
13329 fnext(bave, worktet);
13330 enext2self(worktet);
13331 tsspivot1(worktet, beseg);
13332 if (beseg.sh != dummysh) {
13333 fnext(cbve, worktet);
13334 enextself(worktet);
13335 tssbond1(worktet, beseg);
13337 enextfnext(bave, worktet);
13338 enextself(worktet);
13339 tsspivot1(worktet, ceseg);
13340 if (ceseg.sh != dummysh) {
13341 tssdissolve1(worktet);
13342 fnext(cbve, worktet);
13343 enext2self(worktet);
13344 tssbond1(worktet, ceseg);
13345 fnext(acve, worktet);
13346 enextself(worktet);
13347 tssbond1(worktet, ceseg);
13363 if (b->verbose > 3) {
13364 printf(
" Updating abvd ");
13366 printf(
" Creating bcvd ");
13368 printf(
" Creating cavd ");
13371 printf(
" Updating bave ");
13373 printf(
" Creating cbve ");
13375 printf(
" Creating acve ");
13380 if (flipqueue != (queue *) NULL) {
13382 enqueueflipface(abvd, flipqueue);
13384 enqueueflipface(bcvd, flipqueue);
13386 enqueueflipface(cavd, flipqueue);
13389 enqueueflipface(bave, flipqueue);
13391 enqueueflipface(cbve, flipqueue);
13393 enqueueflipface(acve, flipqueue);
13417 void tetgenmesh::unsplittetface(triface* splittet)
13419 triface abvd, bcvd, cavd, bave, cbve, acve;
13420 triface oldbvd, oldvad, oldvbe, oldave;
13421 triface bcdcasing, cadcasing, cbecasing, acecasing;
13422 face bcdsh, cadsh, cbesh, acesh;
13427 adjustedgering(abvd, CCW);
13428 enextfnext(abvd, oldbvd);
13429 fnext(oldbvd, bcvd);
13432 enext2fnext(abvd, oldvad);
13433 fnext(oldvad, cavd);
13438 mirrorflag = bave.tet != dummytet;
13440 findedge(&bave, dest(abvd), org(abvd));
13441 enextfnext(bave, oldave);
13442 fnext(oldave, acve);
13445 enext2fnext(bave, oldvbe);
13446 fnext(oldvbe, cbve);
13454 tspivot(abvd, abvsh);
13455 if (abvsh.sh != dummysh) {
13457 findedge(&abvsh, org(abvd), dest(abvd));
13460 if (b->verbose > 1) {
13461 printf(
" Removing point %d on face (%d, %d, %d).\n",
13462 pointmark(apex(abvd)), pointmark(org(abvd)), pointmark(dest(abvd)),
13463 pointmark(dest(bcvd)));
13467 sym(bcvd, bcdcasing);
13468 tspivot(bcvd, bcdsh);
13470 sym(cavd, cadcasing);
13471 tspivot(cavd, cadsh);
13474 sym(acve, acecasing);
13475 tspivot(acve, acesh);
13477 sym(cbve, cbecasing);
13478 tspivot(cbve, cbesh);
13482 setapex(abvd, dest(bcvd));
13483 bond(oldbvd, bcdcasing);
13484 if (bcdsh.sh != dummysh) {
13485 tsbond(oldbvd, bcdsh);
13487 bond(oldvad, cadcasing);
13488 if (cadsh.sh != dummysh) {
13489 tsbond(oldvad, cadsh);
13493 setapex(bave, dest(acve));
13494 bond(oldave, acecasing);
13495 if (acesh.sh != dummysh) {
13496 tsbond(oldave, acesh);
13498 bond(oldvbe, cbecasing);
13499 if (cbesh.sh != dummysh) {
13500 tsbond(oldvbe, cbesh);
13505 if (abvsh.sh != dummysh) {
13506 unsplitsubface(&abvsh);
13510 tetrahedrondealloc(bcvd.tet);
13511 tetrahedrondealloc(cavd.tet);
13513 tetrahedrondealloc(acve.tet);
13514 tetrahedrondealloc(cbve.tet);
13542 void tetgenmesh::splitsubface(point newpoint, face* splitface,
13545 triface abvd, bcvd, cavd, bave, cbve, acve;
13546 face abc, oldbc, oldca, bc, ca, spinsh;
13547 face bccasin, bccasout, cacasin, cacasout;
13548 face abv, bcv, cav;
13553 adjustedgering(abc, CCW);
13558 if (b->verbose > 1) {
13559 printf(
" Inserting point %d on subface (%d, %d, %d).\n",
13560 pointmark(newpoint), pointmark(pa), pointmark(pb), pointmark(pc));
13565 senext(abc, oldbc);
13566 senext2(abc, oldca);
13567 spivot(oldbc, bccasout);
13568 sspivot(oldbc, bc);
13569 if (bc.sh != dummysh) {
13570 if (oldbc.sh != bccasout.sh) {
13575 spivotself(spinsh);
13576 }
while (spinsh.sh != oldbc.sh);
13578 bccasout.sh = dummysh;
13582 spivot(oldca, cacasout);
13583 sspivot(oldca, ca);
13584 if (ca.sh != dummysh) {
13585 if (oldca.sh != cacasout.sh) {
13590 spivotself(spinsh);
13591 }
while (spinsh.sh != oldca.sh);
13593 cacasout.sh = dummysh;
13598 makeshellface(subfaces, &bcv);
13599 makeshellface(subfaces, &cav);
13603 setsapex(abv, newpoint);
13606 setsapex(bcv, newpoint);
13609 setsapex(cav, newpoint);
13610 if (b->quality && varconstraint) {
13612 setareabound(bcv, areabound(abv));
13613 setareabound(cav, areabound(abv));
13616 setshellmark(bcv, shellmark(abv));
13617 setshellmark(cav, shellmark(abv));
13619 setshelltype(bcv, shelltype(abv));
13620 setshelltype(cav, shelltype(abv));
13623 setshellpbcgroup(bcv, shellpbcgroup(abv));
13624 setshellpbcgroup(cav, shellpbcgroup(abv));
13627 if (bc.sh != dummysh) {
13628 if (bccasout.sh != dummysh) {
13629 sbond1(bccasin, bcv);
13630 sbond1(bcv, bccasout);
13637 sbond(bcv, bccasout);
13639 if (ca.sh != dummysh) {
13640 if (cacasout.sh != dummysh) {
13641 sbond1(cacasin, cav);
13642 sbond1(cav, cacasout);
13649 sbond(cav, cacasout);
13660 stpivot(abv, abvd);
13661 if (abvd.tet != dummytet) {
13663 findedge(&abvd, sorg(abv), sdest(abv));
13664 enextfnext(abvd, bcvd);
13666 assert(bcvd.tet != dummytet);
13669 enext2fnext(abvd, cavd);
13671 assert(cavd.tet != dummytet);
13680 stpivot(abv, bave);
13681 if (bave.tet != dummytet) {
13685 findedge(&bave, sorg(abv), sdest(abv));
13686 enextfnext(bave, acve);
13688 assert(acve.tet != dummytet);
13691 enext2fnext(bave, cbve);
13693 assert(cbve.tet != dummytet);
13703 if (b->verbose > 3) {
13704 printf(
" Updating abv ");
13706 printf(
" Creating bcv ");
13708 printf(
" Creating cav ");
13712 if (flipqueue != (queue *) NULL) {
13713 enqueueflipedge(abv, flipqueue);
13714 enqueueflipedge(bcv, flipqueue);
13715 enqueueflipedge(cav, flipqueue);
13737 void tetgenmesh::unsplitsubface(face* splitsh)
13739 face abv, bcv, cav;
13740 face oldbv, oldva, bc, ca, spinsh;
13741 face bccasin, bccasout, cacasin, cacasout;
13744 senext(abv, oldbv);
13745 spivot(oldbv, bcv);
13746 if (sorg(bcv) != sdest(oldbv)) {
13750 senext2(abv, oldva);
13751 spivot(oldva, cav);
13752 if (sorg(cav) != sdest(oldva)) {
13757 if (b->verbose > 1) {
13758 printf(
" Removing point %d on subface (%d, %d, %d).\n",
13759 pointmark(sapex(abv)), pointmark(sorg(abv)), pointmark(sdest(abv)),
13760 pointmark(sdest(bcv)));
13763 spivot(bcv, bccasout);
13765 if (bc.sh != dummysh) {
13766 if (bcv.sh != bccasout.sh) {
13771 spivotself(spinsh);
13772 }
while (spinsh.sh != bcv.sh);
13774 bccasout.sh = dummysh;
13777 spivot(cav, cacasout);
13779 if (ca.sh != dummysh) {
13780 if (cav.sh != cacasout.sh) {
13785 spivotself(spinsh);
13786 }
while (spinsh.sh != cav.sh);
13788 cacasout.sh = dummysh;
13793 setsapex(abv, sdest(bcv));
13794 if (bc.sh != dummysh) {
13795 if (bccasout.sh != dummysh) {
13796 sbond1(bccasin, oldbv);
13797 sbond1(oldbv, bccasout);
13800 sbond(oldbv, oldbv);
13804 sbond(oldbv, bccasout);
13806 if (ca.sh != dummysh) {
13807 if (cacasout.sh != dummysh) {
13808 sbond1(cacasin, oldva);
13809 sbond1(oldva, cacasout);
13812 sbond(oldva, oldva);
13816 sbond(oldva, cacasout);
13820 shellfacedealloc(subfaces, bcv.sh);
13821 shellfacedealloc(subfaces, cav.sh);
13848 void tetgenmesh::splittetedge(point newpoint, triface* splittet,
13851 triface *bots, *newtops;
13852 triface oldtop, topcasing;
13853 triface spintet, tmpbond0, tmpbond1;
13854 face abseg, splitsh, topsh, spinsh;
13856 face n1n2seg, n2vseg, n1vseg;
13857 point pa, pb, n1, n2;
13858 REAL attrib, volume;
13859 int wrapcount, hitbdry;
13862 if (checksubfaces) {
13864 tsspivot(splittet, &abseg);
13865 if (abseg.sh != dummysh) {
13868 if (org(*splittet) != sorg(abseg)) {
13869 esymself(*splittet);
13873 spintet = *splittet;
13875 pb = dest(spintet);
13877 if (b->verbose > 1) {
13878 printf(
" Inserting point %d on edge (%d, %d).\n",
13879 pointmark(newpoint), pointmark(pa), pointmark(pb));
13883 n1 = apex(spintet);
13886 if (checksubfaces && abseg.sh != dummysh) {
13891 if (!fnextself(spintet)) {
13894 tspivot(spintet, spinsh);
13896 assert(spinsh.sh != dummysh);
13898 findedge(&spinsh, pa, pb);
13899 sfnextself(spinsh);
13900 stpivot(spinsh, spintet);
13902 assert(spintet.tet != dummytet);
13904 findedge(&spintet, pa, pb);
13906 *splittet = spintet;
13910 if (apex(spintet) == n1)
break;
13914 wrapcount -= hitbdry;
13919 splitsh.sh = dummysh;
13920 while (hitbdry < 2) {
13921 if (checksubfaces && splitsh.sh == dummysh) {
13922 tspivot(spintet, splitsh);
13924 if (fnextself(spintet)) {
13925 if (apex(spintet) == n1)
break;
13930 esym(*splittet, spintet);
13938 esym(spintet, *splittet);
13945 bots =
new triface[wrapcount];
13946 newtops =
new triface[wrapcount];
13948 spintet = *splittet;
13949 for (i = 0; i < wrapcount; i++) {
13951 enext2fnext(spintet, bots[i]);
13954 maketetrahedron(&(newtops[i]));
13956 fnextself(spintet);
13957 if (checksubfaces && abseg.sh != dummysh) {
13958 if (!issymexist(&spintet)) {
13960 tspivot(spintet, spinsh);
13962 assert(spinsh.sh != dummysh);
13964 findedge(&spinsh, pa, pb);
13965 sfnextself(spinsh);
13966 stpivot(spinsh, spintet);
13968 assert(spintet.tet != dummytet);
13970 findedge(&spintet, pa, pb);
13976 for (i = 0; i < wrapcount; i++) {
13978 setoppo(bots[i], newpoint);
13980 n1 = dest(bots[i]);
13981 n2 = apex(bots[i]);
13983 setorg(newtops[i], pb);
13984 setdest(newtops[i], n2);
13985 setapex(newtops[i], n1);
13986 setoppo(newtops[i], newpoint);
13988 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
13989 attrib = elemattribute(bots[i].tet, j);
13990 setelemattribute(newtops[i].tet, j, attrib);
13992 if (b->varvolume) {
13994 volume = volumebound(bots[i].tet);
13995 setvolumebound(newtops[i].tet, volume);
14011 for (i = 0; i < wrapcount; i++) {
14013 enextfnext(bots[i], oldtop);
14014 sym(oldtop, topcasing);
14015 bond(newtops[i], topcasing);
14016 if (checksubfaces) {
14017 tspivot(oldtop, topsh);
14018 if (topsh.sh != dummysh) {
14019 tsdissolve(oldtop);
14020 tsbond(newtops[i], topsh);
14023 enextfnext(newtops[i], tmpbond0);
14024 bond(oldtop, tmpbond0);
14027 fnext(newtops[0], tmpbond0);
14028 enext2fnext(bots[0], spintet);
14029 for (i = 1; i < wrapcount; i ++) {
14030 if (issymexist(&spintet)) {
14031 enext2fnext(newtops[i], tmpbond1);
14032 bond(tmpbond0, tmpbond1);
14034 fnext(newtops[i], tmpbond0);
14035 enext2fnext(bots[i], spintet);
14038 if (issymexist(&spintet)) {
14039 enext2fnext(newtops[0], tmpbond1);
14040 bond(tmpbond0, tmpbond1);
14042 if (checksubsegs) {
14043 for (i = 0; i < wrapcount; i++) {
14044 enextfnext(bots[i], worktet);
14045 tsspivot1(worktet, n1n2seg);
14046 if (n1n2seg.sh != dummysh) {
14047 enext(newtops[i], tmpbond0);
14048 tssbond1(tmpbond0, n1n2seg);
14050 enextself(worktet);
14051 tsspivot1(worktet, n2vseg);
14052 if (n2vseg.sh != dummysh) {
14053 tssdissolve1(worktet);
14054 tssbond1(newtops[i], n2vseg);
14056 enextself(worktet);
14057 tsspivot1(worktet, n1vseg);
14058 if (n1vseg.sh != dummysh) {
14059 tssdissolve1(worktet);
14060 enext2(newtops[i], tmpbond0);
14061 tssbond1(tmpbond0, n1vseg);
14067 if (checksubfaces) {
14068 if (abseg.sh != dummysh) {
14070 spivot(abseg, splitsh);
14072 assert(splitsh.sh != dummysh);
14075 if (splitsh.sh != dummysh) {
14077 findedge(&splitsh, pa, pb);
14078 splitsubedge(newpoint, &splitsh, (queue *) NULL);
14082 if (b->verbose > 3) {
14083 for (i = 0; i < wrapcount; i++) {
14084 printf(
" Updating bots[%i] ", i);
14085 printtet(&(bots[i]));
14086 printf(
" Creating newtops[%i] ", i);
14087 printtet(&(newtops[i]));
14091 if (flipqueue != (queue *) NULL) {
14092 for (i = 0; i < wrapcount; i++) {
14093 enqueueflipface(bots[i], flipqueue);
14094 enqueueflipface(newtops[i], flipqueue);
14100 fnext(bots[0], spintet);
14102 enextself(spintet);
14103 *splittet = spintet;
14127 void tetgenmesh::unsplittetedge(triface* splittet)
14129 triface *bots, *newtops;
14130 triface oldtop, topcasing;
14132 face avseg, splitsh, topsh, spinsh;
14134 int wrapcount, hitbdry;
14137 spintet = *splittet;
14139 pv = dest(spintet);
14140 if (checksubfaces) {
14142 tsspivot(splittet, &avseg);
14143 if (avseg.sh != dummysh) {
14145 if (sorg(avseg) != pa) {
14151 n1 = apex(spintet);
14154 if (checksubfaces && avseg.sh != dummysh) {
14159 if (!fnextself(spintet)) {
14162 tspivot(spintet, spinsh);
14164 assert(spinsh.sh != dummysh);
14166 findedge(&spinsh, pa, pv);
14167 sfnextself(spinsh);
14168 stpivot(spinsh, spintet);
14170 assert(spintet.tet != dummytet);
14172 findedge(&spintet, pa, pv);
14174 *splittet = spintet;
14178 if (apex(spintet) == n1)
break;
14182 wrapcount -= hitbdry;
14187 splitsh.sh = dummysh;
14188 while (hitbdry < 2) {
14189 if (checksubfaces && splitsh.sh == dummysh) {
14190 tspivot(spintet, splitsh);
14192 if (fnextself(spintet)) {
14193 if (apex(spintet) == n1)
break;
14198 esym(*splittet, spintet);
14206 esym(spintet, *splittet);
14213 bots =
new triface[wrapcount];
14214 newtops =
new triface[wrapcount];
14216 spintet = *splittet;
14217 for (i = 0; i < wrapcount; i++) {
14219 enext2fnext(spintet, bots[i]);
14222 enextfnext(bots[i], oldtop);
14224 fnext(oldtop, newtops[i]);
14225 esymself(newtops[i]);
14226 enext2self(newtops[i]);
14228 fnextself(spintet);
14229 if (checksubfaces && avseg.sh != dummysh) {
14230 if (!issymexist(&spintet)) {
14232 tspivot(spintet, spinsh);
14234 assert(spinsh.sh != dummysh);
14236 findedge(&spinsh, pa, pv);
14237 sfnextself(spinsh);
14238 stpivot(spinsh, spintet);
14240 assert(spintet.tet != dummytet);
14242 findedge(&spintet, pa, pv);
14247 if (b->verbose > 1) {
14248 printf(
" Removing point %d from edge (%d, %d).\n",
14249 pointmark(oppo(bots[0])), pointmark(org(bots[0])),
14250 pointmark(org(newtops[0])));
14253 for (i = 0; i < wrapcount; i++) {
14255 setoppo(bots[i], org(newtops[i]));
14257 enextfnext(bots[i], oldtop);
14259 sym(newtops[i], topcasing);
14261 bond(oldtop, topcasing);
14262 if (checksubfaces) {
14263 tspivot(newtops[i], topsh);
14264 if (topsh.sh != dummysh) {
14265 tsbond(oldtop, topsh);
14269 tetrahedrondealloc(newtops[i].tet);
14273 if (checksubfaces) {
14274 if (avseg.sh != dummysh) {
14275 spivot(avseg, splitsh);
14277 assert(splitsh.sh != dummysh);
14280 if (splitsh.sh != dummysh) {
14281 findedge(&splitsh, pa, pv);
14282 unsplitsubedge(&splitsh);
14313 void tetgenmesh::splitsubedge(point newpoint, face* splitsh, queue* flipqueue)
14315 triface abcd, bace, vbcd, bvce;
14316 face startabc, spinabc, spinsh;
14317 face oldbc, bccasin, bccasout;
14319 face avc, vbc, vbc1;
14323 startabc = *splitsh;
14325 sspivot(startabc, ab);
14326 if (ab.sh != dummysh) {
14328 if (sorg(startabc) != sorg(ab)) {
14329 sesymself(startabc);
14332 pa = sorg(startabc);
14333 pb = sdest(startabc);
14335 if (b->verbose > 1) {
14336 printf(
" Inserting point %d on subedge (%d, %d) %s.\n",
14337 pointmark(newpoint), pointmark(pa), pointmark(pb),
14338 (ab.sh != dummysh ?
"(seg)" :
" "));
14342 spinabc = startabc;
14345 if (sorg(spinabc) != pa) {
14346 sesymself(spinabc);
14350 senext(spinabc, oldbc);
14351 spivot(oldbc, bccasout);
14352 sspivot(oldbc, bc);
14353 if (bc.sh != dummysh) {
14354 if (spinabc.sh != bccasout.sh) {
14359 spivotself(spinsh);
14360 }
while (spinsh.sh != oldbc.sh);
14362 bccasout.sh = dummysh;
14367 makeshellface(subfaces, &vbc);
14370 setsdest(avc, newpoint);
14372 vbc.shver = avc.shver;
14373 setsorg(vbc, newpoint);
14375 setsapex(vbc, sapex(avc));
14376 if (b->quality && varconstraint) {
14378 setareabound(vbc, areabound(avc));
14381 setshellmark(vbc, shellmark(avc));
14382 setshelltype(vbc, shelltype(avc));
14385 setshellpbcgroup(vbc, shellpbcgroup(avc));
14392 if (bc.sh != dummysh) {
14393 if (bccasout.sh != dummysh) {
14395 sbond1(bccasin, vbc);
14396 sbond1(vbc, bccasout);
14403 sbond(vbc, bccasout);
14406 spivotself(spinabc);
14407 if (spinabc.sh == dummysh) {
14410 }
while (spinabc.sh != startabc.sh);
14413 senext(startabc, oldbc);
14414 spivot(oldbc, vbc);
14415 if (sorg(vbc) == newpoint) {
14419 assert(sorg(vbc) == sdest(oldbc) && sdest(vbc) == sorg(oldbc));
14423 spinabc = startabc;
14426 spivotself(spinabc);
14427 if (spinabc.sh == dummysh) {
14430 if (sorg(spinabc) != pa) {
14431 sesymself(spinabc);
14434 senext(spinabc, oldbc);
14435 spivot(oldbc, vbc1);
14436 if (sorg(vbc1) == newpoint) {
14440 assert(sorg(vbc1) == sdest(oldbc) && sdest(vbc1) == sorg(oldbc));
14447 }
while (spinabc.sh != startabc.sh);
14450 if (ab.sh != dummysh) {
14453 setsdest(av, newpoint);
14455 makeshellface(subsegs, &vb);
14456 setsorg(vb, newpoint);
14459 setshellmark(vb, shellmark(av));
14460 setshelltype(vb, shelltype(av));
14461 if (b->quality && varconstraint) {
14463 setareabound(vb, areabound(av));
14467 spivot(oldbc, bccasout);
14469 senext2(vb, bccasin);
14470 sbond(bccasin, oldbc);
14471 if (bccasout.sh != dummysh) {
14474 bccasout.shver = 0;
14475 if (sorg(bccasout) != pb) sesymself(bccasout);
14477 assert(sorg(bccasout) == pb);
14479 senext2self(bccasout);
14480 senext(vb, bccasin);
14481 sbond(bccasin, bccasout);
14484 spinabc = startabc;
14487 if (sorg(spinabc) != pa) {
14488 sesymself(spinabc);
14491 senext(spinabc, oldbc);
14492 spivot(oldbc, vbc);
14493 if (sorg(vbc) == newpoint) {
14500 spivotself(spinabc);
14502 assert(spinabc.sh != dummysh);
14504 }
while (spinabc.sh != startabc.sh);
14509 spinabc = startabc;
14512 if (sorg(spinabc) != pa) {
14513 sesymself(spinabc);
14516 senext(spinabc, oldbc);
14517 spivot(oldbc, vbc);
14518 if (sorg(vbc) == newpoint) {
14523 stpivot(spinabc, abcd);
14524 if (abcd.tet != dummytet) {
14525 findedge(&abcd, sorg(spinabc), sdest(spinabc));
14526 enextfnext(abcd, vbcd);
14529 assert(vbcd.tet != dummytet);
14537 sesymself(spinabc);
14538 stpivot(spinabc, bace);
14539 if (bace.tet != dummytet) {
14540 findedge(&bace, sorg(spinabc), sdest(spinabc));
14541 enext2fnext(bace, bvce);
14544 assert(bvce.tet != dummytet);
14551 spivotself(spinabc);
14552 if (spinabc.sh == dummysh) {
14555 }
while (spinabc.sh != startabc.sh);
14557 if (b->verbose > 3) {
14558 spinabc = startabc;
14561 if (sorg(spinabc) != pa) {
14562 sesymself(spinabc);
14564 printf(
" Updating abc:\n");
14567 senext(spinabc, oldbc);
14568 spivot(oldbc, vbc);
14569 if (sorg(vbc) == newpoint) {
14573 printf(
" Creating vbc:\n");
14576 spivotself(spinabc);
14577 if (spinabc.sh == dummysh) {
14580 }
while (spinabc.sh != startabc.sh);
14583 if (flipqueue != (queue *) NULL) {
14584 spinabc = startabc;
14587 if (sorg(spinabc) != pa) {
14588 sesymself(spinabc);
14590 senext2(spinabc, oldbc);
14591 enqueueflipedge(oldbc, flipqueue);
14593 senext(spinabc, oldbc);
14594 spivot(oldbc, vbc);
14595 if (sorg(vbc) == newpoint) {
14599 senext(vbc, oldbc);
14600 enqueueflipedge(oldbc, flipqueue);
14602 spivotself(spinabc);
14603 if (spinabc.sh == dummysh) {
14606 }
while (spinabc.sh != startabc.sh);
14627 void tetgenmesh::unsplitsubedge(face* splitsh)
14629 face startavc, spinavc, spinbcv;
14630 face oldvc, bccasin, bccasout, spinsh;
14634 startavc = *splitsh;
14635 sspivot(startavc, av);
14636 if (av.sh != dummysh) {
14638 if (sorg(av) != sorg(startavc)) {
14642 assert(av.shver == 0);
14645 senext(startavc, oldvc);
14647 if (sorg(vb) != sdest(oldvc)) {
14651 pa = sorg(startavc);
14652 pv = sdest(startavc);
14655 if (b->verbose > 1) {
14656 printf(
" Removing point %d from subedge (%d, %d).\n",
14657 pointmark(pv), pointmark(pa), pointmark(pb));
14661 spinavc = startavc;
14664 if (sorg(spinavc) != pa) {
14665 sesymself(spinavc);
14669 senext(spinavc, oldvc);
14670 spivot(oldvc, spinbcv);
14671 if (sorg(spinbcv) != sdest(oldvc)) {
14672 sesymself(spinbcv);
14674 senext2self(spinbcv);
14675 spivot(spinbcv, bccasout);
14676 sspivot(spinbcv, bc);
14677 if (bc.sh != dummysh) {
14678 if (spinbcv.sh != bccasout.sh) {
14683 spivotself(spinsh);
14684 }
while (spinsh.sh != spinbcv.sh);
14686 bccasout.sh = dummysh;
14690 setsdest(spinavc, pb);
14691 if (bc.sh != dummysh) {
14692 if (bccasout.sh != dummysh) {
14693 sbond1(bccasin, oldvc);
14694 sbond1(oldvc, bccasout);
14697 sbond(oldvc, oldvc);
14701 sbond(oldvc, bccasout);
14704 shellfacedealloc(subfaces, spinbcv.sh);
14706 spivotself(spinavc);
14707 if (spinavc.sh == dummysh) {
14710 }
while (spinavc.sh != startavc.sh);
14713 if (av.sh != dummysh) {
14718 assert(sdest(av) == sorg(vb));
14720 senext(vb, spinbcv);
14721 spivot(spinbcv, bccasout);
14724 sbond(oldvc, bccasout);
14726 shellfacedealloc(subsegs, vb.sh);
14752 enum tetgenmesh::insertsiteresult tetgenmesh::insertsite(point newpoint,
14753 triface* searchtet,
bool approx, queue* flipqueue)
14755 enum locateresult intersect, exactloc;
14757 REAL epspp, checklen;
14760 if (b->verbose > 1) {
14761 printf(
" Insert point to mesh: (%.12g, %.12g, %.12g) %d.\n",
14762 newpoint[0], newpoint[1], newpoint[2], pointmark(newpoint));
14765 if (searchtet->tet == (tetrahedron *) NULL) {
14767 searchtet->tet = dummytet;
14768 exactloc = locate(newpoint, searchtet);
14771 exactloc = preciselocate(newpoint, searchtet, tetrahedrons->items);
14773 intersect = exactloc;
14774 if (approx && (exactloc != ONVERTEX)) {
14776 epspp = b->epsilon;
14778 while (count < 16) {
14779 intersect = adjustlocate(newpoint, searchtet, exactloc, epspp);
14780 if (intersect == ONVERTEX) {
14781 checkpt = org(*searchtet);
14782 checklen = distance(checkpt, newpoint);
14783 if (checklen / longest > b->epsilon) {
14793 recenttet = *searchtet;
14796 switch (intersect) {
14800 if (b->verbose > 1) {
14801 printf(
" Not insert for duplicating point.\n");
14803 return DUPLICATEPOINT;
14806 if (b->verbose > 1) {
14807 printf(
" Not insert for locating outside the mesh.\n");
14809 return OUTSIDEPOINT;
14813 splittetedge(newpoint, searchtet, flipqueue);
14814 return SUCCESSONEDGE;
14818 splittetface(newpoint, searchtet, flipqueue);
14819 return SUCCESSONFACE;
14821 case INTETRAHEDRON:
14823 splittetrahedron(newpoint, searchtet, flipqueue);
14824 return SUCCESSINTET;
14828 return OUTSIDEPOINT;
14845 void tetgenmesh::undosite(
enum insertsiteresult insresult, triface* splittet,
14846 point torg, point tdest, point tapex, point toppo)
14849 findface(splittet, torg, tdest, tapex);
14850 if (oppo(*splittet) != toppo) {
14851 symself(*splittet);
14853 assert(oppo(*splittet) == toppo);
14856 findedge(splittet, torg, tdest);
14860 switch (insresult) {
14863 unsplittetrahedron(splittet);
14865 case SUCCESSONFACE:
14868 unsplittetface(splittet);
14870 case SUCCESSONEDGE:
14872 unsplittetedge(splittet);
14891 void tetgenmesh::closeopenface(triface* openface, queue* flipque)
14893 triface newtet, oldhull;
14894 triface newopenface, closeface;
14895 point inspoint, pa, pb, pc;
14896 REAL attrib, volume;
14900 inspoint = apex(*openface);
14902 esym(*openface, oldhull);
14903 while (fnextself(oldhull)) ;
14904 if (apex(oldhull) != inspoint) {
14907 pb = dest(oldhull);
14908 pc = apex(oldhull);
14909 if (orient3d(pa, pb, pc, inspoint) < 0.0) {
14911 maketetrahedron(&newtet);
14912 setorg(newtet, pa);
14913 setdest(newtet, pb);
14914 setapex(newtet, pc);
14915 setoppo(newtet, inspoint);
14916 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14917 attrib = elemattribute(oldhull.tet, i);
14918 setelemattribute(newtet.tet, i, attrib);
14920 if (b->varvolume) {
14921 volume = volumebound(oldhull.tet);
14922 setvolumebound(newtet.tet, volume);
14925 bond(newtet, oldhull);
14927 fnext(newtet, newopenface);
14928 bond(newopenface, *openface);
14930 enqueueflipface(oldhull, flipque);
14935 for (i = 0; i < 2; i++) {
14936 fnext(newtet, newopenface);
14937 sym(newopenface, closeface);
14938 if (closeface.tet == dummytet) {
14939 closeopenface(&newopenface, flipque);
14947 dummytet[0] = encode(*openface);
14951 bond(*openface, oldhull);
14953 enqueueflipface(*openface, flipque);
14974 void tetgenmesh::inserthullsite(point inspoint, triface* horiz, queue* flipque)
14976 triface firstnewtet;
14977 triface openface, closeface;
14978 REAL attrib, volume;
14982 adjustedgering(*horiz, CW);
14984 maketetrahedron(&firstnewtet);
14985 setorg (firstnewtet, org(*horiz));
14986 setdest(firstnewtet, dest(*horiz));
14987 setapex(firstnewtet, apex(*horiz));
14988 setoppo(firstnewtet, inspoint);
14989 for (i = 0; i < in->numberoftetrahedronattributes; i++) {
14990 attrib = elemattribute(horiz->tet, i);
14991 setelemattribute(firstnewtet.tet, i, attrib);
14993 if (b->varvolume) {
14994 volume = volumebound(horiz->tet);
14995 setvolumebound(firstnewtet.tet, volume);
14998 bond(firstnewtet, *horiz);
15000 enqueueflipface(*horiz, flipque);
15005 for (i = 0; i < 3; i++) {
15007 fnext(firstnewtet, openface);
15009 sym(openface, closeface);
15010 if (closeface.tet == dummytet) {
15011 closeopenface(&openface, flipque);
15014 enextself(firstnewtet);
15049 void tetgenmesh::formbowatcavitysub(point bp, face* bpseg, list* sublist,
15053 face startsh, neighsh;
15055 point pa, pb, pc, pd;
15060 for (i = 0; i < sublist->len(); i++) {
15061 startsh = * (face *)(* sublist)[i];
15063 for (j = 0; j < 3; j++) {
15064 sspivot(startsh, checkseg);
15065 if (checkseg.sh == dummysh) {
15067 spivot(startsh, neighsh);
15069 if (!sinfected(neighsh)) {
15070 stpivot(neighsh, adjtet);
15071 if (adjtet.tet == dummytet) {
15072 sesymself(neighsh);
15073 stpivot(neighsh, adjtet);
15076 adjustedgering(adjtet, CW);
15081 sign = insphere(pa, pb, pc, pd, bp);
15084 if (sorg(neighsh) != sdest(startsh)) sesymself(neighsh);
15087 sublist->append(&neighsh);
15089 subceillist->append(&startsh);
15094 if (bpseg != (face *) NULL) {
15095 if (checkseg.sh != bpseg->sh) {
15096 subceillist->append(&startsh);
15099 subceillist->append(&startsh);
15102 senextself(startsh);
15106 if (b->verbose > 2) {
15107 printf(
" Collect CBC(%d): %d subfaces, %d edges.\n", pointmark(bp),
15108 sublist->len(), subceillist->len());
15126 void tetgenmesh::formbowatcavityquad(point bp, list* tetlist, list* ceillist)
15128 triface starttet, neightet;
15130 point pa, pb, pc, pd;
15135 for (i = 0; i < tetlist->len(); i++) {
15136 starttet = * (triface *)(* tetlist)[i];
15137 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15139 tspivot(starttet, checksh);
15140 if (checksh.sh == dummysh) {
15142 sym(starttet, neightet);
15144 if (!infected(neightet)) {
15146 adjustedgering(neightet, CW);
15147 pa = org(neightet);
15148 pb = dest(neightet);
15149 pc = apex(neightet);
15150 pd = oppo(neightet);
15151 sign = insphere(pa, pb, pc, pd, bp);
15155 tetlist->append(&neightet);
15157 ceillist->append(&starttet);
15162 if (!sinfected(checksh)) {
15163 ceillist->append(&starttet);
15169 if (b->verbose > 2) {
15170 printf(
" Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15171 tetlist->len(), ceillist->len());
15192 void tetgenmesh::formbowatcavitysegquad(point bp, list* tetlist,list* ceillist)
15194 triface starttet, neightet, cavtet;
15196 point pa, pb, pc, pd, pe;
15201 for (i = 0; i < tetlist->len(); i++) {
15202 starttet = * (triface *)(* tetlist)[i];
15203 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
15205 tspivot(starttet, checksh);
15206 if (checksh.sh == dummysh) {
15208 sym(starttet, neightet);
15210 if (!infected(neightet)) {
15212 adjustedgering(neightet, CW);
15213 pa = org(neightet);
15214 pb = dest(neightet);
15215 pc = apex(neightet);
15216 pd = oppo(neightet);
15217 sign = insphere(pa, pb, pc, pd, bp);
15221 tetlist->append(&neightet);
15224 pe = oppo(starttet);
15225 sign = insphere(pa, pb, pc, pd, pe);
15229 tetlist->append(&neightet);
15238 for (i = 0; i < tetlist->len(); i++) {
15239 cavtet = * (triface *)(* tetlist)[i];
15240 for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15241 tspivot(cavtet, checksh);
15242 if (checksh.sh == dummysh) {
15243 sym(cavtet, neightet);
15244 if (!infected(neightet)) {
15245 ceillist->append(&cavtet);
15249 if (!sinfected(checksh)) {
15250 ceillist->append(&cavtet);
15256 if (b->verbose > 2) {
15257 printf(
" Collect BC_i(%d): %d tets, %d faces.\n", pointmark(bp),
15258 tetlist->len(), ceillist->len());
15272 void tetgenmesh::formbowatcavity(point bp, face* bpseg, face* bpsh,
int* n,
15273 int* nmax, list** sublists, list** subceillists, list** tetlists,
15278 face startsh, spinsh;
15283 if (bpseg != (face *) NULL) {
15287 pb = sdest(*bpseg);
15289 spivot(*bpseg, startsh);
15293 spivotself(spinsh);
15294 }
while (spinsh.sh != startsh.sh);
15298 delete [] tetlists;
15299 delete [] ceillists;
15300 delete [] sublists;
15301 delete [] subceillists;
15302 tetlists =
new list*[*n];
15303 ceillists =
new list*[*n];
15304 sublists =
new list*[*n];
15305 subceillists =
new list*[*n];
15310 for (i = 0; i < *n; i++) {
15311 sublists[i] =
new list(
sizeof(face), NULL, 256);
15312 subceillists[i] =
new list(
sizeof(face), NULL, 256);
15316 findedge(&startsh, pa, pb);
15318 sublists[i]->append(&startsh);
15319 formbowatcavitysub(bp, bpseg, sublists[i], subceillists[i]);
15321 spivotself(spinsh);
15323 }
else if (sublists != (list **) NULL) {
15327 sublists[0] =
new list(
sizeof(face), NULL, 256);
15328 subceillists[0] =
new list(
sizeof(face), NULL, 256);
15330 sublists[0]->append(bpsh);
15331 formbowatcavitysub(bp, NULL, sublists[0], subceillists[0]);
15338 for (i = 0; i < *n; i++) {
15339 tetlists[i] =
new list(
sizeof(triface), NULL, 256);
15340 ceillists[i] =
new list(
sizeof(triface), NULL, 256);
15341 if (sublists != (list **) NULL) {
15343 sublist = ((bpseg == (face *) NULL) ? sublists[0] : sublists[i]);
15345 for (j = 0; j < sublist->len(); j++) {
15346 startsh = * (face *)(* sublist)[j];
15348 if ((bpseg == (face *) NULL) && (i == 1)) sesymself(startsh);
15349 stpivot(startsh, adjtet);
15350 if (adjtet.tet != dummytet) {
15351 if (!infected(adjtet)) {
15353 tetlists[i]->append(&adjtet);
15357 if (bpseg != (face *) NULL) {
15359 sublist = ((i < *n - 1) ? sublists[i + 1] : sublists[0]);
15360 for (j = 0; j < sublist->len(); j++) {
15361 startsh = * (face *)(* sublist)[j];
15363 sesymself(startsh);
15364 stpivot(startsh, adjtet);
15365 if (adjtet.tet != dummytet) {
15366 if (!infected(adjtet)) {
15368 tetlists[i]->append(&adjtet);
15375 if (tetlists[i]->len() == 0)
continue;
15380 formbowatcavityquad(bp, tetlists[i], ceillists[i]);
15392 void tetgenmesh::releasebowatcavity(face* bpseg,
int n, list** sublists,
15393 list** subceillist, list** tetlists, list** ceillists)
15399 if (sublists != (list **) NULL) {
15401 for (i = 0; i < n; i++) {
15403 for (j = 0; j < sublists[i]->len(); j++) {
15404 oldsh = * (face *)(* (sublists[i]))[j];
15406 assert(sinfected(oldsh));
15410 delete sublists[i];
15411 delete subceillist[i];
15412 sublists[i] = (list *) NULL;
15413 subceillist[i] = (list *) NULL;
15414 if (bpseg == (face *) NULL)
break;
15418 for (i = 0; i < n; i++) {
15420 for (j = 0; j < tetlists[i]->len(); j++) {
15421 oldtet = * (triface *)(* (tetlists[i]))[j];
15423 assert(infected(oldtet));
15427 delete tetlists[i];
15428 delete ceillists[i];
15429 tetlists[i] = (list *) NULL;
15430 ceillists[i] = (list *) NULL;
15446 bool tetgenmesh::validatebowatcavityquad(point bp,list* ceillist,REAL maxcosd)
15455 for (i = 0; i < ceillist->len(); i++) {
15456 ceiltet = * (triface *)(* ceillist)[i];
15457 if (infected(ceiltet)) {
15458 adjustedgering(ceiltet, CCW);
15460 pb = dest(ceiltet);
15461 pc = apex(ceiltet);
15462 ori = orient3d(pa, pb, pc, bp);
15470 if (maxcosd > -1.0) {
15472 tetalldihedral(pa, pb, pc, bp, NULL, &cosd, NULL);
15474 if (cosd < maxcosd) {
15481 return remcount == 0;
15494 void tetgenmesh::updatebowatcavityquad(list* tetlist, list* ceillist)
15496 triface cavtet, neightet;
15501 for (i = 0; i < tetlist->len(); i++) {
15502 cavtet = * (triface *)(* tetlist)[i];
15503 if (!infected(cavtet)) {
15504 tetlist->del(i, 1);
15511 if (remcount > 0) {
15514 for (i = 0; i < tetlist->len(); i++) {
15515 cavtet = * (triface *)(* tetlist)[i];
15516 for (cavtet.loc = 0; cavtet.loc < 4; cavtet.loc++) {
15517 tspivot(cavtet, checksh);
15518 if (checksh.sh == dummysh) {
15519 sym(cavtet, neightet);
15520 if (!infected(neightet)) {
15521 ceillist->append(&cavtet);
15525 if (!sinfected(checksh)) {
15526 ceillist->append(&cavtet);
15531 if (b->verbose > 2) {
15532 printf(
" Update BC_i(p): %d tets, %d faces.\n", tetlist->len(),
15564 void tetgenmesh::updatebowatcavitysub(list* sublist, list* subceillist,
15567 triface adjtet, rotface;
15568 face checksh, neighsh;
15577 for (i = 0; i < sublist->len(); i++) {
15578 checksh = * (face *)(* sublist)[i];
15580 for (j = 0; j < 2; j++) {
15581 stpivot(checksh, adjtet);
15582 if (adjtet.tet != dummytet) {
15583 if (!infected(adjtet)) {
15585 suninfect(checksh);
15587 sesymself(checksh);
15588 stpivot(checksh, adjtet);
15589 if (adjtet.tet != dummytet) {
15590 if (infected(adjtet)) {
15597 sublist->del(i, 1);
15603 sesymself(checksh);
15606 if (remcount > 0) {
15607 if (b->verbose > 2) {
15608 printf(
" Removed %d subfaces from CBC(p).\n", remcount);
15611 subceillist->clear();
15612 for (i = 0; i < sublist->len(); i++) {
15613 checksh = * (face *)(* sublist)[i];
15614 for (j = 0; j < 3; j++) {
15615 spivot(checksh, neighsh);
15616 if (!sinfected(neighsh)) {
15617 subceillist->append(&checksh);
15619 senextself(checksh);
15622 if (b->verbose > 2) {
15623 printf(
" Update CBC(p): %d subs, %d edges.\n", sublist->len(),
15624 subceillist->len());
15629 for (i = 0; i < subceillist->len(); i++) {
15630 checksh = * (face *)(* subceillist)[i];
15631 sspivot(checksh, checkseg);
15632 if (checkseg.sh != dummysh) {
15634 stpivot(checksh, adjtet);
15635 if (adjtet.tet == dummytet) {
15636 sesym(checksh, neighsh);
15637 stpivot(neighsh, adjtet);
15639 findedge(&adjtet, sorg(checkseg), sdest(checkseg));
15640 adjustedgering(adjtet, CCW);
15641 fnext(adjtet, rotface);
15647 if (!infected(rotface))
break;
15648 tspivot(rotface, neighsh);
15649 if (neighsh.sh != dummysh)
break;
15651 fnextself(rotface);
15652 }
while (apex(rotface) != apex(adjtet));
15654 if (apex(rotface) == apex(adjtet)) {
15662 fnext(adjtet, rotface);
15664 fnextself(rotface);
15665 assert(infected(rotface));
15666 ori1 = orient3d(pa, pb, pc, apex(rotface));
15667 ori2 = orient3d(pa, pb, pc, oppo(rotface));
15668 }
while (ori1 * ori2 > 0.0);
15720 bool tetgenmesh::trimbowatcavity(point bp, face* bpseg,
int n, list** sublists,
15721 list** subceillists, list** tetlists, list** ceillists, REAL maxcosd)
15724 int oldnum, cutnum, cutcount;
15732 for (i = 0; i < n && valflag; i++) {
15733 oldnum = tetlists[i]->len();
15735 while (!validatebowatcavityquad(bp, ceillists[i], maxcosd)) {
15737 updatebowatcavityquad(tetlists[i], ceillists[i]);
15738 valflag = tetlists[i]->len() > 0;
15740 cutnum += (oldnum - tetlists[i]->len());
15742 if (valflag && (sublists != (list **) NULL)) {
15745 for (i = 0; i < n; i++) {
15746 updatebowatcavitysub(sublists[i], subceillists[i], &cutcount);
15748 if (bpseg == (face *) NULL)
break;
15751 if (cutcount > 0) {
15753 for (i = 0; i < n; i++) {
15754 if (tetlists[i]->len() > 0) {
15755 updatebowatcavityquad(tetlists[i], ceillists[i]);
15757 valflag = tetlists[i]->len() > 0;
15761 cutnum += cutcount;
15770 if (valflag && (sublists != (list **) NULL)) {
15771 for (i = 0; i < n && valflag; i++) {
15772 valflag = (sublists[i]->len() > 0);
15773 if (bpseg == (face *) NULL)
break;
15777 if (valflag && (cutnum > 0)) {
15779 if (bpseg != (face *) NULL) {
15781 }
else if (sublists != (list **) NULL) {
15790 if (bpseg != (face *) NULL) {
15792 }
else if (sublists != (list **) NULL) {
15836 void tetgenmesh::bowatinsertsite(point bp,face* splitseg,
int n,list** sublists,
15837 list** subceillists, list** tetlists, list** ceillists, list* verlist,
15838 queue* flipque,
bool chkencseg,
bool chkencsub,
bool chkbadtet)
15840 list *ceillist, *subceillist;
15841 triface oldtet, newtet, newface, rotface, neightet;
15842 face oldsh, newsh, newedge, checksh;
15843 face spinsh, casingin, casingout;
15844 face *apsegshs, *pbsegshs;
15845 face apseg, pbseg, checkseg;
15849 REAL attrib, volume;
15855 if (b->verbose > 1) {
15856 printf(
" Insert point %d (%.12g, %.12g, %.12g)", pointmark(bp), bp[0],
15859 if (splitseg != (face *) NULL) {
15860 if (b->verbose > 1) {
15861 printf(
" on segment.\n");
15865 if (subceillists != (list **) NULL) {
15866 if (b->verbose > 1) {
15867 printf(
" on facet.\n");
15871 if (b->verbose > 1) {
15872 printf(
" in volume.\n");
15879 for (k = 0; k < n; k++) {
15881 ceillist = ceillists[k];
15882 for (i = 0; i < ceillist->len(); i++) {
15883 oldtet = * (triface *)(* ceillist)[i];
15884 adjustedgering(oldtet, CCW);
15888 maketetrahedron(&newtet);
15889 setorg(newtet, pa);
15890 setdest(newtet, pb);
15891 setapex(newtet, pc);
15892 setoppo(newtet, bp);
15893 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
15894 attrib = elemattribute(oldtet.tet, j);
15895 setelemattribute(newtet.tet, j, attrib);
15897 if (b->varvolume) {
15898 volume = volumebound(oldtet.tet);
15899 if (volume > 0.0) {
15900 if (!b->fixedvolume && b->refine) {
15907 setvolumebound(newtet.tet, volume);
15909 sym(oldtet, neightet);
15910 tspivot(oldtet, checksh);
15911 if (neightet.tet != dummytet) {
15912 bond(newtet, neightet);
15914 if (checksh.sh != dummysh) {
15915 tsbond(newtet, checksh);
15917 if (verlist != (list *) NULL) {
15919 idx = pointmark(pa);
15921 setpointmark(pa, -idx - 1);
15922 verlist->append(&pa);
15924 idx = pointmark(pb);
15926 setpointmark(pb, -idx - 1);
15927 verlist->append(&pb);
15929 idx = pointmark(pc);
15931 setpointmark(pc, -idx - 1);
15932 verlist->append(&pc);
15936 * (triface *)(* ceillist)[i] = newtet;
15939 if (verlist != (list *) NULL) {
15941 for (i = 0; i < verlist->len(); i++) {
15942 pa = * (point *)(* verlist)[i];
15943 idx = pointmark(pa);
15944 setpointmark(pa, -(idx + 1));
15950 for (k = 0; k < n; k++) {
15951 ceillist = ceillists[k];
15952 for (i = 0; i < ceillist->len(); i++) {
15953 newtet = * (triface *)(* ceillist)[i];
15955 for (j = 0; j < 3; j++) {
15956 fnext(newtet, newface);
15957 sym(newface, neightet);
15958 if (neightet.tet == dummytet) {
15960 esym(newtet, rotface);
15962 pb = dest(rotface);
15963 while (fnextself(rotface));
15965 tspivot(rotface, checksh);
15966 if (checksh.sh != dummysh) {
15969 findedge(&checksh, pa, pb);
15970 sfnextself(checksh);
15971 assert((sorg(checksh) == pa) && (sdest(checksh) == pb));
15972 stpivot(checksh, rotface);
15973 if (infected(rotface)) {
15978 findedge(&rotface, pa, pb);
15979 while (fnextself(rotface));
15980 tspivot(rotface, checksh);
15981 }
while (checksh.sh != dummysh);
15984 if (apex(rotface) == apex(newface)) {
15986 bond(newface, rotface);
15988 if (flipque != (queue *) NULL) {
15989 enqueueflipface(newface, flipque);
15998 if (subceillists != (list **) NULL) {
16000 if (splitseg != (face *) NULL) {
16002 splitseg->shver = 0;
16003 pa = sorg(*splitseg);
16004 pb = sdest(*splitseg);
16007 apsegshs =
new face[n];
16008 pbsegshs =
new face[n];
16014 for (k = 0; k < n; k++) {
16015 subceillist = subceillists[k];
16018 oldsh = * (face *)(* subceillist)[0];
16019 stpivot(oldsh, neightet);
16020 if (neightet.tet != dummytet) {
16022 stpivot(oldsh, neightet);
16024 if (neightet.tet == dummytet) {
16026 hullsize += (subceillist->len() - sublists[k]->len());
16030 for (i = 0; i < subceillist->len(); i++) {
16031 oldsh = * (face *)(* subceillist)[i];
16032 makeshellface(subfaces, &newsh);
16033 setsorg(newsh, sorg(oldsh));
16034 setsdest(newsh, sdest(oldsh));
16035 setsapex(newsh, bp);
16036 if (b->quality && varconstraint) {
16037 setareabound(newsh, areabound(oldsh));
16039 setshellmark(newsh, shellmark(oldsh));
16040 setshelltype(newsh, shelltype(oldsh));
16042 setshellpbcgroup(newsh, shellpbcgroup(oldsh));
16045 spivot(oldsh, casingout);
16046 sspivot(oldsh, checkseg);
16047 if (checkseg.sh != dummysh) {
16049 if (oldsh.sh != casingout.sh) {
16051 spinsh = casingout;
16054 spivotself(spinsh);
16055 }
while (sapex(spinsh) != sapex(oldsh));
16056 assert(casingin.sh != oldsh.sh);
16058 sbond1(casingin, newsh);
16059 sbond1(newsh, casingout);
16062 sbond(newsh, newsh);
16065 ssbond(newsh, checkseg);
16068 sbond(newsh, casingout);
16072 stpivot(oldsh, neightet);
16073 if (neightet.tet == dummytet) {
16076 stpivot(oldsh, neightet);
16078 assert(infected(neightet));
16080 findedge(&neightet, sorg(oldsh), sdest(oldsh));
16082 adjustedgering(neightet, CCW);
16083 rotface = neightet;
16088 fnextself(rotface);
16089 sym(rotface, neightet);
16090 if (neightet.tet == dummytet) {
16091 tspivot(rotface, checksh);
16092 assert(checksh.sh != dummysh);
16093 stpivot(checksh, newtet);
16095 }
else if (!infected(neightet)) {
16096 sym(neightet, newtet);
16100 assert(newtet.tet != rotface.tet);
16102 findedge(&newtet, sorg(oldsh), sdest(oldsh));
16104 adjustedgering(newtet, CCW);
16105 fnext(newtet, newface);
16106 assert(apex(newface) == bp);
16108 tsbond(newface, newsh);
16109 sym(newface, neightet);
16111 tsbond(neightet, newsh);
16114 * (face *)(* subceillist)[i] = newsh;
16118 for (i = 0; i < subceillist->len(); i++) {
16120 newsh = * (face *)(* subceillist)[i];
16122 stpivot(newsh, newtet);
16123 if (newtet.tet == dummytet) {
16125 stpivot(newsh, newtet);
16127 for (j = 0; j < 2; j++) {
16129 senext(newsh, newedge);
16131 senext2(newsh, newedge);
16132 sesymself(newedge);
16134 if (splitseg != (face *) NULL) {
16136 if (sorg(newedge) == pa) {
16137 apsegshs[k] = newedge;
16139 }
else if (sorg(newedge) == pb) {
16140 pbsegshs[k] = newedge;
16145 sspivot(newedge, checkseg);
16146 assert(checkseg.sh == dummysh);
16147 spivot(newedge, casingout);
16148 if (casingout.sh == dummysh) {
16150 findedge(&rotface, sorg(newedge), sdest(newedge));
16153 adjustedgering(rotface, CCW);
16155 fnextself(rotface);
16156 tspivot(rotface, checksh);
16157 if (checksh.sh != dummysh)
break;
16159 findedge(&checksh, sorg(newedge), sdest(newedge));
16160 sbond(newedge, checksh);
16165 if (splitseg == (face *) NULL)
break;
16168 if (splitseg != (face *) NULL) {
16171 setsdest(apseg, bp);
16173 makeshellface(subsegs, &pbseg);
16174 setsorg(pbseg, bp);
16175 setsdest(pbseg, pb);
16177 setshellmark(pbseg, shellmark(apseg));
16178 setshelltype(pbseg, shelltype(apseg));
16179 if (b->quality && varconstraint) {
16181 setareabound(pbseg, areabound(apseg));
16183 senext(apseg, checkseg);
16185 spivot(checkseg, casingout);
16187 senext2(pbseg, casingin);
16188 sbond(casingin, checkseg);
16189 if (casingout.sh != dummysh) {
16191 casingout.shver = 0;
16193 assert(sorg(casingout) == pb);
16195 senext2self(casingout);
16196 senext(pbseg, casingin);
16197 sbond(casingin, casingout);
16201 for (i = 0; i < n; i++) {
16202 spinsh = apsegshs[i];
16203 findedge(&spinsh, pa, bp);
16204 ssbond(spinsh, apseg);
16205 spinsh = pbsegshs[i];
16206 findedge(&spinsh, bp, pb);
16207 ssbond(spinsh, pbseg);
16210 for (i = 0; i < n; i++) {
16211 spinsh = apsegshs[i];
16213 casingout = apsegshs[i + 1];
16215 casingout = apsegshs[0];
16217 sbond1(spinsh, casingout);
16220 for (i = 0; i < n; i++) {
16221 spinsh = pbsegshs[i];
16223 casingout = pbsegshs[i + 1];
16225 casingout = pbsegshs[0];
16227 sbond1(spinsh, casingout);
16229 delete [] apsegshs;
16230 delete [] pbsegshs;
16235 checkseg4encroach(&apseg, NULL, NULL,
true);
16236 checkseg4encroach(&pbseg, NULL, NULL,
true);
16238 tallencsegs(bp, n, ceillists);
16243 for (k = 0; k < n; k++) {
16244 for (i = 0; i < sublists[k]->len(); i++) {
16245 oldsh = * (face *)(* (sublists[k]))[i];
16246 shellfacedealloc(subfaces, oldsh.sh);
16250 sublists[k]->clear();
16252 if (splitseg == (face *) NULL)
break;
16258 for (k = 0; k < n; k++) {
16259 subceillist = subceillists[k];
16260 for (i = 0; i < subceillist->len(); i++) {
16261 newsh = * (face *)(* subceillist)[i];
16262 checksub4encroach(&newsh, NULL,
true);
16265 if (splitseg == (face *) NULL)
break;
16268 tallencsubs(bp, n, ceillists);
16273 for (k = 0; k < n; k++) {
16274 for (i = 0; i < tetlists[k]->len(); i++) {
16275 oldtet = * (triface *)(* (tetlists[k]))[i];
16276 tetrahedrondealloc(oldtet.tet);
16280 tetlists[k]->clear();
16285 for (k = 0; k < n; k++) {
16286 ceillist = ceillists[k];
16287 for (i = 0; i < ceillist->len(); i++) {
16288 newtet = * (triface *)(* ceillist)[i];
16289 checktet4badqual(&newtet,
true);
16294 if (flipque != (queue *) NULL) {
16298 repairflipcount += flip(flipque, NULL);
16324 void tetgenmesh::formstarpolyhedron(point pt, list* tetlist, list* verlist,
16327 triface starttet, neightet;
16333 starttet = * (triface *)(* tetlist)[0];
16335 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
16336 if (oppo(starttet) == pt)
break;
16338 assert(starttet.loc < 4);
16340 * (triface *)(* tetlist)[0] = starttet;
16342 if (verlist != (list *) NULL) {
16344 ver[0] = org(starttet);
16345 ver[1] = dest(starttet);
16346 ver[2] = apex(starttet);
16347 for (i = 0; i < 3; i++) {
16349 idx = pointmark(ver[i]);
16350 setpointmark(ver[i], -idx - 1);
16351 verlist->append(&(ver[i]));
16356 for (i = 0; i < tetlist->len(); i++) {
16357 starttet = * (triface *)(* tetlist)[i];
16359 for (j = 0; j < 3; j++) {
16360 fnext(starttet, neightet);
16361 tspivot(neightet, checksh);
16363 if ((checksh.sh == dummysh) || complete) {
16366 if ((neightet.tet != dummytet) && !infected(neightet)) {
16368 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
16369 if (oppo(neightet) == pt)
break;
16371 assert(neightet.loc < 4);
16374 tetlist->append(&neightet);
16375 if (verlist != (list *) NULL) {
16377 ver[0] = org(starttet);
16378 ver[1] = dest(starttet);
16379 findedge(&neightet, ver[0], ver[1]);
16380 ver[2] = apex(neightet);
16381 idx = pointmark(ver[2]);
16383 setpointmark(ver[2], -idx - 1);
16384 verlist->append(&(ver[2]));
16389 enextself(starttet);
16394 for (i = 0; i < tetlist->len(); i++) {
16395 starttet = * (triface *)(* tetlist)[i];
16396 uninfect(starttet);
16398 if (verlist != (list *) NULL) {
16400 for (i = 0; i < verlist->len(); i++) {
16401 ver[0] = * (point *)(* verlist)[i];
16402 idx = pointmark(ver[0]);
16403 setpointmark(ver[0], -(idx + 1));
16420 bool tetgenmesh::unifypoint(point testpt, triface *starttet,
enum locateresult
16423 triface symtet, spintet;
16424 point checkpt, tapex;
16431 tol = longest * eps;
16432 if ((loc == OUTSIDE) || (loc == INTETRAHEDRON) || (loc == ONFACE)) {
16434 for (i = 0; i < 4; i++) {
16435 checkpt = (point) starttet->tet[4 + i];
16436 if (distance(testpt, checkpt) < tol) {
16441 if (!merged && (loc == ONFACE)) {
16443 sym(*starttet, symtet);
16444 if (symtet.tet != dummytet) {
16445 checkpt = oppo(symtet);
16446 if (distance(testpt, checkpt) < tol) {
16451 }
else if (loc == ONEDGE) {
16453 checkpt = org(*starttet);
16454 if (distance(testpt, checkpt) < tol) {
16458 checkpt = dest(*starttet);
16459 if (distance(testpt, checkpt) < tol) {
16465 spintet = *starttet;
16466 tapex = apex(*starttet);
16469 checkpt = apex(spintet);
16470 if (distance(testpt, checkpt) < tol) {
16474 if (!fnextself(spintet)) {
16477 esym(*starttet, spintet);
16478 if (!fnextself(spintet)) {
16483 }
while ((apex(spintet) != tapex) && (hitbdry < 2));
16487 if (b->object != tetgenbehavior::STL) {
16489 printf(
"Warning: Point %d is unified to point %d.\n",
16490 pointmark(testpt), pointmark(checkpt));
16496 setpointtype(testpt, DUPLICATEDVERTEX);
16498 setpoint2ppt(testpt, checkpt);
16522 void tetgenmesh::incrflipdelaunay(triface* oldtet, point* insertarray,
16523 long arraysize,
bool jump,
bool merge, REAL eps, queue* flipque)
16525 triface newtet, searchtet;
16526 point swappt, lastpt;
16527 enum locateresult loc;
16529 REAL attrib, volume;
16532 clock_t loc_start, loc_end;
16536 if (b->verbose > 0) {
16537 printf(
" Creating initial tetrahedralization.\n");
16545 for (i = 1; i < arraysize; i++) {
16546 det = distance(insertarray[0], insertarray[i]);
16547 if (det > (longest * eps))
break;
16549 if (i == arraysize) {
16550 printf(
"\nAll points seem to be identical.\n");
16554 swappt = insertarray[i];
16555 insertarray[i] = insertarray[1];
16556 insertarray[1] = swappt;
16559 for (i++; i < arraysize; i++) {
16560 if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
16563 if (i == arraysize) {
16564 printf(
"\nAll points seem to be collinear.\n");
16568 swappt = insertarray[i];
16569 insertarray[i] = insertarray[2];
16570 insertarray[2] = swappt;
16573 for (i++; i < arraysize; i++) {
16574 det = orient3d(insertarray[0], insertarray[1], insertarray[2],
16576 if (det == 0.0)
continue;
16577 if (!iscoplanar(insertarray[0], insertarray[1], insertarray[2],
16578 insertarray[i], det, eps))
break;
16580 if (i == arraysize) {
16586 facenormal(insertarray[0], insertarray[1], insertarray[2], n, &det);
16587 if (det != 0.0)
for (j = 0; j < 3; j++) n[j] /= det;
16589 det = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
16591 makepoint(&lastpt);
16592 for (j = 0; j < 3; j++) lastpt[j] = insertarray[0][j] + det * n[j];
16593 abovepoint = lastpt;
16594 det = orient3d(insertarray[0], insertarray[1], insertarray[2], lastpt);
16598 printf(
"\nAll points seem to be coplanar.\n");
16603 swappt = insertarray[i];
16604 insertarray[i] = insertarray[3];
16605 insertarray[3] = swappt;
16606 lastpt = insertarray[3];
16612 maketetrahedron(&newtet);
16615 swappt = insertarray[0];
16616 insertarray[0] = insertarray[1];
16617 insertarray[1] = swappt;
16619 if (b->verbose > 2) {
16620 printf(
" Create the first tet (%d, %d, %d, %d).\n",
16621 pointmark(insertarray[0]), pointmark(insertarray[1]),
16622 pointmark(insertarray[2]), pointmark(lastpt));
16624 setorg(newtet, insertarray[0]);
16625 setdest(newtet, insertarray[1]);
16626 setapex(newtet, insertarray[2]);
16627 setoppo(newtet, lastpt);
16628 if (oldtet != (triface *) NULL) {
16629 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
16630 attrib = elemattribute(oldtet->tet, j);
16631 setelemattribute(newtet.tet, j, attrib);
16633 if (b->varvolume) {
16634 volume = volumebound(oldtet->tet);
16635 setvolumebound(newtet.tet, volume);
16639 if (pointtype(insertarray[0]) == UNUSEDVERTEX) {
16640 setpointtype(insertarray[0], FREEVOLVERTEX);
16642 if (pointtype(insertarray[1]) == UNUSEDVERTEX) {
16643 setpointtype(insertarray[1], FREEVOLVERTEX);
16645 if (pointtype(insertarray[2]) == UNUSEDVERTEX) {
16646 setpointtype(insertarray[2], FREEVOLVERTEX);
16648 if (pointtype(lastpt) == UNUSEDVERTEX) {
16649 setpointtype(lastpt, FREEVOLVERTEX);
16652 dummytet[0] = encode(newtet);
16653 if (b->verbose > 3) {
16654 printf(
" Creating tetra ");
16660 if (b->verbose > 0) {
16661 printf(
" Incrementally inserting points.\n");
16664 flip23s = flip32s = flip22s = flip44s = 0;
16665 searchtet.tet = (tetrahedron *) NULL;
16668 for (; i < arraysize; i++) {
16671 loc_start = clock();
16674 loc = locate(insertarray[i], &searchtet);
16676 loc = preciselocate(insertarray[i], &searchtet, tetrahedrons->items);
16680 tloctime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16683 recenttet = searchtet;
16684 if (loc == ONVERTEX) {
16685 if (b->object != tetgenbehavior::STL) {
16687 printf(
"Warning: Point %d is identical with point %d.\n",
16688 pointmark(insertarray[i]), pointmark(org(searchtet)));
16694 setpointtype(insertarray[i], DUPLICATEDVERTEX);
16695 if (b->plc || b->refine) {
16697 setpoint2ppt(insertarray[i], org(searchtet));
16703 if (unifypoint(insertarray[i], &searchtet, loc, eps)) {
16708 if (loc != OUTSIDE) {
16709 if (b->verbose > 1) {
16710 printf(
" Insert point %d in tetrahedralization.\n",
16711 pointmark(insertarray[i]));
16713 if (loc == INTETRAHEDRON) {
16714 splittetrahedron(insertarray[i], &searchtet, flipque);
16715 }
else if (loc == ONFACE) {
16716 splittetface(insertarray[i], &searchtet, flipque);
16717 }
else if (loc == ONEDGE) {
16718 splittetedge(insertarray[i], &searchtet, flipque);
16721 if (b->verbose > 1) {
16722 printf(
" Insert point %d on convex hull.\n",
16723 pointmark(insertarray[i]));
16725 inserthullsite(insertarray[i], &searchtet, flipque);
16727 if (pointtype(insertarray[i]) == UNUSEDVERTEX) {
16729 setpointtype(insertarray[i], FREEVOLVERTEX);
16732 loc_start = clock();
16736 flip(flipque, NULL);
16738 lawson(NULL, flipque);
16744 tfliptime += ((REAL) (loc_end - loc_start)) / CLOCKS_PER_SEC;
16748 if (b->verbose > 0) {
16749 printf(
" %ld Flips (T23 %ld, T32 %ld, T22 %ld, T44 %ld)\n",
16750 flip23s+flip32s+flip22s+flip44s, flip23s, flip32s, flip22s, flip44s);
16764 long tetgenmesh::delaunizevertices()
16767 point *insertarray;
16773 printf(
"Constructing Delaunay tetrahedralization.\n");
16775 printf(
"Constructing regular tetrahedralization.\n");
16779 flipque =
new queue(
sizeof(badface));
16781 arraysize = points->items;
16782 insertarray =
new point[arraysize];
16783 points->traversalinit();
16787 for (i = 0; i < arraysize; i++) {
16788 j = (int) randomnation(i + 1);
16789 insertarray[i] = insertarray[j];
16790 insertarray[j] = pointtraverse();
16797 incrflipdelaunay(NULL, insertarray, arraysize,
true, b->plc, b->epsilon,
16802 delete [] insertarray;
16828 void tetgenmesh::formstarpolygon(point pt, list* trilist, list* vertlist)
16830 face steinsh, lnextsh, rnextsh;
16832 point pa, pb, pc, pd;
16836 steinsh = * (face *)(* trilist)[0];
16839 for (i = 0; i < 3; i++) {
16840 if (sapex(steinsh) == pt)
break;
16841 senextself(steinsh);
16845 * (face *)(* trilist)[0] = steinsh;
16846 pa = sorg(steinsh);
16847 pb = sdest(steinsh);
16848 if (vertlist != (list *) NULL) {
16850 vertlist->append(&pa);
16851 vertlist->append(&pb);
16858 senext2self(lnextsh);
16859 assert(sorg(lnextsh) == pt);
16860 sspivot(lnextsh, checkseg);
16861 if (checkseg.sh != dummysh)
break;
16863 spivotself(lnextsh);
16864 if (lnextsh.sh == dummysh)
break;
16866 if (sdest(lnextsh) != pt) sesymself(lnextsh);
16867 assert(sdest(lnextsh) == pt);
16868 senext2self(lnextsh);
16870 trilist->append(&lnextsh);
16872 pc = sorg(lnextsh);
16873 if (pc == pb)
break;
16874 if (vertlist != (list *) NULL) {
16876 vertlist->append(&pc);
16884 senextself(rnextsh);
16885 assert(sdest(rnextsh) == pt);
16886 sspivot(rnextsh, checkseg);
16887 if (checkseg.sh != dummysh)
break;
16889 spivotself(rnextsh);
16890 if (rnextsh.sh == dummysh)
break;
16892 if (sorg(rnextsh) != pt) sesymself(rnextsh);
16893 assert(sorg(rnextsh) == pt);
16894 senextself(rnextsh);
16896 trilist->append(&rnextsh);
16898 pd = sdest(rnextsh);
16899 if (pd == pa)
break;
16900 if (vertlist != (list *) NULL) {
16902 vertlist->append(&pd);
16935 void tetgenmesh::getfacetabovepoint(face* facetsh)
16937 list *verlist, *trilist, *tetlist;
16940 point p1, p2, p3, pa;
16941 enum locateresult loc;
16942 REAL smallcos, cosa;
16943 REAL largevol, volume;
16944 REAL v1[3], v2[3], len;
16945 int smallidx, largeidx;
16951 verlist =
new list(
sizeof(point *), NULL);
16952 trilist =
new list(
sizeof(face), NULL);
16953 tetlist =
new list(
sizeof(triface), NULL);
16959 p1 = sorg(*facetsh);
16960 pa = sdest(*facetsh);
16961 if (pointmark(pa) < pointmark(p1)) p1 = pa;
16962 pa = sapex(*facetsh);
16963 if (pointmark(pa) < pointmark(p1)) p1 = pa;
16965 trilist->append(facetsh);
16966 formstarpolygon(p1, trilist, verlist);
16969 p2 = * (point *)(* verlist)[0];
16971 for (i = 0; i < 3; i++) v1[i] = p2[i] - p1[i];
16972 len = sqrt(dot(v1, v1));
16974 for (i = 0; i < 3; i++) v1[i] /= len;
16980 for (i = 1; i < verlist->len(); i++) {
16981 p3 = * (point *)(* verlist)[i];
16982 for (j = 0; j < 3; j++) v2[j] = p3[j] - p1[j];
16983 len = sqrt(dot(v2, v2));
16985 cosa = fabs(dot(v1, v2)) / len;
16986 if (cosa < smallcos) {
16992 assert(smallcos < 1.0);
16993 p3 = * (point *)(* verlist)[smallidx];
16996 if (tetrahedrons->items > 0l) {
16998 stpivot(*facetsh, adjtet);
16999 if (adjtet.tet == dummytet) {
17000 sesym(*facetsh, symsh);
17001 stpivot(symsh, adjtet);
17003 if (adjtet.tet == dummytet) {
17004 decode(point2tet(p1), adjtet);
17005 if (isdead(&adjtet)) {
17006 adjtet.tet = dummytet;
17008 if (!findorg(&adjtet, p1)) {
17009 adjtet.tet = dummytet;
17013 if (adjtet.tet == dummytet) {
17014 loc = locate(p1, &adjtet);
17015 if (loc == ONVERTEX) {
17016 setpoint2tet(p1, encode(adjtet));
17018 adjtet.tet = dummytet;
17021 if (adjtet.tet != dummytet) {
17023 tetlist->append(&adjtet);
17024 formstarpolyhedron(p1, tetlist, verlist,
false);
17032 for (i = 0; i < verlist->len(); i++) {
17033 pa = * (point *)(* verlist)[i];
17034 volume = orient3d(p1, p2, p3, pa);
17035 if (!iscoplanar(p1, p2, p3, pa, volume, b->epsilon * 1e+2)) {
17036 if (fabs(volume) > largevol) {
17037 largevol = fabs(volume);
17044 if (largevol > 0.0) {
17045 abovepoint = * (point *)(* verlist)[largeidx];
17046 if (b->verbose > 1) {
17047 printf(
" Chosen abovepoint %d for facet %d.\n", pointmark(abovepoint),
17048 shellmark(*facetsh));
17052 facenormal(p1, p2, p3, v1, &len);
17053 if (len != 0.0)
for (i = 0; i < 3; i++) v1[i] /= len;
17055 len = (0.5*(xmax - xmin) + 0.5*(ymax - ymin) + 0.5*(zmax - zmin)) / 3.0;
17057 makepoint(&abovepoint);
17058 setpointtype(abovepoint, UNUSEDVERTEX);
17060 for (i = 0; i < 3; i++) abovepoint[i] = p1[i] + len * v1[i];
17061 if (b->verbose > 1) {
17062 printf(
" Calculated abovepoint %d for facet %d.\n",
17063 pointmark(abovepoint), shellmark(*facetsh));
17067 shmark = shellmark(*facetsh);
17068 facetabovepointarray[shmark] = abovepoint;
17084 void tetgenmesh::collectcavsubs(point newpoint, list* cavsublist)
17086 face startsub, neighsub;
17093 for (i = 0; i < cavsublist->len(); i++) {
17094 startsub = * (face *)(* cavsublist)[i];
17098 for (i = 0; i < cavsublist->len(); i++) {
17099 startsub = * (face *)(* cavsublist)[i];
17100 for (j = 0; j < 3; j++) {
17101 sspivot(startsub, checkseg);
17103 if (checkseg.sh == dummysh) {
17105 spivot(startsub, neighsub);
17106 if (!sinfected(neighsub)) {
17107 pa = sorg(neighsub);
17108 pb = sdest(neighsub);
17109 pc = sapex(neighsub);
17110 sign = insphere(pa, pb, pc, abovepoint, newpoint);
17111 ori = orient3d(pa, pb, pc, abovepoint);
17114 sign = ori > 0.0 ? sign : -sign;
17119 cavsublist->append(&neighsub);
17123 senextself(startsub);
17127 for (i = 0; i < cavsublist->len(); i++) {
17128 startsub = * (face *)(* cavsublist)[i];
17129 suninfect(startsub);
17145 void tetgenmesh::collectvisiblesubs(
int shmark, point inspoint, face* horiz,
17148 face newsh, hullsh;
17149 face rightsh, leftsh, spinedge;
17155 adjustedgering(*horiz, CCW);
17156 horg = sorg(*horiz);
17157 hdest = sdest(*horiz);
17158 ori = orient3d(horg, hdest, sapex(*horiz), abovepoint);
17159 sign = ori > 0.0 ? -1 : 1;
17162 makeshellface(subfaces, &newsh);
17163 setsorg(newsh, hdest);
17164 setsdest(newsh, horg);
17165 setsapex(newsh, inspoint);
17166 setshellmark(newsh, shmark);
17167 if (b->quality && varconstraint) {
17168 setareabound(newsh, areabound(*horiz));
17171 setshellpbcgroup(newsh, shellpbcgroup(*horiz));
17174 sbond(newsh, *horiz);
17176 enqueueflipedge(*horiz, flipqueue);
17181 senext(newsh, rightsh);
17187 senext2self(hullsh);
17188 spivot(hullsh, spinedge);
17189 if (spinedge.sh == dummysh)
break;
17190 if (sorg(spinedge) != horg) sesymself(spinedge);
17191 assert(sorg(spinedge) == horg);
17193 horg = sorg(hullsh);
17195 ori = orient3d(horg, sdest(hullsh), abovepoint, inspoint);
17197 aboveflag = ori < 0.0;
17200 makeshellface(subfaces, &newsh);
17201 setsorg(newsh, sdest(hullsh));
17202 setsdest(newsh, horg);
17203 setsapex(newsh, inspoint);
17204 setshellmark(newsh, shmark);
17205 if (b->quality && varconstraint) {
17206 setareabound(newsh, areabound(hullsh));
17209 setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17212 sbond(newsh, hullsh);
17213 senext2(newsh, leftsh);
17214 sbond(leftsh, rightsh);
17216 enqueueflipedge(hullsh, flipqueue);
17219 dummysh[0] = sencode(rightsh);
17226 spivot(*horiz, newsh);
17228 senext2(newsh, leftsh);
17233 senextself(hullsh);
17234 spivot(hullsh, spinedge);
17235 if (spinedge.sh == dummysh)
break;
17236 if (sdest(spinedge) != hdest) sesymself(spinedge);
17237 assert(sdest(spinedge) == hdest);
17240 hdest = sdest(hullsh);
17242 ori = orient3d(sorg(hullsh), hdest, abovepoint, inspoint);
17244 aboveflag = ori < 0.0;
17247 makeshellface(subfaces, &newsh);
17248 setsorg(newsh, hdest);
17249 setsdest(newsh, sorg(hullsh));
17250 setsapex(newsh, inspoint);
17251 setshellmark(newsh, shmark);
17252 if (b->quality && varconstraint) {
17253 setareabound(newsh, areabound(hullsh));
17256 setshellpbcgroup(newsh, shellpbcgroup(hullsh));
17259 sbond(newsh, hullsh);
17260 senext(newsh, rightsh);
17261 sbond(rightsh, leftsh);
17263 enqueueflipedge(hullsh, flipqueue);
17266 dummysh[0] = sencode(leftsh);
17282 void tetgenmesh::incrflipdelaunaysub(
int shmark, REAL eps, list* ptlist,
17283 int holes, REAL* holelist, queue* flipque)
17285 face newsh, startsh;
17286 point *insertarray;
17289 enum locateresult loc;
17298 insertarray = (point *) ptlist->base;
17299 arraysize = ptlist->len();
17300 if (arraysize < 3)
return;
17303 aboveflag = (arraysize > 3);
17311 for (i = 1; i < arraysize; i++) {
17312 det = distance(insertarray[0], insertarray[i]);
17313 if (det > (longest * eps))
break;
17315 if (i < arraysize) {
17317 swappt = insertarray[i];
17318 insertarray[i] = insertarray[1];
17319 insertarray[1] = swappt;
17322 for (i++; i < arraysize; i++) {
17323 if (!iscollinear(insertarray[0], insertarray[1], insertarray[i], eps))
17326 if (i < arraysize) {
17328 swappt = insertarray[i];
17329 insertarray[i] = insertarray[2];
17330 insertarray[2] = swappt;
17336 if ((eps == 0.0) || (epscount > 16)) {
17337 printf(
"Error: Invalid PLC.\n");
17338 printf(
" Facet (%d, %d, %d", pointmark(insertarray[0]),
17339 pointmark(insertarray[1]), pointmark(insertarray[2]));
17340 if (ptlist->len() > 3) {
17343 printf(
") (%d) is not a valid polygon.\n", shmark);
17344 terminatetetgen(1);
17355 makeshellface(subfaces, &newsh);
17356 setsorg(newsh, insertarray[0]);
17357 setsdest(newsh, insertarray[1]);
17358 setsapex(newsh, insertarray[2]);
17360 setshellmark(newsh, shmark);
17362 if (pointtype(insertarray[0]) == FREEVOLVERTEX) {
17363 setpointtype(insertarray[0], FREESUBVERTEX);
17365 if (pointtype(insertarray[1]) == FREEVOLVERTEX) {
17366 setpointtype(insertarray[1], FREESUBVERTEX);
17368 if (pointtype(insertarray[2]) == FREEVOLVERTEX) {
17369 setpointtype(insertarray[2], FREESUBVERTEX);
17372 dummysh[0] = sencode(newsh);
17375 if (b->quality && (in->facetconstraintlist != (REAL *) NULL)) {
17376 idx = in->facetmarkerlist[shmark - 1];
17377 for (k = 0; k < in->numberoffacetconstraints; k++) {
17378 fmarker = (int) in->facetconstraintlist[k * 2];
17379 if (fmarker == idx) {
17380 area = in->facetconstraintlist[k * 2 + 1];
17381 setareabound(newsh, area);
17389 idx = in->facetmarkerlist[shmark - 1];
17390 for (k = 0; k < in->numberofpbcgroups; k++) {
17391 pd = &subpbcgrouptable[k];
17392 for (j = 0; j < 2; j++) {
17393 if (pd->fmark[j] == idx) {
17394 setshellpbcgroup(newsh, k);
17403 abovepoint = facetabovepointarray[shmark];
17404 if (abovepoint == (point) NULL) {
17405 getfacetabovepoint(&newsh);
17412 for (k = 0; k < holes; k++) {
17413 projpt2face(&(holelist[k * 3]), insertarray[0], insertarray[1],
17414 insertarray[2], prj);
17415 for (j = 0; j < 3; j++) holelist[k * 3 + j] = prj[j];
17420 for (; i < arraysize; i++) {
17422 startsh.sh = dummysh;
17423 loc = locatesub(insertarray[i], &startsh, 0, 0.0);
17424 if (loc == ONFACE) {
17425 splitsubface(insertarray[i], &startsh, flipque);
17426 }
else if (loc == ONEDGE) {
17427 splitsubedge(insertarray[i], &startsh, flipque);
17428 }
else if (loc == OUTSIDE) {
17429 collectvisiblesubs(shmark, insertarray[i], &startsh, flipque);
17430 }
else if (loc == ONVERTEX) {
17434 if (pointtype(insertarray[i]) == FREEVOLVERTEX) {
17435 setpointtype(insertarray[i], FREESUBVERTEX);
17456 enum tetgenmesh::finddirectionresult tetgenmesh::finddirectionsub(
17457 face* searchsh, point tend)
17460 point startpoint, leftpoint, rightpoint;
17461 REAL leftccw, rightccw;
17463 int leftflag, rightflag;
17465 startpoint = sorg(*searchsh);
17467 adjustedgering(*searchsh, CCW);
17469 if (sorg(*searchsh) != startpoint) senextself(*searchsh);
17470 rightpoint = sdest(*searchsh);
17471 leftpoint = sapex(*searchsh);
17472 ori = orient3d(startpoint, rightpoint, leftpoint, abovepoint);
17473 sign = ori > 0.0 ? -1 : 1;
17476 ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17477 leftccw = ori * sign;
17478 leftflag = leftccw > 0.0;
17480 ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17481 rightccw = ori * sign;
17482 rightflag = rightccw > 0.0;
17483 if (leftflag && rightflag) {
17486 senext2(*searchsh, checksh);
17487 spivotself(checksh);
17488 if (checksh.sh == dummysh) {
17496 senext2self(*searchsh);
17497 spivotself(*searchsh);
17498 if (searchsh->sh == dummysh) {
17499 printf(
"Internal error in finddirectionsub(): Unable to find a\n");
17500 printf(
" subface leading from %d to %d.\n", pointmark(startpoint),
17504 if (sorg(*searchsh) != startpoint) sesymself(*searchsh);
17505 assert(sorg(*searchsh) == startpoint);
17506 leftpoint = sapex(*searchsh);
17507 rightccw = leftccw;
17508 ori = orient3d(tend, startpoint, abovepoint, leftpoint);
17509 leftccw = ori * sign;
17510 leftflag = leftccw > 0.0;
17512 while (rightflag) {
17514 spivotself(*searchsh);
17515 if (searchsh->sh == dummysh) {
17516 printf(
"Internal error in finddirectionsub(): Unable to find a\n");
17517 printf(
" subface leading from %d to %d.\n", pointmark(startpoint),
17521 if (sdest(*searchsh) != startpoint) sesymself(*searchsh);
17522 assert(sdest(*searchsh) == startpoint);
17523 senextself(*searchsh);
17524 rightpoint = sdest(*searchsh);
17525 leftccw = rightccw;
17526 ori = orient3d(startpoint, tend, abovepoint, rightpoint);
17527 rightccw = ori * sign;
17528 rightflag = rightccw > 0.0;
17530 if (leftccw == 0.0) {
17531 return LEFTCOLLINEAR;
17532 }
else if (rightccw == 0.0) {
17533 return RIGHTCOLLINEAR;
17550 void tetgenmesh::insertsubseg(face* tri)
17560 sspivot(*tri, newsubseg);
17561 if (newsubseg.sh == dummysh) {
17563 makeshellface(subsegs, &newsubseg);
17566 setsorg(newsubseg, pa);
17567 setsdest(newsubseg, pb);
17569 if (b->quality && (in->segmentconstraintlist != (REAL *) NULL)) {
17570 for (i = 0; i < in->numberofsegmentconstraints; i++) {
17571 e1 = (int) in->segmentconstraintlist[i * 3];
17572 e2 = (
int) in->segmentconstraintlist[i * 3 + 1];
17573 if (((pointmark(pa) == e1) && (pointmark(pb) == e2)) ||
17574 ((pointmark(pa) == e2) && (pointmark(pb) == e1))) {
17575 len = in->segmentconstraintlist[i * 3 + 2];
17576 setareabound(newsubseg, len);
17582 ssbond(*tri, newsubseg);
17583 spivot(*tri, oppotri);
17585 if (oppotri.sh != dummysh) {
17586 ssbond(oppotri, newsubseg);
17606 bool tetgenmesh::scoutsegmentsub(face* searchsh, point tend)
17609 face crosssub, crosssubseg;
17610 point leftpoint, rightpoint;
17611 enum finddirectionresult collinear;
17613 collinear = finddirectionsub(searchsh, tend);
17614 rightpoint = sdest(*searchsh);
17615 leftpoint = sapex(*searchsh);
17616 if (rightpoint == tend || leftpoint == tend) {
17618 if (leftpoint == tend) {
17619 senext2self(*searchsh);
17622 insertsubseg(searchsh);
17624 }
else if (collinear == LEFTCOLLINEAR) {
17627 senextself(*searchsh);
17629 insertsubseg(searchsh);
17631 return scoutsegmentsub(searchsh, tend);
17632 }
else if (collinear == RIGHTCOLLINEAR) {
17635 insertsubseg(searchsh);
17637 senextself(*searchsh);
17639 return scoutsegmentsub(searchsh, tend);
17641 senext(*searchsh, crosssub);
17643 sspivot(crosssub, crosssubseg);
17645 assert(crosssubseg.sh == dummysh);
17663 void tetgenmesh::flipedgerecursive(face* flipedge, queue* flipqueue)
17666 point pa, pb, pc, pd;
17670 pa = sorg(*flipedge);
17671 pb = sdest(*flipedge);
17672 pc = sapex(*flipedge);
17674 spivot(*flipedge, fixupsh);
17675 pd = sapex(fixupsh);
17676 oria = orient3d(pc, pd, abovepoint, pa);
17677 orib = orient3d(pc, pd, abovepoint, pb);
17678 doflip = (oria * orib < 0.0);
17681 flip22sub(flipedge, flipqueue);
17683 findedge(flipedge, pc, pd);
17686 if (sorg(fixupsh) != pb) sesymself(fixupsh);
17687 assert(sdest(fixupsh) == pa);
17688 if (fabs(oria) > fabs(orib)) {
17690 senextself(fixupsh);
17693 senext2self(fixupsh);
17696 flipedgerecursive(&fixupsh, flipqueue);
17713 void tetgenmesh::constrainededge(face* startsh, point tend, queue* flipqueue)
17715 point tstart, tright, tleft;
17719 tstart = sorg(*startsh);
17723 tright = sdest(*startsh);
17724 tleft = sapex(*startsh);
17726 rori = orient3d(tstart, tright, abovepoint, tend);
17727 collision = (rori == 0.0);
17728 if (collision)
break;
17729 lori = orient3d(tstart, tleft, abovepoint, tend);
17730 collision = (lori == 0.0);
17732 senext2self(*startsh);
17735 if (rori * lori < 0.0)
break;
17737 finddirectionsub(startsh, tend);
17739 if (collision)
break;
17741 senextself(*startsh);
17743 flipedgerecursive(startsh, flipqueue);
17745 assert(sorg(*startsh) == tstart);
17746 }
while (sdest(*startsh) != tend);
17749 insertsubseg(startsh);
17754 if (!scoutsegmentsub(startsh, tend)) {
17755 constrainededge(startsh, tend, flipqueue);
17766 void tetgenmesh::recoversegment(point tstart, point tend, queue* flipqueue)
17770 if (b->verbose > 2) {
17771 printf(
" Insert seg (%d, %d).\n", pointmark(tstart), pointmark(tend));
17775 searchsh.sh = dummysh;
17777 if (locatesub(tstart, &searchsh, 0, 0.0) != ONVERTEX) {
17781 newshlist =
new list(
sizeof(face), NULL, 256);
17783 retrievenewsubs(newshlist,
false);
17785 for (i = 0; i < newshlist->len(); i++) {
17786 searchsh = * (face *)(* newshlist)[i];
17787 for (j = 0; j < 3; j++) {
17788 if (sorg(searchsh) == tstart)
break;
17789 senextself(searchsh);
17794 if (sorg(searchsh) != tstart) {
17795 printf(
"Internal error in recoversegment(): Vertex location failed.\n");
17800 if (scoutsegmentsub(&searchsh, tend)) {
17805 constrainededge(&searchsh, tend, flipqueue);
17807 flipsub(flipqueue);
17817 void tetgenmesh::infecthullsub(
memorypool* viri)
17819 face hulltri, nexttri, starttri;
17821 shellface **deadshellface;
17824 hulltri.sh = dummysh;
17826 spivotself(hulltri);
17827 adjustedgering(hulltri, CCW);
17829 starttri = hulltri;
17833 if (!sinfected(hulltri)) {
17835 sspivot(hulltri, hullsubseg);
17836 if (hullsubseg.sh == dummysh) {
17838 if (!sinfected(hulltri)) {
17840 deadshellface = (shellface **) viri->alloc();
17841 *deadshellface = hulltri.sh;
17846 senextself(hulltri);
17847 spivot(hulltri, nexttri);
17848 if (nexttri.sh == hulltri.sh) {
17849 nexttri.sh = dummysh;
17851 adjustedgering(nexttri, CCW);
17852 senextself(nexttri);
17854 while (nexttri.sh != dummysh) {
17856 spivot(hulltri, nexttri);
17857 if (nexttri.sh == hulltri.sh) {
17858 nexttri.sh = dummysh;
17860 adjustedgering(nexttri, CCW);
17861 senextself(nexttri);
17864 }
while (hulltri != starttri);
17877 void tetgenmesh::plaguesub(
memorypool* viri)
17879 face testtri, neighbor, ghostsh;
17880 face neighborsubseg;
17881 shellface **virusloop;
17882 shellface **deadshellface;
17887 viri->traversalinit();
17888 virusloop = (shellface **) viri->traverse();
17889 while (virusloop != (shellface **) NULL) {
17890 testtri.sh = *virusloop;
17892 for (i = 0; i < 3; i++) {
17894 spivot(testtri, neighbor);
17896 sspivot(testtri, neighborsubseg);
17898 if ((neighbor.sh == dummysh) || sinfected(neighbor)) {
17899 if (neighborsubseg.sh != dummysh) {
17903 shellfacedealloc(subsegs, neighborsubseg.sh);
17904 if (neighbor.sh != dummysh) {
17907 ssdissolve(neighbor);
17911 if (neighborsubseg.sh == dummysh) {
17916 deadshellface = (shellface **) viri->alloc();
17917 *deadshellface = neighbor.sh;
17920 ssbond(neighbor, neighborsubseg);
17923 senextself(testtri);
17925 virusloop = (shellface **) viri->traverse();
17928 ghostsh.sh = dummysh;
17929 viri->traversalinit();
17930 virusloop = (shellface **) viri->traverse();
17931 while (virusloop != (shellface **) NULL) {
17932 testtri.sh = *virusloop;
17935 for (i = 0; i < 3; i++) {
17936 spivot(testtri, neighbor);
17937 if (neighbor.sh != dummysh) {
17940 sbond(neighbor, ghostsh);
17942 senextself(testtri);
17945 shellfacedealloc(subfaces, testtri.sh);
17946 virusloop = (shellface **) viri->traverse();
17963 void tetgenmesh::carveholessub(
int holes, REAL* holelist,
memorypool *viri)
17965 face searchtri, triangleloop;
17966 shellface **holetri;
17967 enum locateresult intersect;
17972 infecthullsub(viri);
17976 for (i = 0; i < 3 * holes; i += 3) {
17978 if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
17979 && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)
17980 && (holelist[i + 2] >= zmin) && (holelist[i + 2] <= zmax)) {
17982 searchtri.sh = dummysh;
17984 intersect = locatesub(&holelist[i], &searchtri, 0, 0.0);
17985 if ((intersect != OUTSIDE) && (!sinfected(searchtri))) {
17988 sinfect(searchtri);
17989 holetri = (shellface **) viri->alloc();
17990 *holetri = searchtri.sh;
17996 if (viri->items > 0) {
18021 void tetgenmesh::triangulate(
int shmark, REAL eps, list* ptlist, list* conlist,
18022 int holes, REAL* holelist,
memorypool* viri, queue* flipqueue)
18028 if (b->verbose > 1) {
18029 printf(
" %d vertices, %d segments", ptlist->len(), conlist->len());
18031 printf(
", %d holes", holes);
18033 printf(
", shmark: %d.\n", shmark);
18037 incrflipdelaunaysub(shmark, eps, ptlist, holes, holelist, flipqueue);
18039 if (ptlist->len() > 3) {
18041 for (i = 0; i < conlist->len(); i++) {
18042 cons = (point *)(* conlist)[i];
18043 recoversegment(cons[0], cons[1], flipqueue);
18046 carveholessub(holes, holelist, viri);
18047 }
else if (ptlist->len() == 3) {
18049 newsh.sh = dummysh;
18052 for (i = 0; i < 3; i++) {
18053 insertsubseg(&newsh);
18056 }
else if (ptlist->len() == 2) {
18060 cons = (point *)(* conlist)[0];
18061 makeshellface(subsegs, &newsh);
18062 setsorg(newsh, cons[0]);
18063 setsdest(newsh, cons[1]);
18080 void tetgenmesh::retrievenewsubs(list* newshlist,
bool removeseg)
18082 face startsh, neighsh;
18087 startsh.sh = dummysh;
18089 spivotself(startsh);
18090 assert(startsh.sh != dummysh);
18092 newshlist->append(&startsh);
18095 for (i = 0; i < newshlist->len(); i++) {
18097 startsh = * (face *)(* newshlist)[i];
18098 for (j = 0; j < 3; j++) {
18099 spivot(startsh, neighsh);
18100 if (neighsh.sh != dummysh) {
18101 if (!sinfected(neighsh)) {
18104 newshlist->append(&neighsh);
18110 sspivot(startsh, deadseg);
18111 if (deadseg.sh != dummysh) {
18113 ssdissolve(startsh);
18115 shellfacedealloc(subsegs, deadseg.sh);
18119 senextself(startsh);
18122 for (i = 0; i < newshlist->len(); i++) {
18123 startsh = * (face *)(* newshlist)[i];
18124 suninfect(startsh);
18145 void tetgenmesh::unifysegments()
18148 shellface **facesperverlist;
18149 face subsegloop, testseg;
18150 face sface, sface1, sface2;
18157 if (b->verbose > 0) {
18158 printf(
" Unifying segments.\n");
18162 makesubfacemap(idx2facelist, facesperverlist);
18164 sfacelist =
new list(
sizeof(face), NULL);
18167 subsegs->traversalinit();
18168 subsegloop.sh = shellfacetraverse(subsegs);
18169 while (subsegloop.sh != (shellface *) NULL) {
18170 subsegloop.shver = 0;
18171 torg = sorg(subsegloop);
18172 tdest = sdest(subsegloop);
18173 idx = pointmark(torg) - in->firstnumber;
18178 for (k = idx2facelist[idx]; k < idx2facelist[idx + 1]; k++) {
18179 sface.sh = facesperverlist[k];
18182 if (!isdead(&sface) && isfacehasedge(&sface, torg, tdest)) {
18184 findedge(&sface, torg, tdest);
18186 if (sfacelist->len() < 2) {
18187 sfacelist->append(&sface);
18189 for (m = 0; m < sfacelist->len() - 1; m++) {
18190 sface1 = * (face *)(* sfacelist)[m];
18191 sface2 = * (face *)(* sfacelist)[m + 1];
18192 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(sface));
18193 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
18198 sfacelist->insert(m + 1, &sface);
18202 if (b->verbose > 1) {
18203 printf(
" Identifying %d segments of (%d %d).\n", sfacelist->len(),
18204 pointmark(torg), pointmark(tdest));
18208 for (k = 0; k < sfacelist->len(); k++) {
18209 sface = *(face *)(* sfacelist)[k];
18210 sspivot(sface, testseg);
18214 if ((testseg.sh != subsegloop.sh) && !isdead(&testseg)) {
18215 shellfacedealloc(subsegs, testseg.sh);
18219 ssbond(sface, subsegloop);
18222 sface = *(face *)(* sfacelist)[0];
18223 for (k = 1; k <= sfacelist->len(); k++) {
18224 if (k < sfacelist->len()) {
18225 sface1 = *(face *)(* sfacelist)[k];
18227 sface1 = *(face *)(* sfacelist)[0];
18256 if (b->verbose > 2) {
18257 printf(
" Bond subfaces (%d, %d, %d) and (%d, %d, %d).\n",
18258 pointmark(torg), pointmark(tdest), pointmark(sapex(sface)),
18259 pointmark(torg), pointmark(tdest), pointmark(sapex(sface1)));
18261 sbond1(sface, sface1);
18265 setshellmark(subsegloop, segmarker);
18269 sfacelist->clear();
18270 subsegloop.sh = shellfacetraverse(subsegs);
18273 delete [] idx2facelist;
18274 delete [] facesperverlist;
18290 void tetgenmesh::mergefacets(queue* flipqueue)
18292 face parentsh, neighsh, neineighsh;
18296 bool mergeflag, pbcflag;
18297 int* segspernodelist;
18301 if (b->verbose > 0) {
18302 printf(
" Merging coplanar facets.\n");
18305 segspernodelist =
new int[points->items + 1];
18306 for (i = 0; i < points->items + 1; i++) segspernodelist[i] = 0;
18309 subsegs->traversalinit();
18310 segloop.sh = shellfacetraverse(subsegs);
18311 while (segloop.sh != (shellface *) NULL) {
18313 for (i = 0; i < 2; i++) {
18314 j = pointmark((point) segloop.sh[3 + i]);
18315 segspernodelist[j]++;
18317 segloop.sh = shellfacetraverse(subsegs);
18321 subsegs->traversalinit();
18322 segloop.sh = shellfacetraverse(subsegs);
18323 while (segloop.sh != (shellface *) NULL) {
18324 eorg = sorg(segloop);
18325 edest = sdest(segloop);
18326 spivot(segloop, parentsh);
18327 spivot(parentsh, neighsh);
18328 spivot(neighsh, neineighsh);
18329 if (parentsh.sh != neighsh.sh && parentsh.sh == neineighsh.sh) {
18331 fidx1 = shellmark(parentsh) - 1;
18332 fidx2 = shellmark(neighsh) - 1;
18335 pbcflag = (shellpbcgroup(parentsh) >= 0)
18336 || (shellpbcgroup(neighsh) >= 0);
18339 if ((fidx1 != fidx2) && !pbcflag) {
18341 ori = orient3d(eorg, edest, sapex(parentsh), sapex(neighsh));
18343 if (iscoplanar(eorg, edest, sapex(parentsh), sapex(neighsh), ori,
18349 mergeflag = (in->facetmarkerlist == (
int *) NULL ||
18350 in->facetmarkerlist[fidx1] == in->facetmarkerlist[fidx2]);
18353 if (b->verbose > 1) {
18354 printf(
" Removing segment (%d, %d).\n", pointmark(eorg),
18357 ssdissolve(parentsh);
18358 ssdissolve(neighsh);
18359 shellfacedealloc(subsegs, segloop.sh);
18360 j = pointmark(eorg);
18361 segspernodelist[j]--;
18362 if (segspernodelist[j] == 0) {
18363 setpointtype(eorg, FREESUBVERTEX);
18365 j = pointmark(edest);
18366 segspernodelist[j]--;
18367 if (segspernodelist[j] == 0) {
18368 setpointtype(edest, FREESUBVERTEX);
18371 enqueueflipedge(parentsh, flipqueue);
18376 segloop.sh = shellfacetraverse(subsegs);
18379 if (!flipqueue->empty()) {
18381 flipsub(flipqueue);
18384 delete [] segspernodelist;
18407 long tetgenmesh::meshsurface()
18409 list *ptlist, *conlist;
18411 tetgenio::facet *f;
18412 tetgenio::polygon *p;
18414 point *idx2verlist;
18415 point tstart, tend, *cons;
18421 printf(
"Creating surface mesh.\n");
18425 makeindex2pointmap(idx2verlist);
18427 makepoint2tetmap();
18429 facetabovepointarray =
new point[in->numberoffacets + 1];
18430 for (i = 0; i < in->numberoffacets + 1; i++) {
18431 facetabovepointarray[i] = (point) NULL;
18435 createsubpbcgrouptable();
18439 viri =
new memorypool(
sizeof(shellface *), 1024, POINTER, 0);
18440 flipqueue =
new queue(
sizeof(badface));
18441 ptlist =
new list(
sizeof(point *), NULL, 256);
18442 conlist =
new list(
sizeof(point *) * 2, NULL, 256);
18443 worklist =
new int[points->items + 1];
18444 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
18449 for (shmark = 1; shmark <= in->numberoffacets; shmark++) {
18451 f = &in->facetlist[shmark - 1];
18457 if ((b->object == tetgenbehavior::STL) || dupverts) {
18459 for (i = 0; i < f->numberofpolygons; i++) {
18460 p = &(f->polygonlist[i]);
18462 for (j = 0; j < p->numberofvertices; j++) {
18463 end1 = p->vertexlist[j];
18464 tstart = idx2verlist[end1 - in->firstnumber];
18465 if (pointtype(tstart) == DUPLICATEDVERTEX) {
18467 tend = point2ppt(tstart);
18468 end2 = pointmark(tend);
18469 p->vertexlist[j] = end2;
18476 for (i = 0; i < f->numberofpolygons; i++) {
18478 p = &(f->polygonlist[i]);
18480 end1 = p->vertexlist[0];
18481 if ((end1 < in->firstnumber) ||
18482 (end1 >= in->firstnumber + in->numberofpoints)) {
18484 printf(
"Warning: Invalid the 1st vertex %d of polygon", end1);
18485 printf(
" %d in facet %d.\n", i + 1, shmark);
18489 tstart = idx2verlist[end1 - in->firstnumber];
18491 if (worklist[end1] == 0) {
18492 ptlist->append(&tstart);
18493 worklist[end1] = 1;
18496 for (j = 1; j <= p->numberofvertices; j++) {
18498 if (j < p->numberofvertices) {
18499 end2 = p->vertexlist[j];
18501 end2 = p->vertexlist[0];
18503 if ((end2 < in->firstnumber) ||
18504 (end2 >= in->firstnumber + in->numberofpoints)) {
18506 printf(
"Warning: Invalid vertex %d in polygon %d", end2, i + 1);
18507 printf(
" in facet %d.\n", shmark);
18510 if (end1 != end2) {
18512 tend = idx2verlist[end2 - in->firstnumber];
18514 if (worklist[end2] == 0) {
18515 ptlist->append(&tend);
18516 worklist[end2] = 1;
18519 cons = (point *) conlist->append(NULL);
18527 if (p->numberofvertices > 2) {
18531 printf(
"Warning: Polygon %d has two identical verts", i + 1);
18532 printf(
" in facet %d.\n", shmark);
18539 if (p->numberofvertices == 2)
break;
18543 for (i = 0; i < ptlist->len(); i++) {
18544 tstart = * (point *)(* ptlist)[i];
18545 end1 = pointmark(tstart);
18546 assert(worklist[end1] == 1);
18547 worklist[end1] = 0;
18551 triangulate(shmark, b->epsilon * 1e+2, ptlist, conlist, f->numberofholes,
18552 f->holelist, viri, flipqueue);
18563 insegments = subsegs->items;
18567 createsegpbcgrouptable();
18570 if (b->object == tetgenbehavior::STL) {
18575 if (!b->nomerge && !b->nobisect && !checkpbcs) {
18577 mergefacets(flipqueue);
18580 delete [] idx2verlist;
18581 delete [] worklist;
18587 return subsegs->items;
18619 interecursive(shellface** subfacearray,
int arraysize,
int axis, REAL bxmin,
18620 REAL bxmax, REAL bymin, REAL bymax, REAL bzmin, REAL bzmax,
18623 shellface **leftarray, **rightarray;
18624 face sface1, sface2;
18627 enum interresult intersect;
18629 bool toleft, toright;
18630 int leftsize, rightsize;
18633 if (b->verbose > 1) {
18634 printf(
" Recur %d faces. Bbox (%g, %g, %g),(%g, %g, %g). %s-axis\n",
18635 arraysize, bxmin, bymin, bzmin, bxmax, bymax, bzmax,
18636 axis == 0 ?
"x" : (axis == 1 ?
"y" :
"z"));
18639 leftarray =
new shellface*[arraysize];
18640 if (leftarray == NULL) {
18641 printf(
"Error in interecursive(): Insufficient memory.\n");
18642 terminatetetgen(1);
18644 rightarray =
new shellface*[arraysize];
18645 if (rightarray == NULL) {
18646 printf(
"Error in interecursive(): Insufficient memory.\n");
18647 terminatetetgen(1);
18649 leftsize = rightsize = 0;
18653 split = 0.5 * (bxmin + bxmax);
18654 }
else if (axis == 1) {
18656 split = 0.5 * (bymin + bymax);
18659 split = 0.5 * (bzmin + bzmax);
18662 for (i = 0; i < arraysize; i++) {
18663 sface1.sh = subfacearray[i];
18664 p1 = (point) sface1.sh[3];
18665 p2 = (point) sface1.sh[4];
18666 p3 = (point) sface1.sh[5];
18667 toleft = toright =
false;
18668 if (p1[axis] < split) {
18670 if (p2[axis] >= split || p3[axis] >= split) {
18673 }
else if (p1[axis] > split) {
18675 if (p2[axis] <= split || p3[axis] <= split) {
18685 assert(!(toleft ==
false && toright ==
false));
18688 leftarray[leftsize] = sface1.sh;
18692 rightarray[rightsize] = sface1.sh;
18697 if (leftsize < arraysize && rightsize < arraysize) {
18702 delete [] subfacearray;
18705 interecursive(leftarray, leftsize, 1, bxmin, split, bymin, bymax,
18706 bzmin, bzmax, internum);
18707 interecursive(rightarray, rightsize, 1, split, bxmax, bymin, bymax,
18708 bzmin, bzmax, internum);
18709 }
else if (axis == 1) {
18710 interecursive(leftarray, leftsize, 2, bxmin, bxmax, bymin, split,
18711 bzmin, bzmax, internum);
18712 interecursive(rightarray, rightsize, 2, bxmin, bxmax, split, bymax,
18713 bzmin, bzmax, internum);
18715 interecursive(leftarray, leftsize, 0, bxmin, bxmax, bymin, bymax,
18716 bzmin, split, internum);
18717 interecursive(rightarray, rightsize, 0, bxmin, bxmax, bymin, bymax,
18718 split, bzmax, internum);
18721 if (b->verbose > 1) {
18722 printf(
" Checking intersecting faces.\n");
18725 for (i = 0; i < arraysize; i++) {
18726 sface1.sh = subfacearray[i];
18727 p1 = (point) sface1.sh[3];
18728 p2 = (point) sface1.sh[4];
18729 p3 = (point) sface1.sh[5];
18730 for (j = i + 1; j < arraysize; j++) {
18731 sface2.sh = subfacearray[j];
18732 p4 = (point) sface2.sh[3];
18733 p5 = (point) sface2.sh[4];
18734 p6 = (point) sface2.sh[5];
18735 intersect = tri_tri_inter(p1, p2, p3, p4, p5, p6);
18736 if (intersect == INTERSECT || intersect == SHAREFACE) {
18738 if (intersect == INTERSECT) {
18739 printf(
" Facet #%d intersects facet #%d at triangles:\n",
18740 shellmark(sface1), shellmark(sface2));
18741 printf(
" (%4d, %4d, %4d) and (%4d, %4d, %4d)\n",
18742 pointmark(p1), pointmark(p2), pointmark(p3),
18743 pointmark(p4), pointmark(p5), pointmark(p6));
18745 printf(
" Facet #%d duplicates facet #%d at triangle:\n",
18746 shellmark(sface1), shellmark(sface2));
18747 printf(
" (%4d, %4d, %4d)\n", pointmark(p1), pointmark(p2),
18760 delete [] leftarray;
18761 delete [] rightarray;
18762 delete [] subfacearray;
18791 void tetgenmesh::detectinterfaces()
18793 shellface **subfacearray;
18799 printf(
"Detecting intersecting facets.\n");
18803 subfacearray =
new shellface*[subfaces->items];
18804 subfaces->traversalinit();
18805 shloop.sh = shellfacetraverse(subfaces);
18807 while (shloop.sh != (shellface *) NULL) {
18808 subfacearray[i] = shloop.sh;
18809 shloop.sh = shellfacetraverse(subfaces);
18817 interecursive(subfacearray, subfaces->items, 0, xmin, xmax, ymin, ymax,
18818 zmin, zmax, &internum);
18821 if (internum > 0) {
18822 printf(
"\n!! Found %d pairs of faces are intersecting.\n\n", internum);
18824 printf(
"\nNo faces are intersecting.\n\n");
18828 if (internum > 0) {
18832 subfaces->traversalinit();
18833 shloop.sh = shellfacetraverse(subfaces);
18834 while (shloop.sh != (shellface *) NULL) {
18835 if (sinfected(shloop)) {
18838 shellfacedealloc(subfaces, shloop.sh);
18840 shloop.sh = shellfacetraverse(subfaces);
18844 subfaces->restart();
18866 void tetgenmesh::createsubpbcgrouptable()
18868 tetgenio::pbcgroup *pg;
18870 REAL A[4][4], rhs[4], D;
18874 subpbcgrouptable =
new pbcdata[in->numberofpbcgroups];
18875 for (i = 0; i < in->numberofpbcgroups; i++) {
18876 pg = &(in->pbcgrouplist[i]);
18877 pd = &(subpbcgrouptable[i]);
18879 pd->fmark[0] = pg->fmark1;
18880 pd->fmark[1] = pg->fmark2;
18882 pd->ss[0].sh = dummysh;
18883 pd->ss[1].sh = dummysh;
18885 for (j = 0; j < 4; j++) {
18886 for (k = 0; k < 4; k++) {
18887 pd->transmat[0][j][k] = pg->transmat[j][k];
18889 A[j][k] = pg->transmat[j][k];
18893 lu_decmp(A, 4, indx, &D, 0);
18894 for (j = 0; j < 4; j++) {
18895 for (k = 0; k < 4; k++) rhs[k] = 0.0;
18897 lu_solve(A, 4, indx, rhs, 0);
18898 for (k = 0; k < 4; k++) pd->transmat[1][k][j] = rhs[k];
18913 void tetgenmesh::getsubpbcgroup(face* pbcsub, pbcdata** pd,
int *f1,
int *f2)
18915 int groupid, fmark, idx;
18917 groupid = shellpbcgroup(*pbcsub);
18918 *pd = &subpbcgrouptable[groupid];
18921 idx = shellmark(*pbcsub);
18923 fmark = in->facetmarkerlist[idx - 1];
18924 if ((*pd)->fmark[0] == fmark) {
18928 assert((*pd)->fmark[1] == fmark);
18945 enum tetgenmesh::locateresult tetgenmesh:: getsubpbcsympoint(point newpoint,
18946 face* splitsub, point sympoint, face* symsplitsub)
18951 enum locateresult symloc;
18956 getsubpbcgroup(splitsub, &pd, &f1, &f2);
18959 for (i = 0; i < 3; i++) {
18960 sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
18961 + pd->transmat[f1][i][1] * newpoint[1]
18962 + pd->transmat[f1][i][2] * newpoint[2]
18963 + pd->transmat[f1][i][3] * 1.0;
18967 *symsplitsub = pd->ss[f2];
18969 if ((symsplitsub->sh != dummysh) && !isdead(symsplitsub)) {
18971 i = shellmark(*symsplitsub);
18972 if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
18974 pa = sorg(*symsplitsub);
18975 pb = sdest(*symsplitsub);
18976 pc = sapex(*symsplitsub);
18979 ori = orient3d(pa, pb, pc, sympoint);
18980 if (iscoplanar(pa, pb, pc, sympoint, ori, b->epsilon * 1e+2)) {
18982 abovepoint = facetabovepointarray[shellmark(*symsplitsub)];
18983 if (abovepoint == (point) NULL) {
18984 getfacetabovepoint(symsplitsub);
18986 symloc = locatesub(sympoint, symsplitsub, 0, b->epsilon * 1e+2);
18990 if (symloc == OUTSIDE) {
18992 REAL epspp = b->epsilon * 1e+2;
18996 subfaces->traversalinit();
18997 subloop.sh = shellfacetraverse(subfaces);
18998 while (subloop.sh != (shellface *) NULL) {
18999 i = shellmark(subloop);
19000 if (in->facetmarkerlist[i - 1] == pd->fmark[f2]) {
19002 pa = sorg(subloop);
19003 pb = sdest(subloop);
19004 pc = sapex(subloop);
19007 ori = orient3d(pa, pb, pc, sympoint);
19008 if (iscoplanar(pa, pb, pc, sympoint, ori, epspp)) {
19011 abovepoint = facetabovepointarray[shellmark(subloop)];
19013 if (abovepoint == (point) NULL) {
19014 getfacetabovepoint(&subloop);
19017 symloc = locatesub(sympoint, &subloop, 0, epspp);
19018 if (symloc != OUTSIDE)
break;
19021 subloop.sh = shellfacetraverse(subfaces);
19025 }
while ((symloc == OUTSIDE) && (lcount < 3));
19028 assert(symloc != OUTSIDE);
19031 *symsplitsub = subloop;
19033 pd->ss[f2] = *symsplitsub;
19036 return adjustlocatesub(sympoint, symsplitsub, symloc, b->epsilon);
19052 void tetgenmesh::createsegpbcgrouptable()
19054 shellface** segsperverlist;
19055 pbcdata *pd, *ppd, pd1, pd2;
19056 face segloop, symseg;
19057 face startsh, spinsh, symsh;
19058 point pa, pb, syma, symb;
19059 enum locateresult symloc;
19060 REAL testpt[3], sympt[3];
19063 int segid1, segid2;
19068 segpbcgrouptable =
new list(
sizeof(pbcdata), NULL, 256);
19072 makesegmentmap(idx2seglist, segsperverlist);
19076 subsegs->traversalinit();
19077 segloop.sh = shellfacetraverse(subsegs);
19078 while (segloop.sh != (shellface *) NULL) {
19080 pa = sorg(segloop);
19081 pb = sdest(segloop);
19082 segid1 = shellmark(segloop);
19083 spivot(segloop, startsh);
19087 if (sorg(spinsh) != pa) {
19091 if (shellpbcgroup(spinsh) != -1) {
19094 getsubpbcgroup(&spinsh, &pd, &f1, &f2);
19096 for (i = 0; i < 3; i++) {
19097 sympt[i] = pd->transmat[f1][i][0] * pa[0]
19098 + pd->transmat[f1][i][1] * pa[1]
19099 + pd->transmat[f1][i][2] * pa[2]
19100 + pd->transmat[f1][i][3] * 1.0;
19102 syma = point2pbcpt(pa);
19104 if (distance(sympt, syma) > (longest * b->epsilon)) {
19106 symloc = getsubpbcsympoint(pa, &spinsh, sympt, &symsh);
19107 syma = sorg(symsh);
19108 if (symloc != ONVERTEX) {
19114 for (i = 0; i < 3; i++) {
19115 sympt[i] = pd->transmat[f1][i][0] * pb[0]
19116 + pd->transmat[f1][i][1] * pb[1]
19117 + pd->transmat[f1][i][2] * pb[2]
19118 + pd->transmat[f1][i][3] * 1.0;
19122 j = pointmark(syma) - in->firstnumber;
19123 for (i = idx2seglist[j]; i < idx2seglist[j + 1]; i++) {
19124 symseg.sh = segsperverlist[i];
19125 if (sorg(symseg) == syma) symb = sdest(symseg);
19126 else symb = sorg(symseg);
19127 if (distance(sympt, symb) <= (longest * b->epsilon))
break;
19129 assert(i < idx2seglist[j + 1]);
19132 for (i = 0; i < 3; i++) testpt[i] = 0.5 * (pa[i] + pb[i]);
19133 symloc = getsubpbcsympoint(testpt, &spinsh, sympt, &symsh);
19135 assert(symloc == ONEDGE);
19137 sspivot(symsh, symseg);
19140 assert(symseg.sh != dummysh);
19143 segid2 = shellmark(symseg);
19145 for (i = 0; i < segpbcgrouptable->len() && !inflag; i++) {
19146 pd = (pbcdata *)(* segpbcgrouptable)[i];
19147 if (pd->segid[0] == segid1) {
19148 if (pd->segid[1] == segid2) inflag =
true;
19149 }
else if (pd->segid[0] == segid2) {
19150 if (pd->segid[1] == segid1) inflag =
true;
19155 pd = (pbcdata *) segpbcgrouptable->append(NULL);
19157 pd->segid[0] = segid1;
19158 pd->segid[1] = segid2;
19160 pd->ss[0] = segloop;
19161 pd->ss[1] = symseg;
19163 getsubpbcgroup(&spinsh, &ppd, &f1, &f2);
19164 pd->fmark[0] = ppd->fmark[f1];
19165 pd->fmark[1] = ppd->fmark[f2];
19167 for (i = 0; i < 4; i++) {
19168 for (j = 0; j < 4; j++) {
19169 pd->transmat[0][i][j] = ppd->transmat[f1][i][j];
19173 for (i = 0; i < 4; i++) {
19174 for (j = 0; j < 4; j++) {
19175 pd->transmat[1][i][j] = ppd->transmat[f2][i][j];
19181 spivotself(spinsh);
19182 }
while (spinsh.sh != startsh.sh);
19183 segloop.sh = shellfacetraverse(subsegs);
19187 delete [] segsperverlist;
19188 delete [] idx2seglist;
19195 for (i = 0; i < segpbcgrouptable->len(); i++) {
19196 pd1 = * (pbcdata *)(* segpbcgrouptable)[i];
19197 for (f1 = 0; f1 < 2; f1++) {
19199 for (j = 0; j < segpbcgrouptable->len(); j++) {
19200 if (j == i)
continue;
19201 pd2 = * (pbcdata *)(* segpbcgrouptable)[j];
19203 if (pd1.segid[f1] == pd2.segid[0]) {
19205 }
else if (pd1.segid[f1] == pd2.segid[1]) {
19210 assert(pd1.segid[f1] == pd2.segid[f2]);
19212 segid1 = pd1.segid[1 - f1];
19213 segid2 = pd2.segid[1 - f2];
19216 for (k = 0; k < segpbcgrouptable->len() && !inflag; k++) {
19217 pd = (pbcdata *)(* segpbcgrouptable)[k];
19218 if (pd->segid[0] == segid1) {
19219 if (pd->segid[1] == segid2) inflag =
true;
19220 }
else if (pd->segid[0] == segid2) {
19221 if (pd->segid[1] == segid1) inflag =
true;
19225 pd = (pbcdata *) segpbcgrouptable->append(NULL);
19226 pd->segid[0] = pd1.segid[1 - f1];
19227 pd->segid[1] = pd2.segid[1 - f2];
19228 pd->ss[0] = pd1.ss[1 - f1];
19229 pd->ss[1] = pd2.ss[1 - f2];
19231 pd->fmark[0] = pd->fmark[1] = 0;
19234 for (k = 0; k < 4; k++) {
19235 for (l = 0; l < 4; l++) {
19236 pd->transmat[0][k][l] = pd2.transmat[f2][k][l];
19239 m4xm4(pd->transmat[0], pd1.transmat[1 - f1]);
19242 for (k = 0; k < 4; k++) {
19243 for (l = 0; l < 4; l++) {
19244 pd->transmat[1][k][l] = pd1.transmat[f1][k][l];
19247 m4xm4(pd->transmat[1], pd2.transmat[1 - f2]);
19255 idx2segpglist =
new int[subsegs->items + 1];
19256 for (i = 0; i < subsegs->items + 1; i++) idx2segpglist[i] = 0;
19259 for (i = 0; i < segpbcgrouptable->len(); i++) {
19260 pd = (pbcdata *)(* segpbcgrouptable)[i];
19261 for (j = 0; j < 2; j++) {
19262 k = pd->segid[j] - 1;
19263 idx2segpglist[k]++;
19267 j = idx2segpglist[0];
19268 idx2segpglist[0] = 0;
19269 for (i = 0; i < subsegs->items; i++) {
19270 k = idx2segpglist[i + 1];
19271 idx2segpglist[i + 1] = idx2segpglist[i] + j;
19275 segpglist =
new int[idx2segpglist[i]];
19277 for (i = 0; i < segpbcgrouptable->len(); i++) {
19278 pd = (pbcdata *)(* segpbcgrouptable)[i];
19279 for (j = 0; j < 2; j++) {
19280 k = pd->segid[j] - 1;
19281 segpglist[idx2segpglist[k]] = i;
19282 idx2segpglist[k]++;
19286 for (i = subsegs->items - 1; i >= 0; i--) {
19287 idx2segpglist[i + 1] = idx2segpglist[i];
19289 idx2segpglist[0] = 0;
19302 enum tetgenmesh::locateresult tetgenmesh::
19303 getsegpbcsympoint(point newpoint, face* splitseg, point sympoint,
19304 face* symsplitseg,
int groupid)
19307 enum locateresult symloc;
19308 int segid, f1, f2, i;
19310 pd = (pbcdata *)(* segpbcgrouptable)[groupid];
19311 segid = shellmark(*splitseg);
19312 if (pd->segid[0] == segid) {
19316 assert(pd->segid[1] == segid);
19323 for (i = 0; i < 3; i++) {
19324 sympoint[i] = pd->transmat[f1][i][0] * newpoint[0]
19325 + pd->transmat[f1][i][1] * newpoint[1]
19326 + pd->transmat[f1][i][2] * newpoint[2]
19327 + pd->transmat[f1][i][3] * 1.0;
19330 *symsplitseg = pd->ss[f2];
19332 assert(symsplitseg->sh != dummysh);
19335 symloc = locateseg(sympoint, symsplitseg);
19336 symloc = adjustlocateseg(sympoint, symsplitseg, symloc, b->epsilon * 1e+2);
19354 REAL tetgenmesh::randgenerator(REAL range)
19356 REAL worknumber, result;
19359 if (range == 0.0)
return 0.0;
19362 worknumber = fabs(range);
19364 if (worknumber > 10.0) {
19365 while (worknumber > 10.0) {
19366 worknumber /= 10.0;
19369 }
else if (worknumber < 1.0) {
19370 while (worknumber < 1.0) {
19371 worknumber *= 10.0;
19376 assert(worknumber >= 1.0 && worknumber <= 10.0);
19380 worknumber *= 1e+3;
19383 result = (
double) randomnation((
int) worknumber);
19387 while (expo != 0) {
19391 }
else if (expo < 0) {
19392 while (expo != 0) {
19398 assert((result >= 0.0) && (result <= fabs(range)));
19420 bool tetgenmesh::checksub4cocir(face* testsub, REAL eps,
bool once,
19424 face subloop, neighsub;
19426 point pa, pb, pc, pd;
19430 subloop = *testsub;
19433 abovepoint = facetabovepointarray[shellmark(subloop)];
19435 if (abovepoint == (point) NULL) {
19436 getfacetabovepoint(&subloop);
19439 for (i = 0; i < 3; i++) {
19440 sspivot(subloop, checkseg);
19441 if (checkseg.sh == dummysh) {
19443 spivot(subloop, neighsub);
19445 if (!once || (once && (neighsub.sh > subloop.sh))) {
19446 pa = sorg(subloop);
19447 pb = sdest(subloop);
19448 pc = sapex(subloop);
19449 pd = sapex(neighsub);
19450 sign = insphere(pa, pb, pc, abovepoint, pd);
19451 if ((sign != 0.0) && (eps > 0.0)) {
19452 if (iscospheric(pa, pb, pc, abovepoint, pd, sign, eps)) sign = 0.0;
19456 if (enqflag && badsubfaces != (
memorypool *) NULL) {
19458 cocirsub = (badface *) badsubfaces->alloc();
19459 cocirsub->ss = subloop;
19460 cocirsub->forg = pa;
19461 cocirsub->fdest = pb;
19462 cocirsub->fapex = pc;
19463 cocirsub->foppo = pd;
19464 setshell2badface(cocirsub->ss, cocirsub);
19466 if (b->verbose > 1) {
19467 printf(
" Found set (%d, %d, %d, %d).\n", pointmark(pa),
19468 pointmark(pb), pointmark(pc), pointmark(pd));
19474 senextself(subloop);
19486 void tetgenmesh::tallcocirsubs(REAL eps,
bool enqflag)
19491 subfaces->traversalinit();
19492 subloop.sh = shellfacetraverse(subfaces);
19493 while (subloop.sh != (shellface *) NULL) {
19494 checksub4cocir(&subloop, eps,
true, enqflag);
19495 subloop.sh = shellfacetraverse(subfaces);
19505 bool tetgenmesh::tallencsegsfsubs(point testpt, list* cavsublist)
19507 face startsub, checkseg;
19512 oldencnum = badsubsegs->items;
19515 for (i = 0; i < cavsublist->len(); i++) {
19516 startsub = * (face *)(* cavsublist)[i];
19518 for (j = 0; j < 3; j++) {
19519 sspivot(startsub, checkseg);
19520 if (checkseg.sh != dummysh) {
19521 if (!shell2badface(checkseg)) {
19522 checkseg4encroach(&checkseg, testpt, NULL,
true);
19525 senextself(startsub);
19529 return (badsubsegs->items > oldencnum);
19544 collectflipedges(point inspoint, face* splitseg, queue* flipqueue)
19546 face startsh, spinsh, checksh;
19551 splitseg->shver = 0;
19552 if (sdest(*splitseg) != inspoint) {
19553 sesymself(*splitseg);
19556 assert(sdest(*splitseg) == inspoint);
19558 pa = sorg(*splitseg);
19559 spivot(*splitseg, startsh);
19562 findedge(&spinsh, pa, inspoint);
19563 senext2(spinsh, checksh);
19564 enqueueflipedge(checksh, flipqueue);
19565 spivotself(spinsh);
19566 }
while (spinsh.sh != startsh.sh);
19569 senext(*splitseg, nextseg);
19570 spivotself(nextseg);
19572 assert(nextseg.sh != (shellface *) NULL);
19577 if (sorg(nextseg) != inspoint) {
19578 sesymself(nextseg);
19581 assert(sorg(nextseg) == inspoint);
19583 pb = sdest(nextseg);
19584 spivot(nextseg, startsh);
19587 findedge(&spinsh, inspoint, pb);
19588 senext(spinsh, checksh);
19589 enqueueflipedge(checksh, flipqueue);
19590 spivotself(spinsh);
19591 }
while (spinsh.sh != startsh.sh);
19603 void tetgenmesh::perturbrepairencsegs(queue* flipqueue)
19606 tetrahedron encodedtet;
19608 face splitsub, symsplitsub;
19609 face splitseg, symsplitseg;
19610 point newpoint, sympoint;
19612 enum insertsiteresult success;
19613 enum locateresult loc, symloc;
19614 REAL cent[3], d1, ps, rs;
19619 badsubsegs->traversalinit();
19620 encloop = badfacetraverse(badsubsegs);
19621 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19622 splitseg = encloop->ss;
19624 assert(shell2badface(splitseg) == encloop);
19626 setshell2badface(splitseg, NULL);
19627 pa = sorg(splitseg);
19628 pb = sdest(splitseg);
19629 if ((pa == encloop->forg) && (pb == encloop->fdest)) {
19630 if (b->verbose > 1) {
19631 printf(
" Get seg (%d, %d).\n", pointmark(pa), pointmark(pb));
19634 makepoint(&newpoint);
19636 for (i = 0; i < 3; i++) cent[i] = 0.5 * (pa[i] + pb[i]);
19637 d1 = 0.5 * distance(pa, pb);
19639 ps = randgenerator(d1 * 1.0e-3);
19642 for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19643 setpointtype(newpoint, FREESEGVERTEX);
19645 setpoint2sh(newpoint, sencode(splitseg));
19650 i = shellmark(splitseg) - 1;
19651 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
19652 makepoint(&sympoint);
19653 symloc = getsegpbcsympoint(newpoint, &splitseg, sympoint,
19654 &symsplitseg, segpglist[j]);
19656 assert(symloc != OUTSIDE);
19660 if ((symloc == ONEDGE) && (symsplitseg.sh != splitseg.sh)) {
19661 setpointtype(sympoint, FREESEGVERTEX);
19662 setpoint2sh(sympoint, sencode(symsplitseg));
19664 pc = sorg(symsplitseg);
19665 splittet.tet = dummytet;
19667 encodedtet = point2tet(pc);
19668 if (encodedtet != (tetrahedron) NULL) {
19669 decode(encodedtet, splittet);
19670 if (isdead(&splittet)) {
19671 splittet.tet = dummytet;
19675 success = insertsite(sympoint, &splittet,
false, flipqueue);
19677 assert(success != DUPLICATEPOINT);
19679 if (success == OUTSIDEPOINT) {
19680 inserthullsite(sympoint, &splittet, flipqueue);
19682 if (steinerleft > 0) steinerleft--;
19684 setpoint2tet(sympoint, encode(splittet));
19686 flip(flipqueue, NULL);
19688 symloc = locateseg(sympoint, &symsplitseg);
19689 if (symloc == ONEDGE) {
19690 symsplitseg.shver = 0;
19691 spivot(symsplitseg, symsplitsub);
19693 splitsubedge(sympoint, &symsplitsub, flipqueue);
19697 assert(symloc == ONVERTEX);
19698 assert(checksubfaces);
19701 collectflipedges(sympoint, &symsplitseg, flipqueue);
19704 flipsub(flipqueue);
19708 pointdealloc(sympoint);
19714 splittet.tet = dummytet;
19716 encodedtet = point2tet(pa);
19717 if (encodedtet != (tetrahedron) NULL) {
19718 decode(encodedtet, splittet);
19719 if (isdead(&splittet)) {
19720 splittet.tet = dummytet;
19723 if (splittet.tet == dummytet) {
19724 encodedtet = point2tet(pb);
19725 if (encodedtet != (tetrahedron) NULL) {
19726 decode(encodedtet, splittet);
19727 if (isdead(&splittet)) {
19728 splittet.tet = dummytet;
19733 success = insertsite(newpoint, &splittet,
false, flipqueue);
19735 assert(success != DUPLICATEPOINT);
19737 if (success == OUTSIDEPOINT) {
19741 inserthullsite(newpoint, &splittet, flipqueue);
19743 if (steinerleft > 0) steinerleft--;
19745 setpoint2tet(newpoint, encode(splittet));
19747 flip(flipqueue, NULL);
19749 loc = locateseg(newpoint, &splitseg);
19750 if (loc == ONEDGE) {
19751 splitseg.shver = 0;
19752 spivot(splitseg, splitsub);
19754 splitsubedge(newpoint, &splitsub, flipqueue);
19758 assert(loc == ONVERTEX);
19759 assert(checksubfaces);
19762 collectflipedges(newpoint, &splitseg, flipqueue);
19765 flipsub(flipqueue);
19768 badfacedealloc(badsubsegs, encloop);
19770 encloop = badfacetraverse(badsubsegs);
19785 void tetgenmesh::perturbrepairencsubs(list* cavsublist, queue* flipqueue)
19787 badface *encloop, *encsubseg;
19788 tetrahedron encodedtet;
19790 face splitsub, symsplitsub;
19791 face checkseg, symsplitseg;
19792 point newpoint, sympoint;
19793 point pa, pb, pc, pd;
19794 enum insertsiteresult success;
19795 enum locateresult loc, symloc;
19796 REAL cent[3], d1, ps, rs;
19802 while ((badsubfaces->items > 0) && (steinerleft != 0)) {
19803 badsubfaces->traversalinit();
19804 encloop = badfacetraverse(badsubfaces);
19805 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
19806 splitsub = encloop->ss;
19808 assert(shell2badface(splitsub) == encloop);
19810 setshell2badface(splitsub, NULL);
19811 pa = sorg(splitsub);
19812 pb = sdest(splitsub);
19813 pc = sapex(splitsub);
19817 if ((pa == encloop->forg) && (pb == encloop->fdest) &&
19818 (pc == encloop->fapex)) {
19819 if (b->verbose > 1) {
19820 printf(
" Get subface (%d, %d, %d).\n", pointmark(pa),
19821 pointmark(pb), pointmark(pc));
19824 makepoint(&newpoint);
19826 circumsphere(pa, pb, pc, NULL, cent, &d1);
19832 ps = randgenerator(d1 * 1.0e-3);
19835 for (i = 0; i < 3; i++) newpoint[i] = cent[i] + rs * (cent[i] - pa[i]);
19837 abovepoint = facetabovepointarray[shellmark(splitsub)];
19839 if (abovepoint == (point) NULL) {
19840 getfacetabovepoint(&splitsub);
19842 loc = locatesub(newpoint, &splitsub, 1, 0.0);
19844 assert(loc != ONVERTEX);
19846 if (loc != OUTSIDE) {
19848 cavsublist->append(&splitsub);
19850 collectcavsubs(newpoint, cavsublist);
19852 reject = tallencsegsfsubs(newpoint, cavsublist);
19854 cavsublist->clear();
19857 sspivot(splitsub, checkseg);
19859 assert(checkseg.sh != dummysh);
19862 if (b->verbose > 2) {
19863 printf(
" Queuing boundary segment (%d, %d).\n",
19864 pointmark(sorg(checkseg)), pointmark(sdest(checkseg)));
19866 encsubseg = (badface *) badsubsegs->alloc();
19867 encsubseg->ss = checkseg;
19868 encsubseg->forg = sorg(checkseg);
19869 encsubseg->fdest = sdest(checkseg);
19870 encsubseg->foppo = (point) NULL;
19871 setshell2badface(encsubseg->ss, encsubseg);
19881 if (shellpbcgroup(splitsub) >= 0) {
19883 makepoint(&sympoint);
19885 symloc = getsubpbcsympoint(newpoint, &splitsub, sympoint,
19888 assert(symloc != ONVERTEX);
19890 setpoint2pbcpt(newpoint, sympoint);
19891 setpoint2pbcpt(sympoint, newpoint);
19892 setpointtype(sympoint, FREESUBVERTEX);
19895 pd = sorg(symsplitsub);
19896 splittet.tet = dummytet;
19898 encodedtet = point2tet(pd);
19899 if (encodedtet != (tetrahedron) NULL) {
19900 decode(encodedtet, splittet);
19901 if (isdead(&splittet)) {
19902 splittet.tet = dummytet;
19906 success = insertsite(sympoint, &splittet,
false, flipqueue);
19908 assert(success != DUPLICATEPOINT);
19910 if (success == OUTSIDEPOINT) {
19911 inserthullsite(sympoint, &splittet, flipqueue);
19913 if (steinerleft > 0) steinerleft--;
19915 setpoint2tet(sympoint, encode(splittet));
19917 flip(flipqueue, NULL);
19921 if (symloc == ONFACE) {
19922 splitsubface(sympoint, &symsplitsub, flipqueue);
19923 }
else if (symloc == ONEDGE) {
19924 splitsubedge(sympoint, &symsplitsub, flipqueue);
19928 assert(symloc == ONVERTEX);
19929 assert(checksubfaces);
19932 flipqueue->clear();
19935 flipsub(flipqueue);
19940 splittet.tet = dummytet;
19942 encodedtet = point2tet(pa);
19943 if (encodedtet != (tetrahedron) NULL) {
19944 decode(encodedtet, splittet);
19945 if (isdead(&splittet)) {
19946 splittet.tet = dummytet;
19949 if (splittet.tet == dummytet) {
19950 encodedtet = point2tet(pb);
19951 if (encodedtet != (tetrahedron) NULL) {
19952 decode(encodedtet, splittet);
19953 if (isdead(&splittet)) {
19954 splittet.tet = dummytet;
19959 success = insertsite(newpoint, &splittet,
false, flipqueue);
19961 assert(success != DUPLICATEPOINT);
19963 if (success == OUTSIDEPOINT) {
19964 inserthullsite(newpoint, &splittet, flipqueue);
19966 if (steinerleft > 0) steinerleft--;
19968 setpoint2tet(newpoint, encode(splittet));
19970 flip(flipqueue, NULL);
19977 if (loc == ONFACE) {
19979 splitsubface(newpoint, &splitsub, flipqueue);
19980 }
else if (loc == ONEDGE) {
19982 splitsubedge(newpoint, &splitsub, flipqueue);
19986 assert(loc == ONVERTEX);
19987 assert(checksubfaces);
19990 flipqueue->clear();
19993 setpointtype(newpoint, FREESUBVERTEX);
19997 flipsub(flipqueue);
20000 badfacedealloc(badsubfaces, encloop);
20003 pointdealloc(newpoint);
20005 perturbrepairencsegs(flipqueue);
20007 setshell2badface(encloop->ss, encloop);
20011 badfacedealloc(badsubfaces, encloop);
20016 encloop = badfacetraverse(badsubfaces);
20036 void tetgenmesh::incrperturbvertices(REAL eps)
20043 printf(
"Perturbing vertices.\n");
20046 vertcount = points->items;
20051 flipqueue =
new queue(
sizeof(badface));
20052 cavsublist =
new list(
sizeof(face), NULL, 256);
20054 badsubsegs =
new memorypool(
sizeof(badface), SUBPERBLOCK, POINTER, 0);
20055 badsubfaces =
new memorypool(
sizeof(badface), SUBPERBLOCK, POINTER, 0);
20057 tallcocirsubs(eps,
true);
20058 if (b->verbose && badsubfaces->items > 0) {
20059 printf(
" Removing degenerate subfaces.\n");
20061 perturbrepairencsubs(cavsublist, flipqueue);
20063 if (b->verbose > 0) {
20064 printf(
" %ld break points.\n", points->items - vertcount);
20069 delete badsubfaces;
20100 void tetgenmesh::markacutevertices(REAL acuteangle)
20102 shellface **segsperverlist;
20103 face segloop, nextseg;
20104 point pointloop, edest, eapex;
20105 REAL cosbound, anglearc;
20106 REAL v1[3], v2[3], L, D;
20112 if (b->verbose > 0) {
20113 printf(
" Marking acute vertices.\n");
20116 anglearc = acuteangle * PI / 180.0;
20117 cosbound = cos(anglearc);
20120 makesegmentmap(idx2seglist, segsperverlist);
20123 points->traversalinit();
20124 pointloop = pointtraverse();
20125 while (pointloop != (point) NULL) {
20126 idx = pointmark(pointloop) - in->firstnumber;
20128 if (idx2seglist[idx + 1] > idx2seglist[idx]) {
20130 setpointtype(pointloop, NACUTEVERTEX);
20133 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isacute; i++) {
20134 segloop.sh = segsperverlist[i];
20136 if (sorg(segloop) != pointloop) sesymself(segloop);
20137 edest = sdest(segloop);
20138 for (j = i + 1; j < idx2seglist[idx + 1] && !isacute; j++) {
20139 nextseg.sh = segsperverlist[j];
20141 if (sorg(nextseg) != pointloop) sesymself(nextseg);
20142 eapex = sdest(nextseg);
20144 for (k = 0; k < 3; k++) {
20145 v1[k] = edest[k] - pointloop[k];
20146 v2[k] = eapex[k] - pointloop[k];
20148 L = sqrt(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2]);
20149 for (k = 0; k < 3; k++) v1[k] /= L;
20150 L = sqrt(v2[0] * v2[0] + v2[1] * v2[1] + v2[2] * v2[2]);
20151 for (k = 0; k < 3; k++) v2[k] /= L;
20152 D = v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
20154 isacute = (D >= cosbound);
20159 setpointtype(pointloop, ACUTEVERTEX);
20163 pointloop = pointtraverse();
20166 delete [] idx2seglist;
20167 delete [] segsperverlist;
20169 if ((b->verbose > 0) && (acutecount > 0)) {
20170 printf(
" %d acute vertices.\n", acutecount);
20207 enum tetgenmesh::finddirectionresult tetgenmesh::
20208 finddirection(triface *searchtet, point tend,
long maxtetnumber)
20211 point tstart, tdest, tapex, toppo;
20212 REAL ori1, ori2, ori3;
20215 tstart = org(*searchtet);
20217 assert(tstart != tend);
20219 adjustedgering(*searchtet, CCW);
20220 if (tstart != org(*searchtet)) {
20221 enextself(*searchtet);
20223 tdest = dest(*searchtet);
20224 if (tdest == tend) {
20225 return RIGHTCOLLINEAR;
20227 tapex = apex(*searchtet);
20228 if (tapex == tend) {
20229 return LEFTCOLLINEAR;
20232 ori1 = orient3d(tstart, tdest, tapex, tend);
20235 sym(*searchtet, neightet);
20236 if (neightet.tet != dummytet) {
20237 findorg(&neightet, tstart);
20238 adjustedgering(neightet, CCW);
20239 if (org(neightet) != tstart) {
20240 enextself(neightet);
20243 *searchtet = neightet;
20245 tdest = dest(*searchtet);
20246 tapex = apex(*searchtet);
20260 while ((maxtetnumber > 0) && (tetnumber <= maxtetnumber)) {
20262 toppo = oppo(*searchtet);
20263 if (toppo == tend) {
20264 return TOPCOLLINEAR;
20266 ori2 = orient3d(tstart, toppo, tdest, tend);
20269 fnext(*searchtet, neightet);
20271 if (neightet.tet != dummytet) {
20272 findorg(&neightet, tstart);
20273 adjustedgering(neightet, CCW);
20274 if (org(neightet) != tstart) {
20275 enextself(neightet);
20278 *searchtet = neightet;
20280 tdest = dest(*searchtet);
20281 tapex = apex(*searchtet);
20292 ori3 = orient3d(tapex, toppo, tstart, tend);
20295 enext2fnext(*searchtet, neightet);
20297 if (neightet.tet != dummytet) {
20298 findorg(&neightet, tstart);
20299 adjustedgering(neightet, CCW);
20300 if (org(neightet) != tstart) {
20301 enextself(neightet);
20304 *searchtet = neightet;
20306 tdest = dest(*searchtet);
20307 tapex = apex(*searchtet);
20326 enext2fnextself(*searchtet);
20327 esymself(*searchtet);
20333 fnextself(*searchtet);
20334 esymself(*searchtet);
20335 enextself(*searchtet);
20339 return TOPCOLLINEAR;
20350 return LEFTCOLLINEAR;
20354 assert(ori3 != 0.0);
20357 return RIGHTCOLLINEAR;
20375 void tetgenmesh::getsearchtet(point p1, point p2, triface* searchtet,
20378 tetrahedron encodedtet1, encodedtet2;
20381 if ((searchtet->tet != (tetrahedron *) NULL) && !isdead(searchtet)) {
20383 if (findorg(searchtet, p1)) {
20387 if (findorg(searchtet, p2)) {
20394 *tend = (point) NULL;
20395 encodedtet1 = point2tet(p1);
20396 encodedtet2 = point2tet(p2);
20397 if (encodedtet1 != (tetrahedron) NULL) {
20398 decode(encodedtet1, *searchtet);
20400 if (findorg(searchtet, p1)) {
20403 }
else if (encodedtet2 != (tetrahedron) NULL) {
20404 decode(encodedtet2, *searchtet);
20406 if (findorg(searchtet, p2)) {
20413 if (*tend == (point) NULL) {
20414 if (encodedtet1 != (tetrahedron) NULL) {
20415 decode(encodedtet1, *searchtet);
20418 if (isdead(searchtet)) {
20419 if (encodedtet2 != (tetrahedron) NULL) {
20420 decode(encodedtet2, *searchtet);
20423 if (isdead(searchtet)) {
20424 searchtet->tet = dummytet;
20425 searchtet->loc = 0;
20426 symself(*searchtet);
20429 assert(!isdead(searchtet));
20432 if (locate(p1, searchtet) != ONVERTEX) {
20433 printf(
"Internal error in getsearchtet(): Failed to locate point\n");
20437 setpoint2tet(p1, encode(*searchtet));
20453 bool tetgenmesh::isedgeencroached(point p1, point p2, point testpt,
20459 dotproduct = (p1[0] - testpt[0]) * (p2[0] - testpt[0])
20460 + (p1[1] - testpt[1]) * (p2[1] - testpt[1])
20461 + (p1[2] - testpt[2]) * (p2[2] - testpt[2]);
20462 if (dotproduct < 0) {
20464 }
else if (dotproduct == 0 && degflag) {
20487 tetgenmesh::point tetgenmesh::scoutrefpoint(triface* searchtet, point tend)
20490 point tstart, testpt, refpoint;
20491 REAL cent[3], radius, largest;
20496 if (b->verbose > 2) {
20497 printf(
" Scout the reference point of segment (%d, %d).\n",
20498 pointmark(org(*searchtet)), pointmark(tend));
20501 tstart = org(*searchtet);
20502 refpoint = (point) NULL;
20506 testpt = apex(*searchtet);
20507 if (isedgeencroached(tstart, tend, testpt,
true)) {
20508 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20510 assert(ncollinear);
20515 testpt = dest(*searchtet);
20516 if (isedgeencroached(tstart, tend, testpt,
true)) {
20517 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20519 assert(ncollinear);
20521 if (refpoint == (point) NULL) {
20525 if (radius > largest) {
20531 testpt = oppo(*searchtet);
20532 if (isedgeencroached(tstart, tend, testpt,
true)) {
20533 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20535 assert(ncollinear);
20537 if (refpoint == (point) NULL) {
20541 if (radius > largest) {
20549 sym(*searchtet, checkface);
20550 if (checkface.tet != dummytet) {
20551 testpt = oppo(checkface);
20552 if (isedgeencroached(tstart, tend, testpt,
true)) {
20553 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20555 assert(ncollinear);
20557 if (refpoint == (point) NULL) {
20561 if (radius > largest) {
20570 enextfnext(*searchtet, checkface);
20571 sym(checkface, *searchtet);
20575 assert(searchtet->tet != dummytet);
20578 searchtet->ver = 0;
20580 testpt = oppo(*searchtet);
20581 if (testpt == tend) {
20586 if ((testpt != tstart) && (testpt != refpoint)) {
20587 if (isedgeencroached(tstart, tend, testpt,
true)) {
20588 ncollinear = circumsphere(tstart, tend, testpt, NULL, cent, &radius);
20598 if (refpoint == (point) NULL) {
20602 if (radius > largest) {
20612 for (sides = 0; sides < 3; sides++) {
20613 fnext(*searchtet, checkface);
20614 ahead = orient3d(org(checkface), dest(checkface), testpt, tend);
20617 sym(checkface, *searchtet);
20620 enextself(*searchtet);
20623 assert (sides < 3);
20628 assert(refpoint != (point) NULL);
20644 tetgenmesh::point tetgenmesh::getsegmentorigin(face* splitseg)
20649 farorg = sorg(*splitseg);
20650 if ((pointtype(farorg) != ACUTEVERTEX) &&
20651 (pointtype(farorg) != NACUTEVERTEX)) {
20652 workseg = *splitseg;
20654 senext2self(workseg);
20655 spivotself(workseg);
20656 if (workseg.sh != dummysh) {
20658 if (sdest(workseg) != farorg) {
20659 sesymself(workseg);
20661 assert(sdest(workseg) == farorg);
20664 farorg = sorg(workseg);
20665 if ((pointtype(farorg) == ACUTEVERTEX) ||
20666 (pointtype(farorg) == NACUTEVERTEX))
break;
20668 }
while (workseg.sh != dummysh);
20671 assert((pointtype(farorg) == ACUTEVERTEX) ||
20672 (pointtype(farorg) == NACUTEVERTEX));
20694 tetgenmesh::point tetgenmesh::getsplitpoint(face* splitseg, point refpoint)
20697 point farorg, fardest;
20698 point ei, ej, ek, c;
20699 REAL v[3], r, split;
20700 REAL d1, d2, ps, rs;
20701 bool acuteorg, acutedest;
20706 farorg = getsegmentorigin(splitseg);
20707 acuteorg = (pointtype(farorg) == ACUTEVERTEX);
20708 sesymself(*splitseg);
20709 fardest = getsegmentorigin(splitseg);
20710 acutedest = (pointtype(fardest) == ACUTEVERTEX);
20711 sesymself(*splitseg);
20726 sesymself(*splitseg);
20732 ei = sorg(*splitseg);
20733 ej = sdest(*splitseg);
20735 if (b->verbose > 1) {
20736 printf(
" Splitting segment (%d, %d) type-%d with refpoint %d.\n",
20737 pointmark(ei), pointmark(ej), stype, pointmark(refpoint));
20740 if (stype == 1 || stype == 3) {
20742 REAL eij, eip, ejp;
20743 eij = distance(ei, ej);
20744 eip = distance(ei, refpoint);
20745 ejp = distance(ej, refpoint);
20746 if ((eip < ejp) && (eip < 0.5 * eij)) {
20749 }
else if ((eip > ejp) && (ejp < 0.5 * eij)) {
20758 for (i = 0; i < 3; i++) {
20759 v[i] = c[i] + split * (ej[i] - c[i]);
20764 REAL eki, ekj, ekp, evj, evp, eiv;
20766 eki = distance(ek, ei);
20767 ekj = distance(ek, ej);
20768 ekp = distance(ek, refpoint);
20772 if (!(eki < r && r < ekj)) {
20773 printf(
"Error: Invalid PLC.\n");
20774 printf(
" Hint: Use -d switch to check it.\n");
20775 terminatetetgen(1);
20778 for (i = 0; i < 3; i++) {
20779 v[i] = c[i] + split * (ej[i] - c[i]);
20783 evp = distance(v, refpoint);
20786 eiv = distance(ei, v);
20787 if (evp <= 0.5 * eiv) {
20788 r = eki + eiv - evp;
20790 r = eki + 0.5 * eiv;
20793 assert(eki < r && r < ekj);
20796 for (i = 0; i < 3; i++) {
20797 v[i] = c[i] + split * (ej[i] - c[i]);
20799 if (b->verbose > 1) {
20800 printf(
" Using rule-3.\n");
20807 if (rule == 1) r1count++;
20808 else if (rule == 2) r2count++;
20809 else if (rule == 3) r3count++;
20811 if (b->verbose > 1) {
20813 printf(
" Split = %.12g.\n", distance(ei, v) / distance(ei, ej));
20815 printf(
" Split = %.12g.\n", distance(c, v) / distance(c, ej));
20820 makepoint(&splitpoint);
20822 d1 = distance(c, v);
20823 d2 = distance(refpoint, v);
20824 if (stype == 1 || stype == 3) {
20825 ps = randgenerator(d1 * 1.0e-3);
20830 ps = randgenerator(d2 * 1.0e-5);
20834 for (i = 0; i < 3; i++) {
20835 splitpoint[i] = c[i] + (1.0 + rs) * (v[i] - c[i]);
20842 setpointtype(splitpoint, NACUTEVERTEX);
20845 setpointtype(splitpoint, FREESEGVERTEX);
20847 setpoint2sh(splitpoint, sencode(*splitseg));
20858 bool tetgenmesh::insertsegment(face *insseg, list *misseglist)
20861 triface searchtet, spintet;
20862 point tend, checkpoint;
20864 enum finddirectionresult collinear;
20868 p1 = (point) insseg->sh[3];
20869 p2 = (point) insseg->sh[4];
20870 getsearchtet(p1, p2, &searchtet, &tend);
20871 collinear = finddirection(&searchtet, tend, tetrahedrons->items);
20872 if (collinear == LEFTCOLLINEAR) {
20873 checkpoint = apex(searchtet);
20874 enext2self(searchtet);
20875 esymself(searchtet);
20876 }
else if (collinear == RIGHTCOLLINEAR) {
20877 checkpoint = dest(searchtet);
20878 }
else if (collinear == TOPCOLLINEAR) {
20879 checkpoint = oppo(searchtet);
20880 fnextself(searchtet);
20881 enext2self(searchtet);
20882 esymself(searchtet);
20885 checkpoint = (point) NULL;
20887 if (checkpoint == tend) {
20890 adjustedgering(searchtet, CCW);
20891 fnextself(searchtet);
20892 spintet = searchtet;
20894 tssbond1(spintet, *insseg);
20895 if (!fnextself(spintet)) {
20898 esym(searchtet, spintet);
20899 if (!fnextself(spintet)) {
20904 }
while ((apex(spintet) != apex(searchtet)) && (hitbdry < 2));
20908 if (misseglist != (list *) NULL) {
20909 if (b->verbose > 2) {
20910 printf(
" Queuing missing segment (%d, %d).\n", pointmark(p1),
20913 misseg = (badface *) misseglist->append(NULL);
20914 misseg->ss = *insseg;
20916 misseg->fdest = p2;
20917 misseg->foppo = (point) NULL;
20930 void tetgenmesh::tallmissegs(list *misseglist)
20935 printf(
" Queuing missing segments.\n");
20938 subsegs->traversalinit();
20939 segloop.sh = shellfacetraverse(subsegs);
20940 while (segloop.sh != (shellface *) NULL) {
20941 insertsegment(&segloop, misseglist);
20942 segloop.sh = shellfacetraverse(subsegs);
20983 void tetgenmesh::delaunizesegments()
20988 tetrahedron encodedtet;
20989 triface searchtet, splittet;
20990 face splitsh, symsplitsub;
20991 face segloop, symsplitseg;
20992 point refpoint, splitpoint, sympoint;
20993 point tend, checkpoint;
20995 enum finddirectionresult collinear;
20996 enum insertsiteresult success;
20997 enum locateresult symloc;
21003 printf(
"Delaunizing segments.\n");
21007 makepoint2tetmap();
21009 flipqueue =
new queue(
sizeof(badface));
21011 misseglist =
new list(
sizeof(badface), NULL, SUBPERBLOCK);
21013 tallmissegs(misseglist);
21017 vertcount = points->items;
21019 r1count = r2count = r3count = 0l;
21022 while (misseglist->items > 0) {
21024 i = randomnation(misseglist->items);
21025 misloop = (badface *)(* misseglist)[i];
21026 segloop = misloop->ss;
21028 *misloop = *(badface *)(* misseglist)[misseglist->items - 1];
21029 misseglist->items--;
21031 p1 = (point) segloop.sh[3];
21032 p2 = (point) segloop.sh[4];
21033 if (b->verbose > 1) {
21034 printf(
" Recover segment (%d, %d).\n", pointmark(p1), pointmark(p2));
21036 getsearchtet(p1, p2, &searchtet, &tend);
21037 collinear = finddirection(&searchtet, tend, tetrahedrons->items);
21038 if (collinear == LEFTCOLLINEAR) {
21039 checkpoint = apex(searchtet);
21040 }
else if (collinear == RIGHTCOLLINEAR) {
21041 checkpoint = dest(searchtet);
21042 }
else if (collinear == TOPCOLLINEAR) {
21043 checkpoint = oppo(searchtet);
21046 assert(collinear == ACROSSFACE || collinear == ACROSSEDGE);
21048 checkpoint = (point) NULL;
21050 if (checkpoint != tend) {
21052 splitpoint = (point) NULL;
21053 if (checkpoint != (point) NULL) {
21057 splitpoint = checkpoint;
21058 if (pointtype(checkpoint) == FREEVOLVERTEX) {
21060 setpointtype(splitpoint, NACUTEVERTEX);
21061 }
else if (pointtype(checkpoint) == ACUTEVERTEX) {
21063 }
else if (pointtype(checkpoint) == NACUTEVERTEX) {
21070 refpoint = scoutrefpoint(&searchtet, tend);
21071 if (pointtype(refpoint) == FREEVOLVERTEX) {
21073 coll = iscollinear(p1, p2, refpoint, b->epsilon);
21077 splitpoint = refpoint;
21078 setpointtype(splitpoint, NACUTEVERTEX);
21081 if (splitpoint == (point) NULL) {
21083 splitpoint = getsplitpoint(&segloop, refpoint);
21088 i = shellmark(segloop) - 1;
21089 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
21090 makepoint(&sympoint);
21091 symloc = getsegpbcsympoint(splitpoint, &segloop, sympoint,
21092 &symsplitseg, segpglist[j]);
21094 assert(symloc != OUTSIDE);
21096 if ((symloc == ONEDGE) && (symsplitseg.sh != segloop.sh)) {
21098 assert(symsplitseg.sh != dummysh);
21100 setpointtype(sympoint, FREESEGVERTEX);
21101 setpoint2sh(sympoint, sencode(symsplitseg));
21103 pa = sorg(symsplitseg);
21104 splittet.tet = dummytet;
21106 encodedtet = point2tet(pa);
21107 if (encodedtet != (tetrahedron) NULL) {
21108 decode(encodedtet, splittet);
21109 if (isdead(&splittet)) {
21110 splittet.tet = dummytet;
21114 success = insertsite(sympoint, &splittet,
false, flipqueue);
21116 assert(success != DUPLICATEPOINT);
21118 if (success == OUTSIDEPOINT) {
21119 inserthullsite(sympoint, &splittet, flipqueue);
21121 if (steinerleft > 0) steinerleft--;
21123 setpoint2tet(sympoint, encode(splittet));
21125 lawson(misseglist, flipqueue);
21127 symsplitseg.shver = 0;
21128 spivot(symsplitseg, symsplitsub);
21130 splitsubedge(sympoint, &symsplitsub, flipqueue);
21132 flipsub(flipqueue);
21134 symsplitseg.shver = 0;
21135 insertsegment(&symsplitseg, misseglist);
21136 senextself(symsplitseg);
21137 spivotself(symsplitseg);
21138 symsplitseg.shver = 0;
21139 insertsegment(&symsplitseg, misseglist);
21143 pointdealloc(sympoint);
21149 if (isdead(&searchtet)) searchtet.tet = dummytet;
21150 success = insertsite(splitpoint, &searchtet,
false, flipqueue);
21151 if (success == OUTSIDEPOINT) {
21155 inserthullsite(splitpoint, &searchtet, flipqueue);
21157 if (steinerleft > 0) steinerleft--;
21160 setpoint2tet(splitpoint, encode(searchtet));
21162 lawson(misseglist, flipqueue);
21166 spivot(segloop, splitsh);
21167 splitsubedge(splitpoint, &splitsh, flipqueue);
21168 flipsub(flipqueue);
21171 insertsegment(&segloop, misseglist);
21172 senextself(segloop);
21173 spivotself(segloop);
21175 insertsegment(&segloop, misseglist);
21180 tetrahedrons->traversalinit();
21181 searchtet.tet = tetrahedrontraverse();
21182 while (searchtet.tet != (tetrahedron *) NULL) {
21183 for (i = 0; i < 6; i++) {
21184 searchtet.tet[8 + i] = (tetrahedron) dummysh;
21186 searchtet.tet = tetrahedrontraverse();
21191 if (b->verbose > 0) {
21192 printf(
" %ld protect points.\n", points->items - vertcount);
21193 printf(
" R1: %ld, R2: %ld, R3: %ld.\n", r1count, r2count, r3count);
21217 bool tetgenmesh::insertsubface(face* insertsh, triface* searchtet)
21219 triface spintet, symtet;
21220 face testsh, testseg;
21221 face spinsh, casin, casout;
21222 point tapex, checkpoint;
21223 enum finddirectionresult collinear;
21227 getsearchtet(sorg(*insertsh), sdest(*insertsh), searchtet, &checkpoint);
21228 collinear = finddirection(searchtet, checkpoint, tetrahedrons->items);
21229 if (collinear == LEFTCOLLINEAR) {
21230 enext2self(*searchtet);
21231 esymself(*searchtet);
21232 }
else if (collinear == TOPCOLLINEAR) {
21233 fnextself(*searchtet);
21234 enext2self(*searchtet);
21235 esymself(*searchtet);
21237 if (dest(*searchtet) != checkpoint) {
21243 tapex = sapex(*insertsh);
21244 spintet = *searchtet;
21247 if (apex(spintet) == tapex) {
21249 tspivot(spintet, testsh);
21250 if (testsh.sh == dummysh) {
21251 adjustedgering(spintet, CCW);
21252 findedge(insertsh, org(spintet), dest(spintet));
21253 tsbond(spintet, *insertsh);
21254 sym(spintet, symtet);
21255 sesymself(*insertsh);
21256 tsbond(symtet, *insertsh);
21260 printf(
"Warning: Two subfaces are found duplicated at ");
21261 printf(
"(%d, %d, %d)\n", pointmark(sorg(testsh)),
21262 pointmark(sdest(testsh)), pointmark(sapex(testsh)));
21263 printf(
" Subface of facet #%d is deleted.\n", shellmark(*insertsh));
21266 shellfacedealloc(subfaces, insertsh->sh);
21270 if (!fnextself(spintet)) {
21273 esym(*searchtet, spintet);
21274 if (!fnextself(spintet)) {
21279 }
while (hitbdry < 2 && apex(spintet) != apex(*searchtet));
21296 bool tetgenmesh::tritritest(triface* checktet, point p1, point p2, point p3)
21298 point forg, fdest, fapex;
21299 enum interresult intersect;
21301 forg = org(*checktet);
21302 fdest = dest(*checktet);
21303 fapex = apex(*checktet);
21306 REAL ax, ay, az, bx, by, bz;
21310 ax = forg[0] - fdest[0];
21311 ay = forg[1] - fdest[1];
21312 az = forg[2] - fdest[2];
21313 bx = forg[0] - fapex[0];
21314 by = forg[1] - fapex[1];
21315 bz = forg[2] - fapex[2];
21316 n[0] = ay * bz - by * az;
21317 n[1] = az * bx - bz * ax;
21318 n[2] = ax * by - bx * ay;
21319 assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21322 ax = p1[0] - p2[0];
21323 ay = p1[1] - p2[1];
21324 az = p1[2] - p2[2];
21325 bx = p1[0] - p3[0];
21326 by = p1[1] - p3[1];
21327 bz = p1[2] - p3[2];
21328 n[0] = ay * bz - by * az;
21329 n[1] = az * bx - bz * ax;
21330 n[2] = ax * by - bx * ay;
21331 assert(fabs(n[0]) + fabs(n[1]) + fabs(n[2]) > 0.0);
21335 intersect = tri_tri_inter(forg, fdest, fapex, p1, p2, p3);
21336 return intersect == INTERSECT;
21355 void tetgenmesh::initializecavity(list* floorlist, list* ceillist,
21358 triface neightet, casingtet;
21364 for (i = 0; i < floorlist->len(); i++) {
21366 worksh = * (face *)(* floorlist)[i];
21369 stpivot(worksh, neightet);
21370 assert(neightet.tet == dummytet);
21374 stpivot(worksh, casingtet);
21376 if (casingtet.tet == dummytet) {
21378 maketetrahedron(&faketet);
21379 setorg(faketet, sorg(worksh));
21380 setdest(faketet, sdest(worksh));
21381 setapex(faketet, sapex(worksh));
21382 setoppo(faketet, (point) NULL);
21383 tsbond(faketet, worksh);
21384 frontlist->append(&faketet);
21386 frontlist->append(&casingtet);
21390 for (i = 0; i < ceillist->len(); i++) {
21392 neightet = * (triface *) (* ceillist)[i];
21395 assert(infected(neightet));
21398 sym(neightet, casingtet);
21400 if (casingtet.tet == dummytet) {
21402 maketetrahedron(&faketet);
21404 adjustedgering(neightet, CW);
21405 setorg(faketet, org(neightet));
21406 setdest(faketet, dest(neightet));
21407 setapex(faketet, apex(neightet));
21408 setoppo(faketet, (point) NULL);
21410 tspivot(neightet, worksh);
21411 if (worksh.sh != dummysh) {
21413 tsbond(faketet, worksh);
21416 bond(faketet, neightet);
21419 frontlist->append(&faketet);
21421 frontlist->append(&casingtet);
21435 void tetgenmesh::retrievenewtets(list* newtetlist)
21437 triface searchtet, casingtet;
21441 for (i = 0; i < newtetlist->len(); i++) {
21442 searchtet = * (triface *)(* newtetlist)[i];
21443 if (isdead(&searchtet)) {
21444 newtetlist->del(i, 0); i--;
21450 for (i = 0; i < newtetlist->len(); i++) {
21451 searchtet = * (triface *)(* newtetlist)[i];
21452 for (searchtet.loc = 0; searchtet.loc < 4; searchtet.loc++) {
21453 sym(searchtet, casingtet);
21454 if ((casingtet.tet != dummytet) && !infected(casingtet)) {
21456 newtetlist->append(&casingtet);
21461 for (i = 0; i < newtetlist->len(); i++) {
21462 searchtet = * (triface *)(* newtetlist)[i];
21463 uninfect(searchtet);
21480 void tetgenmesh::delaunizecavvertices(triface* oldtet, list* floorptlist,
21481 list* ceilptlist, list* newtetlist, queue* flipque)
21483 point *insertarray;
21484 triface bakhulltet, newtet;
21491 arraysize = floorptlist->len();
21492 if (ceilptlist != (list *) NULL) {
21493 arraysize += ceilptlist->len();
21495 insertarray =
new point[arraysize];
21496 for (i = 0; i < floorptlist->len(); i++) {
21497 insertarray[i] = * (point *)(* floorptlist)[i];
21499 if (ceilptlist != (list *) NULL) {
21500 for (j = 0; j < ceilptlist->len(); j++) {
21501 insertarray[i + j] = * (point *)(* ceilptlist)[j];
21506 decode(dummytet[0], bakhulltet);
21507 bakhullsize = hullsize;
21508 bakchksub = checksubfaces;
21514 incrflipdelaunay(oldtet, insertarray, arraysize,
false,
false, 0.0, flipque);
21517 decode(dummytet[0], newtet);
21518 newtetlist->append(&newtet);
21520 retrievenewtets(newtetlist);
21523 dummytet[0] = encode(bakhulltet);
21524 hullsize = bakhullsize;
21525 checksubfaces = bakchksub;
21528 delete [] insertarray;
21545 void tetgenmesh::insertauxsubface(triface* front, triface* idfront)
21551 makeshellface(subfaces, &auxsh);
21553 tsbond(*idfront, auxsh);
21555 sym(*idfront, neightet);
21556 if (neightet.tet != dummytet) {
21559 tsbond(neightet, auxsh);
21562 auxsh.sh[0] = (shellface) encode(*front);
21574 bool tetgenmesh::scoutfront(triface* front, triface* idfront, list* newtetlist)
21578 enum locateresult loc;
21579 enum finddirectionresult col;
21587 *idfront = recenttet;
21589 if (isdead(idfront)) {
21591 for (i = 0; i < newtetlist->len(); i++) {
21592 recenttet = * (triface *)(* newtetlist)[i];
21593 if (!isdead(&recenttet))
break;
21595 assert(i < newtetlist->len());
21599 loc = preciselocate(pa, idfront, (
long) newtetlist->len());
21601 assert(loc == ONVERTEX);
21602 recenttet = *idfront;
21604 col = finddirection(idfront, pb, (
long) newtetlist->len());
21605 if (col == RIGHTCOLLINEAR) {
21607 }
else if (col == LEFTCOLLINEAR) {
21608 enext2self(*idfront);
21609 esymself(*idfront);
21610 }
else if (col == TOPCOLLINEAR) {
21611 fnextself(*idfront);
21612 enext2self(*idfront);
21613 esymself(*idfront);
21616 if (dest(*idfront) == pb) {
21619 spintet = *idfront;
21622 if (apex(spintet) == pc) {
21625 *idfront = spintet;
21628 if (!fnextself(spintet)) {
21631 esym(*idfront, spintet);
21632 if (!fnextself(spintet)) {
21637 if (apex(spintet) == apex(*idfront))
break;
21638 }
while (hitbdry < 2);
21642 if (b->verbose > 2) {
21643 printf(
" Front (%d, %d, %d) is missing.\n", pointmark(pa),
21644 pointmark(pb), pointmark(apex(*front)));
21660 void tetgenmesh::gluefronts(triface* front, triface* front1)
21672 tspivot(*front, consh);
21673 if (consh.sh != dummysh) {
21675 tsbond(*front1, consh);
21679 if (oppo(*front) == (point) NULL) {
21681 assert(oppo(*front1) != (point) NULL);
21683 if (consh.sh != dummysh) {
21687 tetrahedrondealloc(front->tet);
21689 dummytet[0] = encode(*front1);
21692 bond(*front, *front1);
21695 if (!isdead(front)) {
21697 tspivot(*front1, consh);
21699 if (oppo(*front1) == (point) NULL) {
21701 assert(oppo(*front) != (point) NULL);
21703 if (consh.sh != dummysh) {
21706 tsbond(*front, consh);
21711 tetrahedrondealloc(front1->tet);
21713 dummytet[0] = encode(*front);
21716 if (consh.sh != dummysh) {
21718 tsbond(*front, consh);
21735 bool tetgenmesh::identifyfronts(list* frontlist, list* misfrontlist,
21738 triface front, front1, tfront;
21739 triface idfront, neightet;
21743 misfrontlist->clear();
21745 recenttet = * (triface *)(* newtetlist)[0];
21748 for (i = 0; i < frontlist->len(); i++) {
21750 front = * (triface *)( *frontlist)[i];
21751 if (scoutfront(&front, &idfront, newtetlist)) {
21753 assert((idfront.tet != dummytet) && !isdead(&idfront));
21755 tspivot(idfront, auxsh);
21756 if (auxsh.sh != dummysh) {
21758 decode((tetrahedron) auxsh.sh[0], front1);
21759 assert((front1.tet != dummytet) && !infected(front1));
21761 tsdissolve(idfront);
21762 sym(idfront, neightet);
21763 if (neightet.tet != dummytet) {
21764 tsdissolve(neightet);
21767 shellfacedealloc(subfaces, auxsh.sh);
21769 frontlist->del(i, 1); i--;
21771 len = frontlist->len();
21772 for (j = 0; j < frontlist->len(); j++) {
21773 tfront = * (triface *)(* frontlist)[j];
21774 if ((tfront.tet == front1.tet) && (tfront.loc == front1.loc)) {
21776 assert((tfront.tet != front.tet) || (tfront.loc != front.loc));
21777 frontlist->del(j, 1); i--;
21781 assert((frontlist->len() + 1) == len);
21784 gluefronts(&front, &front1);
21787 insertauxsubface(&front, &idfront);
21791 frontlist->del(i, 1); i--;
21793 for (j = 0; j < misfrontlist->len(); j++) {
21794 front1 = * (triface *)(* misfrontlist)[j];
21795 if (isfacehaspoint(&front1, org(front)) &&
21796 isfacehaspoint(&front1, dest(front)) &&
21797 isfacehaspoint(&front1, apex(front)))
break;
21799 if (j < misfrontlist->len()) {
21801 misfrontlist->del(j, 1);
21803 gluefronts(&front, &front1);
21806 misfrontlist->append(&front);
21810 return misfrontlist->len() == 0;
21824 void tetgenmesh::detachauxsubfaces(list* newtetlist)
21826 triface newtet, neightet;
21830 for (i = 0; i < newtetlist->len(); i++) {
21832 newtet = * (triface *)(* newtetlist)[i];
21834 if (isdead(&newtet))
continue;
21835 assert(!infected(newtet));
21837 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
21838 tspivot(newtet, auxsh);
21839 if (auxsh.sh != dummysh) {
21841 assert(sorg(auxsh) == (point) NULL);
21842 tsdissolve(newtet);
21843 sym(newtet, neightet);
21844 if (neightet.tet != dummytet) {
21845 assert(!isdead(&neightet));
21846 tsdissolve(neightet);
21849 shellfacedealloc(subfaces, auxsh.sh);
21867 void tetgenmesh::expandcavity(list* frontlist, list* misfrontlist,
21868 list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
21870 triface misfront, newfront, casingtet, crosstet;
21871 triface searchtet, faketet, bakhulltet;
21874 enum insertsiteresult success;
21879 if (b->verbose > 1) {
21880 printf(
" Expand cavity (%d missing fronts).\n", misfrontlist->len());
21885 decode(dummytet[0], bakhulltet);
21886 bakhullsize = hullsize;
21887 bakchksub = checksubfaces;
21892 recenttet = * (triface *)(* newtetlist)[0];
21893 assert((recenttet.tet != dummytet) && !isdead(&recenttet));
21896 for (i = 0; i < misfrontlist->len(); i++) {
21898 misfront = * (triface *)(* misfrontlist)[i];
21900 if (b->verbose > 1) {
21901 printf(
" Get misfront (%d, %d, %d).\n", pointmark(org(misfront)),
21902 pointmark(dest(misfront)), pointmark(apex(misfront)));
21905 tspivot(misfront, checksh);
21906 if (checksh.sh != dummysh) {
21908 sym(misfront, crosstet);
21909 if (!infected(crosstet)) {
21917 if (b->verbose > 1) {
21918 printf(
" Queuing subface (%d, %d, %d).\n",
21919 pointmark(sorg(checksh)), pointmark(sdest(checksh)),
21920 pointmark(sapex(checksh)));
21923 tsdissolve(misfront);
21924 tsdissolve(crosstet);
21926 stdissolve(checksh);
21927 sesymself(checksh);
21928 stdissolve(checksh);
21931 missingshqueue->push(&checksh);
21934 if (infected(misfront))
continue;
21936 pd = oppo(misfront);
21939 assert(pd != (point) NULL);
21944 searchtet = recenttet;
21946 if (isdead(&searchtet)) {
21948 for (j = 0; j < newtetlist->len(); j++) {
21949 recenttet = * (triface *)(* newtetlist)[j];
21950 if (!isdead(&recenttet))
break;
21952 assert(j < newtetlist->len());
21953 searchtet = recenttet;
21955 success = insertsite(pd, &searchtet,
false, flipque);
21956 if (success == OUTSIDEPOINT) {
21958 inserthullsite(pd, &searchtet, flipque);
21960 if (success != DUPLICATEPOINT) {
21962 flip(flipque, NULL);
21967 adjustedgering(misfront, CCW);
21968 for (j = 0; j < 3; j++) {
21972 fnext(misfront, newfront);
21974 sym(newfront, casingtet);
21976 if (!infected(casingtet)) {
21979 if (casingtet.tet == dummytet) {
21981 maketetrahedron(&faketet);
21983 adjustedgering(newfront, CW);
21984 setorg(faketet, org(newfront));
21985 setdest(faketet, dest(newfront));
21986 setapex(faketet, apex(newfront));
21987 setoppo(faketet, (point) NULL);
21989 tspivot(newfront, checksh);
21990 if (checksh.sh != dummysh) {
21991 sesymself(checksh);
21992 tsbond(faketet, checksh);
21995 bond(faketet, newfront);
21996 frontlist->append(&faketet);
21999 frontlist->append(&casingtet);
22005 for (k = frontlist->len() - 1; k >= 0; k--) {
22006 searchtet = * (triface *)(* frontlist)[k];
22007 if ((newfront.tet == searchtet.tet) &&
22008 (newfront.loc == searchtet.loc)) {
22009 frontlist->del(k, 0);
22014 tspivot(newfront, checksh);
22015 if (checksh.sh != dummysh) {
22017 if (b->verbose > 2) {
22018 printf(
" Queuing subface (%d, %d, %d).\n",
22019 pointmark(sorg(checksh)), pointmark(sdest(checksh)),
22020 pointmark(sapex(checksh)));
22022 tsdissolve(newfront);
22023 tsdissolve(casingtet);
22025 stdissolve(checksh);
22026 sesymself(checksh);
22027 stdissolve(checksh);
22029 missingshqueue->push(&checksh);
22032 enextself(misfront);
22035 if (!infected(misfront)) {
22038 crosstetlist->append(&misfront);
22043 for (i = 0; i < misfrontlist->len(); i++) {
22044 misfront = * (triface *)(* misfrontlist)[i];
22045 if (infected(misfront)) {
22047 misfrontlist->del(i, 1);
22053 if (misfrontlist->len() > 0) {
22060 retrievenewtets(newtetlist);
22063 dummytet[0] = encode(bakhulltet);
22064 hullsize = bakhullsize;
22065 checksubfaces = bakchksub;
22088 void tetgenmesh::carvecavity(list* newtetlist, list* outtetlist,
22091 triface newtet, neightet, front, outtet;
22098 outtetlist->clear();
22101 for (i = 0; i < newtetlist->len(); i++) {
22103 newtet = * (triface *)(* newtetlist)[i];
22104 assert(!isdead(&newtet));
22106 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22107 tspivot(newtet, auxsh);
22108 if (auxsh.sh != dummysh) {
22110 sym(newtet, neightet);
22111 if (neightet.tet != dummytet) {
22114 decode((tetrahedron) auxsh.sh[0], front);
22116 adjustedgering(front, CW);
22117 ori = orient3d(org(front), dest(front), apex(front), oppo(newtet));
22118 assert(ori != 0.0);
22127 if (!infected(outtet)) {
22129 outtetlist->append(&outtet);
22137 for (i = 0; i < outtetlist->len(); i++) {
22138 outtet = * (triface *)(* outtetlist)[i];
22139 for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22140 sym(outtet, neightet);
22142 if ((neightet.tet != dummytet) && !infected(neightet)) {
22144 tspivot(outtet, auxsh);
22145 if (auxsh.sh == dummysh) {
22148 outtetlist->append(&neightet);
22155 for (i = 0; i < outtetlist->len(); i++) {
22157 outtet = * (triface *)(* outtetlist)[i];
22159 for (outtet.loc = 0; outtet.loc < 4; outtet.loc++) {
22161 tspivot(outtet, auxsh);
22162 if (auxsh.sh != dummysh) {
22164 sym(outtet, neightet);
22165 assert(!infected(neightet));
22167 dissolve(neightet);
22171 tetrahedrondealloc(outtet.tet);
22175 for (i = 0; i < newtetlist->len(); i++) {
22177 newtet = * (triface *)(* newtetlist)[i];
22179 if (isdead(&newtet))
continue;
22181 for (newtet.loc = 0; newtet.loc < 4; newtet.loc++) {
22183 tspivot(newtet, auxsh);
22184 if (auxsh.sh != dummysh) {
22186 decode((tetrahedron) auxsh.sh[0], front);
22187 assert((front.tet != dummytet) && !infected(front));
22189 tsdissolve(newtet);
22191 shellfacedealloc(subfaces, auxsh.sh);
22194 tspivot(front, consh);
22195 if (consh.sh != dummysh) {
22198 tsbond(newtet, consh);
22201 if (oppo(front) == (point) NULL) {
22203 if (consh.sh != dummysh) {
22209 tetrahedrondealloc(front.tet);
22211 dummytet[0] = encode(newtet);
22214 bond(newtet, front);
22217 if (flipque != (queue *) NULL) {
22218 enqueueflipface(newtet, flipque);
22223 pointptr = org(newtet);
22224 setpoint2tet(pointptr, encode(newtet));
22225 pointptr = dest(newtet);
22226 setpoint2tet(pointptr, encode(newtet));
22227 pointptr = apex(newtet);
22228 setpoint2tet(pointptr, encode(newtet));
22229 pointptr = oppo(newtet);
22230 setpoint2tet(pointptr, encode(newtet));
22245 void tetgenmesh::delaunizecavity(list* floorlist, list* ceillist,
22246 list* ceilptlist, list* floorptlist, list* frontlist, list* misfrontlist,
22247 list* newtetlist, list* crosstetlist, queue* missingshqueue, queue* flipque)
22251 vertnum = floorptlist->len();
22252 vertnum += (ceilptlist != (list *) NULL ? ceilptlist->len() : 0);
22253 if (b->verbose > 1) {
22254 printf(
" Delaunizing cavity (%d floors, %d ceilings, %d vertices).\n",
22255 floorlist->len(), ceillist->len(), vertnum);
22258 if ((floorlist->len() + ceillist->len()) > maxcavfaces) {
22259 maxcavfaces = floorlist->len() + ceillist->len();
22261 if (vertnum > maxcavverts) {
22262 maxcavverts = vertnum;
22266 frontlist->clear();
22267 misfrontlist->clear();
22268 newtetlist->clear();
22271 initializecavity(floorlist, ceillist, frontlist);
22273 delaunizecavvertices(NULL, floorptlist, ceilptlist, newtetlist, flipque);
22275 while (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
22277 detachauxsubfaces(newtetlist);
22279 expandcavity(frontlist, misfrontlist, newtetlist, crosstetlist,
22280 missingshqueue, flipque);
22284 carvecavity(newtetlist, misfrontlist, NULL);
22303 void tetgenmesh::formmissingregion(face* missingsh, list* missingshlist,
22304 list* equatptlist,
int* worklist)
22306 face neighsh, worksh, workseg;
22311 missingshlist->append(missingsh);
22313 workpt[0] = sorg(*missingsh);
22314 workpt[1] = sdest(*missingsh);
22315 workpt[2] = sapex(*missingsh);
22316 for (i = 0; i < 3; i++) {
22317 idx = pointmark(workpt[i]) - in->firstnumber;
22319 equatptlist->append(&workpt[i]);
22322 suninfect(*missingsh);
22325 for (i = 0; i < missingshlist->len(); i++) {
22327 worksh = * (face *)(* missingshlist)[i];
22329 for (j = 0; j < 3; j++) {
22330 sspivot(worksh, workseg);
22331 if (workseg.sh == dummysh) {
22332 spivot(worksh, neighsh);
22333 if (sinfected(neighsh)) {
22335 if (sorg(neighsh) != sdest(worksh)) {
22336 sesymself(neighsh);
22338 if (b->verbose > 2) {
22339 printf(
" Add missing subface (%d, %d, %d).\n",
22340 pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
22341 pointmark(sapex(neighsh)));
22343 missingshlist->append(&neighsh);
22345 workpt[0] = sapex(neighsh);
22346 idx = pointmark(workpt[0]) - in->firstnumber;
22348 if (worklist[idx] == 0) {
22350 equatptlist->append(&workpt[0]);
22353 suninfect(neighsh);
22356 senextself(worksh);
22361 for (i = 0; i < missingshlist->len(); i++) {
22362 worksh = * (face *)(* missingshlist)[i];
22385 void tetgenmesh::rearrangesubfaces(list* missingshlist, list* boundedgelist,
22386 list* equatptlist,
int* worklist)
22388 link *boundedgelink;
22390 triface starttet, spintet, neightet, worktet;
22391 face shloop, newsh, neighsh, spinsh, worksh;
22392 face workseg, casingin, casingout;
22393 point torg, tdest, workpt;
22394 point spt1, spt2, spt3;
22395 enum finddirectionresult collinear;
22396 enum shestype shtype;
22398 bool matchflag, finishflag;
22399 int shmark, pbcgp, idx, hitbdry;
22403 boundedgelink =
new link(
sizeof(face), NULL, 256);
22405 newshlink =
new link(
sizeof(face), NULL, 256);
22408 worksh = * (face *)(* missingshlist)[0];
22409 shtype = shelltype(worksh);
22411 for (i = 1; i < missingshlist->len(); i++) {
22412 worksh = * (face *)(* missingshlist)[i];
22413 assert(shelltype(worksh) == shtype);
22416 shmark = pbcgp = 0;
22420 for (i = 0; i < boundedgelist->len(); i++) {
22421 shloop = * (face *)(* boundedgelist)[i];
22424 shmark = shellmark(shloop);
22425 if (b->quality && varconstraint) {
22427 area = areabound(shloop);
22431 pbcgp = shellpbcgroup(shloop);
22434 abovepoint = facetabovepointarray[shellmark(shloop)];
22435 if (abovepoint == (point) NULL) {
22436 getfacetabovepoint(&shloop);
22439 sspivot(shloop, workseg);
22440 if (workseg.sh == dummysh) {
22442 spivot(shloop, neighsh);
22443 boundedgelink->add(&neighsh);
22446 boundedgelink->add(&shloop);
22460 while (boundedgelink->len() > 0) {
22462 shloop = * (face *) boundedgelink->del(1);
22464 sspivot(shloop, workseg);
22465 torg = sorg(shloop);
22466 tdest = sdest(shloop);
22468 getsearchtet(torg, tdest, &starttet, &workpt);
22469 collinear = finddirection(&starttet, workpt, tetrahedrons->items);
22470 if (collinear == LEFTCOLLINEAR) {
22471 enext2self(starttet);
22472 esymself(starttet);
22473 }
else if (collinear == TOPCOLLINEAR) {
22474 fnextself(starttet);
22475 enext2self(starttet);
22476 esymself(starttet);
22478 assert(dest(starttet) == workpt);
22481 spintet = starttet;
22484 workpt = apex(spintet);
22485 idx = pointmark(workpt) - in->firstnumber;
22486 if (worklist[idx] == 1) {
22488 finishflag =
false;
22489 for (i = 0; i < missingshlist->len(); i++) {
22490 worksh = * (face *)(* missingshlist)[i];
22491 spt1 = sorg(worksh);
22492 spt2 = sdest(worksh);
22493 spt3 = sapex(worksh);
22495 if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22497 finishflag =
true;
break;
22500 if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22502 finishflag =
true;
break;
22505 if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22507 finishflag =
true;
break;
22513 for (i = 0; i < newshlink->len() && matchflag; i++) {
22514 worksh = * (face *) newshlink->getnitem(i + 1);
22515 spt1 = sorg(worksh);
22516 spt2 = sdest(worksh);
22517 spt3 = sapex(worksh);
22519 if (tri_edge_cop_inter(spt1, spt2, spt3, tdest, workpt, abovepoint)
22521 matchflag =
false;
break;
22524 if (tri_edge_cop_inter(spt1, spt2, spt3, workpt, torg, abovepoint)
22526 matchflag =
false;
break;
22529 if (tri_vert_cop_inter(spt1, spt2, spt3, workpt, abovepoint)
22531 matchflag =
false;
break;
22535 if (matchflag ==
true) {
22540 if (!fnextself(spintet)) {
22543 esym(starttet, spintet);
22544 if (!fnextself(spintet)) {
22549 }
while (hitbdry < 2 && apex(spintet) != apex(starttet));
22550 assert(matchflag ==
true);
22551 tspivot(spintet, neighsh);
22552 if (neighsh.sh != dummysh) {
22553 printf(
"Error: Invalid PLC.\n");
22554 printf(
" Facet #%d and facet #%d overlap each other.\n",
22555 shellmark(neighsh), shellmark(shloop));
22556 printf(
" It might be caused by a facet is defined more than once.\n");
22557 printf(
" Hint: Use -d switch to find all overlapping facets.\n");
22561 adjustedgering(spintet, CCW);
22563 makeshellface(subfaces, &newsh);
22564 setsorg(newsh, org(spintet));
22565 setsdest(newsh, dest(spintet));
22566 setsapex(newsh, apex(spintet));
22567 if (b->quality && varconstraint) {
22568 setareabound(newsh, area);
22571 setshellpbcgroup(newsh, pbcgp);
22573 setshellmark(newsh, shmark);
22574 setshelltype(newsh, shtype);
22576 newshlink->add(&newsh);
22578 tsbond(spintet, newsh);
22579 sym(spintet, neightet);
22580 if (neightet.tet != dummytet) {
22581 sesym(newsh, neighsh);
22582 tsbond(neightet, neighsh);
22585 sspivot(shloop, workseg);
22586 if (workseg.sh == dummysh) {
22587 sbond(shloop, newsh);
22596 spivot(shloop, casingout);
22597 if (shloop.sh != casingout.sh) {
22599 spinsh = casingout;
22602 spivotself(spinsh);
22603 }
while (sapex(spinsh) != sapex(shloop));
22604 assert(casingin.sh != shloop.sh);
22606 sbond1(casingin, newsh);
22607 sbond1(newsh, casingout);
22610 sbond(newsh, newsh);
22613 ssbond(newsh, workseg);
22617 for (i = 0; i < 2; i++) {
22619 senext(newsh, worksh);
22621 senext2(newsh, worksh);
22623 torg = sorg(worksh);
22624 tdest = sdest(worksh);
22625 finishflag =
false;
22626 for (j = 0; j < boundedgelink->len() && !finishflag; j++) {
22627 neighsh = * (face *) boundedgelink->getnitem(j + 1);
22628 if ((sorg(neighsh) == torg && sdest(neighsh) == tdest) ||
22629 (sorg(neighsh) == tdest && sdest(neighsh) == torg)) {
22631 sspivot(neighsh, workseg);
22632 if (workseg.sh == dummysh) {
22633 sbond(neighsh, worksh);
22637 spivot(neighsh, casingout);
22638 if (neighsh.sh != casingout.sh) {
22640 spinsh = casingout;
22643 spivotself(spinsh);
22644 }
while (sapex(spinsh) != sapex(neighsh));
22645 assert(casingin.sh != neighsh.sh);
22647 sbond1(casingin, worksh);
22648 sbond1(worksh, casingout);
22651 sbond(worksh, worksh);
22654 ssbond(worksh, workseg);
22657 boundedgelink->del(j + 1);
22663 boundedgelink->add(&worksh);
22669 for (i = 0; i < missingshlist->len(); i++) {
22670 worksh = * (face *)(* missingshlist)[i];
22671 shellfacedealloc(subfaces, worksh.sh);
22674 for (i = 0; i < equatptlist->len(); i++) {
22675 workpt = * (point *)(* equatptlist)[i];
22676 idx = pointmark(workpt) - in->firstnumber;
22680 delete boundedgelink;
22699 bool tetgenmesh::scoutcrossingedge(list* missingshlist, list* boundedgelist,
22700 list* crossedgelist,
int* worklist)
22702 triface starttet, spintet, worktet;
22703 face startsh, neighsh, worksh, workseg;
22704 point torg, tdest, tapex;
22705 point workpt[3], pa, pb, pc;
22706 enum finddirectionresult collinear;
22715 for (i = 0; i < missingshlist->len(); i++) {
22716 worksh = * (face *)(* missingshlist)[i];
22717 for (j = 0; j < 3; j++) {
22718 sspivot(worksh, workseg);
22719 if (workseg.sh == dummysh) {
22720 spivot(worksh, neighsh);
22721 if (!sinfected(neighsh)) {
22722 boundedgelist->append(&worksh);
22725 boundedgelist->append(&worksh);
22727 senextself(worksh);
22734 for (i = 0; i < boundedgelist->len() && !crossflag; i++) {
22735 startsh = * (face *)(* boundedgelist)[i];
22737 torg = sorg(startsh);
22738 tdest = sdest(startsh);
22739 tapex = sapex(startsh);
22740 getsearchtet(torg, tdest, &starttet, &workpt[0]);
22741 collinear = finddirection(&starttet, workpt[0], tetrahedrons->items);
22742 if (collinear == LEFTCOLLINEAR) {
22743 enext2self(starttet);
22744 esymself(starttet);
22745 }
else if (collinear == TOPCOLLINEAR) {
22746 fnextself(starttet);
22747 enext2self(starttet);
22748 esymself(starttet);
22751 assert(dest(starttet) == workpt[0]);
22754 spintet = starttet;
22757 if (fnextself(spintet)) {
22759 workpt[1] = apex(spintet);
22760 workpt[2] = oppo(spintet);
22761 j = pointmark(workpt[1]) - in->firstnumber;
22762 k = pointmark(workpt[2]) - in->firstnumber;
22763 if (worklist[j] == 1) {
22767 ori1 = orient3d(torg, tdest, tapex, workpt[1]);
22769 if (worklist[k] == 1) {
22773 ori2 = orient3d(torg, tdest, tapex, workpt[2]);
22776 if (ori1 * ori2 < 0.0) {
22778 for (j = 0; j < missingshlist->len(); j++) {
22779 worksh = * (face *)(* missingshlist)[j];
22781 pb = sdest(worksh);
22782 pc = sapex(worksh);
22783 crossflag = (tri_tri_inter(pa, pb, pc, workpt[0], workpt[1],
22784 workpt[2]) == INTERSECT);
22788 adjustedgering(worktet, CCW);
22789 enextfnextself(worktet);
22790 enextself(worktet);
22792 crossedgelist->append(&worktet);
22796 if (crossflag)
break;
22798 if (apex(spintet) == apex(starttet))
break;
22803 esym(starttet, spintet);
22806 }
while (hitbdry < 2);
22842 void tetgenmesh::formcavity(list* missingshlist, list* crossedgelist,
22843 list* equatptlist, list* crossshlist, list* crosstetlist,
22844 list* belowfacelist, list* abovefacelist, list* horizptlist,
22845 list* belowptlist, list* aboveptlist, queue* missingshqueue,
int* worklist)
22847 triface starttet, spintet, neightet, worktet;
22848 face startsh, neighsh, worksh, workseg;
22849 point torg, tdest, tapex, workpt[3];
22850 REAL checksign, orgori, destori;
22851 bool crossflag, inlistflag;
22852 bool belowflag, aboveflag;
22857 startsh = * (face *)(* missingshlist)[0];
22858 torg = sorg(startsh);
22859 tdest = sdest(startsh);
22860 tapex = sapex(startsh);
22863 for (i = 0; i < crossedgelist->len(); i++) {
22865 starttet = * (triface *)(* crossedgelist)[i];
22866 adjustedgering(starttet, CCW);
22867 if (b->verbose > 2) {
22868 printf(
" Collect tets containing edge (%d, %d).\n",
22869 pointmark(org(starttet)), pointmark(dest(starttet)));
22871 orgori = orient3d(torg, tdest, tapex, org(starttet));
22872 destori = orient3d(torg, tdest, tapex, dest(starttet));
22875 assert(orgori * destori < 0.0);
22877 spintet = starttet;
22880 fnextself(spintet);
22882 tspivot(spintet, worksh);
22883 if (worksh.sh != dummysh) {
22884 printf(
"Error: Invalid PLC.\n");
22885 printf(
" Two subfaces (%d, %d, %d) and (%d, %d, %d)\n",
22886 pointmark(torg), pointmark(tdest), pointmark(tapex),
22887 pointmark(sorg(worksh)), pointmark(sdest(worksh)),
22888 pointmark(sapex(worksh)));
22889 printf(
" are found intersecting each other.\n");
22890 printf(
" Hint: Use -d switch to find all intersecting facets.\n");
22891 terminatetetgen(1);
22893 if (!infected(spintet)) {
22894 if (b->verbose > 2) {
22895 printf(
" Add crossing tet (%d, %d, %d, %d).\n",
22896 pointmark(org(spintet)), pointmark(dest(spintet)),
22897 pointmark(apex(spintet)), pointmark(oppo(spintet)));
22900 crosstetlist->append(&spintet);
22905 workpt[0] = apex(spintet);
22906 idx = pointmark(workpt[0]) - in->firstnumber;
22907 if (worklist[idx] != 1) {
22909 checksign = orient3d(torg, tdest, tapex, workpt[0]);
22911 assert(checksign != 0.0);
22913 if (checksign * orgori < 0.0) {
22914 enext2(spintet, worktet);
22915 workpt[1] = org(spintet);
22918 assert(checksign * destori < 0.0);
22920 enext(spintet, worktet);
22921 workpt[1] = dest(spintet);
22925 inlistflag =
false;
22926 for (j = 0; j < crossedgelist->len() && !inlistflag; j++) {
22927 neightet = * (triface *)(* crossedgelist)[j];
22928 if (org(neightet) == workpt[0]) {
22929 if (dest(neightet) == workpt[1]) inlistflag =
true;
22930 }
else if (org(neightet) == workpt[1]) {
22931 if (dest(neightet) == workpt[0]) inlistflag =
true;
22935 crossedgelist->append(&worktet);
22938 }
while (apex(spintet) != apex(starttet));
22944 for (i = 0; i < crosstetlist->len(); i++) {
22946 starttet = * (triface *)(* crosstetlist)[i];
22948 assert(infected(starttet));
22950 adjustedgering(starttet, CCW);
22953 for (j = 0; j < 2; j++) {
22955 enextfnext(starttet, worktet);
22957 enext2fnext(starttet, worktet);
22959 sym(worktet, neightet);
22962 if ((neightet.tet == dummytet) || !infected(neightet)) {
22963 workpt[0] = org(worktet);
22964 workpt[1] = dest(worktet);
22965 workpt[2] = apex(worktet);
22966 belowflag = aboveflag =
false;
22968 for (k = 0; k < 3; k++) {
22969 idx = pointmark(workpt[k]) - in->firstnumber;
22970 if (worklist[idx] == 0) {
22972 checksign = orient3d(torg, tdest, tapex, workpt[k]);
22974 assert(checksign != 0.0);
22976 if (checksign > 0.0) {
22979 belowptlist->append(&workpt[k]);
22980 }
else if (checksign < 0.0) {
22983 aboveptlist->append(&workpt[k]);
22986 if (worklist[idx] == 2) {
22989 }
else if (worklist[idx] == 3) {
22995 assert(worklist[idx] == 1);
23004 assert(belowflag ^ aboveflag);
23007 belowfacelist->append(&worktet);
23008 }
else if (aboveflag) {
23009 abovefacelist->append(&worktet);
23018 for (i = 0; i < missingshlist->len(); i++) {
23019 worksh = * (face *)(* missingshlist)[i];
23021 assert(sinfected(worksh));
23023 workpt[0] = sorg(worksh);
23024 workpt[1] = sdest(worksh);
23025 workpt[2] = sapex(worksh);
23027 for (j = 0; j < crosstetlist->len() && !crossflag; j++) {
23029 starttet = * (triface *)(* crosstetlist)[j];
23030 adjustedgering(starttet, CCW);
23032 for (k = 0; k < 2 && !crossflag; k++) {
23034 worktet = starttet;
23036 fnext(starttet, worktet);
23038 crossflag = tritritest(&worktet, workpt[0], workpt[1], workpt[2]);
23044 crossshlist->append(&worksh);
23046 for (k = 0; k < 3; k++) {
23047 idx = pointmark(workpt[k]) - in->firstnumber;
23048 if (worklist[idx] != 4) {
23050 horizptlist->append(&workpt[k]);
23057 for (i = 0; i < crosstetlist->len(); i++) {
23058 starttet = * (triface *)(* crosstetlist)[i];
23059 for (starttet.loc = 0; starttet.loc < 4; starttet.loc++) {
23060 sym(starttet, neightet);
23062 if ((neightet.tet != dummytet) && infected(neightet)) {
23063 tspivot(starttet, worksh);
23064 if (worksh.sh != dummysh) {
23066 if (b->verbose > 2) {
23067 printf(
" Queuing subface (%d, %d, %d).\n",
23068 pointmark(sorg(worksh)), pointmark(sdest(worksh)),
23069 pointmark(sapex(worksh)));
23071 tsdissolve(neightet);
23072 tsdissolve(starttet);
23074 stdissolve(worksh);
23076 stdissolve(worksh);
23078 missingshqueue->push(&worksh);
23085 for (i = 0; i < equatptlist->len(); i++) {
23086 workpt[0] = * (point *)(* equatptlist)[i];
23087 idx = pointmark(workpt[0]) - in->firstnumber;
23089 assert((worklist[idx] == 1) || (worklist[idx] == 4));
23093 for (i = 0; i < belowptlist->len(); i++) {
23094 workpt[0] = * (point *)(* belowptlist)[i];
23095 idx = pointmark(workpt[0]) - in->firstnumber;
23097 assert(worklist[idx] == 2);
23101 for (i = 0; i < aboveptlist->len(); i++) {
23102 workpt[0] = * (point *)(* aboveptlist)[i];
23103 idx = pointmark(workpt[0]) - in->firstnumber;
23105 assert(worklist[idx] == 3);
23121 void tetgenmesh::insertallsubfaces(queue* missingshqueue)
23126 searchtet.tet = (tetrahedron *) NULL;
23127 subfaces->traversalinit();
23128 subloop.sh = shellfacetraverse(subfaces);
23129 while (subloop.sh != (shellface *) NULL) {
23130 if (!insertsubface(&subloop, &searchtet)) {
23131 if (b->verbose > 1) {
23132 printf(
" Queuing subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23133 pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23136 missingshqueue->push(&subloop);
23138 subloop.sh = shellfacetraverse(subfaces);
23166 void tetgenmesh::constrainedfacets()
23168 queue *missingshqueue, *flipque;
23169 list *missingshlist, *equatptlist;
23170 list *boundedgelist, *crossedgelist, *crosstetlist;
23171 list *crossshlist, *belowfacelist, *abovefacelist;
23172 list *horizptlist, *belowptlist, *aboveptlist;
23173 list *frontlist, *misfrontlist, *newtetlist;
23174 triface searchtet, worktet;
23175 face subloop, worksh;
23180 printf(
"Constraining facets.\n");
23184 missingshqueue =
new queue(
sizeof(face));
23185 flipque =
new queue(
sizeof(badface));
23187 missingshlist =
new list(
sizeof(face), NULL);
23188 boundedgelist =
new list(
sizeof(face), NULL);
23189 crossedgelist =
new list(
sizeof(triface), NULL);
23190 equatptlist =
new list((
char*)
"point *");
23191 crossshlist =
new list(
sizeof(face), NULL);
23192 crosstetlist =
new list(
sizeof(triface), NULL);
23193 belowfacelist =
new list(
sizeof(triface), NULL);
23194 abovefacelist =
new list(
sizeof(triface), NULL);
23195 horizptlist =
new list((
char*)
"point *");
23196 belowptlist =
new list((
char*)
"point *");
23197 aboveptlist =
new list((
char*)
"point *");
23198 frontlist =
new list(
sizeof(triface), NULL);
23199 misfrontlist =
new list(
sizeof(triface), NULL);
23200 newtetlist =
new list(
sizeof(triface), NULL);
23202 worklist =
new int[points->items + 1];
23203 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
23206 makepoint2tetmap();
23209 insertallsubfaces(missingshqueue);
23212 while (!missingshqueue->empty()) {
23214 subloop = * (face *) missingshqueue->pop();
23216 if (isdead(&subloop))
continue;
23218 if (!sinfected(subloop))
continue;
23220 if (insertsubface(&subloop, &searchtet)) {
23221 suninfect(subloop);
23224 if (b->verbose > 1) {
23225 printf(
" Recover subface (%d, %d, %d).\n", pointmark(sorg(subloop)),
23226 pointmark(sdest(subloop)), pointmark(sapex(subloop)));
23229 formmissingregion(&subloop, missingshlist, equatptlist, worklist);
23231 if (scoutcrossingedge(missingshlist, boundedgelist, crossedgelist,
23234 formcavity(missingshlist, crossedgelist, equatptlist, crossshlist,
23235 crosstetlist, belowfacelist, abovefacelist, horizptlist,
23236 belowptlist, aboveptlist, missingshqueue, worklist);
23238 delaunizecavity(crossshlist, abovefacelist, aboveptlist, horizptlist,
23239 frontlist, misfrontlist, newtetlist, crosstetlist,
23240 missingshqueue, flipque);
23242 for (i = 0; i < crossshlist->len(); i++) {
23243 worksh = * (face *)(* crossshlist)[i];
23245 * (face *)(* crossshlist)[i] = worksh;
23248 delaunizecavity(crossshlist, belowfacelist, belowptlist, horizptlist,
23249 frontlist, misfrontlist, newtetlist, crosstetlist,
23250 missingshqueue, flipque);
23252 for (i = 0; i < crosstetlist->len(); i++) {
23253 worktet = * (triface *)(* crosstetlist)[i];
23254 tetrahedrondealloc(worktet.tet);
23258 for (i = 0; i < missingshlist->len(); i++) {
23259 worksh = * (face *)(* missingshlist)[i];
23260 if (sinfected(worksh)) {
23262 missingshqueue->push(&worksh);
23265 crossshlist->clear();
23266 belowfacelist->clear();
23267 abovefacelist->clear();
23268 horizptlist->clear();
23269 belowptlist->clear();
23270 aboveptlist->clear();
23271 crosstetlist->clear();
23275 rearrangesubfaces(missingshlist, boundedgelist, equatptlist, worklist);
23278 missingshlist->clear();
23279 boundedgelist->clear();
23280 crossedgelist->clear();
23281 equatptlist->clear();
23287 if (b->verbose > 0) {
23288 printf(
" The biggest cavity: %d faces, %d vertices\n", maxcavfaces,
23290 printf(
" Enlarged %d times\n", expcavcount);
23293 delete missingshqueue;
23295 delete missingshlist;
23296 delete boundedgelist;
23297 delete crossedgelist;
23298 delete equatptlist;
23299 delete crossshlist;
23300 delete crosstetlist;
23301 delete belowfacelist;
23302 delete abovefacelist;
23303 delete horizptlist;
23304 delete belowptlist;
23305 delete aboveptlist;
23307 delete misfrontlist;
23309 delete [] worklist;
23330 void tetgenmesh::infecthull(
memorypool *viri)
23332 triface tetloop, tsymtet;
23333 tetrahedron **deadtet;
23337 if (b->verbose > 0) {
23338 printf(
" Marking concavities for elimination.\n");
23340 tetrahedrons->traversalinit();
23341 tetloop.tet = tetrahedrontraverse();
23342 while (tetloop.tet != (tetrahedron *) NULL) {
23344 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
23345 sym(tetloop, tsymtet);
23346 if (tsymtet.tet == dummytet) {
23348 tspivot(tetloop, hullface);
23349 if (hullface.sh == dummysh) {
23351 if (!infected(tetloop)) {
23353 deadtet = (tetrahedron **) viri->alloc();
23354 *deadtet = tetloop.tet;
23359 if (shellmark(hullface) == 0) {
23360 setshellmark(hullface, 1);
23379 tetloop.tet = tetrahedrontraverse();
23397 tetrahedron **virusloop;
23398 tetrahedron **deadtet;
23399 triface testtet, neighbor;
23400 face neighsh, testseg;
23401 face spinsh, casingin, casingout;
23405 if (b->verbose > 0) {
23406 printf(
" Marking neighbors of marked tetrahedra.\n");
23411 viri->traversalinit();
23412 virusloop = (tetrahedron **) viri->traverse();
23413 while (virusloop != (tetrahedron **) NULL) {
23414 testtet.tet = *virusloop;
23418 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23420 sym(testtet, neighbor);
23422 tspivot(testtet, neighsh);
23424 if ((neighbor.tet == dummytet) || infected(neighbor)) {
23425 if (neighsh.sh != dummysh) {
23431 if (!firstdadsub) {
23434 printf(
"Warning: Detecting an open face (%d, %d, %d).\n",
23435 pointmark(sorg(neighsh)), pointmark(sdest(neighsh)),
23436 pointmark(sapex(neighsh)));
23440 findedge(&testtet, sorg(neighsh), sdest(neighsh));
23441 for (i = 0; i < 3; i++) {
23442 sspivot(neighsh, testseg);
23443 if (testseg.sh != dummysh) {
23448 if (sorg(spinsh) != sorg(testseg)) {
23451 spivot(spinsh, casingout);
23452 if (casingout.sh == spinsh.sh) {
23455 shellfacedealloc(subsegs, testseg.sh);
23457 spinsh = casingout;
23460 spivotself(spinsh);
23461 }
while (spinsh.sh != neighsh.sh);
23463 sbond1(casingin, casingout);
23465 ssbond(casingin, testseg);
23468 senextself(neighsh);
23469 enextself(testtet);
23471 if (neighbor.tet != dummytet) {
23474 tsdissolve(neighbor);
23477 if (in->mesh_dim > 2) {
23478 shellfacedealloc(subfaces, neighsh.sh);
23482 stdissolve(neighsh);
23483 sesymself(neighsh);
23484 stdissolve(neighsh);
23488 if (neighsh.sh == dummysh) {
23492 deadtet = (tetrahedron **) viri->alloc();
23493 *deadtet = neighbor.tet;
23496 stdissolve(neighsh);
23498 if (shellmark(neighsh) == 0) {
23499 setshellmark(neighsh, 1);
23502 dummytet[0] = encode(neighbor);
23509 virusloop = (tetrahedron **) viri->traverse();
23525 regionplague(
memorypool *regionviri, REAL attribute, REAL volume)
23527 tetrahedron **virusloop;
23528 tetrahedron **regiontet;
23529 triface testtet, neighbor;
23532 if (b->verbose > 1) {
23533 printf(
" Marking neighbors of marked tetrahedra.\n");
23538 regionviri->traversalinit();
23539 virusloop = (tetrahedron **) regionviri->traverse();
23540 while (virusloop != (tetrahedron **) NULL) {
23541 testtet.tet = *virusloop;
23544 if (b->regionattrib) {
23546 setelemattribute(testtet.tet, in->numberoftetrahedronattributes,
23549 if (b->varvolume) {
23551 setvolumebound(testtet.tet, volume);
23554 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23556 sym(testtet, neighbor);
23558 tspivot(testtet, neighsh);
23562 if ((neighbor.tet != dummytet) && !infected(neighbor)
23563 && (neighsh.sh == dummysh)) {
23567 regiontet = (tetrahedron **) regionviri->alloc();
23568 *regiontet = neighbor.tet;
23574 virusloop = (tetrahedron **) regionviri->traverse();
23578 if (b->verbose > 1) {
23579 printf(
" Unmarking marked tetrahedra.\n");
23581 regionviri->traversalinit();
23582 virusloop = (tetrahedron **) regionviri->traverse();
23583 while (virusloop != (tetrahedron **) NULL) {
23584 testtet.tet = *virusloop;
23586 virusloop = (tetrahedron **) regionviri->traverse();
23589 regionviri->restart();
23598 void tetgenmesh::removeholetets(
memorypool* viri)
23600 tetrahedron **virusloop;
23601 triface testtet, neighbor;
23603 int *tetspernodelist;
23606 if (b->verbose > 0) {
23607 printf(
" Deleting marked tetrahedra.\n");
23611 tetspernodelist =
new int[points->items + 1];
23612 for (i = 0; i < points->items + 1; i++) tetspernodelist[i] = 0;
23615 tetrahedrons->traversalinit();
23616 testtet.tet = tetrahedrontraverse();
23617 while (testtet.tet != (tetrahedron *) NULL) {
23619 for (i = 0; i < 4; i++) {
23620 j = pointmark((point) testtet.tet[4 + i]);
23621 tetspernodelist[j]++;
23623 testtet.tet = tetrahedrontraverse();
23626 viri->traversalinit();
23627 virusloop = (tetrahedron **) viri->traverse();
23628 while (virusloop != (tetrahedron **) NULL) {
23629 testtet.tet = *virusloop;
23632 for (testtet.loc = 0; testtet.loc < 4; testtet.loc++) {
23633 sym(testtet, neighbor);
23634 if (neighbor.tet == dummytet) {
23641 dissolve(neighbor);
23648 for (i = 0; i < 4; i++) {
23649 checkpt = (point) testtet.tet[4 + i];
23650 j = pointmark(checkpt);
23651 tetspernodelist[j]--;
23652 if (tetspernodelist[j] == 0) {
23654 if ((pointtype(checkpt) == FREEVOLVERTEX) || !b->nojettison) {
23655 setpointtype(checkpt, UNUSEDVERTEX);
23661 tetrahedrondealloc(testtet.tet);
23662 virusloop = (tetrahedron **) viri->traverse();
23665 delete [] tetspernodelist;
23680 void tetgenmesh::assignregionattribs()
23682 list *regionnumlist;
23683 list *regiontetlist;
23684 triface tetloop, regiontet, neightet;
23687 int regionnum, num;
23688 int attridx, count;
23691 if (b->verbose > 0) {
23692 printf(
" Assign region numbers.\n");
23695 regionnumlist =
new list(
sizeof(
int), NULL, 256);
23696 regiontetlist =
new list(
sizeof(triface), NULL, 1024);
23697 attridx = in->numberoftetrahedronattributes;
23701 tetrahedrons->traversalinit();
23702 tetloop.tet = tetrahedrontraverse();
23703 while (tetloop.tet != (tetrahedron *) NULL) {
23704 if (!infected(tetloop)) {
23705 regionnum = (int) elemattribute(tetloop.tet, attridx);
23706 if (regionnum != 0.0) {
23709 regiontetlist->append(&tetloop);
23711 for (i = 0; i < regiontetlist->len(); i++) {
23712 regiontet = * (triface *)(* regiontetlist)[i];
23713 for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23715 tspivot(regiontet, checksh);
23716 if (checksh.sh == dummysh) {
23717 sym(regiontet, neightet);
23718 if ((neightet.tet != dummytet) && !infected(neightet)) {
23721 num = (int) elemattribute(neightet.tet, attridx);
23722 assert(num == regionnum);
23725 regiontetlist->append(&neightet);
23732 for (i = 0; i < regionnumlist->len() && !flag; i++) {
23733 num = * (
int *)(* regionnumlist)[i];
23734 flag = (num == regionnum);
23736 if (!flag) regionnumlist->append(®ionnum);
23738 regiontetlist->clear();
23741 tetloop.tet = tetrahedrontraverse();
23744 if (b->verbose > 0) {
23745 printf(
" %d user-specified regions.\n", regionnumlist->len());
23749 tetrahedrons->traversalinit();
23750 tetloop.tet = tetrahedrontraverse();
23753 while (tetloop.tet != (tetrahedron *) NULL) {
23754 if (!infected(tetloop)) {
23760 for (i = 0; i < regionnumlist->len() && !flag; i++) {
23761 num = * (
int *)(* regionnumlist)[i];
23762 flag = (num == regionnum);
23764 if (flag) regionnum++;
23766 setelemattribute(tetloop.tet, attridx, (REAL) regionnum);
23768 regiontetlist->append(&tetloop);
23770 for (i = 0; i < regiontetlist->len(); i++) {
23771 regiontet = * (triface *)(* regiontetlist)[i];
23772 for (regiontet.loc = 0; regiontet.loc < 4; regiontet.loc++) {
23774 tspivot(regiontet, checksh);
23775 if (checksh.sh == dummysh) {
23776 sym(regiontet, neightet);
23777 if ((neightet.tet != dummytet) && !infected(neightet)) {
23780 num = (int) elemattribute(neightet.tet, attridx);
23783 setelemattribute(neightet.tet, attridx, (REAL) regionnum);
23785 regiontetlist->append(&neightet);
23790 regiontetlist->clear();
23793 tetloop.tet = tetrahedrontraverse();
23797 tetrahedrons->traversalinit();
23798 tetloop.tet = tetrahedrontraverse();
23799 while (tetloop.tet != (tetrahedron *) NULL) {
23801 assert(infected(tetloop));
23804 tetloop.tet = tetrahedrontraverse();
23807 if (b->verbose > 0) {
23808 printf(
" %d regions are numbered.\n", count);
23811 delete regionnumlist;
23812 delete regiontetlist;
23826 void tetgenmesh::carveholes()
23829 tetrahedron *tptr, **holetet, **regiontet;
23830 triface searchtet, *holetets, *regiontets;
23831 enum locateresult intersect;
23835 printf(
"Removing unwanted tetrahedra.\n");
23836 if (b->verbose && (in->numberofholes > 0)) {
23837 printf(
" Marking holes for elimination.\n");
23842 holeviri =
new memorypool(
sizeof(tetrahedron *), 1024, POINTER, 0);
23844 infecthull(holeviri);
23846 if (in->numberofholes > 0) {
23848 holetets = (triface *)
new triface[in->numberofholes];
23850 for (i = 0; i < 3 * in->numberofholes; i += 3) {
23852 if ((in->holelist[i] >= xmin) && (in->holelist[i] <= xmax)
23853 && (in->holelist[i + 1] >= ymin)
23854 && (in->holelist[i + 1] <= ymax)
23855 && (in->holelist[i + 2] >= zmin)
23856 && (in->holelist[i + 2] <= zmax)) {
23857 searchtet.tet = dummytet;
23859 intersect = locate(&in->holelist[i], &searchtet);
23860 if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23862 holetets[i / 3] = searchtet;
23868 for (i = 0; i < in->numberofholes; i++) {
23869 infect(holetets[i]);
23870 holetet = (tetrahedron **) holeviri->alloc();
23871 *holetet = holetets[i].tet;
23874 delete [] holetets;
23882 if (b->regionattrib) {
23884 tetrahedrons->traversalinit();
23885 tptr = tetrahedrontraverse();
23886 while (tptr != (tetrahedron *) NULL) {
23887 setelemattribute(tptr, in->numberoftetrahedronattributes, 0.0);
23888 tptr = tetrahedrontraverse();
23892 if (in->numberofregions > 0) {
23894 if (b->regionattrib) {
23895 if (b->varvolume) {
23896 printf(
"Spreading regional attributes and volume constraints.\n");
23898 printf(
"Spreading regional attributes.\n");
23901 printf(
"Spreading regional volume constraints.\n");
23905 regiontets = (triface *)
new triface[in->numberofregions];
23907 for (i = 0; i < in->numberofregions; i++) {
23908 regiontets[i].tet = dummytet;
23910 if ((in->regionlist[5 * i] >= xmin)
23911 && (in->regionlist[5 * i] <= xmax)
23912 && (in->regionlist[5 * i + 1] >= ymin)
23913 && (in->regionlist[5 * i + 1] <= ymax)
23914 && (in->regionlist[5 * i + 2] >= zmin)
23915 && (in->regionlist[5 * i + 2] <= zmax)) {
23916 searchtet.tet = dummytet;
23918 intersect = locate(&in->regionlist[5 * i], &searchtet);
23919 if ((intersect != OUTSIDE) && (!infected(searchtet))) {
23922 regiontets[i] = searchtet;
23928 regionviri =
new memorypool(
sizeof(tetrahedron *), 1024, POINTER, 0);
23930 for (i = 0; i < in->numberofregions; i++) {
23931 if (regiontets[i].tet != dummytet) {
23934 if (!isdead(&(regiontets[i]))) {
23936 infect(regiontets[i]);
23937 regiontet = (tetrahedron **) regionviri->alloc();
23938 *regiontet = regiontets[i].tet;
23940 regionplague(regionviri, in->regionlist[5 * i + 3],
23941 in->regionlist[5 * i + 4]);
23947 delete [] regiontets;
23952 removeholetets(holeviri);
23956 if (b->regionattrib) {
23957 if (b->regionattrib > 1) {
23959 assignregionattribs();
23962 in->numberoftetrahedronattributes++;
23990 void tetgenmesh::replacepolygonsubs(list* oldshlist, list* newshlist)
23992 face newsh, oldsh, spinsh;
23993 face casingout, casingin;
23998 for (i = 0; i < newshlist->len(); i++) {
24000 newsh = * (face *)(* newshlist)[i];
24002 for (k = 0; k < 3; k++) {
24003 spivot(newsh, casingout);
24005 if (casingout.sh == dummysh) {
24009 for (j = 0; j < oldshlist->len(); j++) {
24010 oldsh = * (face *)(* oldshlist)[j];
24011 for (l = 0; l < 3; l++) {
24012 if (((sorg(oldsh) == pa) && (sdest(oldsh) == pb)) ||
24013 ((sorg(oldsh) == pb) && (sdest(oldsh) == pa)))
break;
24019 if (j < oldshlist->len()) {
24021 spivot(oldsh, casingout);
24022 sspivot(oldsh, checkseg);
24023 if (checkseg.sh != dummysh) {
24025 if (oldsh.sh != casingout.sh) {
24027 spinsh = casingout;
24030 spivotself(spinsh);
24031 }
while (sapex(spinsh) != sapex(oldsh));
24032 assert(casingin.sh != oldsh.sh);
24034 sbond1(casingin, newsh);
24035 sbond1(newsh, casingout);
24038 sbond(newsh, newsh);
24041 ssbond(newsh, checkseg);
24044 sbond(newsh, casingout);
24069 void tetgenmesh::orientnewsubs(list* newshlist, face* orientsh, REAL* norm)
24073 REAL ref[3], ori, len;
24077 pa = sorg(*orientsh);
24078 pb = sdest(*orientsh);
24079 pc = sapex(*orientsh);
24080 facenormal(pa, pb, pc, norm, &len);
24081 for (i = 0; i < 3; i++) ref[i] = pa[i] + norm[i];
24082 for (i = 0; i < 3; i++) norm[i] /= len;
24085 for (i = 0; i < newshlist->len(); i++) {
24086 newsh = (face *)(* newshlist)[i];
24088 pb = sdest(*newsh);
24089 pc = sapex(*newsh);
24090 ori = orient3d(pa, pb, pc, ref);
24091 assert(ori != 0.0);
24119 bool tetgenmesh::constrainedflip(triface* flipface, triface* front,
24122 triface symface, spintet;
24124 point pa, pb, pc, pd, pe;
24128 int ia, ib, ic, id, ie;
24132 tspivot(*flipface, checksh);
24133 if (checksh.sh != dummysh)
return false;
24135 sym(*flipface, symface);
24136 if (symface.tet == dummytet)
return false;
24138 adjustedgering(*flipface, CCW);
24139 pa = dest(*flipface);
24140 pb = org(*flipface);
24141 pc = apex(*flipface);
24142 pd = oppo(*flipface);
24143 pe = oppo(symface);
24145 ia = pointmark(pa);
24146 ib = pointmark(pb);
24147 ic = pointmark(pc);
24148 id = pointmark(pd);
24149 ie = pointmark(pe);
24150 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic,
id, ie);
24151 assert(sign != 0.0);
24158 fc = categorizeface(*flipface);
24176 flip23(flipface, flipque);
24179 }
else if (fc == T32) {
24182 spintet = *flipface;
24183 for (i = 0; i < 2; i++) {
24184 fnextself(spintet);
24185 tspivot(spintet, checksh);
24186 if (checksh.sh != dummysh) {
24187 doflip =
false;
break;
24191 flip32(flipface, flipque);
24194 }
else if (fc == T22 || fc == T44) {
24198 for (i = 0; i < 2; i++) {
24199 spintet = *flipface;
24203 fnextself(spintet);
24204 tspivot(spintet, checksh);
24205 if (checksh.sh != dummysh) {
24206 doflip =
false;
break;
24209 }
else if (fc == T44) {
24210 spintet = *flipface;
24211 for (i = 0; i < 3; i++) {
24212 fnextself(spintet);
24213 tspivot(spintet, checksh);
24214 if (checksh.sh != dummysh) {
24215 doflip =
false;
break;
24220 flip22(flipface, flipque);
24223 }
else if (fc == N32) {
24225 if (front != (triface *) NULL) {
24227 spintet = *flipface;
24228 while (fnextself(spintet)) {
24229 if (apex(spintet) == apex(*flipface))
break;
24231 if (constrainedflip(&spintet, NULL, flipque)) {
24236 findedge(&spintet, org(*flipface), dest(*flipface));
24243 if (front != (triface *) NULL) {
24250 if (oppo(symface) != pc) {
24251 adjustedgering(symface, CCW);
24252 for (i = 0; i < 3; i++) {
24253 fnext(symface, spintet);
24255 sign = orient3d(org(spintet), dest(spintet), apex(spintet), pc);
24257 if (tritritest(&spintet, pa, pb, pc)) {
24258 if (b->verbose > 2) {
24259 printf(
" Next crossface (%d, %d, %d).\n",
24260 pointmark(org(spintet)), pointmark(dest(spintet)),
24261 pointmark(apex(spintet)));
24263 return constrainedflip(&spintet, front, flipque);
24267 enextself(symface);
24283 bool tetgenmesh::recoverfront(triface* front, list* newtetlist, queue* flipque)
24285 triface idfront, starttet, spintet;
24286 point pa, pb, pc, pd, ref;
24287 enum locateresult loc;
24288 enum finddirectionresult col;
24289 REAL ori, ori1, ori2, sign;
24294 for (i = 0; i < 3; i++) {
24298 idfront = recenttet;
24300 if (isdead(&idfront)) {
24302 for (j = 0; j < newtetlist->len(); j++) {
24303 recenttet = * (triface *)(* newtetlist)[j];
24304 if (!isdead(&recenttet))
break;
24306 assert(j < newtetlist->len());
24308 loc = preciselocate(pa, &idfront, (
long) newtetlist->len());
24309 if (loc != ONVERTEX) {
24311 for (j = 0; j < newtetlist->len(); j++) {
24312 idfront = * (triface *)(* newtetlist)[j];
24313 if (isdead(&idfront))
continue;
24314 if (findorg(&idfront, pa))
break;
24316 assert(j < newtetlist->len());
24318 recenttet = idfront;
24320 col = finddirection(&idfront, pb, (
long) newtetlist->len());
24321 if (col == BELOWHULL) {
24323 for (j = 0; j < newtetlist->len(); j++) {
24324 idfront = * (triface *)(* newtetlist)[j];
24325 if (isdead(&idfront))
continue;
24326 if (findorg(&idfront, pa)) {
24327 assert(org(idfront) == pa);
24328 if (dest(idfront) == pb) {
24329 col = RIGHTCOLLINEAR;
break;
24330 }
else if (apex(idfront) == pb) {
24331 col = LEFTCOLLINEAR;
break;
24332 }
else if (oppo(idfront) == pb) {
24333 col = TOPCOLLINEAR;
break;
24338 if (col == RIGHTCOLLINEAR) {
24340 }
else if (col == LEFTCOLLINEAR) {
24341 enext2self(idfront);
24343 }
else if (col == TOPCOLLINEAR) {
24344 fnextself(idfront);
24345 enext2self(idfront);
24348 if (dest(idfront) == pb)
break;
24362 if (apex(spintet) == pc) {
24364 insertauxsubface(front, &spintet);
24367 if (!fnextself(spintet)) {
24370 esym(idfront, spintet);
24371 if (!fnextself(spintet)) {
24376 if (apex(spintet) == apex(idfront))
break;
24377 }
while (hitbdry < 2);
24380 pd = apex(idfront);
24383 ori = orient3d(pa, pb, pc, pd);
24386 esym(idfront, starttet);
24388 }
else if (ori > 0.0) {
24390 starttet = idfront;
24393 assert(ori == 0.0);
24395 ref = oppo(idfront);
24396 ori1 = orient3d(pa, pb, ref, pc);
24397 ori2 = orient3d(pa, pb, ref, pd);
24398 assert(ori1 * ori2 != 0.0);
24399 if (ori1 * ori2 > 0) {
24402 ori1 = orient3d(pb, pc, ref, pd);
24403 ori2 = orient3d(pb, pc, ref, pa);
24404 assert(ori1 * ori2 != 0.0);
24405 if (ori1 * ori2 > 0) {
24407 enextself(idfront);
24410 enext2self(idfront);
24412 adjustedgering(idfront, CCW);
24413 fnextself(idfront);
24414 if (b->verbose > 2) {
24415 printf(
" Get crossface (%d, %d, %d).\n", pointmark(org(idfront)),
24416 pointmark(dest(idfront)), pointmark(apex(idfront)));
24418 if (constrainedflip(&idfront, front, flipque)) {
24420 return recoverfront(front, newtetlist, flipque);
24426 starttet = idfront;
24427 if (fnextself(starttet)) {
24432 esym(idfront, starttet);
24438 assert(sign != 0.0);
24441 pa = org(starttet);
24442 pb = dest(starttet);
24448 spintet = starttet;
24449 while (fnextself(spintet)) {
24450 pd = apex(spintet);
24453 ori = orient3d(pa, pb, pc, pd);
24456 ref = oppo(spintet);
24457 ori1 = orient3d(pb, pc, ref, pd);
24458 ori2 = orient3d(pb, pc, ref, pa);
24459 assert(ori1 * ori2 != 0.0);
24460 if (ori1 * ori2 > 0) {
24462 enextself(spintet);
24465 enext2self(spintet);
24467 adjustedgering(spintet, CCW);
24468 fnextself(spintet);
24469 if (b->verbose > 2) {
24470 printf(
" Get crossface (%d, %d, %d).\n", pointmark(org(spintet)),
24471 pointmark(dest(spintet)), pointmark(apex(spintet)));
24473 if (constrainedflip(&spintet, front, flipque)) {
24475 return recoverfront(front, newtetlist, flipque);
24479 }
else if (ori * sign < 0.0) {
24481 adjustedgering(spintet, CCW);
24482 enextself(spintet);
24483 for (i = 0; i < 2; i++) {
24485 fnext(spintet, starttet);
24486 if (tritritest(&starttet, pa, pb, pc)) {
24487 if (b->verbose > 2) {
24488 printf(
" Get crossface (%d, %d, %d).\n",
24489 pointmark(org(starttet)), pointmark(dest(starttet)),
24490 pointmark(apex(starttet)));
24492 if (constrainedflip(&starttet, front, flipque)) {
24494 return recoverfront(front, newtetlist, flipque);
24497 enextself(spintet);
24514 void tetgenmesh::repairflips(queue* flipque)
24517 triface flipface, symface, spintet;
24519 point pa, pb, pc, pd, pe;
24524 int ia, ib, ic, id, ie;
24527 if (b->verbose > 1) {
24528 printf(
" Repair flip %ld faces.\n", flipque->len());
24530 flipcount = flip23s + flip32s + flip22s + flip44s;
24532 while (!flipque->empty()) {
24533 qface = (badface *) flipque->pop();
24534 flipface = qface->tt;
24536 if (isdead(&flipface) || flipface.tet == dummytet ||
24537 (org(flipface) != qface->forg) ||
24538 (dest(flipface) != qface->fdest) ||
24539 (apex(flipface) != qface->fapex) ||
24540 (oppo(flipface) == (point) NULL))
continue;
24542 tspivot(flipface, checksh);
24543 if (checksh.sh != dummysh)
continue;
24545 sym(flipface, symface);
24546 if (symface.tet == dummytet)
continue;
24548 adjustedgering(flipface, CW);
24549 pa = org(flipface);
24550 pb = dest(flipface);
24551 pc = apex(flipface);
24552 pd = oppo(flipface);
24553 pe = oppo(symface);
24555 ia = pointmark(pa);
24556 ib = pointmark(pb);
24557 ic = pointmark(pc);
24558 id = pointmark(pd);
24559 ie = pointmark(pe);
24560 sign = insphere_sos(pa, pb, pc, pd, pe, ia, ib, ic,
id, ie);
24561 assert(sign != 0.0);
24568 fc = categorizeface(flipface);
24586 flip23(&flipface, flipque);
24588 }
else if (fc == T32) {
24591 spintet = flipface;
24592 for (i = 0; i < 2; i++) {
24593 fnextself(spintet);
24594 tspivot(spintet, checksh);
24595 if (checksh.sh != dummysh) {
24596 doflip =
false;
break;
24600 flip32(&flipface, flipque);
24602 }
else if (fc == T22 || fc == T44) {
24606 for (i = 0; i < 2; i++) {
24607 spintet = flipface;
24611 fnextself(spintet);
24612 tspivot(spintet, checksh);
24613 if (checksh.sh != dummysh) {
24614 doflip =
false;
break;
24617 }
else if (fc == T44) {
24618 spintet = flipface;
24619 for (i = 0; i < 3; i++) {
24620 fnextself(spintet);
24621 tspivot(spintet, checksh);
24622 if (checksh.sh != dummysh) {
24623 doflip =
false;
break;
24628 flip22(&flipface, flipque);
24633 flipcount = flip23s + flip32s + flip22s + flip44s - flipcount;
24634 if (b->verbose > 1) {
24635 printf(
" %ld flips.\n", flipcount);
24648 bool tetgenmesh::constrainedcavity(triface* oldtet, list* floorlist,
24649 list* ceillist, list* ptlist, list* frontlist, list* misfrontlist,
24650 list* newtetlist, queue* flipque)
24652 triface misfront, newtet;
24656 if (b->verbose > 1) {
24657 printf(
" Constrained cavity (%d floors, %d ceilings, %d vertices).\n",
24658 floorlist->len(), ceillist->len(), ptlist->len());
24664 initializecavity(floorlist, ceillist, frontlist);
24666 delaunizecavvertices(oldtet, ptlist, NULL, newtetlist, flipque);
24669 if (!identifyfronts(frontlist, misfrontlist, newtetlist)) {
24671 recenttet = * (triface *)(* newtetlist)[0];
24672 assert((recenttet.tet != dummytet) && !isdead(&recenttet));
24675 facenum = misfrontlist->len();
24676 for (i = 0; i < misfrontlist->len(); i++) {
24678 misfront = * (triface *)(* misfrontlist)[i];
24680 adjustedgering(misfront, CW);
24681 if (b->verbose > 1) {
24682 printf(
" Recover face (%d, %d, %d).\n", pointmark(org(misfront)),
24683 pointmark(dest(misfront)), pointmark(apex(misfront)));
24685 if (recoverfront(&misfront, newtetlist, flipque)) {
24687 frontlist->append(&misfront);
24688 misfrontlist->del(i, 0); i--;
24691 repairflips(flipque);
24694 if (misfrontlist->len() == 0)
break;
24697 }
while (misfrontlist->len() < facenum);
24699 retrievenewtets(newtetlist);
24704 if (misfrontlist->len() == 0) {
24708 carvecavity(newtetlist, misfrontlist, NULL);
24715 detachauxsubfaces(newtetlist);
24717 for (i = 0; i < newtetlist->len(); i++) {
24718 newtet = * (triface *)(* newtetlist)[i];
24719 assert(!isdead(&newtet));
24720 tetrahedrondealloc(newtet.tet);
24722 newtetlist->clear();
24724 for (i = 0; i < misfrontlist->len(); i++) {
24725 misfront = * (triface *)(* misfrontlist)[i];
24726 frontlist->append(&misfront);
24741 void tetgenmesh::expandsteinercavity(point steinpt, REAL eps, list* frontlist,
24744 triface front, symfront, newfront, oldfront;
24748 bool expflag, newflag;
24753 for (i = 0; i < frontlist->len(); i++) {
24755 front = * (triface *)(* frontlist)[i];
24757 tspivot(front, frontsh);
24758 if (frontsh.sh == dummysh) {
24760 adjustedgering(front, CW);
24764 ori = orient3d(pa, pb, pc, steinpt);
24766 if (iscoplanar(pa, pb, pc, steinpt, ori, eps)) {
24772 if (b->verbose > 2) {
24773 printf(
" Remove front (%d, %d, %d).\n", pointmark(pa),
24774 pointmark(pb), pointmark(pc));
24776 frontlist->del(i, 1);
24783 assert(!infected(front) && (oppo(front) != NULL));
24785 adjustedgering(front, CCW);
24786 for (i = 0; i < 3; i++) {
24789 fnext(front, symfront);
24790 tspivot(symfront, frontsh);
24791 sym(symfront, newfront);
24792 if (frontsh.sh == dummysh) {
24793 assert(newfront.tet != dummytet);
24795 if (infected(newfront)) {
24796 for (j = 0; j < frontlist->len(); j++) {
24797 oldfront = * (triface *)(* frontlist)[j];
24798 if ((oldfront.tet == symfront.tet) &&
24799 (oldfront.loc == symfront.loc)) {
24801 if (b->verbose > 2) {
24802 printf(
" Remove front (%d, %d, %d).\n",
24803 pointmark(org(oldfront)), pointmark(dest(oldfront)),
24804 pointmark(apex(oldfront)));
24806 frontlist->del(j, 1);
24814 if (newfront.tet == dummytet) {
24815 sesymself(frontsh);
24817 maketetrahedron(&newfront);
24818 setorg(newfront, sorg(frontsh));
24819 setdest(newfront, sdest(frontsh));
24820 setapex(newfront, sapex(frontsh));
24821 setoppo(newfront, (point) NULL);
24822 tsbond(newfront, frontsh);
24825 assert(!infected(newfront));
24829 if (b->verbose > 2) {
24830 printf(
" Add front (%d, %d, %d).\n", pointmark(org(newfront)),
24831 pointmark(dest(newfront)), pointmark(apex(newfront)));
24833 frontlist->append(&newfront);
24839 oldtetlist->append(&front);
24854 bool tetgenmesh::findrelocatepoint(point sp, point np, REAL* n,
24855 list* frontlist, list* oldtetlist)
24859 REAL tp[3], tvol, mvol;
24864 if (b->verbose > 1) {
24865 printf(
" Find new location for point %d.\n", pointmark(sp));
24874 for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24876 for (i = 0; i < 3; i++) tp[i] = np[i];
24880 for (i = 0; i < frontlist->len(); i++) {
24882 front = * (triface *)(* frontlist)[i];
24884 adjustedgering(front, CW);
24888 ori = orient3d(pa, pb, pc, np);
24889 visible = (ori < 0.0);
24892 for (i = 0; i < 3; i++) np[i] = sp[i] + 0.5 * (sp[i] - np[i]);
24894 if ((tp[0] == np[0]) && (tp[1] == np[1]) && (tp[2] == np[2])) {
24896 expandsteinercavity(sp, eps, frontlist, oldtetlist);
24898 if (eps > b->epsilon * 1000.0) {
24904 for (i = 0; i < 3; i++) np[i] = sp[i] + longest * n[i];
24908 for (i = 0; i < 3; i++) tp[i] = np[i];
24916 mvol = fabs(ori) < mvol ? fabs(ori) : mvol;
24921 }
while (!visible);
24923 if (b->verbose > 1) {
24924 printf(
" %d iterations. minvol = %.12g.\n", j, mvol);
24935 for (i = 0; i < 3; i++) tp[i] = sp[i] + 0.9 * (np[i] - sp[i]);
24938 for (i = 0; i < 3; i++) tp[i] = sp[i] + 1.1 * (np[i] - sp[i]);
24941 for (i = 0; i < frontlist->len(); i++) {
24943 front = * (triface *)(* frontlist)[i];
24945 adjustedgering(front, CW);
24949 ori = orient3d(pa, pb, pc, tp);
24950 visible = (ori < 0.0);
24956 tvol = fabs(ori) < tvol ? fabs(ori) : tvol;
24966 for (i = 0; i < 3; i++) np[i] = tp[i];
24981 if (b->verbose > 1) {
24982 printf(
" %d adjust iterations. minvol = %.12g.\n", j, mvol);
24997 void tetgenmesh::relocatepoint(point steinpt, triface* oldtet, list* frontlist,
24998 list* newtetlist, queue* flipque)
25000 triface front, newtet, newface, neightet;
25003 REAL attrib, volume;
25007 if (b->verbose > 1) {
25008 printf(
" Insert Steiner point (%.12g, %.12g, %.12g) %d.\n",
25009 steinpt[0], steinpt[1], steinpt[2], pointmark(steinpt));
25012 newtetlist->clear();
25015 for (i = 0; i < frontlist->len(); i++) {
25017 front = * (triface *)(* frontlist)[i];
25019 adjustedgering(front, CW);
25020 if (b->verbose > 2) {
25021 printf(
" Get front (%d, %d, %d).\n", pointmark(org(front)),
25022 pointmark(dest(front)), pointmark(apex(front)));
25024 maketetrahedron(&newtet);
25025 newtetlist->append(&newtet);
25026 setorg(newtet, org(front));
25027 setdest(newtet, dest(front));
25028 setapex(newtet, apex(front));
25029 setoppo(newtet, steinpt);
25030 if (oldtet != (triface *) NULL) {
25031 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
25032 attrib = elemattribute(oldtet->tet, j);
25033 setelemattribute(newtet.tet, j, attrib);
25035 if (b->varvolume) {
25036 volume = volumebound(oldtet->tet);
25037 setvolumebound(newtet.tet, volume);
25041 tspivot(front, checksh);
25042 if (oppo(front) == (point) NULL) {
25043 if (checksh.sh != dummysh) {
25044 stdissolve(checksh);
25047 tetrahedrondealloc(front.tet);
25051 dummytet[0] = encode(newtet);
25054 bond(newtet, front);
25056 if (checksh.sh != dummysh) {
25057 sesymself(checksh);
25058 tsbond(newtet, checksh);
25060 if (flipque != (queue *) NULL) {
25062 enqueueflipface(newtet, flipque);
25068 for (i = 0; i < newtetlist->len(); i++) {
25069 newtet = * (triface *)(* newtetlist)[i];
25071 for (j = 0; j < 3; j++) {
25072 fnext(newtet, newface);
25073 sym(newface, neightet);
25074 if (neightet.tet == dummytet) {
25078 pb = dest(newface);
25079 assert(apex(newface) == steinpt);
25080 for (k = i + 1; k < newtetlist->len() && !bdflag; k++) {
25081 neightet = * (triface *)(* newtetlist)[k];
25083 for (l = 0; l < 3; l++) {
25084 if ((org(neightet) == pa && dest(neightet) == pb) ||
25085 (org(neightet) == pb && dest(neightet) == pa)) {
25087 fnextself(neightet);
25088 assert(apex(neightet) == steinpt);
25090 bond(newface, neightet);
25094 enextself(neightet);
25103 setpoint2tet(pa, encode(newtet));
25105 setpoint2tet(pa, encode(newtet));
25107 setpoint2tet(pa, encode(newtet));
25109 setpoint2tet(pa, encode(newtet));
25112 if (flipque != (queue *) NULL) {
25114 flip(flipque, NULL);
25124 bool tetgenmesh::findcollapseedge(point suppt, point *conpt, list* oldtetlist,
25128 point pt, pa, pb, pc;
25129 REAL *lenarray, ltmp, ori;
25131 int *idxarray, itmp;
25134 if (b->verbose > 2) {
25135 printf(
" Search an edge (in %d edges) for collapse %d.\n",
25136 ptlist->len(), pointmark(suppt));
25141 lenarray =
new REAL[n];
25142 idxarray =
new int[n];
25144 for (i = 0; i < n; i++) {
25145 pt = * (point *)(* ptlist)[i];
25146 lenarray[i] = distance(suppt, pt);
25150 for (i = 0; i < n - 1; i++) {
25151 for (j = 0; j < n - 1 - i; j++) {
25152 if (lenarray[j + 1] < lenarray[j]) {
25153 ltmp = lenarray[j];
25154 lenarray[j] = lenarray[j + 1];
25155 lenarray[j + 1] = ltmp;
25156 itmp = idxarray[j];
25157 idxarray[j] = idxarray[j + 1];
25158 idxarray[j + 1] = itmp;
25163 for (i = 0; i < n; i++) {
25164 pt = * (point *)(* ptlist)[idxarray[i]];
25168 for (j = 0; j < oldtetlist->len() && visflag; j++) {
25169 front = * (triface *)(* oldtetlist)[j];
25171 adjustedgering(front, CCW);
25176 if ((pa != pt) && (pb != pt) && (pc != pt)) {
25177 ori = orient3d(pa, pb, pc, pt);
25179 if (iscoplanar(pa, pb, pc, pt, ori, b->epsilon * 1e+2)) ori = 0.0;
25181 visflag = ori < 0.0;
25185 lenarray[i] = fabs(ori);
25187 lenarray[i] = fabs(ori) < lenarray[i] ? fabs(ori) : lenarray[i];
25195 if ((b->verbose > 2) && visflag) {
25196 printf(
" Got candidate %d vol(%g).\n", pointmark(pt), lenarray[i]);
25201 ltmp = lenarray[0];
25202 itmp = idxarray[0];
25203 for (i = 1; i < n; i++) {
25204 if (lenarray[i] != 0.0) {
25205 if (lenarray[i] > ltmp) {
25206 ltmp = lenarray[i];
25207 itmp = idxarray[i];
25212 delete [] lenarray;
25213 delete [] idxarray;
25217 *conpt = (point) NULL;
25220 pt = * (point *)(* ptlist)[itmp];
25232 void tetgenmesh::collapseedge(point suppt, point conpt, list* oldtetlist,
25235 triface oldtet, deadtet;
25236 triface adjtet1, adjtet2;
25241 if (b->verbose > 2) {
25242 printf(
" Collapse edge (%d,%d).\n", pointmark(suppt), pointmark(conpt));
25246 for (i = 0; i < oldtetlist->len(); i++) {
25247 oldtet = * (triface *)(* oldtetlist)[i];
25252 assert(oppo(oldtet) == suppt);
25253 setoppo(oldtet, conpt);
25254 if ((pa == conpt) || (pb == conpt) || (pc == conpt)) {
25255 deadtetlist->append(&oldtet);
25259 for (i = 0; i < deadtetlist->len(); i++) {
25260 deadtet = * (triface *)(* deadtetlist)[i];
25262 sym(deadtet, adjtet1);
25263 tspivot(deadtet, adjsh);
25265 adjustedgering(deadtet, CCW);
25266 for (j = 0; j < 3; j++) {
25267 if (apex(deadtet) == conpt)
break;
25268 enextself(deadtet);
25272 fnext(deadtet, adjtet2);
25274 assert(adjtet2.tet != dummytet);
25275 if (adjtet1.tet != dummytet) {
25276 bond(adjtet1, adjtet2);
25279 dummytet[0] = encode(adjtet2);
25281 if (adjsh.sh != dummysh) {
25282 tsbond(adjtet2, adjsh);
25285 tetrahedrondealloc(deadtet.tet);
25287 deadtetlist->clear();
25300 void tetgenmesh::deallocfaketets(list* frontlist)
25302 triface front, neightet;
25307 for (i = 0; i < frontlist->len(); i++) {
25309 front = * (triface *)(* frontlist)[i];
25311 adjustedgering(front, CW);
25312 sym(front, neightet);
25313 tspivot(front, checksh);
25314 if (oppo(front) == (point) NULL) {
25315 if (b->verbose > 2) {
25316 printf(
" Get fake tet (%d, %d, %d).\n", pointmark(org(front)),
25317 pointmark(dest(front)), pointmark(apex(front)));
25319 if (neightet.tet != dummytet) {
25322 infectflag = infected(neightet);
25323 dissolve(neightet);
25328 if (checksh.sh != dummysh) {
25329 infectflag = sinfected(checksh);
25330 stdissolve(checksh);
25336 tetrahedrondealloc(front.tet);
25340 if (neightet.tet != dummytet) {
25341 dummytet[0] = encode(neightet);
25361 void tetgenmesh::restorepolyhedron(list* oldtetlist)
25363 triface oldtet, neightet, neineitet;
25367 for (i = 0; i < oldtetlist->len(); i++) {
25369 oldtet = * (triface *)(* oldtetlist)[i];
25371 for (oldtet.loc = 0; oldtet.loc < 4; oldtet.loc++) {
25372 sym(oldtet, neightet);
25373 tspivot(oldtet, checksh);
25374 if (neightet.tet != dummytet) {
25375 sym(neightet, neineitet);
25376 if (neineitet.tet != oldtet.tet) {
25378 bond(neightet, oldtet);
25379 if (checksh.sh != dummysh) {
25380 tsbond(oldtet, checksh);
25386 assert(checksh.sh != dummysh);
25387 stpivot(checksh, neineitet);
25388 assert(neineitet.tet != oldtet.tet);
25390 tsbond(oldtet, checksh);
25392 dummytet[0] = encode(oldtet);
25413 bool tetgenmesh::suppressfacetpoint(face* supsh, list* frontlist,
25414 list* misfrontlist, list* ptlist, list* conlist,
memorypool* viri,
25415 queue* flipque,
bool noreloc,
bool optflag)
25417 list *oldtetlist[2], *newtetlist[2];
25418 list *oldshlist, *newshlist;
25419 triface oldtet, newtet;
25421 point suppt, newpt[2];
25428 suppt = sapex(*supsh);
25429 if (b->verbose > 1) {
25430 printf(
" Suppress point %d in facet.\n", pointmark(suppt));
25434 for (i = 0; i < 2; i++) {
25435 oldtetlist[i] = (list *) NULL;
25436 newtetlist[i] = (list *) NULL;
25437 newpt[i] = (point) NULL;
25439 oldshlist =
new list(
sizeof(face), NULL, 256);
25440 newshlist =
new list(
sizeof(face), NULL, 256);
25444 oldshlist->append(supsh);
25445 formstarpolygon(suppt, oldshlist, ptlist);
25447 for (i = 0; i < oldshlist->len(); i++) {
25448 oldsh = * (face *)(* oldshlist)[i];
25449 cons = (point *) conlist->append(NULL);
25450 cons[0] = sorg(oldsh);
25451 cons[1] = sdest(oldsh);
25454 shmark = shellmark(*supsh);
25455 triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25457 retrievenewsubs(newshlist,
true);
25459 replacepolygonsubs(oldshlist, newshlist);
25468 for (i = 0; i < 2 && success; i++) {
25469 if (i == 1) sesymself(*supsh);
25471 stpivot(*supsh, oldtet);
25473 if (oldtet.tet == dummytet)
continue;
25475 oldtetlist[i] =
new list(
sizeof(triface), NULL, 256);
25476 newtetlist[i] =
new list(
sizeof(triface), NULL, 256);
25478 assert(!isdead(&oldtet));
25479 oldtetlist[i]->append(&oldtet);
25480 formstarpolyhedron(suppt, oldtetlist[i], ptlist,
false);
25482 for (j = 0; j < oldtetlist[i]->len(); j++) {
25483 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25487 orientnewsubs(newshlist, supsh, norm);
25489 success = constrainedcavity(&oldtet, newshlist, oldtetlist[i], ptlist,
25490 frontlist, misfrontlist, newtetlist[i], flipque);
25492 if (!success && !noreloc) {
25494 makepoint(&(newpt[i]));
25495 success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25503 relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25504 setpointtype(newpt[i], FREEVOLVERTEX);
25508 deallocfaketets(frontlist);
25509 pointdealloc(newpt[i]);
25510 newpt[i] = (point) NULL;
25511 assert(newtetlist[i]->len() == 0);
25514 if (!success && noreloc) {
25516 deallocfaketets(frontlist);
25520 frontlist->clear();
25521 misfrontlist->clear();
25527 setpointtype(suppt, UNUSEDVERTEX);
25530 for (i = 0; i < oldshlist->len(); i++) {
25531 oldsh = * (face *)(* oldshlist)[i];
25534 stpivot(oldsh, oldtet);
25535 if (oldtet.tet != dummytet) {
25537 stpivot(oldsh, oldtet);
25539 if (oldtet.tet == dummytet) {
25541 j = oldshlist->len() - newshlist->len();
25546 shellfacedealloc(subfaces, oldsh.sh);
25549 for (i = 0; i < 2; i++) {
25550 if (oldtetlist[i] != (list *) NULL) {
25552 for (j = 0; j < oldtetlist[i]->len(); j++) {
25553 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25554 assert(!isdead(&oldtet));
25555 tetrahedrondealloc(oldtet.tet);
25561 for (i = 0; i < 2; i++) {
25562 if (newtetlist[i] != (list *) NULL) {
25563 for (j = 0; j < newtetlist[i]->len(); j++) {
25564 newtet = * (triface *)(* (newtetlist[i]))[j];
25565 if (!isdead(&newtet)) checktet4opt(&newtet,
true);
25574 replacepolygonsubs(newshlist, oldshlist);
25576 for (i = 0; i < newshlist->len(); i++) {
25577 newsh = * (face *)(* newshlist)[i];
25578 shellfacedealloc(subfaces, newsh.sh);
25581 for (i = 0; i < 2; i++) {
25582 if (oldtetlist[i] != (list *) NULL) {
25584 for (j = 0; j < oldtetlist[i]->len(); j++) {
25585 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25586 assert(infected(oldtet));
25590 if (newtetlist[i]->len() > 0) {
25592 restorepolyhedron(oldtetlist[i]);
25594 for (j = 0; j < newtetlist[i]->len(); j++) {
25595 newtet = * (triface *)(* (newtetlist[i]))[j];
25597 if (!isdead(&newtet)) {
25598 tetrahedrondealloc(newtet.tet);
25603 if (newpt[i] != (point) NULL) {
25604 pointdealloc(newpt[i]);
25614 for (i = 0; i < 2; i++) {
25615 if (oldtetlist[i] != (list *) NULL) {
25616 delete oldtetlist[i];
25617 delete newtetlist[i];
25636 bool tetgenmesh::suppresssegpoint(face* supseg, list* spinshlist,
25637 list* newsegshlist, list* frontlist, list* misfrontlist, list* ptlist,
25638 list* conlist,
memorypool* viri, queue* flipque,
bool noreloc,
bool optflag)
25640 list **oldtetlist, **newtetlist;
25641 list **oldshlist, **newshlist;
25642 list *pnewshlist, *dnewshlist;
25643 triface oldtet, newtet;
25645 face startsh, spinsh, segsh1, segsh2;
25646 face nsupseg, newseg, prevseg, nextseg;
25647 point suppt, *newpt;
25648 point pa, pb, *cons;
25649 REAL pnorm[2][3], norm[3];
25655 assert(supseg->shver < 2);
25656 suppt = sdest(*supseg);
25658 senext(*supseg, nsupseg);
25659 spivotself(nsupseg);
25660 assert(nsupseg.sh != dummysh);
25662 if (sorg(nsupseg) != suppt) sesymself(nsupseg);
25663 assert(sorg(nsupseg) == suppt);
25664 pa = sorg(*supseg);
25665 pb = sdest(nsupseg);
25666 if (b->verbose > 1) {
25667 printf(
" Remove point %d on segment (%d, %d).\n",
25668 pointmark(suppt), pointmark(pa), pointmark(pb));
25672 spivot(*supseg, startsh);
25676 spinshlist->append(&spinsh);
25678 spivotself(spinsh);
25679 }
while (spinsh.sh != startsh.sh);
25680 if (spinshlist->len() == 1) {
25683 spinshlist->clear();
25690 n = spinshlist->len();
25691 oldtetlist =
new list*[n];
25692 newtetlist =
new list*[n];
25693 oldshlist =
new list*[n];
25694 newshlist =
new list*[n];
25695 newpt =
new point[n];
25696 for (i = 0; i < n; i++) {
25697 oldtetlist[i] = (list *) NULL;
25698 newtetlist[i] = (list *) NULL;
25699 oldshlist[i] = (list *) NULL;
25700 newshlist[i] = (list *) NULL;
25701 newpt[i] = (point) NULL;
25705 makeshellface(subsegs, &newseg);
25706 setsorg(newseg, pa);
25707 setsdest(newseg, pb);
25709 setshellmark(newseg, shellmark(*supseg));
25710 setshelltype(newseg, shelltype(*supseg));
25711 if (b->quality && varconstraint) {
25713 setareabound(newseg, areabound(*supseg));
25716 senext2(*supseg, prevseg);
25717 spivotself(prevseg);
25718 if (prevseg.sh != dummysh) {
25720 if (sdest(prevseg) != pa) sesymself(prevseg);
25721 assert(sdest(prevseg) == pa);
25722 senextself(prevseg);
25723 senext2self(newseg);
25724 sbond(newseg, prevseg);
25728 senext(nsupseg, nextseg);
25729 spivotself(nextseg);
25730 if (nextseg.sh != dummysh) {
25732 if (sorg(nextseg) != pb) sesymself(nextseg);
25733 assert(sorg(nextseg) == pb);
25734 senext2self(nextseg);
25735 senextself(newseg);
25736 sbond(newseg, nextseg);
25741 for (i = 0; i < spinshlist->len(); i++) {
25742 spinsh = * (face *)(* spinshlist)[i];
25744 oldshlist[i] =
new list(
sizeof(face), NULL, 256);
25745 newshlist[i] =
new list(
sizeof(face), NULL, 256);
25747 oldshlist[i]->append(&spinsh);
25748 formstarpolygon(suppt, oldshlist[i], ptlist);
25750 for (j = 0; j < oldshlist[i]->len(); j++) {
25751 oldsh = * (face *)(* (oldshlist[i]))[j];
25752 cons = (point *) conlist->append(NULL);
25753 cons[0] = sorg(oldsh);
25754 cons[1] = sdest(oldsh);
25757 cons = (point *) conlist->append(NULL);
25761 shmark = shellmark(spinsh);
25762 triangulate(shmark, b->epsilon, ptlist, conlist, 0, NULL, viri, flipque);
25764 retrievenewsubs(newshlist[i],
true);
25766 replacepolygonsubs(oldshlist[i], newshlist[i]);
25768 for (j = 0; j < newshlist[i]->len(); j++) {
25769 segsh1 = * (face *)(* (newshlist[i]))[j];
25770 for (k = 0; k < 3; k++) {
25771 if (((sorg(segsh1) == pa) && (sdest(segsh1) == pb)) ||
25772 ((sorg(segsh1) == pb) && (sdest(segsh1) == pa)))
break;
25773 senextself(segsh1);
25777 assert(j < newshlist[i]->len());
25779 ssbond(segsh1, newseg);
25781 newsegshlist->append(&segsh1);
25789 for (i = 0; i < newsegshlist->len(); i++) {
25790 segsh1 = * (face *)(* newsegshlist)[i];
25791 if ((i + 1) == newsegshlist->len()) {
25792 segsh2 = * (face *)(* newsegshlist)[0];
25794 segsh2 = * (face *)(* newsegshlist)[i + 1];
25796 sbond1(segsh1, segsh2);
25800 dnewshlist =
new list(
sizeof(face), NULL, 256);
25804 for (i = 0; i < spinshlist->len() && success; i++) {
25806 spinsh = * (face *)(* spinshlist)[i];
25809 if (sorg(spinsh) != pa) sesymself(spinsh);
25811 stpivot(spinsh, oldtet);
25813 if (oldtet.tet == dummytet)
continue;
25815 oldtetlist[i] =
new list(
sizeof(triface), NULL, 256);
25816 newtetlist[i] =
new list(
sizeof(triface), NULL, 256);
25818 oldtetlist[i]->append(&oldtet);
25819 formstarpolyhedron(suppt, oldtetlist[i], ptlist,
false);
25821 for (j = 0; j < oldtetlist[i]->len(); j++) {
25822 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25826 for (k = 0; k < 2; k++) {
25827 if ((i + k) < spinshlist->len()) {
25828 pnewshlist = newshlist[i + k];
25829 segsh1 = * (face *)(* spinshlist)[i + k];
25831 pnewshlist = newshlist[0];
25832 segsh1 = * (face *)(* spinshlist)[0];
25836 if (sorg(segsh1) != pa) sesymself(segsh1);
25837 assert(sorg(segsh1) == pa);
25839 if (sdest(segsh1) != pa) sesymself(segsh1);
25840 assert(sdest(segsh1) == pa);
25843 orientnewsubs(pnewshlist, &segsh1, pnorm[k]);
25844 for (j = 0; j < pnewshlist->len(); j++) {
25845 dnewshlist->append((face *)(* pnewshlist)[j]);
25849 success = constrainedcavity(&oldtet, dnewshlist, oldtetlist[i], ptlist,
25850 frontlist, misfrontlist, newtetlist[i], flipque);
25851 if (!success && !noreloc) {
25853 makepoint(&(newpt[i]));
25854 for (j = 0; j < 3; j++) norm[j] = 0.5 * (pnorm[0][j] + pnorm[1][j]);
25855 success = findrelocatepoint(suppt, newpt[i], norm, frontlist,
25862 relocatepoint(newpt[i], &oldtet, frontlist, newtetlist[i], NULL);
25863 setpointtype(newpt[i], FREEVOLVERTEX);
25867 deallocfaketets(frontlist);
25868 pointdealloc(newpt[i]);
25869 newpt[i] = (point) NULL;
25870 assert(newtetlist[i]->len() == 0);
25873 if (!success && noreloc) {
25875 deallocfaketets(frontlist);
25878 dnewshlist->clear();
25880 frontlist->clear();
25881 misfrontlist->clear();
25887 setpointtype(suppt, UNUSEDVERTEX);
25890 setpoint2sh(pa, sencode(newseg));
25891 setpoint2sh(pb, sencode(newseg));
25893 shellfacedealloc(subsegs, supseg->sh);
25894 shellfacedealloc(subsegs, nsupseg.sh);
25896 for (i = 0; i < spinshlist->len(); i++) {
25897 for (j = 0; j < oldshlist[i]->len(); j++) {
25898 oldsh = * (face *)(* (oldshlist[i]))[j];
25901 stpivot(oldsh, oldtet);
25902 if (oldtet.tet != dummytet) {
25904 stpivot(oldsh, oldtet);
25906 if (oldtet.tet == dummytet) {
25908 k = oldshlist[i]->len() - newshlist[i]->len();
25913 shellfacedealloc(subfaces, oldsh.sh);
25917 for (i = 0; i < spinshlist->len(); i++) {
25919 if (oldtetlist[i] != (list *) NULL) {
25920 for (j = 0; j < oldtetlist[i]->len(); j++) {
25921 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25922 assert(!isdead(&oldtet));
25923 tetrahedrondealloc(oldtet.tet);
25928 for (i = 0; i < spinshlist->len(); i++) {
25930 if (newtetlist[i] != (list *) NULL) {
25931 for (j = 0; j < newtetlist[i]->len(); j++) {
25932 newtet = * (triface *)(* (newtetlist[i]))[j];
25933 if (!isdead(&newtet)) checktet4opt(&newtet,
true);
25942 senext2(*supseg, prevseg);
25943 spivotself(prevseg);
25944 if (prevseg.sh != dummysh) {
25946 if (sdest(prevseg) != pa) sesymself(prevseg);
25947 assert(sdest(prevseg) == pa);
25948 senextself(prevseg);
25949 senext2self(*supseg);
25950 sbond(*supseg, prevseg);
25951 senextself(*supseg);
25952 assert(supseg->shver < 2);
25955 senext(nsupseg, nextseg);
25956 spivotself(nextseg);
25957 if (nextseg.sh != dummysh) {
25959 if (sorg(nextseg) != pb) sesymself(nextseg);
25960 assert(sorg(nextseg) == pb);
25961 senext2self(nextseg);
25962 senextself(nsupseg);
25963 sbond(nsupseg, nextseg);
25965 senext2self(nsupseg);
25966 assert(nsupseg.shver < 2);
25969 shellfacedealloc(subsegs, newseg.sh);
25971 for (i = 0; i < spinshlist->len(); i++) {
25972 replacepolygonsubs(newshlist[i], oldshlist[i]);
25974 for (j = 0; j < newshlist[i]->len(); j++) {
25975 newsh = * (face *)(* (newshlist[i]))[j];
25976 shellfacedealloc(subfaces, newsh.sh);
25980 for (i = 0; i < spinshlist->len(); i++) {
25981 if (oldtetlist[i] != (list *) NULL) {
25983 for (j = 0; j < oldtetlist[i]->len(); j++) {
25984 oldtet = * (triface *)(* (oldtetlist[i]))[j];
25985 assert(infected(oldtet));
25989 if (newtetlist[i]->len() > 0) {
25991 restorepolyhedron(oldtetlist[i]);
25993 for (j = 0; j < newtetlist[i]->len(); j++) {
25994 newtet = * (triface *)(* (newtetlist[i]))[j];
25996 if (!isdead(&newtet)) {
25997 tetrahedrondealloc(newtet.tet);
26002 if (newpt[i] != (point) NULL) {
26003 pointdealloc(newpt[i]);
26012 for (i = 0; i < spinshlist->len(); i++) {
26013 delete oldshlist[i];
26014 delete newshlist[i];
26016 delete [] oldshlist;
26017 delete [] newshlist;
26018 for (i = 0; i < spinshlist->len(); i++) {
26019 if (oldtetlist[i] != (list *) NULL) {
26020 delete oldtetlist[i];
26021 delete newtetlist[i];
26024 delete [] oldtetlist;
26025 delete [] newtetlist;
26027 newsegshlist->clear();
26028 spinshlist->clear();
26045 bool tetgenmesh::suppressvolpoint(triface* suptet, list* frontlist,
26046 list* misfrontlist, list* ptlist, queue* flipque,
bool optflag)
26048 list *myfrontlist, *mymisfrontlist, *myptlist;
26049 list *oldtetlist, *newtetlist;
26052 triface oldtet, newtet;
26053 point suppt, conpt;
26058 oldtetlist =
new list(
sizeof(triface), NULL, 256);
26059 newtetlist =
new list(
sizeof(triface), NULL, 256);
26060 newshlist =
new list(
sizeof(face), NULL, 256);
26062 myfrontlist = mymisfrontlist = myptlist = (list *) NULL;
26063 myflipque = (queue *) NULL;
26064 if (frontlist == (list *) NULL) {
26065 myfrontlist =
new list(
sizeof(triface), NULL, 256);
26066 frontlist = myfrontlist;
26067 mymisfrontlist =
new list(
sizeof(triface), NULL, 256);
26068 misfrontlist = mymisfrontlist;
26069 myptlist =
new list(
sizeof(point *), NULL, 256);
26071 myflipque =
new queue(
sizeof(badface));
26072 flipque = myflipque;
26075 suppt = org(*suptet);
26079 if (b->verbose > 1) {
26080 printf(
" Remove point %d in mesh.\n", pointmark(suppt));
26084 oldtetlist->append(&oldtet);
26085 formstarpolyhedron(suppt, oldtetlist, ptlist,
false);
26087 for (j = 0; j < oldtetlist->len(); j++) {
26088 oldtet = * (triface *)(* oldtetlist)[j];
26092 success = constrainedcavity(&oldtet, newshlist, oldtetlist, ptlist,
26093 frontlist, misfrontlist, newtetlist, flipque);
26096 deallocfaketets(frontlist);
26098 conpt = (point) NULL;
26099 assert(newtetlist->len() == 0);
26100 if (findcollapseedge(suppt, &conpt, oldtetlist, ptlist)) {
26102 collapseedge(suppt, conpt, oldtetlist, newtetlist);
26105 assert(newtetlist->len() == 0);
26106 for (j = 0; j < oldtetlist->len(); j++) {
26107 newtet = * (triface *)(* oldtetlist)[j];
26108 newtetlist->append(&newtet);
26111 oldtetlist->clear();
26118 setpointtype(suppt, UNUSEDVERTEX);
26122 for (j = 0; j < oldtetlist->len(); j++) {
26123 oldtet = * (triface *)(* oldtetlist)[j];
26124 assert(!isdead(&oldtet));
26125 tetrahedrondealloc(oldtet.tet);
26129 for (j = 0; j < newtetlist->len(); j++) {
26130 newtet = * (triface *)(* newtetlist)[j];
26131 if (!isdead(&newtet)) checktet4opt(&newtet,
true);
26137 for (j = 0; j < oldtetlist->len(); j++) {
26138 oldtet = * (triface *)(* oldtetlist)[j];
26139 assert(infected(oldtet));
26146 frontlist->clear();
26147 misfrontlist->clear();
26150 if (myfrontlist != (list *) NULL) {
26151 delete myfrontlist;
26152 delete mymisfrontlist;
26180 bool tetgenmesh::smoothpoint(point smthpt, point e1, point e2, list *starlist,
26181 bool invtori, REAL *key)
26185 REAL fcent[3], startpt[3], nextpt[3], bestpt[3];
26186 REAL iniTmax, oldTmax, newTmax;
26187 REAL ori, aspT, aspTmax, imprate;
26188 REAL cosd, maxcosd;
26189 bool segflag, randflag;
26194 segflag = (e1 != (point) NULL);
26196 numdirs = segflag ? 2 : starlist->len();
26197 randflag = numdirs > 10;
26204 for (i = 0; i < starlist->len(); i++) {
26205 starttet = * (triface *)(* starlist)[i];
26206 adjustedgering(starttet, !invtori ? CCW : CW);
26207 pa = org(starttet);
26208 pb = dest(starttet);
26209 pc = apex(starttet);
26210 aspT = tetaspectratio(pa, pb, pc, smthpt);
26214 aspTmax = aspT > aspTmax ? aspT : aspTmax;
26219 if (b->verbose > 1) {
26220 printf(
" Smooth %s point %d (%g, %g, %g).\n", segflag ?
"seg" :
"vol",
26221 pointmark(smthpt), smthpt[0], smthpt[1], smthpt[2]);
26222 printf(
" Initial max L/h = %g.\n", iniTmax);
26224 for (i = 0; i < 3; i++) {
26225 bestpt[i] = startpt[i] = smthpt[i];
26234 for (i = 0; i < numdirs; i++) {
26239 j = (int) randomnation(starlist->len());
26243 starttet = * (triface *)(* starlist)[j];
26244 adjustedgering(starttet, !invtori ? CCW : CW);
26245 pa = org(starttet);
26246 pb = dest(starttet);
26247 pc = apex(starttet);
26248 for (j = 0; j < 3; j++) {
26249 fcent[j] = (pa[j] + pb[j] + pc[j]) / 3.0;
26252 for (j = 0; j < 3; j++) {
26253 fcent[j] = (i == 0 ? e1[j] : e2[j]);
26256 for (j = 0; j < 3; j++) {
26257 nextpt[j] = startpt[j] + 0.01 * (fcent[j] - startpt[j]);
26260 for (j = 0; j < starlist->len(); j++) {
26261 starttet = * (triface *)(* starlist)[j];
26262 adjustedgering(starttet, !invtori ? CCW : CW);
26263 pa = org(starttet);
26264 pb = dest(starttet);
26265 pc = apex(starttet);
26266 ori = orient3d(pa, pb, pc, nextpt);
26268 aspT = tetaspectratio(pa, pb, pc, nextpt);
26272 aspTmax = aspT > aspTmax ? aspT : aspTmax;
26279 if (aspTmax >= newTmax)
break;
26281 if (aspTmax < newTmax) {
26284 for (j = 0; j < 3; j++) bestpt[j] = nextpt[j];
26288 imprate = fabs(oldTmax - newTmax) / oldTmax;
26289 if (imprate < 1e-3)
break;
26291 for (j = 0; j < 3; j++) startpt[j] = bestpt[j];
26300 for (j = 0; j < starlist->len(); j++) {
26301 starttet = * (triface *)(* starlist)[j];
26302 adjustedgering(starttet, !invtori ? CCW : CW);
26303 pa = org(starttet);
26304 pb = dest(starttet);
26305 pc = apex(starttet);
26306 tetalldihedral(pa, pb, pc, startpt, NULL, &cosd, NULL);
26312 maxcosd = maxcosd < cosd ? maxcosd : cosd;
26315 if (iter > 0) *key = maxcosd;
26320 segflag ? smoothsegverts++ : smoothvolverts++;
26321 for (i = 0; i < 3; i++) smthpt[i] = startpt[i];
26322 if (b->verbose > 1) {
26323 printf(
" Move to new location (%g, %g, %g).\n", smthpt[0], smthpt[1],
26325 printf(
" Final max L/h = %g. (%d iterations)\n", newTmax, iter);
26327 printf(
" Max. dihed = %g (degree).\n", acos(*key) / PI * 180.0);
26332 if (b->verbose > 1) {
26333 printf(
" Not smoothed.\n");
26345 void tetgenmesh::removesteiners(
bool coarseflag)
26347 list *frontlist, *misfrontlist;
26348 list *spinshlist, *newsegshlist;
26349 list *ptlist, *conlist;
26354 face segloop, nextseg;
26359 int oldnum, rmstein;
26364 printf(
"Removing Steiner points.\n");
26366 printf(
"Coarsening mesh.\n");
26371 frontlist =
new list(
sizeof(triface), NULL);
26372 misfrontlist =
new list(
sizeof(triface), NULL);
26373 spinshlist =
new list(
sizeof(face), NULL);
26374 newsegshlist =
new list(
sizeof(face), NULL);
26375 ptlist =
new list(
sizeof(point *), NULL);
26376 conlist =
new list(
sizeof(point *) * 2, NULL);
26377 flipque =
new queue(
sizeof(badface));
26378 viri =
new memorypool(
sizeof(shellface *), 1024, POINTER, 0);
26380 relverts = suprelverts = collapverts = unsupverts;
26381 smoothvolverts = 0;
26386 rmstein = unuverts;
26387 subfaces->traversalinit();
26388 shloop.sh = shellfacetraverse(subfaces);
26389 while (shloop.sh != (shellface *) NULL) {
26393 for (i = 0; i < 3; i++) {
26394 pa = sapex(shloop);
26395 if (pointtype(pa) == FREESUBVERTEX) {
26398 j = pointmark(pa) - in->firstnumber;
26399 if (j >= in->numberofpoints) {
26400 if (b->nobisect == 1) {
26402 stpivot(shloop, checktet);
26403 if (checktet.tet != dummytet) {
26405 stpivot(shloop, checktet);
26407 remflag = (checktet.tet == dummytet);
26415 if (b->nobisect == 0) {
26420 spinshlist->append(&shloop);
26421 formstarpolygon(pa, spinshlist, ptlist);
26423 for (j = 0; j < ptlist->len(); j++) {
26424 neipt = * (point *)(* ptlist)[j];
26425 len += distance(pa, neipt);
26427 len /= ptlist->len();
26429 remflag = len < pa[pointmtrindex];
26430 spinshlist->clear();
26436 j = pointmark(pa) - in->firstnumber;
26437 if (j < in->numberofpoints) {
26438 remflag = (in->pointmarkerlist[j] == 0);
26443 if (remflag)
break;
26445 senextself(shloop);
26448 suppressfacetpoint(&shloop, frontlist, misfrontlist, ptlist, conlist,
26449 viri, flipque, coarseflag,
false);
26451 shloop.sh = shellfacetraverse(subfaces);
26454 }
while (unuverts > rmstein);
26457 shellface **segsperverlist;
26463 makesegmentmap(idx2seglist, segsperverlist);
26464 subsegs->traversalinit();
26465 segloop.sh = shellfacetraverse(subsegs);
26466 while (segloop.sh != (shellface *) NULL) {
26467 for (i = 0; i < 2; i++) {
26469 senext(segloop, nextseg);
26470 spivotself(nextseg);
26471 if ((nextseg.sh == dummysh) || (nextseg.sh > segloop.sh)) {
26473 pa = sdest(segloop);
26474 j = pointmark(pa) - in->firstnumber;
26475 if (idx2seglist[j + 1] - idx2seglist[j] == 2) {
26477 nextseg.sh = segsperverlist[idx2seglist[j]];
26478 if (nextseg.sh == segloop.sh) {
26479 nextseg.sh = segsperverlist[idx2seglist[j] + 1];
26482 if (sorg(nextseg) != pa) sesymself(nextseg);
26484 e1 = sorg(segloop);
26485 e2 = sdest(nextseg);
26486 if (iscollinear(e1, pa, e2, b->epsilon)) {
26488 if (b->verbose > 1) {
26489 printf(
" Glue two insegs (%d, %d) at %d.\n", pointmark(e1),
26490 pointmark(e2), pointmark(pa));
26492 senext(segloop, seg1);
26493 senext2(nextseg, seg2);
26499 segloop.sh = shellfacetraverse(subsegs);
26501 delete [] segsperverlist;
26502 delete [] idx2seglist;
26507 rmstein = unuverts;
26508 subsegs->traversalinit();
26509 segloop.sh = shellfacetraverse(subsegs);
26510 while (segloop.sh != (shellface *) NULL) {
26516 senext(segloop, nextseg);
26517 spivotself(nextseg);
26518 if (nextseg.sh != dummysh) {
26519 pa = sdest(segloop);
26521 if (sorg(nextseg) != pa) sesymself(nextseg);
26522 assert(sorg(nextseg) == pa);
26525 j = pointmark(pa) - in->firstnumber;
26526 if (j >= in->numberofpoints) {
26527 if (b->nobisect == 1) {
26529 sstpivot(&segloop, &checktet);
26530 assert(checktet.tet != dummytet);
26531 pa = apex(checktet);
26533 if (!fnextself(checktet)) {
26535 remflag =
true;
break;
26537 }
while (pa != apex(checktet));
26545 if (b->nobisect == 0) {
26549 neipt = sorg(segloop);
26550 for (j = 0; j < 2; j++) {
26551 len += distance(pa, neipt);
26557 neipt = sdest(nextseg);
26561 remflag = len < pa[pointmtrindex];
26566 j = pointmark(pa) - in->firstnumber;
26567 if (j < in->numberofpoints) {
26568 remflag = (in->pointmarkerlist[j] == 0);
26577 suppresssegpoint(&segloop, spinshlist, newsegshlist, frontlist,
26578 misfrontlist, ptlist, conlist, viri, flipque, coarseflag,
false);
26580 segloop.sh = shellfacetraverse(subsegs);
26583 }
while (unuverts > rmstein);
26585 if ((relverts > 0) || coarseflag) {
26586 worklist =
new int[points->items + 1];
26591 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26592 rmstein = unuverts;
26593 tetrahedrons->traversalinit();
26594 checktet.tet = tetrahedrontraverse();
26595 while (checktet.tet != (tetrahedron *) NULL) {
26597 for (i = 0; i < 4; i++) {
26598 pa = (point) checktet.tet[4 + i];
26599 if (pointtype(pa) == FREEVOLVERTEX) {
26606 if (worklist[pointmark(pa)] < 3) {
26607 worklist[pointmark(pa)]++;
26610 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26617 frontlist->append(&checktet);
26618 formstarpolyhedron(pa, frontlist, ptlist,
true);
26620 for (j = 0; j < ptlist->len(); j++) {
26621 neipt = * (point *)(* ptlist)[j];
26622 len += distance(pa, neipt);
26624 len /= ptlist->len();
26626 remflag = len < pa[pointmtrindex];
26627 frontlist->clear();
26633 j = pointmark(pa) - in->firstnumber;
26634 if (j < in->numberofpoints) {
26635 remflag = (in->pointmarkerlist[j] == 0);
26639 if (remflag)
break;
26644 findorg(&checktet, pa);
26645 assert(org(checktet) == pa);
26646 suppressvolpoint(&checktet, frontlist, misfrontlist, ptlist, flipque,
26649 checktet.tet = tetrahedrontraverse();
26652 }
while (unuverts > rmstein);
26656 if (!coarseflag && (relverts > suprelverts)) {
26658 printf(
" Smoothing relocated points.\n");
26660 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
26661 tetrahedrons->traversalinit();
26662 checktet.tet = tetrahedrontraverse();
26663 while (checktet.tet != (tetrahedron *) NULL) {
26664 for (i = 0; i < 4; i++) {
26665 pa = (point) checktet.tet[4 + i];
26666 if (pointtype(pa) == FREEVOLVERTEX) {
26667 if (worklist[pointmark(pa)] == 0) {
26668 worklist[pointmark(pa)] = 1;
26669 if (pointmark(pa) >= (in->numberofpoints + in->firstnumber)) {
26671 findorg(&checktet, pa);
26672 frontlist->append(&checktet);
26673 formstarpolyhedron(pa, frontlist, NULL,
false);
26674 smoothpoint(pa, NULL, NULL, frontlist,
false, NULL);
26675 frontlist->clear();
26680 checktet.tet = tetrahedrontraverse();
26683 delete [] worklist;
26686 if (b->verbose > 0) {
26688 printf(
" %d points removed from boundary", unuverts - oldnum);
26689 if (expcavcount > 0) {
26690 printf(
" (%d cavity corrections)", expcavcount);
26693 if (relverts > 0) {
26694 printf(
" %d points relocated (%d suppressed, %d collapsed).\n",
26695 relverts, suprelverts - collapverts, collapverts);
26696 if (smoothvolverts > 0) {
26697 printf(
" %d points are smoothed.\n", smoothvolverts);
26700 if (unsupverts > 0) {
26701 printf(
" !! %d points are unsuppressed.\n", unsupverts);
26704 printf(
" %d points are removed.\n", unuverts - oldnum);
26710 delete misfrontlist;
26712 delete newsegshlist;
26760 long tetgenmesh::reconstructmesh()
26762 tetrahedron **tetsperverlist;
26763 shellface **facesperverlist;
26764 triface tetloop, neightet, neineightet, spintet;
26765 face subloop, neighsh, neineighsh, subseg;
26766 face sface1, sface2;
26767 point *idx2verlist;
26768 point torg, tdest, tapex, toppo;
26769 point norg, ndest, napex;
26770 list *neighshlist, *markerlist;
26771 REAL sign, attrib, volume;
26773 bool bondflag, insertsegflag;
26777 int facetidx, marker;
26778 int iorg, idest, iapex, ioppo;
26779 int inorg, indest, inapex;
26783 printf(
"Reconstructing mesh.\n");
26787 makeindex2pointmap(idx2verlist);
26790 for (i = 0; i < in->numberoftetrahedra; i++) {
26793 maketetrahedron(&tetloop);
26794 index = i * in->numberofcorners;
26796 iorg = in->tetrahedronlist[index] - in->firstnumber;
26797 idest = in->tetrahedronlist[index + 1] - in->firstnumber;
26798 iapex = in->tetrahedronlist[index + 2] - in->firstnumber;
26799 ioppo = in->tetrahedronlist[index + 3] - in->firstnumber;
26800 torg = idx2verlist[iorg];
26801 tdest = idx2verlist[idest];
26802 tapex = idx2verlist[iapex];
26803 toppo = idx2verlist[ioppo];
26804 sign = orient3d(torg, tdest, tapex, toppo);
26806 norg = torg; torg = tdest; tdest = norg;
26807 }
else if (sign == 0.0) {
26809 printf(
"Warning: Tet %d is degenerate.\n", i + in->firstnumber);
26812 setorg(tetloop, torg);
26813 setdest(tetloop, tdest);
26814 setapex(tetloop, tapex);
26815 setoppo(tetloop, toppo);
26818 setpointtype(torg, FREEVOLVERTEX);
26819 setpointtype(tdest, FREEVOLVERTEX);
26820 setpointtype(tapex, FREEVOLVERTEX);
26821 setpointtype(toppo, FREEVOLVERTEX);
26823 for (j = 0; j < in->numberoftetrahedronattributes; j++) {
26824 index = i * in->numberoftetrahedronattributes;
26825 attrib = in->tetrahedronattributelist[index + j];
26826 setelemattribute(tetloop.tet, j, attrib);
26830 if (b->varvolume) {
26831 if (in->tetrahedronvolumelist != (REAL *) NULL) {
26832 volume = in->tetrahedronvolumelist[i];
26836 setvolumebound(tetloop.tet, volume);
26843 maketetrahedronmap(idx2tetlist, tetsperverlist);
26845 worklist =
new int[points->items];
26846 for (i = 0; i < points->items; i++) worklist[i] = 0;
26849 tetrahedrons->traversalinit();
26850 tetloop.tet = tetrahedrontraverse();
26851 while (tetloop.tet != (tetrahedron *) NULL) {
26853 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26854 sym(tetloop, neightet);
26855 if (neightet.tet != dummytet)
continue;
26856 torg = org(tetloop);
26857 tdest = dest(tetloop);
26858 tapex = apex(tetloop);
26859 iorg = pointmark(torg) - in->firstnumber;
26860 idest = pointmark(tdest) - in->firstnumber;
26861 iapex = pointmark(tapex) - in->firstnumber;
26862 worklist[iorg] = 1;
26863 worklist[idest] = 1;
26864 worklist[iapex] = 1;
26867 for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26869 if (tetsperverlist[j] == tetloop.tet)
continue;
26870 neightet.tet = tetsperverlist[j];
26871 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26872 sym(neightet, neineightet);
26873 if (neineightet.tet == dummytet) {
26874 norg = org(neightet);
26875 ndest = dest(neightet);
26876 napex = apex(neightet);
26877 inorg = pointmark(norg) - in->firstnumber;
26878 indest = pointmark(ndest) - in->firstnumber;
26879 inapex = pointmark(napex) - in->firstnumber;
26880 if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26882 bond(tetloop, neightet);
26892 dummytet[0] = encode(tetloop);
26893 if ((in->pointmarkerlist != (
int *) NULL) && !b->coarse) {
26895 if (in->pointmarkerlist[iorg] == 0) {
26896 in->pointmarkerlist[iorg] = 1;
26898 if (in->pointmarkerlist[idest] == 0) {
26899 in->pointmarkerlist[idest] = 1;
26901 if (in->pointmarkerlist[iapex] == 0) {
26902 in->pointmarkerlist[iapex] = 1;
26906 worklist[iorg] = 0;
26907 worklist[idest] = 0;
26908 worklist[iapex] = 0;
26910 tetloop.tet = tetrahedrontraverse();
26919 if (in->trifacelist != (
int *) NULL) {
26921 for (i = 0; i < in->numberoftrifaces; i++) {
26923 iorg = in->trifacelist[index] - in->firstnumber;
26924 idest = in->trifacelist[index + 1] - in->firstnumber;
26925 iapex = in->trifacelist[index + 2] - in->firstnumber;
26927 worklist[iorg] = 1;
26928 worklist[idest] = 1;
26929 worklist[iapex] = 1;
26932 for (j = idx2tetlist[iorg]; j < idx2tetlist[iorg + 1] && !bondflag;
26934 neightet.tet = tetsperverlist[j];
26935 for (neightet.loc = 0; neightet.loc < 4; neightet.loc++) {
26936 norg = org(neightet);
26937 ndest = dest(neightet);
26938 napex = apex(neightet);
26939 inorg = pointmark(norg) - in->firstnumber;
26940 indest = pointmark(ndest) - in->firstnumber;
26941 inapex = pointmark(napex) - in->firstnumber;
26942 if ((worklist[inorg] + worklist[indest] + worklist[inapex]) == 3) {
26950 makeshellface(subfaces, &subloop);
26951 torg = idx2verlist[iorg];
26952 tdest = idx2verlist[idest];
26953 tapex = idx2verlist[iapex];
26954 setsorg(subloop, torg);
26955 setsdest(subloop, tdest);
26956 setsapex(subloop, tapex);
26959 setpointtype(torg, FREESUBVERTEX);
26960 setpointtype(tdest, FREESUBVERTEX);
26961 setpointtype(tapex, FREESUBVERTEX);
26962 if (in->trifacemarkerlist != (
int *) NULL) {
26963 setshellmark(subloop, in->trifacemarkerlist[i]);
26965 adjustedgering(neightet, CCW);
26966 findedge(&subloop, org(neightet), dest(neightet));
26967 tsbond(neightet, subloop);
26968 sym(neightet, neineightet);
26969 if (neineightet.tet != dummytet) {
26970 sesymself(subloop);
26971 tsbond(neineightet, subloop);
26975 printf(
"Warning: Subface %d is discarded.\n", i + in->firstnumber);
26978 worklist[iorg] = 0;
26979 worklist[idest] = 0;
26980 worklist[iapex] = 0;
26985 tetrahedrons->traversalinit();
26986 tetloop.tet = tetrahedrontraverse();
26987 while (tetloop.tet != (tetrahedron *) NULL) {
26989 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
26990 tspivot(tetloop, subloop);
26991 if (subloop.sh != dummysh)
continue;
26993 sym(tetloop, neightet);
26994 if (neightet.tet == dummytet) {
27000 if (in->numberoftetrahedronattributes > 0) {
27001 if (elemattribute(neightet.tet,
27002 in->numberoftetrahedronattributes - 1) !=
27003 elemattribute(tetloop.tet,
27004 in->numberoftetrahedronattributes - 1)) {
27010 adjustedgering(tetloop, CCW);
27011 makeshellface(subfaces, &subloop);
27012 torg = org(tetloop);
27013 tdest = dest(tetloop);
27014 tapex = apex(tetloop);
27015 setsorg(subloop, torg);
27016 setsdest(subloop, tdest);
27017 setsapex(subloop, tapex);
27020 setpointtype(torg, FREESUBVERTEX);
27021 setpointtype(tdest, FREESUBVERTEX);
27022 setpointtype(tapex, FREESUBVERTEX);
27023 tsbond(tetloop, subloop);
27024 if (neightet.tet != dummytet) {
27025 sesymself(subloop);
27026 tsbond(neightet, subloop);
27030 tetloop.tet = tetrahedrontraverse();
27036 neighshlist =
new list(
sizeof(face), NULL);
27038 makesubfacemap(idx2facelist, facesperverlist);
27041 subfaces->traversalinit();
27042 subloop.sh = shellfacetraverse(subfaces);
27043 while (subloop.sh != (shellface *) NULL) {
27044 for (i = 0; i < 3; i++) {
27045 spivot(subloop, neighsh);
27046 if (neighsh.sh == dummysh) {
27048 torg = sorg(subloop);
27049 tdest = sdest(subloop);
27050 tapex = sapex(subloop);
27051 neighshlist->append(&subloop);
27052 iorg = pointmark(torg) - in->firstnumber;
27054 for (j = idx2facelist[iorg]; j < idx2facelist[iorg + 1]; j++) {
27055 neighsh.sh = facesperverlist[j];
27056 if (neighsh.sh == subloop.sh)
continue;
27058 if (isfacehasedge(&neighsh, torg, tdest)) {
27059 findedge(&neighsh, torg, tdest);
27061 if (neighshlist->len() < 2) {
27062 neighshlist->append(&neighsh);
27064 for (index = 0; index < neighshlist->len() - 1; index++) {
27065 sface1 = * (face *)(* neighshlist)[index];
27066 sface2 = * (face *)(* neighshlist)[index + 1];
27067 da1 = facedihedral(torg, tdest, sapex(sface1), sapex(neighsh));
27068 da2 = facedihedral(torg, tdest, sapex(sface1), sapex(sface2));
27073 neighshlist->insert(index + 1, &neighsh);
27078 if (neighshlist->len() > 1) {
27079 neighsh = * (face *)(* neighshlist)[0];
27080 for (j = 1; j <= neighshlist->len(); j++) {
27081 if (j < neighshlist->len()) {
27082 neineighsh = * (face *)(* neighshlist)[j];
27084 neineighsh = * (face *)(* neighshlist)[0];
27086 sbond1(neighsh, neineighsh);
27087 neighsh = neineighsh;
27091 sbond(subloop, subloop);
27093 neighshlist->clear();
27095 senextself(subloop);
27097 subloop.sh = shellfacetraverse(subfaces);
27102 subfaces->traversalinit();
27103 subloop.sh = shellfacetraverse(subfaces);
27104 while (subloop.sh != (shellface *) NULL) {
27105 for (i = 0; i < 3; i++) {
27106 sspivot(subloop, subseg);
27107 if (subseg.sh == dummysh) {
27109 torg = sorg(subloop);
27110 tdest = sdest(subloop);
27111 tapex = sapex(subloop);
27112 spivot(subloop, neighsh);
27113 spivot(neighsh, neineighsh);
27114 insertsegflag =
false;
27115 if (subloop.sh == neighsh.sh || subloop.sh != neineighsh.sh) {
27118 insertsegflag =
true;
27122 assert(subloop.sh != neighsh.sh);
27124 napex = sapex(neighsh);
27125 sign = orient3d(torg, tdest, tapex, napex);
27126 if (iscoplanar(torg, tdest, tapex, napex, sign, b->epsilon)) {
27129 insertsegflag = (shellmark(subloop) != shellmark(neighsh));
27132 insertsegflag =
true;
27135 if (insertsegflag) {
27137 makeshellface(subsegs, &subseg);
27138 setsorg(subseg, torg);
27139 setsdest(subseg, tdest);
27142 setpointtype(torg, NACUTEVERTEX);
27143 setpointtype(tdest, NACUTEVERTEX);
27144 setshellmark(subseg, marker);
27149 ssbond(neighsh, subseg);
27150 spivotself(neighsh);
27151 }
while (neighsh.sh != subloop.sh);
27154 senextself(subloop);
27156 subloop.sh = shellfacetraverse(subfaces);
27159 insegments = subsegs->items;
27163 markerlist =
new list((
char*)
"int");
27165 subfaces->traversalinit();
27166 subloop.sh = shellfacetraverse(subfaces);
27167 while (subloop.sh != (shellface *) NULL) {
27169 if (!sinfected(subloop)) {
27171 marker = shellmark(subloop);
27172 markerlist->append(&marker);
27173 facetidx = markerlist->len();
27174 setshellmark(subloop, facetidx);
27176 neighshlist->append(&subloop);
27178 for (i = 0; i < neighshlist->len(); i++) {
27179 neighsh = * (face *) (* neighshlist)[i];
27180 for (j = 0; j < 3; j++) {
27181 sspivot(neighsh, subseg);
27182 if (subseg.sh == dummysh) {
27183 spivot(neighsh, neineighsh);
27184 if (!sinfected(neineighsh)) {
27187 assert(shellmark(neineighsh) == marker);
27189 setshellmark(neineighsh, facetidx);
27190 sinfect(neineighsh);
27191 neighshlist->append(&neineighsh);
27194 senextself(neighsh);
27197 neighshlist->clear();
27199 subloop.sh = shellfacetraverse(subfaces);
27202 subfaces->traversalinit();
27203 subloop.sh = shellfacetraverse(subfaces);
27204 while (subloop.sh != (shellface *) NULL) {
27206 assert(sinfected(subloop));
27208 suninfect(subloop);
27209 subloop.sh = shellfacetraverse(subfaces);
27212 in->numberoffacets = markerlist->len();
27213 in->facetmarkerlist =
new int[in->numberoffacets];
27214 for (i = 0; i < in->numberoffacets; i++) {
27215 marker = * (
int *) (* markerlist)[i];
27216 in->facetmarkerlist[i] = marker;
27219 facetabovepointarray =
new point[in->numberoffacets + 1];
27220 for (i = 0; i < in->numberoffacets + 1; i++) {
27221 facetabovepointarray[i] = (point) NULL;
27231 tetgenio::pbcgroup *pg;
27234 createsubpbcgrouptable();
27236 for (i = 0; i < in->numberofpbcgroups; i++) {
27237 pg = &(in->pbcgrouplist[i]);
27238 pd = &(subpbcgrouptable[i]);
27240 for (j = 0; j < 2; j++) {
27241 subfaces->traversalinit();
27242 subloop.sh = shellfacetraverse(subfaces);
27243 while (subloop.sh != (shellface *) NULL) {
27244 facetidx = shellmark(subloop);
27245 marker = in->facetmarkerlist[facetidx - 1];
27246 if (marker == pd->fmark[j]) {
27247 setshellpbcgroup(subloop, i);
27248 pd->ss[j] = subloop;
27250 subloop.sh = shellfacetraverse(subfaces);
27253 if (pg->pointpairlist != (
int *) NULL) {
27255 for (j = 0; j < pg->numberofpointpairs; j++) {
27256 iorg = pg->pointpairlist[j * 2] - in->firstnumber;
27257 idest = pg->pointpairlist[j * 2 + 1] - in->firstnumber;
27258 torg = idx2verlist[iorg];
27259 tdest = idx2verlist[idest];
27260 setpoint2pbcpt(torg, tdest);
27261 setpoint2pbcpt(tdest, torg);
27266 createsegpbcgrouptable();
27270 delete neighshlist;
27271 delete [] worklist;
27272 delete [] idx2tetlist;
27273 delete [] tetsperverlist;
27274 delete [] idx2facelist;
27275 delete [] facesperverlist;
27276 delete [] idx2verlist;
27287 void tetgenmesh::insertconstrainedpoints(tetgenio *addio)
27291 face checksh, checkseg;
27293 enum locateresult loc;
27296 int covertices, outvertices;
27301 printf(
"Insert additional points into mesh.\n");
27304 flipqueue =
new queue(
sizeof(badface));
27305 recenttet.tet = dummytet;
27306 covertices = outvertices = 0;
27309 for (i = 0; i < addio->numberofpoints; i++) {
27311 makepoint(&newpoint);
27312 newpoint[0] = addio->pointlist[index++];
27313 newpoint[1] = addio->pointlist[index++];
27314 newpoint[2] = addio->pointlist[index++];
27316 if ((addio->numberofpointattributes > 0) &&
27317 (in->numberofpointattributes > 0)) {
27318 attr = addio->pointattributelist + addio->numberofpointattributes * i;
27319 for (j = 0; j < in->numberofpointattributes; j++) {
27320 if (j < addio->numberofpointattributes) {
27321 newpoint[3 + j] = attr[j];
27326 searchtet = recenttet;
27327 loc = locate(newpoint, &searchtet);
27328 if (loc != ONVERTEX) {
27329 loc = adjustlocate(newpoint, &searchtet, loc, b->epsilon2);
27331 if (loc == OUTSIDE) {
27332 loc = hullwalk(newpoint, &searchtet);
27333 if (loc == OUTSIDE) {
27335 tetrahedrons->traversalinit();
27336 searchtet.tet = tetrahedrontraverse();
27337 while (searchtet.tet != (tetrahedron *) NULL) {
27338 loc = adjustlocate(newpoint, &searchtet, OUTSIDE, b->epsilon2);
27339 if (loc != OUTSIDE)
break;
27340 searchtet.tet = tetrahedrontraverse();
27347 case INTETRAHEDRON:
27348 setpointtype(newpoint, FREEVOLVERTEX);
27349 splittetrahedron(newpoint, &searchtet, flipqueue);
27352 tspivot(searchtet, checksh);
27353 if (checksh.sh != dummysh) {
27356 insertflag =
false;
27358 setpointtype(newpoint, FREESUBVERTEX);
27361 setpointtype(newpoint, FREEVOLVERTEX);
27364 splittetface(newpoint, &searchtet, flipqueue);
27368 tsspivot(&searchtet, &checkseg);
27369 if (checkseg.sh != dummysh) {
27371 insertflag =
false;
27373 setpointtype(newpoint, FREESEGVERTEX);
27374 setpoint2sh(newpoint, sencode(checkseg));
27377 tspivot(searchtet, checksh);
27378 if (checksh.sh != dummysh) {
27380 insertflag =
false;
27382 setpointtype(newpoint, FREESUBVERTEX);
27385 setpointtype(newpoint, FREEVOLVERTEX);
27389 splittetedge(newpoint, &searchtet, flipqueue);
27393 insertflag =
false;
27397 insertflag =
false;
27402 recenttet = searchtet;
27404 pointdealloc(newpoint);
27406 flip(flipqueue, NULL);
27411 if (covertices > 0) {
27412 printf(
" %d constrained points already exist.\n", covertices);
27414 if (outvertices > 0) {
27415 printf(
" %d constrained points lie outside the mesh.\n", outvertices);
27417 printf(
" %d constrained points have been inserted.\n",
27418 addio->numberofpoints - covertices - outvertices);
27433 bool tetgenmesh::p1interpolatebgm(point pt, triface* bgmtet,
long *scount)
27436 enum locateresult loc;
27437 REAL vol, volpt[4], weights[4];
27440 loc = bgm->preciselocate(pt, bgmtet, bgm->tetrahedrons->items);
27441 if (loc == OUTSIDE) {
27442 loc = bgm->hullwalk(pt, bgmtet);
27443 if (loc == OUTSIDE) {
27446 printf(
"Warning: Global point location.\n");
27448 if (scount) (*scount)++;
27449 bgm->tetrahedrons->traversalinit();
27450 bgmtet->tet = bgm->tetrahedrontraverse();
27451 while (bgmtet->tet != (tetrahedron *) NULL) {
27452 loc = bgm->adjustlocate(pt, bgmtet, OUTSIDE, b->epsilon);
27453 if (loc != OUTSIDE)
break;
27454 bgmtet->tet = bgm->tetrahedrontraverse();
27458 if (loc != OUTSIDE) {
27460 setpoint2bgmtet(pt, encode(*bgmtet));
27462 for (i = 0; i < 4; i++) bgmpt[i] = (point) bgmtet->tet[4 + i];
27464 vol = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], bgmpt[3]);
27465 volpt[0] = orient3d(pt, bgmpt[1], bgmpt[2], bgmpt[3]);
27466 volpt[1] = orient3d(bgmpt[0], pt, bgmpt[2], bgmpt[3]);
27467 volpt[2] = orient3d(bgmpt[0], bgmpt[1], pt, bgmpt[3]);
27468 volpt[3] = orient3d(bgmpt[0], bgmpt[1], bgmpt[2], pt);
27469 for (i = 0; i < 4; i++) weights[i] = fabs(volpt[i] / vol);
27471 for (i = 0; i < bgm->in->numberofpointmtrs; i++) {
27472 pt[pointmtrindex + i] = weights[0] * bgmpt[0][bgm->pointmtrindex + i]
27473 + weights[1] * bgmpt[1][bgm->pointmtrindex + i]
27474 + weights[2] * bgmpt[2][bgm->pointmtrindex + i]
27475 + weights[3] * bgmpt[3][bgm->pointmtrindex + i];
27478 setpoint2bgmtet(pt, (tetrahedron) NULL);
27480 return loc != OUTSIDE;
27496 void tetgenmesh::interpolatesizemap()
27499 triface tetloop, neightet, bgmtet;
27507 printf(
" Interpolating size map.\n");
27510 worklist =
new int[points->items + 1];
27511 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
27515 tetrahedrons->traversalinit();
27516 tetloop.tet = tetrahedrontraverse();
27517 while (tetloop.tet != (tetrahedron *) NULL) {
27518 if (!infected(tetloop)) {
27520 adjtetlist =
new list(
sizeof(triface), NULL, 1024);
27523 for (i = 0; i < 4; i++) {
27524 searchpt = (point) tetloop.tet[4 + i];
27527 worklist[pointmark(searchpt)] = 1;
27529 bgm->decode(point2bgmtet(searchpt), bgmtet);
27530 if (bgm->isdead(&bgmtet)) {
27531 bgmtet = bgm->recenttet;
27533 if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27534 bgm->recenttet = bgmtet;
27538 adjtetlist->append(&tetloop);
27540 for (i = 0; i < adjtetlist->len(); i++) {
27541 tetloop = * (triface *)(* adjtetlist)[i];
27542 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27543 sym(tetloop, neightet);
27544 if ((neightet.tet != dummytet) && !infected(neightet)) {
27546 searchpt = oppo(neightet);
27547 if (worklist[pointmark(searchpt)] == 0) {
27548 worklist[pointmark(searchpt)] = 1;
27549 decode(point2bgmtet(searchpt), bgmtet);
27550 if (bgm->isdead(&bgmtet)) {
27551 bgmtet = bgm->recenttet;
27553 if (p1interpolatebgm(searchpt, &bgmtet, &scount)) {
27554 bgm->recenttet = bgmtet;
27558 adjtetlist->append(&neightet);
27566 tetloop.tet = tetrahedrontraverse();
27570 tetrahedrons->traversalinit();
27571 tetloop.tet = tetrahedrontraverse();
27572 while (tetloop.tet != (tetrahedron *) NULL) {
27573 assert(infected(tetloop));
27575 tetloop.tet = tetrahedrontraverse();
27577 delete [] worklist;
27580 if (b->verbose && scount > 0l) {
27581 printf(
" %ld brute-force searches.\n", scount);
27583 if (b->verbose && sepcount > 0) {
27584 printf(
" %d separate domains.\n", sepcount);
27598 void tetgenmesh::duplicatebgmesh()
27600 triface tetloop, btetloop;
27601 triface symtet, bsymtet;
27602 face bhullsh, bneighsh;
27603 point *idx2bplist, *tetptbaklist;
27604 point ploop, bploop;
27608 printf(
"Duplicating background mesh.\n");
27617 idx2bplist =
new point[points->items + 1];
27618 idx = in->firstnumber;
27619 points->traversalinit();
27620 ploop = pointtraverse();
27621 while (ploop != (point) NULL) {
27622 bgm->makepoint(&bploop);
27624 for (i = 0; i < 3 + in->numberofpointattributes; i++) {
27625 bploop[i] = ploop[i];
27628 for (i = 0; i < bgm->sizeoftensor; i++) {
27629 bploop[bgm->pointmtrindex + i] = ploop[pointmtrindex + i];
27631 if (bploop[bgm->pointmtrindex + i] <= 0.0) {
27632 printf(
"Error: Point %d has non-positive size %g (-m option).\n",
27633 bgm->pointmark(bploop), bploop[bgm->pointmtrindex + i]);
27634 terminatetetgen(1);
27638 idx2bplist[idx++] = bploop;
27639 ploop = pointtraverse();
27643 tetptbaklist =
new point[tetrahedrons->items + 1];
27644 idx = in->firstnumber;
27645 tetrahedrons->traversalinit();
27646 tetloop.tet = tetrahedrontraverse();
27647 while (tetloop.tet != (tetrahedron *) NULL) {
27648 bgm->maketetrahedron(&btetloop);
27650 for (i = 0; i < 4; i++) {
27651 ploop = (point) tetloop.tet[4 + i];
27652 bploop = idx2bplist[pointmark(ploop)];
27653 btetloop.tet[4 + i] = (tetrahedron) bploop;
27656 tetptbaklist[idx++] = (point) tetloop.tet[4];
27657 tetloop.tet[4] = (tetrahedron) btetloop.tet;
27658 tetloop.tet = tetrahedrontraverse();
27663 idx = in->firstnumber;
27664 tetrahedrons->traversalinit();
27665 tetloop.tet = tetrahedrontraverse();
27666 while (tetloop.tet != (tetrahedron *) NULL) {
27668 btetloop.tet = (tetrahedron *) tetloop.tet[4];
27670 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
27671 btetloop.loc = tetloop.loc;
27672 sym(tetloop, symtet);
27673 if ((symtet.tet != dummytet) && (symtet.tet > tetloop.tet)) {
27675 bsymtet.tet = (tetrahedron *) symtet.tet[4];
27676 bsymtet.loc = symtet.loc;
27677 bgm->bond(btetloop, bsymtet);
27678 }
else if (symtet.tet == dummytet) {
27680 bgm->makeshellface(bgm->subfaces, &bhullsh);
27681 bgm->adjustedgering(btetloop, CCW);
27682 bgm->setsorg(bhullsh, bgm->org(btetloop));
27683 bgm->setsdest(bhullsh, bgm->dest(btetloop));
27684 bgm->setsapex(bhullsh, bgm->apex(btetloop));
27685 bgm->tsbond(btetloop, bhullsh);
27687 bgm->dummytet[0] = bgm->encode(btetloop);
27691 tetloop.tet[4] = (tetrahedron) tetptbaklist[idx++];
27694 for (i = 0; i < 4; i++) {
27695 ploop = (point) tetloop.tet[4 + i];
27696 setpoint2bgmtet(ploop, bgm->encode(btetloop));
27699 tetloop.tet = tetrahedrontraverse();
27703 bgm->subfaces->traversalinit();
27704 bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27705 while (bhullsh.sh != (shellface *) NULL) {
27707 bgm->stpivot(bhullsh, btetloop);
27708 assert(btetloop.tet != bgm->dummytet);
27709 bgm->adjustedgering(btetloop, CCW);
27710 for (i = 0; i < 3; i++) {
27711 bgm->spivot(bhullsh, bneighsh);
27712 if (bneighsh.sh == bgm->dummysh) {
27714 bsymtet = btetloop;
27715 while (bgm->fnextself(bsymtet));
27716 bgm->tspivot(bsymtet, bneighsh);
27717 bgm->findedge(&bneighsh, bgm->sdest(bhullsh), bgm->sorg(bhullsh));
27718 bgm->sbond(bhullsh, bneighsh);
27720 bgm->enextself(btetloop);
27721 bgm->senextself(bhullsh);
27723 bhullsh.sh = bgm->shellfacetraverse(bgm->subfaces);
27726 delete [] tetptbaklist;
27727 delete [] idx2bplist;
27752 void tetgenmesh::marksharpsegments(REAL sharpangle)
27755 face startsh, spinsh, neighsh;
27756 face segloop, prevseg, nextseg;
27758 REAL ang, smallang;
27762 if (b->verbose > 0) {
27763 printf(
" Marking sharp segments.\n");
27766 smallang = sharpangle * PI / 180.;
27768 eorg = edest = (point) NULL;
27772 subsegs->traversalinit();
27773 segloop.sh = shellfacetraverse(subsegs);
27774 while (segloop.sh != (shellface *) NULL) {
27776 senext2(segloop, prevseg);
27777 spivotself(prevseg);
27778 if (prevseg.sh == dummysh) {
27780 assert(shelltype(segloop) != SHARP);
27782 spivot(segloop, startsh);
27783 if (startsh.sh != dummysh) {
27785 eorg = sorg(segloop);
27786 edest = sdest(segloop);
27789 if (sorg(spinsh) != eorg) {
27793 stpivot(spinsh, adjtet);
27794 if (adjtet.tet != dummytet) {
27796 spivot(spinsh, neighsh);
27798 if (neighsh.sh != spinsh.sh) {
27800 ang = facedihedral(eorg, edest, sapex(spinsh), sapex(neighsh));
27802 if (!issharp) issharp = (ang < smallang);
27804 minfacetdihed = minfacetdihed < ang ? minfacetdihed : ang;
27808 spivotself(spinsh);
27809 }
while (spinsh.sh != startsh.sh);
27814 if (sorg(spinsh) != eorg) {
27825 ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27826 senext2self(neighsh);
27827 sspivot(neighsh, nextseg);
27828 if (nextseg.sh != dummysh)
break;
27830 spivotself(neighsh);
27831 assert(neighsh.sh != dummysh);
27832 if (sorg(neighsh) != eorg) {
27833 sesymself(neighsh);
27837 if (!issharp) issharp = (ang < smallang);
27839 minfaceang = minfaceang < ang ? minfaceang : ang;
27841 spivotself(spinsh);
27842 }
while (spinsh.sh != startsh.sh);
27846 setshelltype(segloop, SHARP);
27848 senext(segloop, nextseg);
27849 spivotself(nextseg);
27850 while (nextseg.sh != dummysh) {
27852 setshelltype(nextseg, SHARP);
27853 senextself(nextseg);
27854 spivotself(nextseg);
27859 segloop.sh = shellfacetraverse(subsegs);
27865 subsegs->traversalinit();
27866 segloop.sh = shellfacetraverse(subsegs);
27867 while (segloop.sh != (shellface *) NULL) {
27870 senext(segloop, nextseg);
27871 spivotself(nextseg);
27873 if (nextseg.sh == dummysh) {
27875 issharp = (shelltype(segloop) == SHARP);
27876 spivot(segloop, startsh);
27877 if (startsh.sh != dummysh) {
27879 eorg = sdest(segloop);
27882 if (sorg(spinsh) != eorg) {
27889 ang += interiorangle(eorg, sdest(neighsh), sapex(neighsh), NULL);
27890 senext2self(neighsh);
27891 sspivot(neighsh, nextseg);
27892 if (nextseg.sh != dummysh)
break;
27894 spivotself(neighsh);
27895 assert(neighsh.sh != dummysh);
27896 if (sorg(neighsh) != eorg) {
27897 sesymself(neighsh);
27901 if (!issharp) issharp = (ang < smallang);
27903 minfaceang = minfaceang < ang ? minfaceang : ang;
27905 spivotself(spinsh);
27906 }
while (spinsh.sh != startsh.sh);
27909 setshelltype(segloop, SHARP);
27911 senext2(segloop, prevseg);
27912 spivotself(prevseg);
27913 while (prevseg.sh != dummysh) {
27915 setshelltype(prevseg, SHARP);
27916 senext2self(prevseg);
27917 spivotself(prevseg);
27922 segloop.sh = shellfacetraverse(subsegs);
27925 if ((b->verbose > 0) && (sharpsegcount > 0)) {
27926 printf(
" %d sharp segments.\n", sharpsegcount);
27950 void tetgenmesh::decidefeaturepointsizes()
27952 list *tetlist, *verlist;
27953 shellface **segsperverlist;
27956 face checkseg, prevseg, nextseg, testseg;
27957 point ploop, adjpt, e1, e2;
27958 REAL lfs_0, len, vol, maxlen, varlen;
27966 if (b->verbose > 0) {
27967 printf(
" Deciding feature-point sizes.\n");
27971 makesegmentmap(idx2seglist, segsperverlist);
27973 tetlist =
new list(
sizeof(triface), NULL, 256);
27974 verlist =
new list(
sizeof(point *), NULL, 256);
27976 if (b->fixedvolume) {
27979 maxlen = pow(6.0 * b->maxvolume, 1.0/3.0);
27985 points->traversalinit();
27986 ploop = pointtraverse();
27987 while (ploop != (point) NULL) {
27988 if (pointtype(ploop) == NACUTEVERTEX) {
27989 if (point2sh(ploop) != (shellface) NULL) {
27990 setpointtype(ploop, FREESEGVERTEX);
27994 ploop = pointtraverse();
27997 if ((b->verbose > 0) && (featurecount > 0)) {
27998 printf(
" %d Steiner points correction.\n", featurecount);
28007 points->traversalinit();
28008 ploop = pointtraverse();
28009 while (ploop != (point) NULL) {
28010 if (pointtype(ploop) != FREESEGVERTEX) {
28013 idx = pointmark(ploop) - in->firstnumber;
28014 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature; i++) {
28015 checkseg.sh = segsperverlist[i];
28016 isfeature = (shelltype(checkseg) == SHARP);
28021 sstpivot(&checkseg, &starttet);
28023 tetlist->append(&starttet);
28024 formstarpolyhedron(ploop, tetlist, verlist,
true);
28026 if (ploop[pointmtrindex] == 0.0) {
28029 for (i = 0; i < verlist->len(); i++) {
28030 adjpt = * (point *)(* verlist)[i];
28031 if (pointtype(adjpt) == FREESEGVERTEX) {
28033 sdecode(point2sh(adjpt), checkseg);
28034 assert(checkseg.sh != dummysh);
28035 checkseg.shver = 0;
28037 prevseg = checkseg;
28039 senext2(prevseg, testseg);
28040 spivotself(testseg);
28041 if (testseg.sh == dummysh)
break;
28046 nextseg = checkseg;
28048 senext(nextseg, testseg);
28049 spivotself(testseg);
28050 if (testseg.sh == dummysh)
break;
28054 e1 = sorg(prevseg);
28055 e2 = sdest(nextseg);
28060 }
else if (ploop == e2) {
28065 len = distance(ploop, adjpt);
28066 if (lfs_0 > len) lfs_0 = len;
28068 ploop[pointmtrindex] = lfs_0;
28070 if (b->fixedvolume) {
28072 if (ploop[pointmtrindex] > maxlen) {
28073 ploop[pointmtrindex] = maxlen;
28076 if (b->varvolume) {
28078 for (i = 0; i < tetlist->len(); i++) {
28079 starttet = * (triface *)(* tetlist)[i];
28080 vol = volumebound(starttet.tet);
28082 varlen = pow(6 * vol, 1.0/3.0);
28083 if (ploop[pointmtrindex] > varlen) {
28084 ploop[pointmtrindex] = varlen;
28095 ploop[pointmtrindex] = 0.0;
28098 ploop = pointtraverse();
28101 if (b->verbose > 0) {
28102 printf(
" %d feature points.\n", featurecount);
28110 points->traversalinit();
28111 ploop = pointtraverse();
28112 while (ploop != (point) NULL) {
28113 if (pointtype(ploop) == FREESEGVERTEX) {
28114 if (ploop[pointmtrindex] == 0.0) {
28115 sdecode(point2sh(ploop), checkseg);
28116 assert(checkseg.sh != dummysh);
28117 if (shelltype(checkseg) == SHARP) {
28118 checkseg.shver = 0;
28120 prevseg = checkseg;
28122 senext2(prevseg, testseg);
28123 spivotself(testseg);
28124 if (testseg.sh == dummysh)
break;
28129 nextseg = checkseg;
28131 senext(nextseg, testseg);
28132 spivotself(testseg);
28133 if (testseg.sh == dummysh)
break;
28137 e1 = sorg(prevseg);
28138 e2 = sdest(nextseg);
28139 len = distance(e1, e2);
28140 lfs_0 = distance(e1, ploop);
28142 if (b->nobisect == 0) {
28143 assert(lfs_0 < len);
28145 ploop[pointmtrindex] = e1[pointmtrindex]
28146 + (lfs_0 / len) * (e2[pointmtrindex] - e1[pointmtrindex]);
28150 ploop[pointmtrindex] = 0.0;
28154 ploop = pointtraverse();
28156 if ((b->verbose > 0) && (featurecount > 0)) {
28157 printf(
" %d Steiner feature points.\n", featurecount);
28161 if (varconstraint) {
28163 if (in->facetconstraintlist) {
28165 subfaces->traversalinit();
28166 shloop.sh = shellfacetraverse(subfaces);
28167 while (shloop.sh != (shellface *) NULL) {
28168 varlen = areabound(shloop);
28169 if (varlen > 0.0) {
28171 varlen = sqrt(varlen);
28172 for (j = 0; j < 3; j++) {
28173 ploop = (point) shloop.sh[3 + j];
28175 idx = pointmark(ploop) - in->firstnumber;
28176 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28178 checkseg.sh = segsperverlist[i];
28179 isfeature = (shelltype(checkseg) == SHARP);
28182 assert(ploop[pointmtrindex] > 0.0);
28183 if (ploop[pointmtrindex] > varlen) {
28184 ploop[pointmtrindex] = varlen;
28189 shloop.sh = shellfacetraverse(subfaces);
28192 if (in->segmentconstraintlist) {
28194 subsegs->traversalinit();
28195 shloop.sh = shellfacetraverse(subsegs);
28196 while (shloop.sh != (shellface *) NULL) {
28197 varlen = areabound(shloop);
28198 if (varlen > 0.0) {
28200 for (j = 0; j < 2; j++) {
28201 ploop = (point) shloop.sh[3 + j];
28203 idx = pointmark(ploop) - in->firstnumber;
28204 for (i = idx2seglist[idx]; i < idx2seglist[idx + 1] && !isfeature;
28206 checkseg.sh = segsperverlist[i];
28207 isfeature = (shelltype(checkseg) == SHARP);
28210 assert(ploop[pointmtrindex] > 0.0);
28211 if (ploop[pointmtrindex] > varlen) {
28212 ploop[pointmtrindex] = varlen;
28217 shloop.sh = shellfacetraverse(subsegs);
28222 delete [] segsperverlist;
28223 delete [] idx2seglist;
28234 void tetgenmesh::enqueueencsub(face* testsub, point encpt,
int quenumber,
28240 encsub = (badface *) badsubfaces->alloc();
28241 encsub->ss = *testsub;
28242 encsub->forg = sorg(*testsub);
28243 encsub->fdest = sdest(*testsub);
28244 encsub->fapex = sapex(*testsub);
28245 encsub->foppo = (point) encpt;
28246 for (i = 0; i < 3; i++) encsub->cent[i] = cent[i];
28247 encsub->nextitem = (badface *) NULL;
28250 setshell2badface(encsub->ss, encsub);
28252 *subquetail[quenumber] = encsub;
28254 subquetail[quenumber] = &encsub->nextitem;
28255 if (b->verbose > 2) {
28256 printf(
" Queuing subface (%d, %d, %d) [%d].\n", pointmark(encsub->forg),
28257 pointmark(encsub->fdest), pointmark(encsub->fapex), quenumber);
28267 tetgenmesh::badface* tetgenmesh::dequeueencsub(
int* pquenumber)
28273 for (quenumber = 2; quenumber >= 0; quenumber--) {
28274 result = subquefront[quenumber];
28275 if (result != (badface *) NULL) {
28277 subquefront[quenumber] = result->nextitem;
28279 if (subquefront[quenumber] == (badface *) NULL) {
28280 subquetail[quenumber] = &subquefront[quenumber];
28282 *pquenumber = quenumber;
28286 return (badface *) NULL;
28295 void tetgenmesh::enqueuebadtet(triface* testtet, REAL ratio2, REAL* cent)
28297 badface *newbadtet;
28302 newbadtet = (badface *) badtetrahedrons->alloc();
28303 newbadtet->tt = *testtet;
28304 newbadtet->key = ratio2;
28305 if (cent != NULL) {
28306 for (i = 0; i < 3; i++) newbadtet->cent[i] = cent[i];
28308 for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
28310 newbadtet->forg = org(*testtet);
28311 newbadtet->fdest = dest(*testtet);
28312 newbadtet->fapex = apex(*testtet);
28313 newbadtet->foppo = oppo(*testtet);
28314 newbadtet->nextitem = (badface *) NULL;
28316 if (ratio2 > b->goodratio) {
28318 queuenumber = (int) (64.0 - 64.0 / ratio2);
28320 if ((queuenumber > 63) || (queuenumber < 0)) {
28329 if (tetquefront[queuenumber] == (badface *) NULL) {
28331 if (queuenumber > firstnonemptyq) {
28333 nextnonemptyq[queuenumber] = firstnonemptyq;
28334 firstnonemptyq = queuenumber;
28337 i = queuenumber + 1;
28338 while (tetquefront[i] == (badface *) NULL) {
28342 nextnonemptyq[queuenumber] = nextnonemptyq[i];
28343 nextnonemptyq[i] = queuenumber;
28346 tetquefront[queuenumber] = newbadtet;
28349 tetquetail[queuenumber]->nextitem = newbadtet;
28352 tetquetail[queuenumber] = newbadtet;
28354 if (b->verbose > 2) {
28355 printf(
" Queueing bad tet: (%d, %d, %d, %d), ratio %g, qnum %d.\n",
28356 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
28357 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
28358 sqrt(ratio2), queuenumber);
28368 tetgenmesh::badface* tetgenmesh::topbadtetra()
28372 recentq = firstnonemptyq;
28374 if (firstnonemptyq < 0) {
28375 return (badface *) NULL;
28378 return tetquefront[firstnonemptyq];
28382 void tetgenmesh::dequeuebadtet()
28384 badface *deadbadtet;
28388 if (recentq >= 0) {
28390 deadbadtet = tetquefront[recentq];
28392 tetquefront[recentq] = deadbadtet->nextitem;
28394 if (deadbadtet == tetquetail[recentq]) {
28396 if (firstnonemptyq == recentq) {
28398 firstnonemptyq = nextnonemptyq[firstnonemptyq];
28402 while (tetquefront[i] == (badface *) NULL) {
28405 nextnonemptyq[i] = nextnonemptyq[recentq];
28409 badfacedealloc(badtetrahedrons, deadbadtet);
28429 bool tetgenmesh::checkseg4encroach(face* testseg, point testpt, point* prefpt,
28432 badface *encsubseg;
28433 triface starttet, spintet;
28434 point eorg, edest, eapex, encpt;
28435 REAL cent[3], radius, dist, diff;
28441 eorg = sorg(*testseg);
28442 edest = sdest(*testseg);
28443 cent[0] = 0.5 * (eorg[0] + edest[0]);
28444 cent[1] = 0.5 * (eorg[1] + edest[1]);
28445 cent[2] = 0.5 * (eorg[2] + edest[2]);
28446 radius = distance(cent, eorg);
28448 if (varconstraint && (areabound(*testseg) > 0.0)) {
28449 enq = (2.0 * radius) > areabound(*testseg);
28454 if (testpt == (point) NULL) {
28456 sstpivot(testseg, &starttet);
28457 eapex = apex(starttet);
28458 spintet = starttet;
28461 dist = distance(cent, apex(spintet));
28462 diff = dist - radius;
28463 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28467 if (prefpt != (point *) NULL) {
28469 encpt = apex(spintet);
28470 circumsphere(eorg, edest, encpt, NULL, NULL, &dist);
28471 if (dist > maxradius) {
28480 if (!fnextself(spintet)) {
28483 esym(starttet, spintet);
28484 if (!fnextself(spintet)) {
28489 }
while (apex(spintet) != eapex && (hitbdry < 2));
28492 dist = distance(cent, testpt);
28493 diff = dist - radius;
28494 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28495 enq = (diff <= 0.0);
28499 if (enq && enqflag) {
28500 if (b->verbose > 2) {
28501 printf(
" Queuing encroaching subsegment (%d, %d).\n",
28502 pointmark(eorg), pointmark(edest));
28504 encsubseg = (badface *) badsubsegs->alloc();
28505 encsubseg->ss = *testseg;
28506 encsubseg->forg = eorg;
28507 encsubseg->fdest = edest;
28508 encsubseg->foppo = (point) NULL;
28511 setshell2badface(encsubseg->ss, encsubseg);
28530 bool tetgenmesh::checksub4encroach(face* testsub, point testpt,
bool enqflag)
28533 point pa, pb, pc, encpt;
28534 REAL A[4][4], rhs[4], D;
28535 REAL cent[3], area;
28536 REAL radius, dist, diff;
28543 encpt = (point) NULL;
28545 pa = sorg(*testsub);
28546 pb = sdest(*testsub);
28547 pc = sapex(*testsub);
28550 A[0][0] = pb[0] - pa[0];
28551 A[0][1] = pb[1] - pa[1];
28552 A[0][2] = pb[2] - pa[2];
28553 A[1][0] = pc[0] - pa[0];
28554 A[1][1] = pc[1] - pa[1];
28555 A[1][2] = pc[2] - pa[2];
28556 cross(A[0], A[1], A[2]);
28558 if (varconstraint && (areabound(*testsub) > 0.0)) {
28560 area = 0.5 * sqrt(dot(A[2], A[2]));
28561 enq = area > areabound(*testsub);
28568 rhs[0] = 0.5 * dot(A[0], A[0]);
28569 rhs[1] = 0.5 * dot(A[1], A[1]);
28573 if (lu_decmp(A, 3, indx, &D, 0)) {
28574 lu_solve(A, 3, indx, rhs, 0);
28575 cent[0] = pa[0] + rhs[0];
28576 cent[1] = pa[1] + rhs[1];
28577 cent[2] = pa[2] + rhs[2];
28578 radius = sqrt(rhs[0] * rhs[0] + rhs[1] * rhs[1] + rhs[2] * rhs[2]);
28583 if (testpt == (point) NULL) {
28584 stpivot(*testsub, abuttet);
28585 if (abuttet.tet != dummytet) {
28586 dist = distance(cent, oppo(abuttet));
28587 diff = dist - radius;
28588 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28589 enq = (diff <= 0.0);
28590 if (enq) encpt = oppo(abuttet);
28593 sesymself(*testsub);
28594 stpivot(*testsub, abuttet);
28595 if (abuttet.tet != dummytet) {
28596 dist = distance(cent, oppo(abuttet));
28597 diff = dist - radius;
28598 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28599 enq = (diff <= 0.0);
28600 if (enq) encpt = oppo(abuttet);
28604 dist = distance(cent, testpt);
28605 diff = dist - radius;
28606 if (fabs(diff) / radius <= b->epsilon) diff = 0.0;
28607 enq = (diff <= 0.0);
28614 if (enq && enqflag) {
28615 enqueueencsub(testsub, encpt, quenumber, cent);
28631 bool tetgenmesh::checktet4badqual(triface* testtet,
bool enqflag)
28633 point pa, pb, pc, pd, pe1, pe2;
28634 REAL vda[3], vdb[3], vdc[3];
28635 REAL vab[3], vbc[3], vca[3];
28636 REAL N[4][3], A[4][4], rhs[4], D;
28637 REAL elen[6], circumcent[3];
28638 REAL bicent[3], offcent[3];
28642 REAL volume, L, cosd;
28643 REAL radius2, smlen2, ratio2;
28644 REAL dist, sdist, split;
28649 pa = (point) testtet->tet[4];
28650 pb = (point) testtet->tet[5];
28651 pc = (point) testtet->tet[6];
28652 pd = (point) testtet->tet[7];
28656 for (i = 0; i < 3; i++) A[0][i] = vda[i] = pa[i] - pd[i];
28657 for (i = 0; i < 3; i++) A[1][i] = vdb[i] = pb[i] - pd[i];
28658 for (i = 0; i < 3; i++) A[2][i] = vdc[i] = pc[i] - pd[i];
28660 for (i = 0; i < 3; i++) vab[i] = pb[i] - pa[i];
28661 for (i = 0; i < 3; i++) vbc[i] = pc[i] - pb[i];
28662 for (i = 0; i < 3; i++) vca[i] = pa[i] - pc[i];
28665 lu_decmp(A, 3, indx, &D, 0);
28667 volume = (A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
28668 if (volume < 0.0) volume = -volume;
28670 rhs[0] = 0.5 * dot(vda, vda);
28671 rhs[1] = 0.5 * dot(vdb, vdb);
28672 rhs[2] = 0.5 * dot(vdc, vdc);
28673 lu_solve(A, 3, indx, rhs, 0);
28675 for (i = 0; i < 3; i++) circumcent[i] = pd[i] + rhs[i];
28677 radius2 = dot(rhs, rhs);
28679 elen[0] = dot(vda, vda);
28680 elen[1] = dot(vdb, vdb);
28681 elen[2] = dot(vdc, vdc);
28682 elen[3] = dot(vab, vab);
28683 elen[4] = dot(vbc, vbc);
28684 elen[5] = dot(vca, vca);
28685 smlen2 = elen[0]; sidx = 0;
28686 for (i = 1; i < 6; i++) {
28687 if (smlen2 > elen[i]) { smlen2 = elen[i]; sidx = i; }
28690 ratio2 = radius2 / smlen2;
28692 enq = ratio2 > b->goodratio;
28699 for (j = 0; j < 3; j++) {
28700 for (i = 0; i < 3; i++) rhs[i] = 0.0;
28702 lu_solve(A, 3, indx, rhs, 0);
28703 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
28706 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
28708 for (i = 0; i < 4; i++) {
28709 L = sqrt(dot(N[i], N[i]));
28711 for (j = 0; j < 3; j++) N[i][j] /= L;
28716 for (i = 1; i < 4 && !enq; i++) {
28717 cosd = -dot(N[0], N[i]);
28718 enq = cosd > cosmindihed;
28721 for (i = 2; i < 4 && !enq; i++) {
28722 cosd = -dot(N[1], N[i]);
28723 enq = cosd > cosmindihed;
28726 cosd = -dot(N[2], N[3]);
28727 enq = cosd > cosmindihed;
28731 }
else if (b->offcenter) {
28735 pe1 = pd; pe2 = pa;
break;
28737 pe1 = pd; pe2 = pb;
break;
28739 pe1 = pd; pe2 = pc;
break;
28741 pe1 = pa; pe2 = pb;
break;
28743 pe1 = pb; pe2 = pc;
break;
28745 pe1 = pc; pe2 = pa;
break;
28747 pe1 = pe2 = (point) NULL;
28750 for (i = 0; i < 3; i++) bicent[i] = 0.5 * (pe1[i] + pe2[i]);
28751 dist = distance(bicent, circumcent);
28754 sdist = b->alpha3 * (b->minratio+sqrt(b->goodratio-0.25))* sqrt(smlen2);
28755 split = sdist / dist;
28756 if (split > 1.0) split = 1.0;
28758 for (i = 0; i < 3; i++) {
28759 offcent[i] = bicent[i] + split * (circumcent[i] - bicent[i]);
28763 if (!enq && (b->varvolume || b->fixedvolume)) {
28765 enq = b->fixedvolume && (volume > b->maxvolume);
28766 if (!enq && b->varvolume) {
28767 enq = (volume > volumebound(testtet->tet)) &&
28768 (volumebound(testtet->tet) > 0.0);
28776 sdist = sqrt(radius2) / b->alpha1;
28777 for (i = 0; i < 4; i++) {
28778 pa = (point) testtet->tet[4 + i];
28780 dist = pa[pointmtrindex];
28781 enq = ((dist < sdist) && (dist > 0.0));
28791 if (enq && enqflag) {
28792 if (b->offcenter && (ratio2 > b->goodratio)) {
28793 for (i = 0; i < 3; i++) circumcent[i] = offcent[i];
28795 enqueuebadtet(testtet, ratio2, circumcent);
28818 bool tetgenmesh::acceptsegpt(point segpt, point refpt, face* splitseg)
28824 if (b->nobisect == 1) {
28828 sstpivot(splitseg, &spintet);
28829 assert(spintet.tet != dummytet);
28830 pc = apex(spintet);
28832 if (!fnextself(spintet)) {
28836 }
while (pc != apex(spintet));
28837 }
else if (b->nobisect > 1) {
28842 p[0] = sorg(*splitseg);
28843 p[1] = sdest(*splitseg);
28844 if (varconstraint && (areabound(*splitseg) > 0)) {
28845 lfs = areabound(*splitseg);
28846 L = distance(p[0], p[1]);
28853 for (i = 0; i < 2; i++) {
28855 if (p[i][pointmtrindex] > 0.0) {
28856 lfs = b->alpha2 * p[i][pointmtrindex];
28857 L = distance(p[i], segpt);
28861 if (j == 0)
return true;
28864 if (refpt != (point) NULL) {
28865 cdtenforcesegpts++;
28888 bool tetgenmesh::acceptfacpt(point facpt, list* subceillist, list* verlist)
28895 if (b->nobisect == 1) {
28898 testsh = (face *)(* subceillist)[0];
28899 stpivot(*testsh, testtet);
28900 if (testtet.tet != dummytet) {
28901 sesymself(*testsh);
28902 stpivot(*testsh, testtet);
28904 if (testtet.tet == dummytet)
return false;
28905 }
else if (b->nobisect > 1) {
28911 for (i = 0; i < subceillist->len(); i++) {
28912 testsh = (face *)(* subceillist)[i];
28913 p[0] = sorg(*testsh);
28914 p[1] = sdest(*testsh);
28915 for (j = 0; j < 2; j++) {
28916 idx = pointmark(p[j]);
28918 setpointmark(p[j], -idx - 1);
28919 verlist->append(&(p[j]));
28925 for (i = 0; i < verlist->len(); i++) {
28926 ploop = * (point *)(* verlist)[i];
28928 idx = pointmark(ploop);
28929 setpointmark(ploop, -(idx + 1));
28931 if (ploop[pointmtrindex] > 0.0) {
28932 lfs = b->alpha2 * ploop[pointmtrindex];
28933 L = distance(ploop, facpt);
28939 if (j == 0)
return true;
28956 bool tetgenmesh::acceptvolpt(point volpt, list* ceillist, list* verlist)
28964 for (i = 0; i < ceillist->len(); i++) {
28965 testtet = (triface *)(* ceillist)[i];
28966 p[0] = org(*testtet);
28967 p[1] = dest(*testtet);
28968 p[2] = apex(*testtet);
28969 for (j = 0; j < 3; j++) {
28970 idx = pointmark(p[j]);
28972 setpointmark(p[j], -idx - 1);
28973 verlist->append(&(p[j]));
28979 for (i = 0; i < verlist->len(); i++) {
28980 ploop = * (point *)(* verlist)[i];
28982 idx = pointmark(ploop);
28983 setpointmark(ploop, -(idx + 1));
28985 if (ploop[pointmtrindex] > 0.0) {
28986 lfs = b->alpha2 * ploop[pointmtrindex];
28987 L = distance(ploop, volpt);
28993 if (j == 0)
return true;
29005 void tetgenmesh::getsplitpoint(point e1, point e2, point refpt, point newpt)
29008 REAL split, L, d1, d2, ps, rs;
29009 bool acutea, acuteb;
29012 if (refpt != (point) NULL) {
29014 acutea = (pointtype(e1) == ACUTEVERTEX);
29015 acuteb = (pointtype(e2) == ACUTEVERTEX);
29016 if (acutea ^ acuteb) {
29018 ei = acutea ? e1 : e2;
29019 ej = acutea ? e2 : e1;
29020 L = distance(ei, ej);
29022 d1 = distance(ei, refpt);
29024 for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29026 d2 = distance(refpt, newpt);
29027 if (d2 > (L - d1)) {
29029 if ((d1 - d2) > (0.5 * d1)) {
29030 split = (d1 - d2) / L;
29032 split = 0.5 * d1 / L;
29034 for (i = 0; i < 3; i++) newpt[i] = ei[i] + split * (ej[i] - ei[i]);
29035 if (b->verbose > 1) {
29036 printf(
" Found by rule-3:");
29040 if (b->verbose > 1) {
29041 printf(
" Found by rule-2:");
29045 if (b->verbose > 1) {
29046 printf(
" center %d, split = %.12g.\n", pointmark(ei), split);
29049 d1 = distance(ei, newpt);
29050 d2 = distance(newpt, refpt);
29051 ps = randgenerator(d2 * b->epsilon2 * 1e+2);
29054 for (i = 0; i < 3; i++) newpt[i] = ei[i] + (1.0+rs) * (newpt[i] - ei[i]);
29057 for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29059 d1 = 0.5 * distance(e1, e2);
29060 ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29062 for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29066 for (i = 0; i < 3; i++) newpt[i] = 0.5 * (e1[i] + e2[i]);
29068 d1 = 0.5 * distance(e1, e2);
29069 ps = randgenerator(d1 * b->epsilon2 * 1e+2);
29071 for (i = 0; i < 3; i++) newpt[i] = e1[i] + (1.0+rs) * (newpt[i] - e1[i]);
29086 void tetgenmesh::shepardinterpolate(point newpt, list *verlist)
29089 REAL *weights, sumweight;
29093 weights =
new REAL[verlist->len()];
29097 for (i = 0; i < verlist->len(); i++) {
29098 neipt = * (point *)(* verlist)[i];
29099 for (j = 0; j < 3; j++) vec[j] = neipt[j] - newpt[j];
29100 weights[i] = 1.0 / dot(vec, vec);
29101 sumweight += weights[i];
29104 newpt[pointmtrindex] = 0.0;
29105 for (i = 0; i < verlist->len(); i++) {
29106 neipt = * (point *)(* verlist)[i];
29107 newpt[pointmtrindex] += (weights[i] * neipt[pointmtrindex]) / sumweight;
29122 void tetgenmesh::setnewpointsize(point newpt, point e1, point e2)
29128 decode(point2bgmtet(e1), bgmtet);
29129 p1interpolatebgm(newpt, &bgmtet, NULL);
29131 if (e2 != (point) NULL) {
29134 l = distance(e1, e2);
29135 d = distance(e1, newpt);
29139 assert(e1[pointmtrindex] > 0.0);
29140 assert(e2[pointmtrindex] > 0.0);
29142 newpt[pointmtrindex] = (1.0 - split) * e1[pointmtrindex]
29143 + split * e2[pointmtrindex];
29154 void tetgenmesh::splitencseg(point newpt, face* splitseg, list* tetlist,
29155 list* sublist, list* verlist, queue* flipque,
bool chkencsub,
bool chkbadtet,
29161 face startsh, spinsh, checksh;
29168 mytetlist =
new list(
sizeof(triface), NULL, 1024);
29169 myflipque =
new queue(
sizeof(badface));
29170 tetlist = mytetlist;
29171 flipque = myflipque;
29175 splitseg->shver = 0;
29177 sstpivot(splitseg, &starttet);
29178 splittetedge(newpt, &starttet, flipque);
29180 flip(flipque, NULL);
29184 for (i = 0; i < 2; i++) {
29185 if (!shell2badface(*splitseg)) {
29186 checkseg4encroach(splitseg, NULL, NULL,
true);
29189 senextself(*splitseg);
29190 spivotself(*splitseg);
29192 assert(splitseg->sh != (shellface *) NULL);
29194 splitseg->shver = 0;
29198 spivot(*splitseg, startsh);
29201 sublist->append(&spinsh);
29202 formstarpolygon(newpt, sublist, verlist);
29203 for (i = 0; i < sublist->len(); i++) {
29204 checksh = * (face *)(* sublist)[i];
29205 if (!shell2badface(checksh)) {
29206 checksub4encroach(&checksh, NULL,
true);
29210 if (verlist) verlist->clear();
29211 spivotself(spinsh);
29212 }
while (spinsh.sh != startsh.sh);
29217 sstpivot(splitseg, &starttet);
29218 tetlist->append(&starttet);
29219 formstarpolyhedron(newpt, tetlist, verlist,
true);
29223 tallencsegs(newpt, 1, &tetlist);
29226 tallencsubs(newpt, 1, &tetlist);
29230 for (i = 0; i < tetlist->len(); i++) {
29231 starttet = * (triface *)(* tetlist)[i];
29232 checktet4badqual(&starttet,
true);
29238 for (i = 0; i < tetlist->len(); i++) {
29239 starttet = * (triface *)(* tetlist)[i];
29240 checktet4opt(&starttet,
true);
29260 bool tetgenmesh::tallencsegs(point testpt,
int n, list **ceillists)
29269 oldencnum = badsubsegs->items;
29271 if (ceillists != (list **) NULL) {
29272 for (k = 0; k < n; k++) {
29273 ceillist = ceillists[k];
29275 for (i = 0; i < ceillist->len(); i++) {
29276 ceiltet = * (triface *)(* ceillist)[i];
29278 for (j = 0; j < 3; j++) {
29279 tsspivot(&ceiltet, &checkseg);
29280 if (checkseg.sh != dummysh) {
29282 if (!shell2badface(checkseg)) {
29283 checkseg4encroach(&checkseg, testpt, NULL,
true);
29286 enextself(ceiltet);
29292 subsegs->traversalinit();
29293 checkseg.sh = shellfacetraverse(subsegs);
29294 while (checkseg.sh != (shellface *) NULL) {
29296 if (!shell2badface(checkseg)) {
29297 checkseg4encroach(&checkseg, testpt, NULL,
true);
29299 checkseg.sh = shellfacetraverse(subsegs);
29303 return (badsubsegs->items > oldencnum);
29319 bool tetgenmesh::tallencsubs(point testpt,
int n, list** ceillists)
29328 oldencnum = badsubfaces->items;
29330 if (ceillists != (list **) NULL) {
29331 for (k = 0; k < n; k++) {
29332 ceillist = ceillists[k];
29334 for (i = 0; i < ceillist->len(); i++) {
29335 ceiltet = * (triface *)(* ceillist)[i];
29336 tspivot(ceiltet, checksh);
29337 if (checksh.sh != dummysh) {
29339 if (!shell2badface(checksh)) {
29340 checksub4encroach(&checksh, testpt,
true);
29347 subfaces->traversalinit();
29348 checksh.sh = shellfacetraverse(subfaces);
29349 while (checksh.sh != (shellface *) NULL) {
29351 if (!shell2badface(checksh)) {
29352 checksub4encroach(&checksh, testpt,
true);
29354 checksh.sh = shellfacetraverse(subfaces);
29358 return (badsubfaces->items > oldencnum);
29367 void tetgenmesh::tallbadtetrahedrons()
29371 tetrahedrons->traversalinit();
29372 tetloop.tet = tetrahedrontraverse();
29373 while (tetloop.tet != (tetrahedron *) NULL) {
29374 checktet4badqual(&tetloop,
true);
29375 tetloop.tet = tetrahedrontraverse();
29393 void tetgenmesh::repairencsegs(
bool chkencsub,
bool chkbadtet)
29395 list **tetlists, **ceillists;
29396 list **sublists, **subceillists;
29397 list *tetlist, *sublist;
29400 face splitseg, symsplitseg;
29401 point newpt, sympt, refpt;
29403 enum locateresult symloc;
29408 subceillists = NULL;
29416 if (!b->fliprepair) {
29417 tetlists =
new list*[nmax];
29418 ceillists =
new list*[nmax];
29419 sublists =
new list*[nmax];
29420 subceillists =
new list*[nmax];
29422 tetlist =
new list(
sizeof(triface), NULL, 1024);
29423 sublist =
new list(
sizeof(face), NULL, 256);
29424 flipque =
new queue(
sizeof(badface));
29429 while ((badsubsegs->items > 0) && (steinerleft != 0)) {
29430 badsubsegs->traversalinit();
29431 encloop = badfacetraverse(badsubsegs);
29432 while ((encloop != (badface *) NULL) && (steinerleft != 0)) {
29434 splitseg = encloop->ss;
29436 setshell2badface(splitseg, NULL);
29437 if ((sorg(splitseg) == encloop->forg) &&
29438 (sdest(splitseg) == encloop->fdest)) {
29439 if (b->verbose > 1) {
29440 printf(
" Get an enc-seg (%d, %d)\n", pointmark(encloop->forg),
29441 pointmark(encloop->fdest));
29443 refpt = (point) NULL;
29444 if (b->conformdel) {
29446 checkseg4encroach(&splitseg, NULL, &refpt,
false);
29450 getsplitpoint(encloop->forg, encloop->fdest, refpt, newpt);
29451 setpointtype(newpt, FREESEGVERTEX);
29452 setpoint2sh(newpt, sencode(splitseg));
29454 if (acceptsegpt(newpt, refpt, &splitseg)) {
29458 i = shellmark(splitseg) - 1;
29459 for (j = idx2segpglist[i]; j < idx2segpglist[i + 1]; j++) {
29461 symloc = getsegpbcsympoint(newpt, &splitseg, sympt, &symsplitseg,
29463 if (symloc == ONEDGE) {
29464 if (symsplitseg.sh != splitseg.sh) {
29466 setpointtype(sympt, FREESEGVERTEX);
29467 setpoint2sh(sympt, sencode(symsplitseg));
29469 e1 = sorg(symsplitseg);
29470 if (shelltype(symsplitseg) == SHARP) {
29471 e2 = sdest(symsplitseg);
29475 if (!b->fliprepair) {
29477 formbowatcavity(sympt, &symsplitseg, NULL, &n, &nmax,
29478 sublists, subceillists, tetlists, ceillists);
29480 if (trimbowatcavity(sympt, &symsplitseg, n, sublists,
29481 subceillists, tetlists, ceillists, -1.0)) {
29482 bowatinsertsite(sympt, &symsplitseg, n, sublists,
29483 subceillists, tetlists, ceillists, NULL, flipque,
29484 true, chkencsub, chkbadtet);
29485 setnewpointsize(sympt, e1, e2);
29486 if (steinerleft > 0) steinerleft--;
29489 pointdealloc(sympt);
29492 releasebowatcavity(&symsplitseg, n, sublists, subceillists,
29493 tetlists, ceillists);
29495 splitencseg(sympt, &symsplitseg, tetlist, sublist, NULL,
29496 flipque, chkencsub, chkbadtet,
false);
29497 setnewpointsize(sympt, e1, e2);
29498 if (steinerleft > 0) steinerleft--;
29503 pointdealloc(sympt);
29505 }
else if (symloc == ONVERTEX) {
29508 pointdealloc(sympt);
29512 pointdealloc(sympt);
29517 e1 = sorg(splitseg);
29518 if (shelltype(splitseg) == SHARP) {
29519 e2 = sdest(splitseg);
29523 if (!b->fliprepair) {
29525 formbowatcavity(newpt, &splitseg, NULL, &n, &nmax, sublists,
29526 subceillists, tetlists, ceillists);
29528 if (trimbowatcavity(newpt, &splitseg, n, sublists, subceillists,
29529 tetlists, ceillists, -1.0)) {
29530 bowatinsertsite(newpt, &splitseg, n, sublists, subceillists,
29531 tetlists, ceillists, NULL, flipque,
true,
29532 chkencsub, chkbadtet);
29533 setnewpointsize(newpt, e1, e2);
29534 if (steinerleft > 0) steinerleft--;
29537 pointdealloc(newpt);
29540 releasebowatcavity(&splitseg, n, sublists, subceillists, tetlists,
29543 splitencseg(newpt, &splitseg, tetlist, sublist, NULL, flipque,
29544 chkencsub, chkbadtet,
false);
29545 setnewpointsize(newpt, e1, e2);
29546 if (steinerleft > 0) steinerleft--;
29550 pointdealloc(newpt);
29553 badfacedealloc(badsubsegs, encloop);
29554 encloop = badfacetraverse(badsubsegs);
29558 if (!b->fliprepair) {
29559 delete [] tetlists;
29560 delete [] ceillists;
29561 delete [] sublists;
29562 delete [] subceillists;
29583 void tetgenmesh::repairencsubs(
bool chkbadtet)
29585 list *tetlists[2], *ceillists[2];
29586 list *sublist, *subceillist;
29589 face splitsub, symsplitsub;
29590 point newpt, sympt, e1;
29591 enum locateresult loc, symloc;
29594 int quenumber, n, i;
29598 sublist = (list *) NULL;
29599 subceillist = (list *) NULL;
29600 verlist =
new list(
sizeof(point *), NULL, 256);
29604 while ((badsubfaces->items > 0) && (steinerleft != 0)) {
29606 encloop = dequeueencsub(&quenumber);
29607 splitsub = encloop->ss;
29609 setshell2badface(splitsub, NULL);
29611 if (!isdead(&splitsub)
29612 && (sorg(splitsub) == encloop->forg)
29613 && (sdest(splitsub) == encloop->fdest)
29614 && (sapex(splitsub) == encloop->fapex)) {
29615 if (b->verbose > 1) {
29616 printf(
" Dequeuing ensub (%d, %d, %d) [%d].\n",
29617 pointmark(encloop->forg), pointmark(encloop->fdest),
29618 pointmark(encloop->fapex), quenumber);
29622 for (i = 0; i < 3; i++) newpt[i] = encloop->cent[i];
29623 setpointtype(newpt, FREESUBVERTEX);
29624 setpoint2sh(newpt, sencode(splitsub));
29626 abovepoint = facetabovepointarray[shellmark(splitsub)];
29627 if (abovepoint == (point) NULL) {
29628 getfacetabovepoint(&splitsub);
29632 loc = locatesub(newpt, &splitsub, 1, b->epsilon * 1e+2);
29633 if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29635 formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29636 &subceillist, tetlists, ceillists);
29638 reject = tallencsegs(newpt, 2, ceillists);
29641 reject = !acceptfacpt(newpt, subceillist, verlist);
29645 reject = !trimbowatcavity(newpt, NULL, n, &sublist, &subceillist,
29646 tetlists, ceillists, -1.0);
29653 reject = !sinfected(encloop->ss);
29657 if (shellpbcgroup(splitsub) >= 0) {
29660 symloc = getsubpbcsympoint(newpt,&splitsub,sympt,&symsplitsub);
29661 if (symloc != ONVERTEX) {
29663 releasebowatcavity(NULL, 2, &sublist, &subceillist, tetlists,
29666 formbowatcavity(sympt, NULL, &symsplitsub, &n, NULL, &sublist,
29667 &subceillist, tetlists, ceillists);
29668 reject = tallencsegs(sympt, 2, ceillists);
29670 reject = !acceptfacpt(sympt, subceillist, verlist);
29673 reject = !trimbowatcavity(sympt,NULL,n,&sublist,&subceillist,
29674 tetlists, ceillists, -1.0);
29678 setpoint2pbcpt(newpt, sympt);
29679 setpoint2pbcpt(sympt, newpt);
29680 setpointtype(sympt, FREESUBVERTEX);
29681 setpoint2sh(sympt, sencode(symsplitsub));
29683 e1 = sorg(symsplitsub);
29684 bowatinsertsite(sympt, NULL, n, &sublist, &subceillist,
29685 tetlists,ceillists,NULL,NULL,
false,
true,chkbadtet);
29686 setnewpointsize(sympt, e1, NULL);
29687 if (steinerleft > 0) steinerleft--;
29689 releasebowatcavity(NULL, n, &sublist, &subceillist, tetlists,
29696 pointdealloc(sympt);
29701 pointdealloc(sympt);
29711 if (shellpbcgroup(splitsub) >= 0) {
29713 formbowatcavity(newpt, NULL, &splitsub, &n, NULL, &sublist,
29714 &subceillist, tetlists, ceillists);
29715 trimbowatcavity(newpt, NULL, n, &sublist, &subceillist, tetlists,
29720 e1 = sorg(splitsub);
29721 bowatinsertsite(newpt, NULL, n, &sublist, &subceillist, tetlists,
29722 ceillists, NULL, NULL,
true,
true, chkbadtet);
29723 setnewpointsize(newpt, e1, NULL);
29724 if (steinerleft > 0) steinerleft--;
29732 pointdealloc(newpt);
29735 releasebowatcavity(NULL,n,&sublist,&subceillist,tetlists,ceillists);
29738 if (badsubsegs->items > 0) {
29740 oldptnum = points->items;
29741 repairencsegs(
true, chkbadtet);
29742 if (points->items > oldptnum) {
29744 splitsub = encloop->ss;
29745 if (!isdead(&splitsub)) {
29746 if (!shell2badface(splitsub)) {
29747 checksub4encroach(&splitsub, NULL,
true);
29763 if (loc == ONVERTEX) {
29764 printf(
"Internal error in repairencsubs():\n");
29765 printf(
" During repairing encroached subface (%d, %d, %d)\n",
29766 pointmark(encloop->forg), pointmark(encloop->fdest),
29767 pointmark(encloop->fapex));
29768 printf(
" New point %d is coincident with an existing vertex %d\n",
29769 pointmark(newpt), pointmark(sorg(splitsub)));
29775 pointdealloc(newpt);
29778 if (!isdead(&splitsub)) {
29780 checksub4encroach(&splitsub, NULL,
true);
29784 badfacedealloc(badsubfaces, encloop);
29802 void tetgenmesh::repairbadtets()
29804 list *tetlist, *ceillist;
29809 enum locateresult loc;
29814 tetlist =
new list(
sizeof(triface), NULL, 1024);
29815 ceillist =
new list(
sizeof(triface), NULL, 1024);
29816 verlist =
new list(
sizeof(point *), NULL, 256);
29820 while ((badtetrahedrons->items > 0) && (steinerleft != 0)) {
29822 badtet = topbadtetra();
29825 if ((badtet != (badface *) NULL) && !isdead(&badtet->tt)
29826 && org(badtet->tt) == badtet->forg
29827 && dest(badtet->tt) == badtet->fdest
29828 && apex(badtet->tt) == badtet->fapex
29829 && oppo(badtet->tt) == badtet->foppo) {
29830 if (b->verbose > 1) {
29831 printf(
" Dequeuing btet (%d, %d, %d, %d).\n",
29832 pointmark(badtet->forg), pointmark(badtet->fdest),
29833 pointmark(badtet->fapex), pointmark(badtet->foppo));
29837 for (i = 0; i < 3; i++) newpt[i] = badtet->cent[i];
29838 setpointtype(newpt, FREEVOLVERTEX);
29840 starttet = badtet->tt;
29841 loc = preciselocate(newpt, &starttet, tetrahedrons->items);
29842 if ((loc != ONVERTEX) && (loc != OUTSIDE)) {
29845 tetlist->append(&starttet);
29846 formbowatcavityquad(newpt, tetlist, ceillist);
29848 reject = tallencsegs(newpt, 1, &ceillist);
29851 reject = tallencsubs(newpt, 1, &ceillist);
29856 reject = !acceptvolpt(newpt, ceillist, verlist);
29859 reject = !trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist,
29867 reject = !infected(badtet->tt);
29868 if (reject) outbowatcircumcount++;
29872 e1 = org(starttet);
29874 bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist,
29875 NULL, NULL,
false,
false,
true);
29876 setnewpointsize(newpt, e1, NULL);
29877 if (steinerleft > 0) steinerleft--;
29885 pointdealloc(newpt);
29887 for (i = 0; i < tetlist->len(); i++) {
29888 starttet = * (triface *)(* tetlist)[i];
29889 uninfect(starttet);
29896 oldptnum = points->items;
29897 if (badsubsegs->items > 0) {
29898 repairencsegs(
true,
true);
29900 if (badsubfaces->items > 0) {
29901 repairencsubs(
true);
29903 if (points->items > oldptnum) {
29906 starttet = badtet->tt;
29907 if (!isdead(&starttet)) {
29908 checktet4badqual(&starttet,
true);
29922 if (loc == ONVERTEX) {
29923 printf(
"Internal error in repairbadtets():\n");
29924 printf(
" During repairing bad tet (%d, %d, %d, %d)\n",
29925 pointmark(badtet->forg), pointmark(badtet->fdest),
29926 pointmark(badtet->fapex), pointmark(badtet->foppo));
29927 printf(
" New point %d is coincident with an existing vertex %d\n",
29928 pointmark(newpt), pointmark(org(starttet)));
29935 pointdealloc(newpt);
29953 void tetgenmesh::enforcequality()
29955 long total, vertcount;
29959 printf(
"Adding Steiner points to enforce quality.\n");
29962 total = vertcount = 0l;
29963 if (b->conformdel) {
29964 r2count = r3count = 0l;
29968 if (b->conformdel && b->refine) {
29969 markacutevertices(65.0);
29974 marksharpsegments(65.0);
29976 decidefeaturepointsizes();
29980 badsubsegs =
new memorypool(
sizeof(badface), SUBPERBLOCK, POINTER, 0);
29982 tallencsegs(NULL, 0, NULL);
29983 if (b->verbose && badsubsegs->items > 0) {
29984 printf(
" Splitting encroached subsegments.\n");
29986 vertcount = points->items;
29988 repairencsegs(
false,
false);
29989 if (b->verbose > 0) {
29990 printf(
" %ld split points.\n", points->items - vertcount);
29992 total += points->items - vertcount;
29995 badsubfaces =
new memorypool(
sizeof(badface), SUBPERBLOCK, POINTER, 0);
29997 for (i = 0; i < 3; i++) subquefront[i] = (badface *) NULL;
29998 for (i = 0; i < 3; i++) subquetail[i] = &subquefront[i];
30000 tallencsubs(NULL, 0, NULL);
30001 if (b->verbose && badsubfaces->items > 0) {
30002 printf(
" Splitting encroached subfaces.\n");
30004 vertcount = points->items;
30006 repairencsubs(
false);
30007 if (b->verbose > 0) {
30008 printf(
" %ld split points.\n", points->items - vertcount);
30010 total += points->items - vertcount;
30015 if ((b->minratio > 0.0) || b->varvolume || b->fixedvolume) {
30017 badtetrahedrons =
new memorypool(
sizeof(badface), ELEPERBLOCK, POINTER, 0);
30019 for (i = 0; i < 64; i++) tetquefront[i] = (badface *) NULL;
30020 firstnonemptyq = -1;
30023 cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30024 cosmindihed = cos(b->mindihedral * PI / 180.0);
30025 tallbadtetrahedrons();
30026 if (b->verbose && badtetrahedrons->items > 0) {
30027 printf(
" Splitting bad tetrahedra.\n");
30029 vertcount = points->items;
30031 if (b->verbose > 0) {
30032 printf(
" %ld refinement points.\n", points->items - vertcount);
30034 total += points->items - vertcount;
30035 delete badtetrahedrons;
30038 if (b->verbose > 0) {
30039 printf(
" Totally added %ld points.\n", total);
30042 delete badsubfaces;
30054 void tetgenmesh::dumpbadtets()
30060 printf(
" Writing bad tets to file bad-dump.lua.\n");
30061 fout = fopen(
"bad-dump.lua",
"w");
30062 fprintf(fout,
"-- %ld remaining bad tets (> %g degree).\n",
30063 badtetrahedrons->items, b->maxdihedral);
30064 badtetrahedrons->traversalinit();
30065 remtet = badfacetraverse(badtetrahedrons);
30066 while (remtet != (badface *) NULL) {
30067 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30068 dest(remtet->tt) == remtet->fdest &&
30069 apex(remtet->tt) == remtet->fapex &&
30070 oppo(remtet->tt) == remtet->foppo) {
30071 fprintf(fout,
"p:draw_tet(%d, %d, %d, %d) -- %g\n",
30072 pointmark(remtet->forg), pointmark(remtet->fdest),
30073 pointmark(remtet->fapex), pointmark(remtet->foppo),
30074 acos(remtet->key) * 180.0 / PI);
30076 remtet = badfacetraverse(badtetrahedrons);
30093 bool tetgenmesh::checktet4ill(triface* testtet,
bool enqflag)
30095 badface *newbadtet;
30097 face checksh1, checksh2;
30103 for (testtet->loc = 0; testtet->loc < 4; testtet->loc++) {
30104 tspivot(*testtet, checksh1);
30105 if (checksh1.sh != dummysh) {
30107 findedge(&checksh1, org(*testtet), dest(*testtet));
30108 for (i = 0; i < 3; i++) {
30109 fnext(*testtet, checktet);
30110 tspivot(checktet, checksh2);
30111 if (checksh2.sh != dummysh) {
30113 sspivot(checksh1, checkseg);
30114 if (checkseg.sh == dummysh) {
30117 enextfnextself(*testtet);
30118 enextself(*testtet);
30123 enextself(*testtet);
30124 senextself(checksh1);
30127 if (illflag)
break;
30130 if (illflag && enqflag) {
30132 newbadtet = (badface *) badtetrahedrons->alloc();
30133 newbadtet->tt = *testtet;
30134 newbadtet->key = -1.0;
30135 for (i = 0; i < 3; i++) newbadtet->cent[i] = 0.0;
30136 newbadtet->forg = org(*testtet);
30137 newbadtet->fdest = dest(*testtet);
30138 newbadtet->fapex = apex(*testtet);
30139 newbadtet->foppo = oppo(*testtet);
30140 newbadtet->nextitem = (badface *) NULL;
30141 if (b->verbose > 2) {
30142 printf(
" Queueing illtet: (%d, %d, %d, %d).\n",
30143 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30144 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo));
30169 bool tetgenmesh::checktet4opt(triface* testtet,
bool enqflag)
30171 badface *newbadtet;
30172 point pa, pb, pc, pd;
30180 pa = (point) testtet->tet[4];
30181 pb = (point) testtet->tet[5];
30182 pc = (point) testtet->tet[6];
30183 pd = (point) testtet->tet[7];
30185 tetallnormal(pa, pb, pc, pd, N, NULL);
30187 for (i = 0; i < 4; i++) {
30188 len = sqrt(dot(N[i], N[i]));
30190 for (j = 0; j < 3; j++) N[i][j] /= len;
30194 for (i = 0; i < 6; i++) {
30200 cosd = -dot(N[2], N[3]);
30203 enextfnextself(*testtet);
30204 enextself(*testtet);
30205 cosd = -dot(N[0], N[1]);
30208 enextfnextself(*testtet);
30209 enext2self(*testtet);
30210 cosd = -dot(N[0], N[2]);
30213 enextself(*testtet);
30214 cosd = -dot(N[0], N[3]);
30217 enext2fnextself(*testtet);
30218 enextself(*testtet);
30219 cosd = -dot(N[1], N[2]);
30222 enext2self(*testtet);
30223 cosd = -dot(N[1], N[3]);
30226 if (cosd < cosmaxdihed) {
30230 newbadtet = (badface *) badtetrahedrons->alloc();
30231 newbadtet->tt = *testtet;
30232 newbadtet->key = cosd;
30233 for (j = 0; j < 3; j++) newbadtet->cent[j] = 0.0;
30234 newbadtet->forg = org(*testtet);
30235 newbadtet->fdest = dest(*testtet);
30236 newbadtet->fapex = apex(*testtet);
30237 newbadtet->foppo = oppo(*testtet);
30238 newbadtet->nextitem = (badface *) NULL;
30239 if (b->verbose > 2) {
30240 printf(
" Queueing tet: (%d, %d, %d, %d), dihed %g (degree).\n",
30241 pointmark(newbadtet->forg), pointmark(newbadtet->fdest),
30242 pointmark(newbadtet->fapex), pointmark(newbadtet->foppo),
30243 acos(cosd) * 180.0 / PI);
30276 bool tetgenmesh::removeedge(badface* remedge,
bool optflag)
30278 triface abcd, badc;
30279 triface baccasing, abdcasing;
30280 triface abtetlist[11];
30281 triface bftetlist[11];
30282 triface newtetlist[33];
30286 bool remflag, subflag;
30287 int n, n1, m, i, j;
30291 abcd = remedge->tt;
30292 adjustedgering(abcd, CCW);
30295 sym(abcd, baccasing);
30297 if (baccasing.tet == dummytet) {
30299 sym(badc, abdcasing);
30300 if (abdcasing.tet == dummytet) {
30302 if (removetetbypeeloff(&abcd)) {
30303 if (b->verbose > 1) {
30304 printf(
" Stripped tet from the mesh.\n");
30312 enext2fnextself(abcd);
30320 abcd = remedge->tt;
30321 adjustedgering(abcd, CW);
30323 abtetlist[n] = abcd;
30326 if (n == 10)
break;
30328 tspivot(abtetlist[n], checksh);
30329 if (checksh.sh != dummysh) {
30332 subflag =
true;
break;
30335 fnext(abtetlist[n], abtetlist[n + 1]);
30337 }
while (apex(abtetlist[n]) != apex(abcd));
30340 key = remedge->key;
30342 if (subflag && optflag) {
30343 abcd = remedge->tt;
30344 adjustedgering(abcd, CCW);
30346 for (j = 0; j < 2; j++) {
30348 enext2fnext(abcd, abtetlist[0]);
30350 enextfnext(abcd, abtetlist[0]);
30352 fty = categorizeface(abtetlist[0]);
30355 sym(abtetlist[0], abtetlist[1]);
30356 assert(abtetlist[1].tet != dummytet);
30359 remflag = removefacebyflip23(&key, abtetlist, newtetlist, NULL);
30360 }
else if (fty == T22) {
30363 newtetlist[0] = abtetlist[0];
30364 adjustedgering(newtetlist[0], CW);
30365 fnext(newtetlist[0], newtetlist[1]);
30366 assert(newtetlist[1].tet != dummytet);
30368 if (fnext(newtetlist[1], newtetlist[2])) {
30369 fnext(newtetlist[2], newtetlist[3]);
30370 assert(newtetlist[3].tet != dummytet);
30374 remflag = removeedgebyflip22(&key, n, newtetlist, NULL);
30378 if (b->verbose > 1) {
30379 printf(
" Done flip %d-to-%d. Qual: %g -> %g.\n", n, m,
30380 acos(remedge->key) / PI * 180.0, acos(key) / PI * 180.0);
30384 for (i = 0; i < n; i++) {
30385 tetrahedrondealloc(abtetlist[i].tet);
30388 for (i = 0; i < m; i++) {
30389 checktet4opt(&(newtetlist[i]),
true);
30402 remflag = removeedgebyflip32(&key, abtetlist, newtetlist, NULL);
30403 }
else if ((n == 4) || (n == 5) || (n == 6)) {
30405 remflag = removeedgebytranNM(&key,n,abtetlist,newtetlist,NULL,NULL,NULL);
30407 if (b->verbose > 1) {
30408 printf(
" !! Unhandled case: n = %d.\n", n);
30414 for (i = 0; i < n; i++) {
30415 tetrahedrondealloc(abtetlist[i].tet);
30418 if (b->verbose > 1) {
30419 printf(
" Done flip %d-to-%d. ", n, m);
30421 printf(
"Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30422 acos(key) / PI * 180.0);
30428 if (!remflag && (key == remedge->key) && (n < 7)) {
30431 remflag = removeedgebycombNM(&key, n, abtetlist, &n1, bftetlist,
30436 for (i = 0; i < n; i++) {
30437 tetrahedrondealloc(abtetlist[i].tet);
30439 for (i = 0; i < n1; i++) {
30440 if (!isdead(&(bftetlist[i]))) {
30441 tetrahedrondealloc(bftetlist[i].tet);
30444 m = ((n1 - 2) * 2 - 1) + (n - 3) * 2;
30445 if (b->verbose > 1) {
30446 printf(
" Done flip %d-to-%d (n-1=%d, n1=%d). ", n+n1-2, m, n-1,n1);
30448 printf(
"Qual: %g -> %g.", acos(remedge->key) / PI * 180.0,
30449 acos(key) / PI * 180.0);
30458 for (i = 0; i < m; i++) {
30460 checktet4opt(&(newtetlist[i]),
true);
30462 checktet4ill(&(newtetlist[i]),
true);
30479 bool tetgenmesh::smoothsliver(badface* remedge, list *starlist)
30488 for (i = 0; i < 4 && !smthed; i++) {
30489 smthpt = (point) remedge->tt.tet[4 + i];
30491 if (pointtype(smthpt) == FREEVOLVERTEX) {
30493 idx = pointmark(smthpt) - in->firstnumber;
30494 if (!(idx < in->numberofpoints)) {
30496 starlist->append(&(remedge->tt.tet));
30497 formstarpolyhedron(smthpt, starlist, NULL,
false);
30498 smthed = smoothpoint(smthpt,NULL,NULL,starlist,
false,&remedge->key);
30501 for (j = 0; j < starlist->len(); j++) {
30502 checktet = * (triface *)(* starlist)[j];
30503 checktet4opt(&checktet,
true);
30562 bool tetgenmesh::splitsliver(badface *remedge, list *tetlist, list *ceillist)
30566 point newpt, pt[4];
30570 starttet = remedge->tt;
30573 adjustedgering(starttet, CCW);
30574 enextfnextself(starttet);
30575 enextself(starttet);
30576 tsspivot(&starttet, &checkseg);
30577 if (b->nobisect == 0) {
30578 if (checkseg.sh != dummysh) {
30581 checkseg.shver = 0;
30582 pt[0] = sorg(checkseg);
30583 pt[1] = sdest(checkseg);
30585 getsplitpoint(pt[0], pt[1], NULL, newpt);
30586 setpointtype(newpt, FREESEGVERTEX);
30587 setpoint2sh(newpt, sencode(checkseg));
30589 sstpivot(&checkseg, &starttet);
30590 splittetedge(newpt, &starttet, NULL);
30592 sstpivot(&checkseg, &starttet);
30593 ceillist->append(&starttet);
30594 formstarpolyhedron(newpt, ceillist, NULL,
true);
30595 setnewpointsize(newpt, pt[0], NULL);
30596 if (steinerleft > 0) steinerleft--;
30598 smoothpoint(newpt, pt[0], pt[1], ceillist,
false, NULL);
30600 for (i = 0; i < ceillist->len(); i++) {
30601 starttet = * (triface *)(* ceillist)[i];
30602 checktet4opt(&starttet,
true);
30610 for (i = 0; i < 4; i++) {
30611 pt[i] = (point) starttet.tet[4 + i];
30615 for (i = 0; i < 3; i++) {
30616 newpt[i] = 0.25 * (pt[0][i] + pt[1][i] + pt[2][i] + pt[3][i]);
30618 setpointtype(newpt, FREEVOLVERTEX);
30623 tetlist->append(&starttet);
30624 formbowatcavityquad(newpt, tetlist, ceillist);
30625 if (trimbowatcavity(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, -1.0)) {
30627 if (smoothpoint( newpt, NULL, NULL, ceillist,
false, &remedge->key)) {
30629 bowatinsertsite(newpt, NULL, 1, NULL, NULL, &tetlist, &ceillist, NULL,
30630 NULL,
false,
false,
false);
30631 setnewpointsize(newpt, pt[0], NULL);
30632 if (steinerleft > 0) steinerleft--;
30634 for (i = 0; i < ceillist->len(); i++) {
30635 starttet = * (triface *)(* ceillist)[i];
30636 checktet4opt(&starttet,
true);
30644 pointdealloc(newpt);
30646 for (i = 0; i < tetlist->len(); i++) {
30647 starttet = * (triface *)(* tetlist)[i];
30648 uninfect(starttet);
30663 void tetgenmesh::tallslivers(
bool optflag)
30667 tetrahedrons->traversalinit();
30668 tetloop.tet = tetrahedrontraverse();
30669 while (tetloop.tet != (tetrahedron *) NULL) {
30671 checktet4opt(&tetloop,
true);
30673 checktet4ill(&tetloop,
true);
30675 tetloop.tet = tetrahedrontraverse();
30693 void tetgenmesh::optimizemesh(
bool optflag)
30695 list *splittetlist, *tetlist, *ceillist;
30696 badface *remtet, *lastentry;
30698 REAL objdihed, curdihed;
30706 printf(
"Optimizing mesh.\n");
30708 printf(
"Repairing mesh.\n");
30713 if (optflag && (b->verbose)) {
30714 printf(
" level = %d.\n", b->optlevel);
30719 badtetrahedrons =
new memorypool(
sizeof(badface), ELEPERBLOCK, POINTER, 0);
30721 cosmaxdihed = cos(b->maxdihedral * PI / 180.0);
30722 cosmindihed = cos(b->mindihedral * PI / 180.0);
30726 objdihed = b->maxdihedral + 5.0;
30727 if (objdihed < 170.0) objdihed = 170.0;
30728 objdihed = objdihed / 180.0 * PI;
30731 tallslivers(optflag);
30735 optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l;
30739 lastentry = (badface *) NULL;
30741 while (badtetrahedrons->items > 0) {
30742 badtetrahedrons->traversalinit();
30743 remtet = badfacetraverse(badtetrahedrons);
30744 while (remtet != (badface *) NULL) {
30747 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30748 dest(remtet->tt) == remtet->fdest &&
30749 apex(remtet->tt) == remtet->fapex &&
30750 oppo(remtet->tt) == remtet->foppo) {
30751 if (b->verbose > 1) {
30752 printf(
" Repair tet (%d, %d, %d, %d) %g (degree).\n",
30753 pointmark(remtet->forg), pointmark(remtet->fdest),
30754 pointmark(remtet->fapex), pointmark(remtet->foppo),
30755 acos(remtet->key) / PI * 180.0);
30757 if (!removeedge(remtet, optflag)) {
30759 if (lastentry != (badface *) NULL) {
30760 if (remtet == lastentry)
break;
30763 lastentry = remtet;
30767 lastentry = (badface *) NULL;
30769 badfacedealloc(badtetrahedrons, remtet);
30773 badfacedealloc(badtetrahedrons, remtet);
30775 remtet = badfacetraverse(badtetrahedrons);
30778 if (remtet != (badface *) NULL)
break;
30782 if (optcount[0] > 0l) {
30783 printf(
" %ld tets are peeled off.\n", optcount[0]);
30785 if (optcount[1] > 0l) {
30786 printf(
" %ld faces are flipped.\n", optcount[1]);
30788 if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30789 optcount[9] > 0l) {
30790 printf(
" %ld edges are flipped.\n", optcount[3] + optcount[4] +
30791 optcount[5] + optcount[6] + optcount[9]);
30798 if ((badtetrahedrons->items > 0l) && optflag && (b->optlevel > 2)) {
30799 splittetlist =
new list(
sizeof(badface), NULL, 256);
30800 tetlist =
new list(
sizeof(triface), NULL, 256);
30801 ceillist =
new list(
sizeof(triface), NULL, 256);
30802 oldnum = points->items;
30803 smoothsegverts = smoothvolverts = 0;
30805 optcount[3] = optcount[4] = optcount[5] = optcount[6] = 0l;
30811 badtetrahedrons->traversalinit();
30812 remtet = badfacetraverse(badtetrahedrons);
30813 while (remtet != (badface *) NULL) {
30814 splittetlist->append(remtet);
30816 badfacedealloc(badtetrahedrons, remtet);
30817 remtet = badfacetraverse(badtetrahedrons);
30819 for (i = 0; i < splittetlist->len(); i++) {
30820 remtet = (badface *)(* splittetlist)[i];
30823 if (!isdead(&remtet->tt) && org(remtet->tt) == remtet->forg &&
30824 dest(remtet->tt) == remtet->fdest &&
30825 apex(remtet->tt) == remtet->fapex &&
30826 oppo(remtet->tt) == remtet->foppo) {
30828 curdihed = facedihedral(remtet->forg, remtet->fdest, remtet->fapex,
30831 if (curdihed > PI) curdihed = 2 * PI - curdihed;
30833 if (curdihed > objdihed) {
30834 remtet->key = cos(curdihed);
30835 if (b->verbose > 1) {
30836 printf(
" Get sliver (%d, %d, %d, %d) %g (degree).\n",
30837 pointmark(remtet->forg), pointmark(remtet->fdest),
30838 pointmark(remtet->fapex), pointmark(remtet->foppo),
30839 acos(remtet->key) / PI * 180.0);
30841 if (!removeedge(remtet, optflag)) {
30842 if (!smoothsliver(remtet, tetlist)) {
30843 splitsliver(remtet, tetlist, ceillist);
30850 }
while ((badtetrahedrons->items > 0l) && (iter < b->optpasses));
30853 printf(
" %d passes.\n", iter);
30854 if ((points->items - oldnum) > 0l) {
30855 printf(
" %ld points are inserted (%d on segment).\n",
30856 points->items - oldnum, smoothsegverts);
30858 if (optcount[1] > 0l) {
30859 printf(
" %ld faces are flipped.\n", optcount[1]);
30861 if (optcount[3] + optcount[4] + optcount[5] + optcount[6] +
30862 optcount[9] > 0l) {
30863 printf(
" %ld edges are flipped.\n", optcount[3] + optcount[4] +
30864 optcount[5] + optcount[6] + optcount[9]);
30872 delete splittetlist;
30875 delete badtetrahedrons;
30898 void tetgenmesh::transfernodes()
30911 for (i = 0; i < in->numberofpoints; i++) {
30912 makepoint(&pointloop);
30914 x = pointloop[0] = in->pointlist[coordindex++];
30915 y = pointloop[1] = in->pointlist[coordindex++];
30916 z = pointloop[2] = in->pointlist[coordindex++];
30918 for (j = 0; j < in->numberofpointattributes; j++) {
30919 pointloop[3 + j] = in->pointattributelist[attribindex++];
30922 for (j = 0; j < in->numberofpointmtrs; j++) {
30923 pointloop[pointmtrindex + j] = in->pointmtrlist[mtrindex++];
30931 xmin = (x < xmin) ? x : xmin;
30932 xmax = (x > xmax) ? x : xmax;
30933 ymin = (y < ymin) ? y : ymin;
30934 ymax = (y > ymax) ? y : ymax;
30935 zmin = (z < zmin) ? z : zmin;
30936 zmax = (z > zmax) ? z : zmax;
30943 longest = sqrt(x * x + y * y + z * z);
30944 if (longest == 0.0) {
30945 printf(
"Error: The point set is trivial.\n");
30946 terminatetetgen(1);
30949 lengthlimit = longest * b->epsilon * 1e+2;
30964 void tetgenmesh::jettisonnodes()
30968 int oldidx, newidx;
30972 printf(
"Jettisoning redundants points.\n");
30975 points->traversalinit();
30976 pointloop = pointtraverse();
30977 oldidx = newidx = 0;
30979 while (pointloop != (point) NULL) {
30980 jetflag = (pointtype(pointloop) == DUPLICATEDVERTEX) ||
30981 (pointtype(pointloop) == UNUSEDVERTEX);
30984 pointdealloc(pointloop);
30988 setpointmark(pointloop, newidx + in->firstnumber);
30989 if (in->pointmarkerlist != (
int *) NULL) {
30990 if (oldidx < in->numberofpoints) {
30992 in->pointmarkerlist[newidx] = in->pointmarkerlist[oldidx];
30998 if (oldidx == in->numberofpoints) {
31000 in->numberofpoints -= remcount;
31002 jettisoninverts = remcount;
31004 pointloop = pointtraverse();
31007 printf(
" %d duplicated vertices have been removed.\n", dupverts);
31008 printf(
" %d unused vertices have been removed.\n", unuverts);
31016 points->deaditemstack = (
void *) NULL;
31029 void tetgenmesh::highorder()
31031 triface tetloop, worktet;
31032 triface spintet, adjtet;
31033 point torg, tdest, tapex;
31034 point *extralist, *adjextralist;
31036 int hitbdry, ptmark;
31040 printf(
"Adding vertices for second-order tetrahedra.\n");
31044 highordertable =
new point[tetrahedrons->items * 6];
31045 if (highordertable == (point *) NULL) {
31046 printf(
"Error: Out of memory.\n");
31047 terminatetetgen(1);
31055 points->deaditemstack = (
void *) NULL;
31060 tetrahedrons->traversalinit();
31061 tetloop.tet = tetrahedrontraverse();
31062 while (tetloop.tet != (tetrahedron *) NULL) {
31063 tetloop.tet[highorderindex] = (tetrahedron) &highordertable[i];
31064 for (j = 0; j < 6; j++) {
31065 highordertable[i + j] = (point) NULL;
31068 tetloop.tet = tetrahedrontraverse();
31076 tetrahedrons->traversalinit();
31077 tetloop.tet = tetrahedrontraverse();
31078 while (tetloop.tet != (tetrahedron *) NULL) {
31080 extralist = (point *) tetloop.tet[highorderindex];
31081 worktet.tet = tetloop.tet;
31082 for (i = 0; i < 6; i++) {
31083 if (extralist[i] == (point) NULL) {
31085 worktet.loc = edge2locver[i][0];
31086 worktet.ver = edge2locver[i][1];
31088 torg = org(worktet);
31089 tdest = dest(worktet);
31091 newpoint = (point) points->alloc();
31093 for (j = 0; j < 3 + in->numberofpointattributes; j++) {
31094 newpoint[j] = 0.5 * (torg[j] + tdest[j]);
31096 ptmark = (int) points->items - (in->firstnumber == 1 ? 0 : 1);
31097 setpointmark(newpoint, ptmark);
31099 extralist[i] = newpoint;
31102 tapex = apex(worktet);
31105 while (hitbdry < 2) {
31106 if (fnextself(spintet)) {
31108 adjextralist = (point *) spintet.tet[highorderindex];
31110 j = locver2edge[spintet.loc][spintet.ver];
31113 if (adjextralist[j] == (point) NULL) {
31114 adjextralist[j] = newpoint;
31116 if (apex(spintet) == tapex) {
31122 esym(worktet, spintet);
31128 tetloop.tet = tetrahedrontraverse();
31141 void tetgenmesh::outnodes(tetgenio* out)
31144 char outnodefilename[FILENAMESIZE];
31149 point *extralist, ep[3];
31150 int nextras, bmark, shmark, marker;
31151 int coordindex, attribindex;
31152 int pointnumber, firstindex;
31155 if (out == (tetgenio *) NULL) {
31156 strcpy(outnodefilename, b->outfilename);
31157 strcat(outnodefilename,
".node");
31161 if (out == (tetgenio *) NULL) {
31162 printf(
"Writing %s.\n", outnodefilename);
31164 printf(
"Writing nodes.\n");
31168 nextras = in->numberofpointattributes;
31169 bmark = !b->nobound && in->pointmarkerlist;
31172 outfile = (FILE *) NULL;
31173 marker = coordindex = 0;
31175 if (out == (tetgenio *) NULL) {
31176 outfile = fopen(outnodefilename,
"w");
31177 if (outfile == (FILE *) NULL) {
31178 printf(
"File I/O Error: Cannot create file %s.\n", outnodefilename);
31179 terminatetetgen(1);
31183 fprintf(outfile,
"%ld %d %d %d\n", points->items, 3, nextras, bmark);
31186 out->pointlist =
new REAL[points->items * 3];
31187 if (out->pointlist == (REAL *) NULL) {
31188 printf(
"Error: Out of memory.\n");
31189 terminatetetgen(1);
31193 out->pointattributelist =
new REAL[points->items * nextras];
31194 if (out->pointattributelist == (REAL *) NULL) {
31195 printf(
"Error: Out of memory.\n");
31196 terminatetetgen(1);
31201 out->pointmarkerlist =
new int[points->items];
31202 if (out->pointmarkerlist == (
int *) NULL) {
31203 printf(
"Error: Out of memory.\n");
31204 terminatetetgen(1);
31207 out->numberofpoints = points->items;
31208 out->numberofpointattributes = nextras;
31213 if (bmark && (b->plc || b->refine)) {
31215 points->traversalinit();
31216 pointloop = pointtraverse();
31217 while (pointloop != (point) NULL) {
31218 setpoint2tet(pointloop, (tetrahedron) NULL);
31219 pointloop = pointtraverse();
31223 subfaces->traversalinit();
31224 subloop.sh = shellfacetraverse(subfaces);
31225 while (subloop.sh != (shellface *) NULL) {
31228 for (i = 0; i < 3; i++) {
31229 pointloop = (point) subloop.sh[3 + i];
31230 setpoint2tet(pointloop, (tetrahedron) sencode(subloop));
31232 if (b->order == 2) {
31234 stpivot(subloop, adjtet);
31235 if (adjtet.tet == dummytet) {
31236 sesymself(subloop);
31237 stpivot(subloop, adjtet);
31239 assert(adjtet.tet != dummytet);
31240 extralist = (point *) adjtet.tet[highorderindex];
31241 switch (adjtet.loc) {
31243 ep[0] = extralist[0];
31244 ep[1] = extralist[1];
31245 ep[2] = extralist[2];
31248 ep[0] = extralist[0];
31249 ep[1] = extralist[4];
31250 ep[2] = extralist[3];
31253 ep[0] = extralist[1];
31254 ep[1] = extralist[5];
31255 ep[2] = extralist[4];
31258 ep[0] = extralist[2];
31259 ep[1] = extralist[3];
31260 ep[2] = extralist[5];
31264 for (i = 0; i < 3; i++) {
31265 setpoint2tet(ep[i], (tetrahedron) sencode(subloop));
31268 subloop.sh = shellfacetraverse(subfaces);
31273 firstindex = b->zeroindex ? 0 : in->firstnumber;
31275 points->traversalinit();
31276 pointloop = pointtraverse();
31277 pointnumber = firstindex;
31279 while (pointloop != (point) NULL) {
31284 if (index < in->numberofpoints) {
31286 marker = in->pointmarkerlist[index];
31289 if ((marker == 0) && (b->plc || b->refine)) {
31290 subptr = (shellface) point2tet(pointloop);
31291 if (subptr != (shellface) NULL) {
31294 if (in->facetmarkerlist != (
int *) NULL) {
31296 sdecode(subptr, subloop);
31297 shmark = shellmark(subloop);
31298 marker = in->facetmarkerlist[shmark - 1];
31303 if (out == (tetgenio *) NULL) {
31305 fprintf(outfile,
"%4d %.17g %.17g %.17g", pointnumber,
31306 pointloop[0], pointloop[1], pointloop[2]);
31307 for (i = 0; i < nextras; i++) {
31309 fprintf(outfile,
" %.17g", pointloop[3 + i]);
31313 fprintf(outfile,
" %d", marker);
31315 fprintf(outfile,
"\n");
31318 out->pointlist[coordindex++] = pointloop[0];
31319 out->pointlist[coordindex++] = pointloop[1];
31320 out->pointlist[coordindex++] = pointloop[2];
31322 for (i = 0; i < nextras; i++) {
31324 out->pointattributelist[attribindex++] = pointloop[3 + i];
31328 out->pointmarkerlist[index] = marker;
31331 pointloop = pointtraverse();
31336 if (out == (tetgenio *) NULL) {
31337 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31348 void tetgenmesh::outmetrics(tetgenio* out)
31351 char outmtrfilename[FILENAMESIZE];
31352 list *tetlist, *ptlist;
31354 point ptloop, neipt;
31361 if (out == (tetgenio *) NULL) {
31362 strcpy(outmtrfilename, b->outfilename);
31363 strcat(outmtrfilename,
".mtr");
31367 if (out == (tetgenio *) NULL) {
31368 printf(
"Writing %s.\n", outmtrfilename);
31370 printf(
"Writing metrics.\n");
31375 outfile = (FILE *) NULL;
31378 if (out == (tetgenio *) NULL) {
31379 outfile = fopen(outmtrfilename,
"w");
31380 if (outfile == (FILE *) NULL) {
31381 printf(
"File I/O Error: Cannot create file %s.\n", outmtrfilename);
31382 terminatetetgen(1);
31386 fprintf(outfile,
"%ld %d\n", points->items, 1);
31390 out->pointmtrlist =
new REAL[points->items];
31391 if (out->pointmtrlist == (REAL *) NULL) {
31392 printf(
"Error: Out of memory.\n");
31393 terminatetetgen(1);
31395 out->numberofpointmtrs = 1;
31400 points->traversalinit();
31401 ptloop = pointtraverse();
31402 while (ptloop != (point) NULL) {
31403 setpoint2tet(ptloop, (tetrahedron) NULL);
31404 ptloop = pointtraverse();
31407 tetrahedrons->traversalinit();
31408 tetloop.tet = tetrahedrontraverse();
31409 while (tetloop.tet != (tetrahedron *) NULL) {
31410 for (i = 0; i < 4; i++) {
31411 ptloop = (point) tetloop.tet[4 + i];
31412 setpoint2tet(ptloop, encode(tetloop));
31414 tetloop.tet = tetrahedrontraverse();
31417 tetlist =
new list(
sizeof(triface), NULL, 256);
31418 ptlist =
new list(
sizeof(point *), NULL, 256);
31420 points->traversalinit();
31421 ptloop = pointtraverse();
31422 while (ptloop != (point) NULL) {
31423 decode(point2tet(ptloop), tetloop);
31424 if (!isdead(&tetloop)) {
31426 tetlist->append(&tetloop);
31427 formstarpolyhedron(ptloop, tetlist, ptlist,
true);
31431 for (i = 0; i < ptlist->len(); i++) {
31432 neipt = * (point *)(* ptlist)[i];
31433 len = distance(ptloop, neipt);
31438 lave /= ptlist->len();
31440 if (out == (tetgenio *) NULL) {
31444 if (ptlist->len() > 0) {
31446 fprintf(outfile,
"%-16.8e ", lave);
31448 fprintf(outfile,
"0.0 ");
31450 fprintf(outfile,
"\n");
31455 if (ptlist->len() > 0) {
31458 out->pointmtrlist[mtrindex++] = lave;
31462 out->pointmtrlist[mtrindex++] = 0.0;
31467 ptloop = pointtraverse();
31473 if (out == (tetgenio *) NULL) {
31474 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31486 void tetgenmesh::outelements(tetgenio* out)
31489 char outelefilename[FILENAMESIZE];
31493 int firstindex, shift;
31496 point p1, p2, p3, p4;
31502 if (out == (tetgenio *) NULL) {
31503 strcpy(outelefilename, b->outfilename);
31504 strcat(outelefilename,
".ele");
31508 if (out == (tetgenio *) NULL) {
31509 printf(
"Writing %s.\n", outelefilename);
31511 printf(
"Writing elements.\n");
31516 outfile = (FILE *) NULL;
31517 tlist = (
int *) NULL;
31518 talist = (
double *) NULL;
31519 pointindex = attribindex = 0;
31521 eextras = in->numberoftetrahedronattributes;
31522 if (out == (tetgenio *) NULL) {
31523 outfile = fopen(outelefilename,
"w");
31524 if (outfile == (FILE *) NULL) {
31525 printf(
"File I/O Error: Cannot create file %s.\n", outelefilename);
31526 terminatetetgen(1);
31529 fprintf(outfile,
"%ld %d %d\n", tetrahedrons->items,
31530 b->order == 1 ? 4 : 10, eextras);
31533 out->tetrahedronlist =
new int[tetrahedrons->items *
31534 (b->order == 1 ? 4 : 10)];
31535 if (out->tetrahedronlist == (
int *) NULL) {
31536 printf(
"Error: Out of memory.\n");
31537 terminatetetgen(1);
31541 out->tetrahedronattributelist =
new REAL[tetrahedrons->items * eextras];
31542 if (out->tetrahedronattributelist == (REAL *) NULL) {
31543 printf(
"Error: Out of memory.\n");
31544 terminatetetgen(1);
31547 out->numberoftetrahedra = tetrahedrons->items;
31548 out->numberofcorners = b->order == 1 ? 4 : 10;
31549 out->numberoftetrahedronattributes = eextras;
31550 tlist = out->tetrahedronlist;
31551 talist = out->tetrahedronattributelist;
31557 firstindex = b->zeroindex ? 0 : in->firstnumber;
31559 if ((in->firstnumber == 1) && (firstindex == 0)) {
31563 tetrahedrons->traversalinit();
31564 tptr = tetrahedrontraverse();
31565 elementnumber = firstindex;
31566 while (tptr != (tetrahedron *) NULL) {
31567 p1 = (point) tptr[4];
31568 p2 = (point) tptr[5];
31569 p3 = (point) tptr[6];
31570 p4 = (point) tptr[7];
31571 if (out == (tetgenio *) NULL) {
31573 fprintf(outfile,
"%5d %5d %5d %5d %5d", elementnumber,
31574 pointmark(p1) - shift, pointmark(p2) - shift,
31575 pointmark(p3) - shift, pointmark(p4) - shift);
31576 if (b->order == 2) {
31577 extralist = (point *) tptr[highorderindex];
31579 fprintf(outfile,
" %5d %5d %5d %5d %5d %5d",
31580 pointmark(extralist[0]) - shift, pointmark(extralist[1]) - shift,
31581 pointmark(extralist[2]) - shift, pointmark(extralist[3]) - shift,
31582 pointmark(extralist[4]) - shift, pointmark(extralist[5]) - shift);
31584 for (i = 0; i < eextras; i++) {
31585 fprintf(outfile,
" %.17g", elemattribute(tptr, i));
31587 fprintf(outfile,
"\n");
31589 tlist[pointindex++] = pointmark(p1) - shift;
31590 tlist[pointindex++] = pointmark(p2) - shift;
31591 tlist[pointindex++] = pointmark(p3) - shift;
31592 tlist[pointindex++] = pointmark(p4) - shift;
31593 if (b->order == 2) {
31594 extralist = (point *) tptr[highorderindex];
31595 tlist[pointindex++] = pointmark(extralist[0]) - shift;
31596 tlist[pointindex++] = pointmark(extralist[1]) - shift;
31597 tlist[pointindex++] = pointmark(extralist[2]) - shift;
31598 tlist[pointindex++] = pointmark(extralist[3]) - shift;
31599 tlist[pointindex++] = pointmark(extralist[4]) - shift;
31600 tlist[pointindex++] = pointmark(extralist[5]) - shift;
31602 for (i = 0; i < eextras; i++) {
31603 talist[attribindex++] = elemattribute(tptr, i);
31608 * (
int *) (tptr + elemmarkerindex) = elementnumber;
31610 tptr = tetrahedrontraverse();
31615 * (
int *) (dummytet + elemmarkerindex) = -1;
31618 if (out == (tetgenio *) NULL) {
31619 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31633 void tetgenmesh::outfaces(tetgenio* out)
31636 char facefilename[FILENAMESIZE];
31639 int neigh1, neigh2;
31641 triface tface, tsymface;
31643 point torg, tdest, tapex;
31645 int bmark, faceid, marker;
31646 int firstindex, shift;
31652 if (out == (tetgenio *) NULL) {
31653 strcpy(facefilename, b->outfilename);
31654 strcat(facefilename,
".face");
31658 if (out == (tetgenio *) NULL) {
31659 printf(
"Writing %s.\n", facefilename);
31661 printf(
"Writing faces.\n");
31666 outfile = (FILE *) NULL;
31667 elist = (
int *) NULL;
31668 emlist = (
int *) NULL;
31669 index = marker = 0;
31671 faces = (4l * tetrahedrons->items + hullsize) / 2l;
31672 bmark = !b->nobound && in->facetmarkerlist;
31674 if (out == (tetgenio *) NULL) {
31675 outfile = fopen(facefilename,
"w");
31676 if (outfile == (FILE *) NULL) {
31677 printf(
"File I/O Error: Cannot create file %s.\n", facefilename);
31678 terminatetetgen(1);
31680 fprintf(outfile,
"%ld %d\n", faces, bmark);
31683 out->trifacelist =
new int[faces * 3];
31684 if (out->trifacelist == (
int *) NULL) {
31685 printf(
"Error: Out of memory.\n");
31686 terminatetetgen(1);
31690 out->trifacemarkerlist =
new int[faces];
31691 if (out->trifacemarkerlist == (
int *) NULL) {
31692 printf(
"Error: Out of memory.\n");
31693 terminatetetgen(1);
31696 if (b->neighout > 1) {
31698 out->adjtetlist =
new int[subfaces->items * 2];
31699 if (out->adjtetlist == (
int *) NULL) {
31700 printf(
"Error: Out of memory.\n");
31701 terminatetetgen(1);
31704 out->numberoftrifaces = faces;
31705 elist = out->trifacelist;
31706 emlist = out->trifacemarkerlist;
31711 firstindex = b->zeroindex ? 0 : in->firstnumber;
31713 if ((in->firstnumber == 1) && (firstindex == 0)) {
31717 tetrahedrons->traversalinit();
31718 tface.tet = tetrahedrontraverse();
31719 facenumber = firstindex;
31726 while (tface.tet != (tetrahedron *) NULL) {
31727 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31728 sym(tface, tsymface);
31729 if ((tsymface.tet == dummytet) || (tface.tet < tsymface.tet)) {
31731 tdest = dest(tface);
31732 tapex = apex(tface);
31736 if (b->useshelles) {
31738 tspivot(tface, checkmark);
31739 if (checkmark.sh == dummysh) {
31742 faceid = shellmark(checkmark) - 1;
31743 marker = in->facetmarkerlist[faceid];
31747 marker = tsymface.tet != dummytet ? 1 : 0;
31750 if (b->neighout > 1) {
31752 neigh1 = * (
int *)(tface.tet + elemmarkerindex);
31753 if (tsymface.tet != dummytet) {
31754 neigh2 = * (
int *)(tsymface.tet + elemmarkerindex);
31759 if (out == (tetgenio *) NULL) {
31761 fprintf(outfile,
"%5d %4d %4d %4d", facenumber,
31762 pointmark(torg) - shift, pointmark(tdest) - shift,
31763 pointmark(tapex) - shift);
31766 fprintf(outfile,
" %d", marker);
31768 if (b->neighout > 1) {
31769 fprintf(outfile,
" %5d %5d", neigh1, neigh2);
31771 fprintf(outfile,
"\n");
31774 elist[index++] = pointmark(torg) - shift;
31775 elist[index++] = pointmark(tdest) - shift;
31776 elist[index++] = pointmark(tapex) - shift;
31778 emlist[facenumber - in->firstnumber] = marker;
31780 if (b->neighout > 1) {
31781 out->adjtetlist[(facenumber - in->firstnumber) * 2] = neigh1;
31782 out->adjtetlist[(facenumber - in->firstnumber) * 2 + 1] = neigh2;
31788 tface.tet = tetrahedrontraverse();
31791 if (out == (tetgenio *) NULL) {
31792 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31808 void tetgenmesh::outhullfaces(tetgenio* out)
31811 char facefilename[FILENAMESIZE];
31814 triface tface, tsymface;
31816 point torg, tdest, tapex;
31817 int firstindex, shift;
31820 if (out == (tetgenio *) NULL) {
31821 strcpy(facefilename, b->outfilename);
31822 strcat(facefilename,
".face");
31826 if (out == (tetgenio *) NULL) {
31827 printf(
"Writing %s.\n", facefilename);
31829 printf(
"Writing faces.\n");
31834 outfile = (FILE *) NULL;
31835 elist = (
int *) NULL;
31838 if (out == (tetgenio *) NULL) {
31839 outfile = fopen(facefilename,
"w");
31840 if (outfile == (FILE *) NULL) {
31841 printf(
"File I/O Error: Cannot create file %s.\n", facefilename);
31842 terminatetetgen(1);
31844 fprintf(outfile,
"%ld 0\n", hullsize);
31847 out->trifacelist =
new int[hullsize * 3];
31848 if (out->trifacelist == (
int *) NULL) {
31849 printf(
"Error: Out of memory.\n");
31850 terminatetetgen(1);
31852 out->numberoftrifaces = hullsize;
31853 elist = out->trifacelist;
31858 firstindex = b->zeroindex ? 0 : in->firstnumber;
31860 if ((in->firstnumber == 1) && (firstindex == 0)) {
31864 tetrahedrons->traversalinit();
31865 tface.tet = tetrahedrontraverse();
31866 facenumber = firstindex;
31870 while (tface.tet != (tetrahedron *) NULL) {
31871 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
31872 sym(tface, tsymface);
31873 if (tsymface.tet == dummytet) {
31875 tdest = dest(tface);
31876 tapex = apex(tface);
31877 if (out == (tetgenio *) NULL) {
31879 fprintf(outfile,
"%5d %4d %4d %4d", facenumber,
31880 pointmark(torg) - shift, pointmark(tdest) - shift,
31881 pointmark(tapex) - shift);
31882 fprintf(outfile,
"\n");
31885 elist[index++] = pointmark(torg) - shift;
31886 elist[index++] = pointmark(tdest) - shift;
31887 elist[index++] = pointmark(tapex) - shift;
31892 tface.tet = tetrahedrontraverse();
31895 if (out == (tetgenio *) NULL) {
31896 fprintf(outfile,
"# Generated by %s\n", b->commandline);
31912 void tetgenmesh::outsubfaces(tetgenio* out)
31915 char facefilename[FILENAMESIZE];
31918 int index, index1, index2;
31919 triface abuttingtet;
31921 point torg, tdest, tapex;
31922 int bmark, faceid, marker;
31923 int firstindex, shift;
31924 int neigh1, neigh2;
31927 if (out == (tetgenio *) NULL) {
31928 strcpy(facefilename, b->outfilename);
31929 strcat(facefilename,
".face");
31933 if (out == (tetgenio *) NULL) {
31934 printf(
"Writing %s.\n", facefilename);
31936 printf(
"Writing faces.\n");
31941 outfile = (FILE *) NULL;
31942 elist = (
int *) NULL;
31943 emlist = (
int *) NULL;
31944 index = index1 = index2 = 0;
31945 faceid = marker = 0;
31946 neigh1 = neigh2 = 0;
31948 bmark = !b->nobound && in->facetmarkerlist;
31950 if (out == (tetgenio *) NULL) {
31951 outfile = fopen(facefilename,
"w");
31952 if (outfile == (FILE *) NULL) {
31953 printf(
"File I/O Error: Cannot create file %s.\n", facefilename);
31954 terminatetetgen(1);
31957 fprintf(outfile,
"%ld %d\n", subfaces->items, bmark);
31960 out->trifacelist =
new int[subfaces->items * 3];
31961 if (out->trifacelist == (
int *) NULL) {
31962 printf(
"Error: Out of memory.\n");
31963 terminatetetgen(1);
31967 out->trifacemarkerlist =
new int[subfaces->items];
31968 if (out->trifacemarkerlist == (
int *) NULL) {
31969 printf(
"Error: Out of memory.\n");
31970 terminatetetgen(1);
31973 if (b->neighout > 1) {
31975 out->adjtetlist =
new int[subfaces->items * 2];
31976 if (out->adjtetlist == (
int *) NULL) {
31977 printf(
"Error: Out of memory.\n");
31978 terminatetetgen(1);
31981 out->numberoftrifaces = subfaces->items;
31982 elist = out->trifacelist;
31983 emlist = out->trifacemarkerlist;
31987 firstindex = b->zeroindex ? 0 : in->firstnumber;
31989 if ((in->firstnumber == 1) && (firstindex == 0)) {
31993 subfaces->traversalinit();
31994 faceloop.sh = shellfacetraverse(subfaces);
31995 facenumber = firstindex;
31996 while (faceloop.sh != (shellface *) NULL) {
31997 stpivot(faceloop, abuttingtet);
31998 if (abuttingtet.tet == dummytet) {
31999 sesymself(faceloop);
32000 stpivot(faceloop, abuttingtet);
32002 if (abuttingtet.tet != dummytet) {
32006 adjustedgering(abuttingtet, CCW);
32007 torg = org(abuttingtet);
32008 tdest = dest(abuttingtet);
32009 tapex = apex(abuttingtet);
32012 torg = sorg(faceloop);
32013 tdest = sdest(faceloop);
32014 tapex = sapex(faceloop);
32017 faceid = shellmark(faceloop) - 1;
32018 marker = in->facetmarkerlist[faceid];
32020 if (b->neighout > 1) {
32023 stpivot(faceloop, abuttingtet);
32024 if (abuttingtet.tet != dummytet) {
32025 neigh1 = * (
int *)(abuttingtet.tet + elemmarkerindex);
32028 sesymself(faceloop);
32029 stpivot(faceloop, abuttingtet);
32030 if (abuttingtet.tet != dummytet) {
32031 neigh2 = * (
int *)(abuttingtet.tet + elemmarkerindex);
32034 if (out == (tetgenio *) NULL) {
32035 fprintf(outfile,
"%5d %4d %4d %4d", facenumber,
32036 pointmark(torg) - shift, pointmark(tdest) - shift,
32037 pointmark(tapex) - shift);
32039 fprintf(outfile,
" %d", marker);
32041 if (b->neighout > 1) {
32042 fprintf(outfile,
" %5d %5d", neigh1, neigh2);
32044 fprintf(outfile,
"\n");
32047 elist[index++] = pointmark(torg) - shift;
32048 elist[index++] = pointmark(tdest) - shift;
32049 elist[index++] = pointmark(tapex) - shift;
32051 emlist[index1++] = marker;
32053 if (b->neighout > 1) {
32054 out->adjtetlist[index2++] = neigh1;
32055 out->adjtetlist[index2++] = neigh2;
32059 faceloop.sh = shellfacetraverse(subfaces);
32062 if (out == (tetgenio *) NULL) {
32063 fprintf(outfile,
"# Generated by %s\n", b->commandline);
32074 void tetgenmesh::outedges(tetgenio* out)
32077 char edgefilename[FILENAMESIZE];
32078 int *elist, *emlist;
32080 triface tetloop, worktet, spintet;
32084 int firstindex, shift;
32085 int edgenumber, faceid, marker;
32088 if (out == (tetgenio *) NULL) {
32089 strcpy(edgefilename, b->outfilename);
32090 strcat(edgefilename,
".edge");
32094 if (out == (tetgenio *) NULL) {
32095 printf(
"Writing %s.\n", edgefilename);
32097 printf(
"Writing edges.\n");
32102 outfile = (FILE *) NULL;
32103 elist = (
int *) NULL;
32104 emlist = (
int *) NULL;
32105 index = index1 = 0;
32106 faceid = marker = 0;
32109 faces = (4l * tetrahedrons->items + hullsize) / 2l;
32110 edges = points->items + faces - tetrahedrons->items - 1l;
32112 if (out == (tetgenio *) NULL) {
32113 outfile = fopen(edgefilename,
"w");
32114 if (outfile == (FILE *) NULL) {
32115 printf(
"File I/O Error: Cannot create file %s.\n", edgefilename);
32116 terminatetetgen(1);
32119 fprintf(outfile,
"%ld %d\n", edges, !b->nobound);
32122 out->edgelist =
new int[edges * 2];
32123 if (out->edgelist == (
int *) NULL) {
32124 printf(
"Error: Out of memory.\n");
32125 terminatetetgen(1);
32128 out->edgemarkerlist =
new int[edges];
32130 out->numberofedges = edges;
32131 elist = out->edgelist;
32132 emlist = out->edgemarkerlist;
32136 firstindex = b->zeroindex ? 0 : in->firstnumber;
32138 if ((in->firstnumber == 1) && (firstindex == 0)) {
32142 tetrahedrons->traversalinit();
32143 tetloop.tet = tetrahedrontraverse();
32144 edgenumber = firstindex;
32145 while (tetloop.tet != (tetrahedron *) NULL) {
32149 worktet.tet = tetloop.tet;
32150 for (i = 0; i < 6; i++) {
32151 worktet.loc = edge2locver[i][0];
32152 worktet.ver = edge2locver[i][1];
32153 adjustedgering(worktet, CW);
32156 while (hitbdry < 2) {
32157 if (fnextself(spintet)) {
32158 if (apex(spintet) == apex(worktet))
break;
32159 if (spintet.tet < worktet.tet)
break;
32163 esym(worktet, spintet);
32164 fnextself(spintet);
32169 if (spintet.tet >= worktet.tet) {
32170 torg = org(worktet);
32171 tdest = dest(worktet);
32172 if (out == (tetgenio *) NULL) {
32173 fprintf(outfile,
"%5d %4d %4d", edgenumber,
32174 pointmark(torg) - shift, pointmark(tdest) - shift);
32177 elist[index++] = pointmark(torg) - shift;
32178 elist[index++] = pointmark(tdest) - shift;
32185 if ((b->plc || b->refine) && in->facetmarkerlist) {
32186 tspivot(spintet, checksh);
32187 faceid = shellmark(checksh) - 1;
32188 marker = in->facetmarkerlist[faceid];
32195 if (out == (tetgenio *) NULL) {
32196 fprintf(outfile,
" %d", marker);
32198 emlist[index1++] = marker;
32201 if (out == (tetgenio *) NULL) {
32202 fprintf(outfile,
"\n");
32207 tetloop.tet = tetrahedrontraverse();
32210 if (out == (tetgenio *) NULL) {
32211 fprintf(outfile,
"# Generated by %s\n", b->commandline);
32222 void tetgenmesh::outsubsegments(tetgenio* out)
32225 char edgefilename[FILENAMESIZE];
32230 int firstindex, shift;
32233 if (out == (tetgenio *) NULL) {
32234 strcpy(edgefilename, b->outfilename);
32235 strcat(edgefilename,
".edge");
32239 if (out == (tetgenio *) NULL) {
32240 printf(
"Writing %s.\n", edgefilename);
32242 printf(
"Writing edges.\n");
32247 outfile = (FILE *) NULL;
32248 elist = (
int *) NULL;
32251 if (out == (tetgenio *) NULL) {
32252 outfile = fopen(edgefilename,
"w");
32253 if (outfile == (FILE *) NULL) {
32254 printf(
"File I/O Error: Cannot create file %s.\n", edgefilename);
32255 terminatetetgen(1);
32258 fprintf(outfile,
"%ld\n", subsegs->items);
32261 out->edgelist =
new int[subsegs->items * 2];
32262 if (out->edgelist == (
int *) NULL) {
32263 printf(
"Error: Out of memory.\n");
32264 terminatetetgen(1);
32266 out->numberofedges = subsegs->items;
32267 elist = out->edgelist;
32271 firstindex = b->zeroindex ? 0 : in->firstnumber;
32273 if ((in->firstnumber == 1) && (firstindex == 0)) {
32277 subsegs->traversalinit();
32278 edgeloop.sh = shellfacetraverse(subsegs);
32279 edgenumber = firstindex;
32280 while (edgeloop.sh != (shellface *) NULL) {
32281 torg = sorg(edgeloop);
32282 tdest = sdest(edgeloop);
32283 if (out == (tetgenio *) NULL) {
32284 fprintf(outfile,
"%5d %4d %4d\n", edgenumber,
32285 pointmark(torg) - shift, pointmark(tdest) - shift);
32288 elist[index++] = pointmark(torg) - shift;
32289 elist[index++] = pointmark(tdest) - shift;
32292 edgeloop.sh = shellfacetraverse(subsegs);
32295 if (out == (tetgenio *) NULL) {
32296 fprintf(outfile,
"# Generated by %s\n", b->commandline);
32307 void tetgenmesh::outneighbors(tetgenio* out)
32310 char neighborfilename[FILENAMESIZE];
32313 triface tetloop, tetsym;
32314 int neighbor1, neighbor2, neighbor3, neighbor4;
32318 if (out == (tetgenio *) NULL) {
32319 strcpy(neighborfilename, b->outfilename);
32320 strcat(neighborfilename,
".neigh");
32324 if (out == (tetgenio *) NULL) {
32325 printf(
"Writing %s.\n", neighborfilename);
32327 printf(
"Writing neighbors.\n");
32332 outfile = (FILE *) NULL;
32333 nlist = (
int *) NULL;
32336 if (out == (tetgenio *) NULL) {
32337 outfile = fopen(neighborfilename,
"w");
32338 if (outfile == (FILE *) NULL) {
32339 printf(
"File I/O Error: Cannot create file %s.\n", neighborfilename);
32340 terminatetetgen(1);
32343 fprintf(outfile,
"%ld %d\n", tetrahedrons->items, 4);
32346 out->neighborlist =
new int[tetrahedrons->items * 4];
32347 if (out->neighborlist == (
int *) NULL) {
32348 printf(
"Error: Out of memory.\n");
32349 terminatetetgen(1);
32351 nlist = out->neighborlist;
32355 firstindex = b->zeroindex ? 0 : in->firstnumber;
32357 tetrahedrons->traversalinit();
32358 tetloop.tet = tetrahedrontraverse();
32359 elementnumber = firstindex;
32360 while (tetloop.tet != (tetrahedron *) NULL) {
32362 sym(tetloop, tetsym);
32363 neighbor1 = * (
int *) (tetsym.tet + elemmarkerindex);
32365 sym(tetloop, tetsym);
32366 neighbor2 = * (
int *) (tetsym.tet + elemmarkerindex);
32368 sym(tetloop, tetsym);
32369 neighbor3 = * (
int *) (tetsym.tet + elemmarkerindex);
32371 sym(tetloop, tetsym);
32372 neighbor4 = * (
int *) (tetsym.tet + elemmarkerindex);
32373 if (out == (tetgenio *) NULL) {
32375 fprintf(outfile,
"%4d %4d %4d %4d %4d\n", elementnumber,
32376 neighbor1, neighbor2, neighbor3, neighbor4);
32378 nlist[index++] = neighbor1;
32379 nlist[index++] = neighbor2;
32380 nlist[index++] = neighbor3;
32381 nlist[index++] = neighbor4;
32383 tetloop.tet = tetrahedrontraverse();
32387 if (out == (tetgenio *) NULL) {
32388 fprintf(outfile,
"# Generated by %s\n", b->commandline);
32411 void tetgenmesh::outvoronoi(tetgenio* out)
32414 char outfilename[FILENAMESIZE];
32415 tetgenio::voroedge *vedge;
32416 tetgenio::vorofacet *vfacet;
32417 list *tetlist, *ptlist;
32418 triface tetloop, worktet, spintet;
32419 point pt[4], ptloop, neipt;
32420 REAL ccent[3], infvec[3], vec1[3], vec2[3], L;
32422 int *tetfaceindexarray, *tetedgeindexarray;
32423 int arraysize, *vertarray;
32424 int vpointcount, vedgecount, vfacecount, tcount;
32427 int hitbdry, i, j, k;
32435 if (out == (tetgenio *) NULL) {
32436 strcpy(outfilename, b->outfilename);
32437 strcat(outfilename,
".v.node");
32441 if (out == (tetgenio *) NULL) {
32442 printf(
"Writing %s.\n", outfilename);
32444 printf(
"Writing Voronoi vertices.\n");
32449 shift = (b->zeroindex ? 0 : in->firstnumber);
32451 faces = (4l * tetrahedrons->items + hullsize) / 2l;
32453 edges = points->items + faces - tetrahedrons->items - 1;
32454 outfile = (FILE *) NULL;
32456 if (out == (tetgenio *) NULL) {
32457 outfile = fopen(outfilename,
"w");
32458 if (outfile == (FILE *) NULL) {
32459 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
32460 terminatetetgen(1);
32463 fprintf(outfile,
"%ld 3 0 0\n", tetrahedrons->items);
32466 out->numberofvpoints = (int) tetrahedrons->items;
32467 out->vpointlist =
new REAL[out->numberofvpoints * 3];
32468 if (out->vpointlist == (REAL *) NULL) {
32469 printf(
"Error: Out of memory.\n");
32470 terminatetetgen(1);
32477 tetrahedrons->traversalinit();
32478 tetloop.tet = tetrahedrontraverse();
32481 while (tetloop.tet != (tetrahedron *) NULL) {
32483 for (i = 0; i < 4; i++) {
32484 pt[i] = (point) tetloop.tet[4 + i];
32485 setpoint2tet(pt[i], encode(tetloop));
32487 circumsphere(pt[0], pt[1], pt[2], pt[3], ccent, NULL);
32488 if (out == (tetgenio *) NULL) {
32489 fprintf(outfile,
"%4d %16.8e %16.8e %16.8e\n", vpointcount + shift,
32490 ccent[0], ccent[1], ccent[2]);
32492 out->vpointlist[index++] = ccent[0];
32493 out->vpointlist[index++] = ccent[1];
32494 out->vpointlist[index++] = ccent[2];
32497 * (
int *) (tetloop.tet + elemmarkerindex) = vpointcount;
32499 tetloop.tet = tetrahedrontraverse();
32502 * (
int *) (dummytet + elemmarkerindex) = -1;
32504 if (out == (tetgenio *) NULL) {
32505 fprintf(outfile,
"# Generated by %s\n", b->commandline);
32510 if (out == (tetgenio *) NULL) {
32511 strcpy(outfilename, b->outfilename);
32512 strcat(outfilename,
".v.edge");
32516 if (out == (tetgenio *) NULL) {
32517 printf(
"Writing %s.\n", outfilename);
32519 printf(
"Writing Voronoi edges.\n");
32523 if (out == (tetgenio *) NULL) {
32524 outfile = fopen(outfilename,
"w");
32525 if (outfile == (FILE *) NULL) {
32526 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
32527 terminatetetgen(1);
32530 fprintf(outfile,
"%ld 0\n", faces);
32533 out->numberofedges = (int) faces;
32534 out->vedgelist =
new tetgenio::voroedge[out->numberofvedges];
32542 tetfaceindexarray =
new int[tetrahedrons->items * 4];
32543 tetrahedrons->traversalinit();
32544 tetloop.tet = tetrahedrontraverse();
32547 while (tetloop.tet != (tetrahedron *) NULL) {
32551 end1 = * (
int *) (tetloop.tet + elemmarkerindex);
32552 for (i = 0; i < 4; i++) {
32553 decode(tetloop.tet[i], worktet);
32554 if ((worktet.tet == dummytet) || (tetloop.tet < worktet.tet)) {
32555 if (out == (tetgenio *) NULL) {
32556 fprintf(outfile,
"%4d %4d", vedgecount + shift, end1 + shift);
32558 vedge = &(out->vedgelist[index++]);
32559 vedge->v1 = end1 + shift;
32561 end2 = * (
int *) (worktet.tet + elemmarkerindex);
32565 worktet.tet = tetloop.tet;
32568 pt[0] = org(worktet);
32569 pt[1] = dest(worktet);
32570 pt[2] = apex(worktet);
32571 for (j = 0; j < 3; j++) vec1[j] = pt[1][j] - pt[0][j];
32572 for (j = 0; j < 3; j++) vec2[j] = pt[2][j] - pt[0][j];
32573 cross(vec1, vec2, infvec);
32575 L = sqrt(infvec[0] * infvec[0] + infvec[1] * infvec[1]
32576 + infvec[2] * infvec[2]);
32577 if (L > 0)
for (j = 0; j < 3; j++) infvec[j] /= L;
32578 if (out == (tetgenio *) NULL) {
32579 fprintf(outfile,
" -1");
32580 fprintf(outfile,
" %g %g %g\n", infvec[0], infvec[1], infvec[2]);
32583 vedge->vnormal[0] = infvec[0];
32584 vedge->vnormal[1] = infvec[1];
32585 vedge->vnormal[2] = infvec[2];
32588 if (out == (tetgenio *) NULL) {
32589 fprintf(outfile,
" %4d\n", end2 + shift);
32591 vedge->v2 = end2 + shift;
32592 vedge->vnormal[0] = 0.0;
32593 vedge->vnormal[1] = 0.0;
32594 vedge->vnormal[2] = 0.0;
32598 tetfaceindexarray[end1 * 4 + i] = vedgecount;
32600 tetfaceindexarray[end2 * 4 + worktet.loc] = vedgecount;
32605 tetloop.tet = tetrahedrontraverse();
32608 if (out == (tetgenio *) NULL) {
32609 fprintf(outfile,
"# Generated by %s\n", b->commandline);
32614 if (out == (tetgenio *) NULL) {
32615 strcpy(outfilename, b->outfilename);
32616 strcat(outfilename,
".v.face");
32620 if (out == (tetgenio *) NULL) {
32621 printf(
"Writing %s.\n", outfilename);
32623 printf(
"Writing Voronoi faces.\n");
32627 if (out == (tetgenio *) NULL) {
32628 outfile = fopen(outfilename,
"w");
32629 if (outfile == (FILE *) NULL) {
32630 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
32631 terminatetetgen(1);
32634 fprintf(outfile,
"%ld 0\n", edges);
32636 out->numberofvfacets = edges;
32637 out->vfacetlist =
new tetgenio::vorofacet[out->numberofvfacets];
32638 if (out->vfacetlist == (tetgenio::vorofacet *) NULL) {
32639 printf(
"Error: Out of memory.\n");
32640 terminatetetgen(1);
32649 tetedgeindexarray =
new int[tetrahedrons->items * 6];
32650 tetrahedrons->traversalinit();
32651 tetloop.tet = tetrahedrontraverse();
32653 while (tetloop.tet != (tetrahedron *) NULL) {
32658 for (i = 0; i < 6; i++) {
32659 worktet.loc = edge2locver[i][0];
32660 worktet.ver = edge2locver[i][1];
32663 adjustedgering(worktet, CW);
32666 while (hitbdry < 2) {
32667 if (fnextself(spintet)) {
32668 if (apex(spintet) == apex(worktet))
break;
32669 if (spintet.tet < worktet.tet)
break;
32674 esym(worktet, spintet);
32675 fnextself(spintet);
32680 if (spintet.tet >= worktet.tet) {
32682 pt[0] = org(worktet);
32683 pt[1] = dest(worktet);
32684 end1 = pointmark(pt[0]) - in->firstnumber;
32685 end2 = pointmark(pt[1]) - in->firstnumber;
32686 if (out == (tetgenio *) NULL) {
32687 fprintf(outfile,
"%4d %4d %4d %-2d ", vfacecount + shift,
32688 end1 + shift, end2 + shift, tcount + (hitbdry > 0));
32690 vfacet = &(out->vfacetlist[vfacecount]);
32691 vfacet->c1 = end1 + shift;
32692 vfacet->c2 = end2 + shift;
32693 vfacet->elist =
new int[tcount + (hitbdry > 0) + 1];
32694 vfacet->elist[0] = tcount + (hitbdry > 0);
32700 vpointcount = * (
int *) (spintet.tet + elemmarkerindex);
32701 vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32702 if (out == (tetgenio *) NULL) {
32703 fprintf(outfile,
" %d", vedgecount + shift);
32705 vfacet->elist[index++] = vedgecount + shift;
32708 tetedgeindexarray[vpointcount * 6 +
32709 locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32711 fnextself(spintet);
32714 for (j = 0; j < tcount; j++) {
32715 vpointcount = * (
int *) (spintet.tet + elemmarkerindex);
32716 vedgecount = tetfaceindexarray[vpointcount * 4 + spintet.loc];
32717 if (out == (tetgenio *) NULL) {
32718 fprintf(outfile,
" %d", vedgecount + shift);
32720 vfacet->elist[index++] = vedgecount + shift;
32723 tetedgeindexarray[vpointcount * 6 +
32724 locver2edge[spintet.loc][spintet.ver]] = vfacecount;
32725 fnextself(spintet);
32727 if (out == (tetgenio *) NULL) {
32728 fprintf(outfile,
"\n");
32733 tetloop.tet = tetrahedrontraverse();
32736 if (out == (tetgenio *) NULL) {
32737 fprintf(outfile,
"# Generated by %s\n", b->commandline);
32742 if (out == (tetgenio *) NULL) {
32743 strcpy(outfilename, b->outfilename);
32744 strcat(outfilename,
".v.cell");
32748 if (out == (tetgenio *) NULL) {
32749 printf(
"Writing %s.\n", outfilename);
32751 printf(
"Writing Voronoi cells.\n");
32755 if (out == (tetgenio *) NULL) {
32756 outfile = fopen(outfilename,
"w");
32757 if (outfile == (FILE *) NULL) {
32758 printf(
"File I/O Error: Cannot create file %s.\n", outfilename);
32759 terminatetetgen(1);
32762 fprintf(outfile,
"%ld\n", points->items);
32764 out->numberofvcells = points->items;
32765 out->vcelllist =
new int*[out->numberofvcells];
32766 if (out->vcelllist == (
int **) NULL) {
32767 printf(
"Error: Out of memory.\n");
32768 terminatetetgen(1);
32773 tetlist =
new list(
sizeof(triface), NULL, 256);
32774 ptlist =
new list(
sizeof(point *), NULL, 256);
32775 points->traversalinit();
32776 ptloop = pointtraverse();
32778 while (ptloop != (point) NULL) {
32779 decode(point2tet(ptloop), tetloop);
32781 if (!isdead(&tetloop)) {
32783 tetlist->append(&tetloop);
32784 formstarpolyhedron(ptloop, tetlist, ptlist,
true);
32785 tcount = ptlist->len();
32786 if (out == (tetgenio *) NULL) {
32787 fprintf(outfile,
"%4d %-2d ", vpointcount + shift, tcount);
32789 arraysize = tcount;
32790 vertarray = out->vcelllist[vpointcount];
32791 vertarray =
new int[arraysize + 1];
32792 vertarray[0] = arraysize;
32796 for (i = 0; i < ptlist->len(); i++) {
32797 neipt = * (point *)(* ptlist)[i];
32799 for (j = 0; j < tetlist->len(); j++) {
32800 tetloop = * (triface *)(* tetlist)[j];
32801 for (k = 0; k < 6; k++) {
32802 tetloop.loc = edge2locver[k][0];
32803 tetloop.ver = edge2locver[k][1];
32804 if (org(tetloop) == ptloop) {
32805 if (dest(tetloop) == neipt)
break;
32806 }
else if (org(tetloop) == neipt) {
32807 if (dest(tetloop) == ptloop)
break;
32812 assert(j < tetlist->len());
32814 end1 = * (
int *) (tetloop.tet + elemmarkerindex);
32815 vfacecount = tetedgeindexarray[end1 * 6 + k];
32816 if (out == (tetgenio *) NULL) {
32817 fprintf(outfile,
" %d", vfacecount + shift);
32819 vertarray[index++] = vfacecount + shift;
32822 if (out == (tetgenio *) NULL) {
32823 fprintf(outfile,
"\n");
32829 ptloop = pointtraverse();
32833 delete [] tetfaceindexarray;
32834 delete [] tetedgeindexarray;
32836 if (out == (tetgenio *) NULL) {
32837 fprintf(outfile,
"# Generated by %s\n", b->commandline);
32848 void tetgenmesh::outpbcnodes(tetgenio* out)
32851 char pbcfilename[FILENAMESIZE];
32853 tetgenio::pbcgroup *pgi, *pgo;
32856 face checkseg, symseg;
32857 point *ptpair, pa, pb;
32858 enum locateresult loc;
32859 REAL sympt[3], d1, d2;
32861 int firstindex, shift;
32865 if (out == (tetgenio *) NULL) {
32866 strcpy(pbcfilename, b->outfilename);
32867 strcat(pbcfilename,
".pbc");
32871 if (out == (tetgenio *) NULL) {
32872 printf(
"Writing %s.\n", pbcfilename);
32874 printf(
"Writing pbc nodes.\n");
32879 outfile = (FILE *) NULL;
32880 pgo = (tetgenio::pbcgroup *) NULL;
32883 if (out == (tetgenio *) NULL) {
32884 outfile = fopen(pbcfilename,
"w");
32885 if (outfile == (FILE *) NULL) {
32886 printf(
"File I/O Error: Cannot create file %s.\n", pbcfilename);
32887 terminatetetgen(1);
32890 fprintf(outfile,
"# number of PBCs.\n");
32891 fprintf(outfile,
"%d\n\n", in->numberofpbcgroups);
32893 out->numberofpbcgroups = in->numberofpbcgroups;
32895 out->pbcgrouplist =
new tetgenio::pbcgroup[in->numberofpbcgroups];
32897 if (out->pbcgrouplist == (tetgenio::pbcgroup *) NULL) {
32898 printf(
"Error: Out of memory.\n");
32899 terminatetetgen(1);
32903 ptpairlist =
new list(2 *
sizeof(point *), NULL, 256);
32904 worklist =
new int[points->items + 1];
32905 for (i = 0; i < points->items + 1; i++) worklist[i] = 0;
32908 firstindex = b->zeroindex ? 0 : in->firstnumber;
32910 if ((in->firstnumber == 1) && (firstindex == 0)) {
32914 for (i = 0; i < in->numberofpbcgroups; i++) {
32916 pgi = &(in->pbcgrouplist[i]);
32917 if (out == (tetgenio *) NULL) {
32918 fprintf(outfile,
"# PBC %d\n", in->firstnumber + i);
32920 fprintf(outfile,
"%d %d\n", pgi->fmark1, pgi->fmark2);
32922 fprintf(outfile,
"[\n");
32923 for (j = 0; j < 4; j++) {
32924 fprintf(outfile,
" %.12g %.12g %.12g %.12g\n", pgi->transmat[j][0],
32925 pgi->transmat[j][1], pgi->transmat[j][2], pgi->transmat[j][3]);
32927 fprintf(outfile,
"]\n");
32929 pgo = &(out->pbcgrouplist[i]);
32931 pgo->fmark1 = pgi->fmark1;
32932 pgo->fmark2 = pgi->fmark2;
32933 for (j = 0; j < 4; j++) {
32934 for (k = 0; k < 4; k++) pgo->transmat[j][k] = pgi->transmat[j][k];
32939 subfaces->traversalinit();
32940 faceloop.sh = shellfacetraverse(subfaces);
32941 while (faceloop.sh != (shellface *) NULL) {
32942 if (shellpbcgroup(faceloop) == i) {
32944 idx = shellmark(faceloop) - 1;
32945 if (in->facetmarkerlist[idx] == pgi->fmark1) {
32947 for (j = 0; j < 3; j++) {
32948 sspivot(faceloop, checkseg);
32950 for (k = 0; k < 2; k++) {
32951 if (k == 0) pa = sorg(faceloop);
32952 else pa = sdest(faceloop);
32953 if (worklist[pointmark(pa)] == 0) {
32955 if (checkseg.sh != dummysh) {
32958 idx = shellmark(checkseg) - 1;
32959 for (l = idx2segpglist[idx]; l < idx2segpglist[idx + 1];
32961 pd = (pbcdata *)(* segpbcgrouptable)[segpglist[l]];
32962 if (((pd->fmark[0] == pgi->fmark1) &&
32963 (pd->fmark[1] == pgi->fmark2)) ||
32964 ((pd->fmark[0] == pgi->fmark2) &&
32965 (pd->fmark[1] == pgi->fmark1)))
break;
32968 assert(l < idx2segpglist[idx + 1]);
32970 loc = getsegpbcsympoint(pa, &checkseg, sympt, &symseg,
32972 if (loc != ONVERTEX) {
32976 d1 = distance(sympt, sorg(symseg));
32977 d2 = distance(sympt, sdest(symseg));
32978 if (d1 > d2) sesymself(symseg);
32983 if (pointtype(pa) == FREESUBVERTEX) {
32984 pb = point2pbcpt(pa);
32987 if (pb != (point) NULL) {
32989 ptpair = (point *) ptpairlist->append(NULL);
32993 worklist[pointmark(pa)] = 1;
32998 senextself(faceloop);
33002 faceloop.sh = shellfacetraverse(subfaces);
33006 if (out == (tetgenio *) NULL) {
33007 fprintf(outfile,
"%d\n", ptpairlist->len());
33009 pgo->numberofpointpairs = ptpairlist->len();
33010 pgo->pointpairlist =
new int[pgo->numberofpointpairs * 2];
33013 for (j = 0; j < ptpairlist->len(); j++) {
33014 ptpair = (point *)(* ptpairlist)[j];
33017 if (out == (tetgenio *) NULL) {
33018 fprintf(outfile,
" %4d %4d\n", pointmark(pa) - shift,
33019 pointmark(pb) - shift);
33021 pgo->pointpairlist[index++] = pointmark(pa) - shift;
33022 pgo->pointpairlist[index++] = pointmark(pb) - shift;
33025 worklist[pointmark(pa)] = 0;
33027 if (out == (tetgenio *) NULL) {
33028 fprintf(outfile,
"\n");
33030 ptpairlist->clear();
33033 delete [] worklist;
33036 if (out == (tetgenio *) NULL) {
33037 fprintf(outfile,
"# Generated by %s\n", b->commandline);
33053 void tetgenmesh::outsmesh(
char* smfilename)
33056 char nodfilename[FILENAMESIZE];
33057 char smefilename[FILENAMESIZE];
33060 int firstindex, shift;
33062 int faceid, marker;
33065 if (smfilename != (
char *) NULL && smfilename[0] !=
'\0') {
33066 strcpy(smefilename, smfilename);
33067 }
else if (b->outfilename[0] !=
'\0') {
33068 strcpy(smefilename, b->outfilename);
33070 strcpy(smefilename,
"unnamed");
33072 strcpy(nodfilename, smefilename);
33073 strcat(smefilename,
".smesh");
33074 strcat(nodfilename,
".node");
33077 printf(
"Writing %s.\n", smefilename);
33079 outfile = fopen(smefilename,
"w");
33080 if (outfile == (FILE *) NULL) {
33081 printf(
"File I/O Error: Cannot create file %s.\n", smefilename);
33086 firstindex = b->zeroindex ? 0 : in->firstnumber;
33088 if ((in->firstnumber == 1) && (firstindex == 0)) {
33092 fprintf(outfile,
"# %s. TetGen's input file.\n", smefilename);
33093 fprintf(outfile,
"\n# part 1: node list.\n");
33094 fprintf(outfile,
"0 3 0 0 # nodes are found in %s.\n", nodfilename);
33097 bmark = !b->nobound && in->facetmarkerlist;
33099 fprintf(outfile,
"\n# part 2: facet list.\n");
33101 fprintf(outfile,
"%ld %d\n", subfaces->items, bmark);
33103 subfaces->traversalinit();
33104 faceloop.sh = shellfacetraverse(subfaces);
33105 while (faceloop.sh != (shellface *) NULL) {
33106 p1 = sorg(faceloop);
33107 p2 = sdest(faceloop);
33108 p3 = sapex(faceloop);
33110 faceid = shellmark(faceloop) - 1;
33112 marker = in->facetmarkerlist[faceid];
33117 fprintf(outfile,
"3 %4d %4d %4d", pointmark(p1) - shift,
33118 pointmark(p2) - shift, pointmark(p3) - shift);
33120 fprintf(outfile,
" %d", marker);
33122 fprintf(outfile,
"\n");
33123 faceloop.sh = shellfacetraverse(subfaces);
33127 fprintf(outfile,
"\n# part 3: hole list.\n");
33128 fprintf(outfile,
"%d\n", in->numberofholes);
33129 for (i = 0; i < in->numberofholes; i++) {
33130 fprintf(outfile,
"%d %g %g %g\n", i + in->firstnumber,
33131 in->holelist[i * 3], in->holelist[i * 3 + 1],
33132 in->holelist[i * 3 + 2]);
33136 fprintf(outfile,
"\n# part 4: region list.\n");
33137 fprintf(outfile,
"%d\n", in->numberofregions);
33138 for (i = 0; i < in->numberofregions; i++) {
33139 fprintf(outfile,
"%d %g %g %g %d %g\n", i + in->firstnumber,
33140 in->regionlist[i * 5], in->regionlist[i * 5 + 1],
33141 in->regionlist[i * 5 + 2], (
int) in->regionlist[i * 5 + 3],
33142 in->regionlist[i * 5 + 4]);
33145 fprintf(outfile,
"# Generated by %s\n", b->commandline);
33160 void tetgenmesh::outmesh2medit(
char* mfilename)
33163 char mefilename[FILENAMESIZE];
33164 tetrahedron* tetptr;
33165 triface tface, tsymface;
33166 face segloop, checkmark;
33167 point ptloop, p1, p2, p3, p4;
33172 if (mfilename != (
char *) NULL && mfilename[0] !=
'\0') {
33173 strcpy(mefilename, mfilename);
33174 }
else if (b->outfilename[0] !=
'\0') {
33175 strcpy(mefilename, b->outfilename);
33177 strcpy(mefilename,
"unnamed");
33179 strcat(mefilename,
".mesh");
33182 printf(
"Writing %s.\n", mefilename);
33184 outfile = fopen(mefilename,
"w");
33185 if (outfile == (FILE *) NULL) {
33186 printf(
"File I/O Error: Cannot create file %s.\n", mefilename);
33190 fprintf(outfile,
"MeshVersionFormatted 1\n");
33191 fprintf(outfile,
"\n");
33192 fprintf(outfile,
"Dimension\n");
33193 fprintf(outfile,
"3\n");
33194 fprintf(outfile,
"\n");
33196 fprintf(outfile,
"\n# Set of mesh vertices\n");
33197 fprintf(outfile,
"Vertices\n");
33198 fprintf(outfile,
"%ld\n", points->items);
33200 points->traversalinit();
33201 ptloop = pointtraverse();
33203 while (ptloop != (point) NULL) {
33205 fprintf(outfile,
"%.17g %.17g %.17g", ptloop[0], ptloop[1], ptloop[2]);
33206 if (in->numberofpointattributes > 0) {
33208 fprintf(outfile,
" %.17g\n", ptloop[3]);
33210 fprintf(outfile,
" 0\n");
33212 setpointmark(ptloop, pointnumber);
33213 ptloop = pointtraverse();
33218 faces = (4l * tetrahedrons->items + hullsize) / 2l;
33220 fprintf(outfile,
"\n# Set of Triangles\n");
33221 fprintf(outfile,
"Triangles\n");
33222 fprintf(outfile,
"%ld\n", faces);
33224 tetrahedrons->traversalinit();
33225 tface.tet = tetrahedrontraverse();
33232 while (tface.tet != (tetrahedron *) NULL) {
33233 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33234 sym(tface, tsymface);
33235 if (tface.tet < tsymface.tet || tsymface.tet == dummytet) {
33239 fprintf(outfile,
"%5d %5d %5d",
33240 pointmark(p1), pointmark(p2), pointmark(p3));
33241 fprintf(outfile,
" 0\n");
33244 tface.tet = tetrahedrontraverse();
33247 fprintf(outfile,
"\n# Set of Tetrahedra\n");
33248 fprintf(outfile,
"Tetrahedra\n");
33249 fprintf(outfile,
"%ld\n", tetrahedrons->items);
33251 tetrahedrons->traversalinit();
33252 tetptr = tetrahedrontraverse();
33253 while (tetptr != (tetrahedron *) NULL) {
33254 p1 = (point) tetptr[4];
33255 p2 = (point) tetptr[5];
33256 p3 = (point) tetptr[6];
33257 p4 = (point) tetptr[7];
33258 fprintf(outfile,
"%5d %5d %5d %5d",
33259 pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33260 if (in->numberoftetrahedronattributes > 0) {
33261 fprintf(outfile,
" %.17g", elemattribute(tetptr, 0));
33263 fprintf(outfile,
" 0");
33265 fprintf(outfile,
"\n");
33266 tetptr = tetrahedrontraverse();
33269 fprintf(outfile,
"\nCorners\n");
33270 fprintf(outfile,
"%d\n", in->numberofpoints);
33272 for (i = 0; i < in->numberofpoints; i++) {
33273 fprintf(outfile,
"%4d\n", i + 1);
33276 if (b->useshelles) {
33277 fprintf(outfile,
"\nEdges\n");
33278 fprintf(outfile,
"%ld\n", subsegs->items);
33280 subsegs->traversalinit();
33281 segloop.sh = shellfacetraverse(subsegs);
33282 while (segloop.sh != (shellface *) NULL) {
33283 p1 = sorg(segloop);
33284 p2 = sdest(segloop);
33285 fprintf(outfile,
"%5d %5d", pointmark(p1), pointmark(p2));
33286 fprintf(outfile,
" 0\n");
33287 segloop.sh = shellfacetraverse(subsegs);
33291 fprintf(outfile,
"\nEnd\n");
33307 void tetgenmesh::outmesh2gid(
char* gfilename)
33310 char gidfilename[FILENAMESIZE];
33311 tetrahedron* tetptr;
33312 triface tface, tsymface;
33314 point ptloop, p1, p2, p3, p4;
33318 if (gfilename != (
char *) NULL && gfilename[0] !=
'\0') {
33319 strcpy(gidfilename, gfilename);
33320 }
else if (b->outfilename[0] !=
'\0') {
33321 strcpy(gidfilename, b->outfilename);
33323 strcpy(gidfilename,
"unnamed");
33325 strcat(gidfilename,
".ele.msh");
33328 printf(
"Writing %s.\n", gidfilename);
33330 outfile = fopen(gidfilename,
"w");
33331 if (outfile == (FILE *) NULL) {
33332 printf(
"File I/O Error: Cannot create file %s.\n", gidfilename);
33336 fprintf(outfile,
"mesh dimension = 3 elemtype tetrahedron nnode = 4\n");
33337 fprintf(outfile,
"coordinates\n");
33339 points->traversalinit();
33340 ptloop = pointtraverse();
33342 while (ptloop != (point) NULL) {
33344 fprintf(outfile,
"%4d %.17g %.17g %.17g", pointnumber,
33345 ptloop[0], ptloop[1], ptloop[2]);
33346 if (in->numberofpointattributes > 0) {
33348 fprintf(outfile,
" %.17g", ptloop[3]);
33350 fprintf(outfile,
"\n");
33351 setpointmark(ptloop, pointnumber);
33352 ptloop = pointtraverse();
33356 fprintf(outfile,
"end coordinates\n");
33357 fprintf(outfile,
"elements\n");
33359 tetrahedrons->traversalinit();
33360 tetptr = tetrahedrontraverse();
33362 while (tetptr != (tetrahedron *) NULL) {
33363 p1 = (point) tetptr[4];
33364 p2 = (point) tetptr[5];
33365 p3 = (point) tetptr[6];
33366 p4 = (point) tetptr[7];
33367 fprintf(outfile,
"%5d %5d %5d %5d %5d", elementnumber,
33368 pointmark(p1), pointmark(p2), pointmark(p3), pointmark(p4));
33369 if (in->numberoftetrahedronattributes > 0) {
33370 fprintf(outfile,
" %.17g", elemattribute(tetptr, 0));
33372 fprintf(outfile,
"\n");
33373 tetptr = tetrahedrontraverse();
33377 fprintf(outfile,
"end elements\n");
33380 if (gfilename != (
char *) NULL && gfilename[0] !=
'\0') {
33381 strcpy(gidfilename, gfilename);
33382 }
else if (b->outfilename[0] !=
'\0') {
33383 strcpy(gidfilename, b->outfilename);
33385 strcpy(gidfilename,
"unnamed");
33387 strcat(gidfilename,
".face.msh");
33390 printf(
"Writing %s.\n", gidfilename);
33392 outfile = fopen(gidfilename,
"w");
33393 if (outfile == (FILE *) NULL) {
33394 printf(
"File I/O Error: Cannot create file %s.\n", gidfilename);
33398 fprintf(outfile,
"mesh dimension = 3 elemtype triangle nnode = 3\n");
33399 fprintf(outfile,
"coordinates\n");
33401 points->traversalinit();
33402 ptloop = pointtraverse();
33404 while (ptloop != (point) NULL) {
33406 fprintf(outfile,
"%4d %.17g %.17g %.17g", pointnumber,
33407 ptloop[0], ptloop[1], ptloop[2]);
33408 if (in->numberofpointattributes > 0) {
33410 fprintf(outfile,
" %.17g", ptloop[3]);
33412 fprintf(outfile,
"\n");
33413 setpointmark(ptloop, pointnumber);
33414 ptloop = pointtraverse();
33418 fprintf(outfile,
"end coordinates\n");
33419 fprintf(outfile,
"elements\n");
33421 tetrahedrons->traversalinit();
33422 tface.tet = tetrahedrontraverse();
33424 while (tface.tet != (tetrahedron *) NULL) {
33425 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33426 sym(tface, tsymface);
33427 if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33431 if (tsymface.tet == dummytet) {
33433 fprintf(outfile,
"%5d %d %d %d\n", elementnumber,
33434 pointmark(p1), pointmark(p2), pointmark(p3));
33436 }
else if (b->useshelles) {
33438 tspivot(tface, sface);
33439 if (sface.sh != dummysh) {
33440 fprintf(outfile,
"%5d %d %d %d\n", elementnumber,
33441 pointmark(p1), pointmark(p2), pointmark(p3));
33447 tface.tet = tetrahedrontraverse();
33450 fprintf(outfile,
"end elements\n");
33463 void tetgenmesh::outmesh2off(
char* ofilename)
33466 char offfilename[FILENAMESIZE];
33467 triface tface, tsymface;
33468 point ptloop, p1, p2, p3;
33472 if (ofilename != (
char *) NULL && ofilename[0] !=
'\0') {
33473 strcpy(offfilename, ofilename);
33474 }
else if (b->outfilename[0] !=
'\0') {
33475 strcpy(offfilename, b->outfilename);
33477 strcpy(offfilename,
"unnamed");
33479 strcat(offfilename,
".off");
33482 printf(
"Writing %s.\n", offfilename);
33484 outfile = fopen(offfilename,
"w");
33485 if (outfile == (FILE *) NULL) {
33486 printf(
"File I/O Error: Cannot create file %s.\n", offfilename);
33491 faces = (4l * tetrahedrons->items + hullsize) / 2l;
33494 fprintf(outfile,
"OFF\n%ld %ld %ld\n", points->items, faces, hullsize);
33497 points->traversalinit();
33498 ptloop = pointtraverse();
33499 while (ptloop != (point) NULL) {
33500 fprintf(outfile,
" %.17g %.17g %.17g\n",ptloop[0], ptloop[1], ptloop[2]);
33501 ptloop = pointtraverse();
33505 shift = in->firstnumber == 1 ? 1 : 0;
33507 tetrahedrons->traversalinit();
33508 tface.tet = tetrahedrontraverse();
33515 while (tface.tet != (tetrahedron *) NULL) {
33516 for (tface.loc = 0; tface.loc < 4; tface.loc ++) {
33517 sym(tface, tsymface);
33518 if ((tface.tet < tsymface.tet) || (tsymface.tet == dummytet)) {
33523 fprintf(outfile,
"3 %4d %4d %4d\n", pointmark(p1) - shift,
33524 pointmark(p2) - shift, pointmark(p3) - shift);
33527 tface.tet = tetrahedrontraverse();
33530 fprintf(outfile,
"# Generated by %s\n", b->commandline);
33548 void tetgenmesh::internalerror()
33550 printf(
" Please report this bug to sihang@mail.berlios.de. Include the\n");
33551 printf(
" message above, your input data set, and the exact command\n");
33552 printf(
" line you used to run this program, thank you.\n");
33553 terminatetetgen(2);
33562 void tetgenmesh::checkmesh()
33565 triface oppotet, oppooppotet;
33566 point tetorg, tetdest, tetapex, tetoppo;
33571 printf(
" Checking consistency of mesh...\n");
33576 tetrahedrons->traversalinit();
33577 tetraloop.tet = tetrahedrontraverse();
33578 while (tetraloop.tet != (tetrahedron *) NULL) {
33580 for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33581 tetorg = org(tetraloop);
33582 tetdest = dest(tetraloop);
33583 tetapex = apex(tetraloop);
33584 tetoppo = oppo(tetraloop);
33585 if (tetraloop.loc == 0) {
33586 oritest = orient3d(tetorg, tetdest, tetapex, tetoppo);
33587 if (oritest >= 0.0) {
33588 printf(
" !! !! %s ", oritest > 0.0 ?
"Inverted" :
"Degenerated");
33589 printtet(&tetraloop);
33590 printf(
" orient3d = %.17g.\n", oritest);
33595 sym(tetraloop, oppotet);
33596 if (oppotet.tet != dummytet) {
33598 sym(oppotet, oppooppotet);
33599 if ((tetraloop.tet != oppooppotet.tet)
33600 || (tetraloop.loc != oppooppotet.loc)) {
33601 printf(
" !! !! Asymmetric tetra-tetra bond:\n");
33602 if (tetraloop.tet == oppooppotet.tet) {
33603 printf(
" (Right tetrahedron, wrong orientation)\n");
33606 printtet(&tetraloop);
33607 printf(
" Second (nonreciprocating) ");
33608 printtet(&oppotet);
33613 tetraloop.tet = tetrahedrontraverse();
33615 if (horrors == 0) {
33617 printf(
" In my studied opinion, the mesh appears to be consistent.\n");
33619 }
else if (horrors == 1) {
33620 printf(
" !! !! !! !! Precisely one festering wound discovered.\n");
33622 printf(
" !! !! !! !! %d abominations witnessed.\n", horrors);
33632 void tetgenmesh::checkshells()
33634 triface oppotet, oppooppotet, testtet;
33635 face shloop, segloop, spin;
33636 face testsh, testseg, testshsh;
33637 point shorg, shdest, segorg, segdest;
33644 printf(
" Checking consistency of the mesh boundary...\n");
33649 subfaces->traversalinit();
33650 shloop.sh = shellfacetraverse(subfaces);
33651 while (shloop.sh != (shellface *) NULL) {
33654 stpivot(shloop, oppotet);
33655 if (oppotet.tet != dummytet) {
33656 tspivot(oppotet, testsh);
33657 if (testsh.sh != shloop.sh) {
33658 printf(
" !! !! Wrong tetra-subface connection.\n");
33659 printf(
" Tetra: ");
33660 printtet(&oppotet);
33661 printf(
" Subface: ");
33665 if (oppo(oppotet) != (point) NULL) {
33666 adjustedgering(oppotet, CCW);
33667 checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33669 if (checksign >= 0.0) {
33670 printf(
" !! !! Wrong subface orientation.\n");
33671 printf(
" Subface: ");
33678 stpivot(shloop, oppooppotet);
33679 if (oppooppotet.tet != dummytet) {
33680 tspivot(oppooppotet, testsh);
33681 if (testsh.sh != shloop.sh) {
33682 printf(
" !! !! Wrong tetra-subface connection.\n");
33683 printf(
" Tetra: ");
33684 printtet(&oppooppotet);
33685 printf(
" Subface: ");
33689 if (oppotet.tet != dummytet) {
33690 sym(oppotet, testtet);
33691 if (testtet.tet != oppooppotet.tet) {
33692 printf(
" !! !! Wrong tetra-subface-tetra connection.\n");
33693 printf(
" Tetra 1: ");
33694 printtet(&oppotet);
33695 printf(
" Subface: ");
33697 printf(
" Tetra 2: ");
33698 printtet(&oppooppotet);
33702 if (oppo(oppooppotet) != (point) NULL) {
33703 adjustedgering(oppooppotet, CCW);
33704 checksign = orient3d(sorg(shloop), sdest(shloop), sapex(shloop),
33705 oppo(oppooppotet));
33706 if (checksign >= 0.0) {
33707 printf(
" !! !! Wrong subface orientation.\n");
33708 printf(
" Subface: ");
33716 for (i = 0; i < 3; i++) {
33717 shorg = sorg(shloop);
33718 shdest = sdest(shloop);
33719 sspivot(shloop, testseg);
33720 if (testseg.sh != dummysh) {
33721 segorg = sorg(testseg);
33722 segdest = sdest(testseg);
33723 same = ((shorg == segorg) && (shdest == segdest))
33724 || ((shorg == segdest) && (shdest == segorg));
33726 printf(
" !! !! Wrong subface-subsegment connection.\n");
33727 printf(
" Subface: ");
33729 printf(
" Subsegment: ");
33734 spivot(shloop, testsh);
33735 if (testsh.sh != dummysh) {
33736 segorg = sorg(testsh);
33737 segdest = sdest(testsh);
33738 same = ((shorg == segorg) && (shdest == segdest))
33739 || ((shorg == segdest) && (shdest == segorg));
33741 printf(
" !! !! Wrong subface-subface connection.\n");
33742 printf(
" Subface 1: ");
33744 printf(
" Subface 2: ");
33748 spivot(testsh, testshsh);
33749 shorg = sorg(testshsh);
33750 shdest = sdest(testshsh);
33751 same = ((shorg == segorg) && (shdest == segdest))
33752 || ((shorg == segdest) && (shdest == segorg));
33754 printf(
" !! !! Wrong subface-subface connection.\n");
33755 printf(
" Subface 1: ");
33757 printf(
" Subface 2: ");
33758 printsh(&testshsh);
33761 if (testseg.sh == dummysh) {
33762 if (testshsh.sh != shloop.sh) {
33763 printf(
" !! !! Wrong subface-subface connection.\n");
33764 printf(
" Subface 1: ");
33766 printf(
" Subface 2: ");
33772 senextself(shloop);
33774 shloop.sh = shellfacetraverse(subfaces);
33778 subsegs->traversalinit();
33779 segloop.sh = shellfacetraverse(subsegs);
33780 while (segloop.sh != (shellface *) NULL) {
33781 segorg = sorg(segloop);
33782 segdest = sdest(segloop);
33783 spivot(segloop, testsh);
33784 if (testsh.sh == dummysh) {
33785 printf(
" !! !! Wrong subsegment-subface connection.\n");
33786 printf(
" Subsegment: ");
33789 segloop.sh = shellfacetraverse(subsegs);
33792 shorg = sorg(testsh);
33793 shdest = sdest(testsh);
33794 same = ((shorg == segorg) && (shdest == segdest))
33795 || ((shorg == segdest) && (shdest == segorg));
33797 printf(
" !! !! Wrong subsegment-subface connection.\n");
33798 printf(
" Subsegment : ");
33800 printf(
" Subface : ");
33803 segloop.sh = shellfacetraverse(subsegs);
33811 shorg = sorg(spin);
33812 shdest = sdest(spin);
33813 same = ((shorg == segorg) && (shdest == segdest))
33814 || ((shorg == segdest) && (shdest == segorg));
33816 printf(
" !! !! Wrong subsegment-subface connection.\n");
33817 printf(
" Subsegment : ");
33819 printf(
" Subface : ");
33825 }
while (spin.sh != testsh.sh && i < 1000);
33827 printf(
" !! !! Wrong subsegment-subface connection.\n");
33828 printf(
" Subsegment : ");
33832 segloop.sh = shellfacetraverse(subsegs);
33834 if (horrors == 0) {
33836 printf(
" Mesh boundaries connected correctly.\n");
33839 printf(
" !! !! !! !! %d boundary connection viewed with horror.\n",
33853 void tetgenmesh::checkdelaunay(REAL eps, queue* flipqueue)
33858 point tetorg, tetdest, tetapex, tetoppo;
33862 int shouldbedelaunay;
33866 printf(
" Checking Delaunay property of the mesh...\n");
33870 tetrahedrons->traversalinit();
33871 tetraloop.tet = tetrahedrontraverse();
33872 while (tetraloop.tet != (tetrahedron *) NULL) {
33874 for (tetraloop.loc = 0; tetraloop.loc < 4; tetraloop.loc++) {
33875 tetorg = org(tetraloop);
33876 tetdest = dest(tetraloop);
33877 tetapex = apex(tetraloop);
33878 tetoppo = oppo(tetraloop);
33879 sym(tetraloop, oppotet);
33880 oppooppo = oppo(oppotet);
33883 shouldbedelaunay = (oppotet.tet != dummytet)
33884 && (tetoppo != (point) NULL)
33885 && (oppooppo != (point) NULL)
33886 && (tetraloop.tet < oppotet.tet);
33887 if (checksubfaces && shouldbedelaunay) {
33890 tspivot(tetraloop, opposhelle);
33891 if (opposhelle.sh != dummysh){
33892 shouldbedelaunay = 0;
33895 if (shouldbedelaunay) {
33896 sign = insphere(tetdest, tetorg, tetapex, tetoppo, oppooppo);
33897 if ((sign > 0.0) && (eps > 0.0)) {
33898 if (iscospheric(tetdest, tetorg, tetapex, tetoppo, oppooppo, sign,
33903 enqueueflipface(tetraloop, flipqueue);
33905 printf(
" !! Non-locally Delaunay face (%d, %d, %d) ",
33906 pointmark(tetorg), pointmark(tetdest), pointmark(tetapex));
33907 fc = categorizeface(tetraloop);
33909 case T23: printf(
"\"T23\"");
break;
33910 case T32: printf(
"\"T32\"");
break;
33911 case T22: printf(
"\"T22\"");
break;
33912 case T44: printf(
"\"T44\"");
break;
33913 case N32: printf(
"\"N32\"");
break;
33914 case N40: printf(
"\"N40\"");
break;
33915 case FORBIDDENFACE:printf(
"\"FORBIDDENFACE\"");
break;
33916 case FORBIDDENEDGE:printf(
"\"FORBIDDENEDGE\"");
break;
33924 tetraloop.tet = tetrahedrontraverse();
33926 if (flipqueue == (queue *) NULL) {
33927 if (horrors == 0) {
33929 printf(
" The mesh is %s.\n",
33930 checksubfaces ?
"constrained Delaunay" :
"Delaunay");
33933 printf(
" !! !! !! !! %d obscenities viewed with horror.\n", horrors);
33944 void tetgenmesh::checkconforming()
33946 face segloop, shloop;
33947 int encsubsegs, encsubfaces;
33950 printf(
" Checking conforming Delaunay property of mesh...\n");
33952 encsubsegs = encsubfaces = 0;
33954 subsegs->traversalinit();
33955 segloop.sh = shellfacetraverse(subsegs);
33956 while (segloop.sh != (shellface *) NULL) {
33957 if (checkseg4encroach(&segloop, NULL, NULL,
false)) {
33958 printf(
" !! !! Non-conforming subsegment: (%d, %d)\n",
33959 pointmark(sorg(segloop)), pointmark(sdest(segloop)));
33962 segloop.sh = shellfacetraverse(subsegs);
33965 subfaces->traversalinit();
33966 shloop.sh = shellfacetraverse(subfaces);
33967 while (shloop.sh != (shellface *) NULL) {
33968 if (checksub4encroach(&shloop, NULL,
false)) {
33969 printf(
" !! !! Non-conforming subface: (%d, %d, %d)\n",
33970 pointmark(sorg(shloop)), pointmark(sdest(shloop)),
33971 pointmark(sapex(shloop)));
33974 shloop.sh = shellfacetraverse(subfaces);
33976 if (encsubsegs == 0 && encsubfaces == 0) {
33978 printf(
" The mesh is conforming Delaunay.\n");
33981 if (encsubsegs > 0) {
33982 printf(
" !! !! %d subsegments are non-conforming.\n", encsubsegs);
33984 if (encsubfaces > 0) {
33985 printf(
" !! !! %d subfaces are non-conforming.\n", encsubfaces);
33998 void tetgenmesh::algorithmicstatistics()
34038 #endif // #ifdef SELF_CHECK 34046 void tetgenmesh::qualitystatistics()
34048 triface tetloop, neightet;
34051 REAL radiusratiotable[12];
34052 REAL aspectratiotable[12];
34053 REAL A[4][4], rhs[4], D;
34054 REAL V[6][3], N[4][3], H[4];
34055 REAL edgelength[6], alldihed[6], faceangle[3];
34056 REAL shortest, longest;
34057 REAL smallestvolume, biggestvolume;
34058 REAL smallestdiangle, biggestdiangle;
34059 REAL smallestfaangle, biggestfaangle;
34060 REAL tetvol, minaltitude;
34061 REAL cirradius, minheightinv;
34062 REAL shortlen, longlen;
34063 REAL tetaspect, tetradius;
34064 REAL smalldiangle, bigdiangle;
34065 REAL smallfaangle, bigfaangle;
34066 int radiustable[12];
34067 int aspecttable[16];
34068 int dihedangletable[18];
34069 int faceangletable[18];
34076 smallfaangle = 0.0;
34079 printf(
"Mesh quality statistics:\n\n");
34082 shortlen = longlen = 0.0;
34083 smalldiangle = bigdiangle = 0.0;
34085 radiusratiotable[0] = 0.707; radiusratiotable[1] = 1.0;
34086 radiusratiotable[2] = 1.1; radiusratiotable[3] = 1.2;
34087 radiusratiotable[4] = 1.4; radiusratiotable[5] = 1.6;
34088 radiusratiotable[6] = 1.8; radiusratiotable[7] = 2.0;
34089 radiusratiotable[8] = 2.5; radiusratiotable[9] = 3.0;
34090 radiusratiotable[10] = 10.0; radiusratiotable[11] = 0.0;
34092 aspectratiotable[0] = 1.5; aspectratiotable[1] = 2.0;
34093 aspectratiotable[2] = 2.5; aspectratiotable[3] = 3.0;
34094 aspectratiotable[4] = 4.0; aspectratiotable[5] = 6.0;
34095 aspectratiotable[6] = 10.0; aspectratiotable[7] = 15.0;
34096 aspectratiotable[8] = 25.0; aspectratiotable[9] = 50.0;
34097 aspectratiotable[10] = 100.0; aspectratiotable[11] = 0.0;
34099 for (i = 0; i < 12; i++) radiustable[i] = 0;
34100 for (i = 0; i < 12; i++) aspecttable[i] = 0;
34101 for (i = 0; i < 18; i++) dihedangletable[i] = 0;
34102 for (i = 0; i < 18; i++) faceangletable[i] = 0;
34104 minaltitude = xmax - xmin + ymax - ymin + zmax - zmin;
34105 minaltitude = minaltitude * minaltitude;
34106 shortest = minaltitude;
34108 smallestvolume = minaltitude;
34109 biggestvolume = 0.0;
34110 smallestdiangle = smallestfaangle = 180.0;
34111 biggestdiangle = biggestfaangle = 0.0;
34114 tetrahedrons->traversalinit();
34115 tetloop.tet = tetrahedrontraverse();
34116 while (tetloop.tet != (tetrahedron *) NULL) {
34119 for (i = 0; i < 4; i++) p[i] = (point) tetloop.tet[4 + i];
34121 for (i = 0; i < 3; i++) V[0][i] = p[0][i] - p[3][i];
34122 for (i = 0; i < 3; i++) V[1][i] = p[1][i] - p[3][i];
34123 for (i = 0; i < 3; i++) V[2][i] = p[2][i] - p[3][i];
34124 for (i = 0; i < 3; i++) V[3][i] = p[1][i] - p[0][i];
34125 for (i = 0; i < 3; i++) V[4][i] = p[2][i] - p[1][i];
34126 for (i = 0; i < 3; i++) V[5][i] = p[0][i] - p[2][i];
34128 for (j = 0; j < 3; j++) {
34129 for (i = 0; i < 3; i++) A[j][i] = V[j][i];
34132 lu_decmp(A, 3, indx, &D, 0);
34134 tetvol = fabs(A[indx[0]][0] * A[indx[1]][1] * A[indx[2]][2]) / 6.0;
34136 for (j = 0; j < 3; j++) {
34137 for (i = 0; i < 3; i++) rhs[i] = 0.0;
34139 lu_solve(A, 3, indx, rhs, 0);
34140 for (i = 0; i < 3; i++) N[j][i] = rhs[i];
34143 for (i = 0; i < 3; i++) N[3][i] = - N[0][i] - N[1][i] - N[2][i];
34145 for (i = 0; i < 3; i++) rhs[i] = 0.5 * dot(V[i], V[i]);
34146 lu_solve(A, 3, indx, rhs, 0);
34147 cirradius = sqrt(dot(rhs, rhs));
34149 for (i = 0; i < 4; i++) {
34151 H[i] = sqrt(dot(N[i], N[i]));
34152 for (j = 0; j < 3; j++) N[i][j] /= H[i];
34157 minheightinv = H[0];
34158 for (i = 1; i < 3; i++) {
34159 if (H[i] > minheightinv) minheightinv = H[i];
34162 for (i = 0; i < 6; i++) edgelength[i] = dot(V[i], V[i]);
34165 for (i = 1; i < 4; i++) {
34166 alldihed[j] = -dot(N[0], N[i]);
34167 if (alldihed[j] < -1.0) alldihed[j] = -1;
34168 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34169 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34172 for (i = 2; i < 4; i++) {
34173 alldihed[j] = -dot(N[1], N[i]);
34174 if (alldihed[j] < -1.0) alldihed[j] = -1;
34175 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34176 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34179 alldihed[j] = -dot(N[2], N[3]);
34180 if (alldihed[j] < -1.0) alldihed[j] = -1;
34181 else if (alldihed[j] > 1.0) alldihed[j] = 1;
34182 alldihed[j] = acos(alldihed[j]) / PI * 180.0;
34185 for (i = 0; i < 6; i++) {
34187 shortlen = longlen = edgelength[i];
34189 shortlen = edgelength[i] < shortlen ? edgelength[i] : shortlen;
34190 longlen = edgelength[i] > longlen ? edgelength[i] : longlen;
34192 if (edgelength[i] > longest) {
34193 longest = edgelength[i];
34195 if (edgelength[i] < shortest) {
34196 shortest = edgelength[i];
34201 if (tetvol < smallestvolume) {
34202 smallestvolume = tetvol;
34204 if (tetvol > biggestvolume) {
34205 biggestvolume = tetvol;
34209 for (i = 0; i < 6; i++) {
34211 smalldiangle = bigdiangle = alldihed[i];
34213 smalldiangle = alldihed[i] < smalldiangle ? alldihed[i] : smalldiangle;
34214 bigdiangle = alldihed[i] > bigdiangle ? alldihed[i] : bigdiangle;
34216 if (alldihed[i] < smallestdiangle) {
34217 smallestdiangle = alldihed[i];
34219 if (alldihed[i] > biggestdiangle) {
34220 biggestdiangle = alldihed[i];
34224 if (smalldiangle < 5.0) {
34226 }
else if (smalldiangle >= 5.0 && smalldiangle < 10.0) {
34228 }
else if (smalldiangle >= 80.0 && smalldiangle < 110.0) {
34231 tendegree = (int) (smalldiangle / 10.);
34232 if (smalldiangle < 80.0) {
34238 dihedangletable[tendegree]++;
34239 if (bigdiangle >= 80.0 && bigdiangle < 110.0) {
34241 }
else if (bigdiangle >= 170.0 && bigdiangle < 175.0) {
34243 }
else if (bigdiangle >= 175.0) {
34246 tendegree = (int) (bigdiangle / 10.);
34247 if (bigdiangle < 80.0) {
34253 dihedangletable[tendegree]++;
34257 for (tetloop.loc = 0; tetloop.loc < 4; tetloop.loc++) {
34258 sym(tetloop, neightet);
34260 if ((neightet.tet == dummytet) || (tetloop.tet < neightet.tet)) {
34261 p[0] = org(tetloop);
34262 p[1] = dest(tetloop);
34263 p[2] = apex(tetloop);
34264 faceangle[0] = interiorangle(p[0], p[1], p[2], NULL);
34265 faceangle[1] = interiorangle(p[1], p[2], p[0], NULL);
34266 faceangle[2] = PI - (faceangle[0] + faceangle[1]);
34268 for (i = 0; i < 3; i++) {
34269 faceangle[i] = (faceangle[i] * 180.0) / PI;
34272 for (i = 0; i < 3; i++) {
34274 smallfaangle = bigfaangle = faceangle[i];
34276 smallfaangle = faceangle[i] < smallfaangle ?
34277 faceangle[i] : smallfaangle;
34278 bigfaangle = faceangle[i] > bigfaangle ? faceangle[i] : bigfaangle;
34280 if (faceangle[i] < smallestfaangle) {
34281 smallestfaangle = faceangle[i];
34283 if (faceangle[i] > biggestfaangle) {
34284 biggestfaangle = faceangle[i];
34287 tendegree = (int) (smallfaangle / 10.);
34288 faceangletable[tendegree]++;
34289 tendegree = (int) (bigfaangle / 10.);
34290 faceangletable[tendegree]++;
34295 tetradius = cirradius / sqrt(shortlen);
34297 tetaspect = sqrt(longlen) * minheightinv;
34299 while ((tetaspect > aspectratiotable[aspectindex]) && (aspectindex < 11)) {
34302 aspecttable[aspectindex]++;
34304 while ((tetradius > radiusratiotable[radiusindex]) && (radiusindex < 11)) {
34307 radiustable[radiusindex]++;
34309 tetloop.tet = tetrahedrontraverse();
34312 shortest = sqrt(shortest);
34313 longest = sqrt(longest);
34314 minaltitude = sqrt(minaltitude);
34316 printf(
" Smallest volume: %16.5g | Largest volume: %16.5g\n",
34317 smallestvolume, biggestvolume);
34318 printf(
" Shortest edge: %16.5g | Longest edge: %16.5g\n",
34319 shortest, longest);
34320 sprintf(sbuf,
"%.17g", biggestfaangle);
34321 if (strlen(sbuf) > 8) {
34324 printf(
" Smallest facangle: %14.5g | Largest facangle: %s\n",
34325 smallestfaangle, sbuf);
34326 sprintf(sbuf,
"%.17g", biggestdiangle);
34327 if (strlen(sbuf) > 8) {
34330 printf(
" Smallest dihedral: %14.5g | Largest dihedral: %s\n\n",
34331 smallestdiangle, sbuf);
34352 printf(
" Aspect ratio histogram:\n");
34353 printf(
" < %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
34354 aspectratiotable[0], aspecttable[0], aspectratiotable[5],
34355 aspectratiotable[6], aspecttable[6]);
34356 for (i = 1; i < 5; i++) {
34357 printf(
" %6.6g - %-6.6g : %8d | %6.6g - %-6.6g : %8d\n",
34358 aspectratiotable[i - 1], aspectratiotable[i], aspecttable[i],
34359 aspectratiotable[i + 5], aspectratiotable[i + 6],
34360 aspecttable[i + 6]);
34362 printf(
" %6.6g - %-6.6g : %8d | %6.6g - : %8d\n",
34363 aspectratiotable[4], aspectratiotable[5], aspecttable[5],
34364 aspectratiotable[10], aspecttable[11]);
34365 printf(
" (A tetrahedron's aspect ratio is its longest edge length");
34366 printf(
" divided by its\n");
34367 printf(
" smallest side height)\n\n");
34369 printf(
" Face angle histogram:\n");
34370 for (i = 0; i < 9; i++) {
34371 printf(
" %3d - %3d degrees: %8d | %3d - %3d degrees: %8d\n",
34372 i * 10, i * 10 + 10, faceangletable[i],
34373 i * 10 + 90, i * 10 + 100, faceangletable[i + 9]);
34375 if (minfaceang != PI) {
34376 printf(
" Minimum input face angle is %g (degree).\n",
34377 minfaceang / PI * 180.0);
34381 printf(
" Dihedral angle histogram:\n");
34383 printf(
" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34384 0, 5, dihedangletable[0], 80, 110, dihedangletable[9]);
34385 printf(
" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34386 5, 10, dihedangletable[1], 110, 120, dihedangletable[10]);
34388 for (i = 2; i < 7; i++) {
34389 printf(
" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34390 (i - 1) * 10, (i - 1) * 10 + 10, dihedangletable[i],
34391 (i - 1) * 10 + 110, (i - 1) * 10 + 120, dihedangletable[i + 9]);
34394 printf(
" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34395 60, 70, dihedangletable[7], 170, 175, dihedangletable[16]);
34396 printf(
" %3d - %2d degrees: %8d | %3d - %3d degrees: %8d\n",
34397 70, 80, dihedangletable[8], 175, 180, dihedangletable[17]);
34398 if (minfacetdihed != PI) {
34399 printf(
" Minimum input facet dihedral angle is %g (degree).\n",
34400 minfacetdihed / PI * 180.0);
34411 void tetgenmesh::statistics()
34413 printf(
"\nStatistics:\n\n");
34414 printf(
" Input points: %d\n", in->numberofpoints + jettisoninverts);
34416 printf(
" Input tetrahedra: %d\n", in->numberoftetrahedra);
34419 printf(
" Input facets: %d\n", in->numberoffacets);
34420 printf(
" Input segments: %ld\n", insegments);
34421 printf(
" Input holes: %d\n", in->numberofholes);
34422 printf(
" Input regions: %d\n", in->numberofregions);
34425 printf(
"\n Mesh points: %ld\n", points->items);
34426 printf(
" Mesh tetrahedra: %ld\n", tetrahedrons->items);
34427 if (b->plc || b->refine) {
34428 printf(
" Mesh triangles: %ld\n", (4l*tetrahedrons->items+hullsize)/2l);
34430 if (b->plc || b->refine) {
34431 printf(
" Mesh subfaces: %ld\n", subfaces->items);
34432 printf(
" Mesh subsegments: %ld\n\n", subsegs->items);
34434 printf(
" Convex hull triangles: %ld\n\n", hullsize);
34436 if (b->verbose > 0) {
34437 qualitystatistics();
34438 unsigned long totalmeshbytes;
34439 printf(
"Memory allocation statistics:\n\n");
34440 printf(
" Maximum number of vertices: %ld\n", points->maxitems);
34441 totalmeshbytes = points->maxitems * points->itembytes;
34442 printf(
" Maximum number of tetrahedra: %ld\n", tetrahedrons->maxitems);
34443 totalmeshbytes += tetrahedrons->maxitems * tetrahedrons->itembytes;
34445 printf(
" Maximum number of subfaces: %ld\n", subfaces->maxitems);
34446 totalmeshbytes += subfaces->maxitems * subfaces->itembytes;
34449 printf(
" Maximum number of segments: %ld\n", subsegs->maxitems);
34450 totalmeshbytes += subsegs->maxitems * subsegs->itembytes;
34452 printf(
" Approximate heap memory used by the mesh (K bytes): %g\n\n",
34453 (
double) totalmeshbytes / 1024.0);
34455 algorithmicstatistics();
34474 tetgenmesh::~tetgenmesh()
34476 bgm = (tetgenmesh *) NULL;
34477 in = (tetgenio *) NULL;
34478 b = (tetgenbehavior *) NULL;
34481 delete tetrahedrons;
34492 if (dummytetbase != (tetrahedron *) NULL) {
34493 delete [] dummytetbase;
34495 if (dummyshbase != (shellface *) NULL) {
34496 delete [] dummyshbase;
34498 if (facetabovepointarray != (point *) NULL) {
34499 delete [] facetabovepointarray;
34501 if (highordertable != (point *) NULL) {
34502 delete [] highordertable;
34504 if (subpbcgrouptable != (pbcdata *) NULL) {
34505 delete [] subpbcgrouptable;
34507 if (segpbcgrouptable != (list *) NULL) {
34508 delete segpbcgrouptable;
34509 delete [] idx2segpglist;
34510 delete [] segpglist;
34520 tetgenmesh::tetgenmesh()
34522 bgm = (tetgenmesh *) NULL;
34523 in = (tetgenio *) NULL;
34524 b = (tetgenbehavior *) NULL;
34535 dummytet = (tetrahedron *) NULL;
34536 dummytetbase = (tetrahedron *) NULL;
34537 dummysh = (shellface *) NULL;
34538 dummyshbase = (shellface *) NULL;
34540 facetabovepointarray = (point *) NULL;
34541 abovepoint = (point) NULL;
34542 highordertable = (point *) NULL;
34543 subpbcgrouptable = (pbcdata *) NULL;
34544 segpbcgrouptable = (list *) NULL;
34545 idx2segpglist = (
int *) NULL;
34546 segpglist = (
int *) NULL;
34548 xmax = xmin = ymax = ymin = zmax = zmin = 0.0;
34553 pointmarkindex = 0;
34554 point2simindex = 0;
34555 point2pbcptindex = 0;
34556 highorderindex = 0;
34557 elemattribindex = 0;
34558 volumeboundindex = 0;
34560 areaboundindex = 0;
34572 jettisoninverts = 0;
34577 minfaceang = minfacetdihed = PI;
34578 maxcavfaces = maxcavverts = 0;
34581 bowatvolcount = bowatsubcount = bowatsegcount = 0l;
34582 updvolcount = updsubcount = updsegcount = 0l;
34583 repairflipcount = 0l;
34584 outbowatcircumcount = 0l;
34585 failvolcount = failsubcount = failsegcount = 0l;
34586 r1count = r2count = r3count = 0l;
34587 cdtenforcesegpts = 0l;
34588 rejsegpts = rejsubpts = rejtetpts = 0l;
34589 flip23s = flip32s = flip22s = flip44s = 0l;
34590 tloctime = tfliptime = 0.0;
34625 void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
34626 tetgenio *addin, tetgenio *bgmin)
34636 m.macheps = exactinit();
34637 m.steinerleft = b->steiner;
34639 m.bgm =
new tetgenmesh();
34642 m.bgm->macheps = exactinit();
34644 m.initializepools();
34650 m.reconstructmesh();
34652 m.delaunizevertices();
34659 printf(
"Mesh reconstruction seconds:");
34661 printf(
"Delaunay seconds:");
34663 printf(
" %g\n", (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
34667 if (bgmin != (tetgenio *) NULL) {
34668 m.bgm->initializepools();
34669 m.bgm->transfernodes();
34670 m.bgm->reconstructmesh();
34673 m.bgm->initializepools();
34674 m.duplicatebgmesh();
34682 printf(
"Background mesh reconstruct seconds: %g\n",
34683 (tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
34687 if (b->useshelles && !b->refine) {
34689 if (b->diagnose != 1) {
34690 m.markacutevertices(89.0);
34691 m.incrperturbvertices(b->epsilon);
34692 m.delaunizesegments();
34696 oldnum = m.points->items;
34697 m.incrperturbvertices(b->epsilon);
34698 if (m.points->items > oldnum) {
34699 oldnum = m.points->items;
34700 m.delaunizesegments();
34702 }
while (oldnum < m.points->items);
34704 m.constrainedfacets();
34706 m.detectinterfaces();
34713 if (b->useshelles && !b->refine) {
34714 if (b->diagnose != 1) {
34715 printf(
"Segment and facet ");
34717 printf(
"Intersection ");
34719 printf(
"seconds: %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
34723 if (b->plc && !(b->diagnose == 1)) {
34730 if (b->plc && !(b->diagnose == 1)) {
34731 printf(
"Hole seconds: %g\n", (tv[5] - tv[4]) / (REAL) CLOCKS_PER_SEC);
34735 if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34736 m.optimizemesh(
false);
34742 if ((b->plc || b->refine) && !(b->diagnose == 1)) {
34743 printf(
"Repair seconds: %g\n", (tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
34747 if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34748 m.removesteiners(
false);
34754 if ((b->plc && b->nobisect) && !(b->diagnose == 1)) {
34755 printf(
"Steiner removal seconds: %g\n",
34756 (tv[7] - tv[6]) / (REAL) CLOCKS_PER_SEC);
34760 if (b->insertaddpoints && (addin != (tetgenio *) NULL)) {
34761 if (addin->numberofpoints > 0) {
34762 m.insertconstrainedpoints(addin);
34769 if ((b->plc || b->refine) && (b->insertaddpoints)) {
34770 printf(
"Constrained points seconds: %g\n",
34771 (tv[8] - tv[7]) / (REAL) CLOCKS_PER_SEC);
34776 m.interpolatesizemap();
34783 printf(
"Size interpolating seconds: %g\n",
34784 (tv[9] - tv[8]) / (REAL) CLOCKS_PER_SEC);
34789 m.removesteiners(
true);
34796 printf(
"Mesh coarsening seconds: %g\n",
34797 (tv[10] - tv[9]) / (REAL) CLOCKS_PER_SEC);
34802 m.enforcequality();
34809 printf(
"Quality seconds: %g\n",
34810 (tv[11] - tv[10]) / (REAL) CLOCKS_PER_SEC);
34814 if (b->quality && (b->optlevel > 0)) {
34815 m.optimizemesh(
true);
34821 if (b->quality && (b->optlevel > 0)) {
34822 printf(
"Optimize seconds: %g\n",
34823 (tv[12] - tv[11]) / (REAL) CLOCKS_PER_SEC);
34827 if (!b->nojettison && ((m.dupverts > 0) || (m.unuverts > 0)
34828 || (b->refine && (in->numberofcorners == 10)))) {
34832 if (b->order > 1) {
34840 if (out != (tetgenio *) NULL) {
34841 out->firstnumber = in->firstnumber;
34842 out->mesh_dim = in->mesh_dim;
34845 if (b->nonodewritten || b->noiterationnum) {
34847 printf(
"NOT writing a .node file.\n");
34850 if (b->diagnose == 1) {
34851 if (m.subfaces->items > 0l) {
34856 if (b->quality || b->metric) {
34862 if (b->noelewritten) {
34864 printf(
"NOT writing an .ele file.\n");
34867 if (!(b->diagnose == 1)) {
34868 if (m.tetrahedrons->items > 0l) {
34869 m.outelements(out);
34874 if (b->nofacewritten) {
34876 printf(
"NOT writing an .face file.\n");
34880 if (m.tetrahedrons->items > 0l) {
34884 if (b->diagnose == 1) {
34885 if (m.subfaces->items > 0l) {
34886 m.outsubfaces(out);
34888 }
else if (b->plc || b->refine) {
34889 if (m.subfaces->items > 0l) {
34890 m.outsubfaces(out);
34893 if (m.tetrahedrons->items > 0l) {
34894 m.outhullfaces(out);
34901 m.outpbcnodes(out);
34905 if (b->edgesout > 1) {
34908 m.outsubsegments(out);
34912 if (!out && b->plc &&
34913 ((b->object == tetgenbehavior::OFF) ||
34914 (b->object == tetgenbehavior::PLY) ||
34915 (b->object == tetgenbehavior::STL))) {
34916 m.outsmesh(b->outfilename);
34919 if (!out && b->meditview) {
34920 m.outmesh2medit(b->outfilename);
34923 if (!out && b->gidview) {
34924 m.outmesh2gid(b->outfilename);
34927 if (!out && b->geomview) {
34928 m.outmesh2off(b->outfilename);
34932 m.outneighbors(out);
34942 printf(
"\nOutput seconds: %g\n",
34943 (tv[13] - tv[12]) / (REAL) CLOCKS_PER_SEC);
34944 printf(
"Total running seconds: %g\n",
34945 (tv[13] - tv[0]) / (REAL) CLOCKS_PER_SEC);
34950 if (m.checksubfaces) {
34953 if (b->docheck > 1) {
34954 m.checkdelaunay(0.0, NULL);
34955 if (b->docheck > 2) {
34956 if (b->quality || b->refine) {
34957 m.checkconforming();
34980 int main(
int argc,
char *argv[])
34982 #else // with TETLIBRARY 34990 void tetrahedralize(
char *switches, tetgenio *in, tetgenio *out,
34991 tetgenio *addin, tetgenio *bgmin)
34993 #endif // not TETLIBRARY 35000 tetgenio in, addin, bgmin;
35002 if (!b.parse_commandline(argc, argv)) {
35003 terminatetetgen(1);
35006 if (!in.load_tetmesh(b.infilename)) {
35007 terminatetetgen(1);
35010 if (!in.load_plc(b.infilename, (
int) b.object)) {
35011 terminatetetgen(1);
35014 if (b.insertaddpoints) {
35015 if (!addin.load_node(b.addinfilename)) {
35016 addin.numberofpoints = 0l;
35020 if (!bgmin.load_tetmesh(b.bgmeshfilename)) {
35021 bgmin.numberoftetrahedra = 0l;
35025 if (bgmin.numberoftetrahedra > 0l) {
35026 tetrahedralize(&b, &in, NULL, &addin, &bgmin);
35028 tetrahedralize(&b, &in, NULL, &addin, NULL);
35033 #else // with TETLIBRARY 35035 if (!b.parse_commandline(switches)) {
35036 terminatetetgen(1);
35038 tetrahedralize(&b, in, out, addin, bgmin);
35040 #endif // not TETLIBRARY 35048 int main(
int argc,
char *argv[])
35050 tetgen::main(argc, argv);
35052 #endif // not TETLIBRARY
for(i=STARTINDEX;i< argc;i++)