10 #include "GmshConfig.h"
13 #if defined(HAVE_TETGENBR)
29 #if !defined(HAVE_NO_STDINT_H)
31 #elif defined(HAVE_NO_INTPTR_T)
32 typedef unsigned long intptr_t;
35 #if defined(HAVE_POST)
39 #if defined(HAVE_FLTK)
45 static int computeTetGenVersion2(uint32_t v1, uint32_t* v2Choices,
49 for (i = 0; i < 3; i++) {
50 if(v1 == v2Choices[i]){
56 Msg::Error(
"Should never happen (file:%s line:%d)", __FILE__, __LINE__);
60 return 4 * i + iface2;
77 int numberofpointattributes;
78 int numberoftetrahedronattributes;
79 int numberofsegmentconstraints;
80 REAL *segmentconstraintlist;
81 int numberoffacetconstraints;
82 REAL *facetconstraintlist;
85 int *pointattributelist;
86 int numberofpointmakers;
88 int numberofpointmtrs;
101 numberofpointattributes = 0;
102 numberoftetrahedronattributes = 0;
103 numberofsegmentconstraints = 0;
104 segmentconstraintlist =
nullptr;
105 numberoffacetconstraints = 0;
106 facetconstraintlist =
nullptr;
109 pointattributelist =
nullptr;
110 numberofpointmakers = 0;
111 pointmarkerlist =
nullptr;
112 numberofpointmtrs = 0;
113 pointmtrlist =
nullptr;
116 edgemarkerlist =
nullptr;
120 regionlist =
nullptr;
126 #define orient3d robustPredicates::orient3d
127 #define insphere robustPredicates::insphere
128 static double orient4d(
double *,
double *,
double *,
double *,
double *,
129 double,
double,
double,
double,
double)
133 static int clock() {
return 0; }
135 #if !defined(TETLIBRARY)
138 #define printf Msg::Auto
145 GRegion *_gr = ((brdata *)p)->gr;
149 sprintf(opts,
"YpeQT%gp/%g",
CTX::instance()->mesh.toleranceInitialDelaunay,
151 b->parse_commandline(opts);
154 std::vector<MVertex *> _vertices;
155 std::map<int, MVertex *> _extras;
158 std::set<MVertex *, MVertexPtrLessThan> all;
159 std::vector<GFace *>
const &
f = _gr->
faces();
160 for(
auto it =
f.begin(); it !=
f.end(); ++it) {
162 for(std::size_t i = 0; i < gf->
triangles.size(); i++) {
171 for(std::size_t i = 0; i < gf->
quadrangles.size(); i++) {
177 new MVertex((v0->
x() + v1->
x() + v2->
x() + v3->
x()) * 0.25,
178 (v0->
y() + v1->
y() + v2->
y() + v3->
y()) * 0.25,
179 (v0->
z() + v1->
z() + v2->
z() + v3->
z()) * 0.25, gf);
183 _sqr->
add(mf, newv, gf);
193 for(
auto it = e.begin(); it != e.end(); ++it) {
195 for(std::size_t i = 0; i < ge->
lines.size(); i++) {
196 all.insert(ge->
lines[i]->getVertex(0));
197 all.insert(ge->
lines[i]->getVertex(1));
201 for(
auto it = v.begin(); it != v.end(); ++it) {
203 for(std::size_t i = 0; i < gv->
points.size(); i++) {
204 all.insert(gv->
points[i]->getVertex(0));
209 _vertices.insert(_vertices.begin(), all.begin(), all.end());
216 std::map<MVertex *, SPoint3> originalCoordinates;
217 for(std::size_t i = 0; i < _vertices.size(); i++) {
219 originalCoordinates[v] = v->
point();
222 std::vector<MTetrahedron *> tets;
228 Msg::Debug(
"Points have been tetrahedralized");
235 for(std::size_t i = 0; i < _vertices.size(); i++) {
236 makepoint(&pointloop, UNUSEDVERTEX);
238 x = pointloop[0] = _vertices[i]->x();
239 y = pointloop[1] = _vertices[i]->y();
240 z = pointloop[2] = _vertices[i]->z();
248 xmin = (x < xmin) ? x : xmin;
249 xmax = (x > xmax) ? x : xmax;
250 ymin = (y < ymin) ? y : ymin;
251 ymax = (y > ymax) ? y : ymax;
252 zmin = (
z < zmin) ?
z : zmin;
253 zmax = (
z > zmax) ?
z : zmax;
261 longest = sqrt(x * x + y * y +
z *
z);
268 if(minedgelength == 0.0) { minedgelength = longest * b->epsilon; }
274 makeindex2pointmap(idx2verlist);
276 idx2verlist[0] = dummypoint;
279 for(std::size_t i = 0; i < _vertices.size(); i++) {
280 _vertices[i]->setIndex(i + 1);
285 triface tetloop, checktet, prevchktet;
286 triface hulltet, face1, face2;
297 ver2tetarray =
new tetrahedron[_vertices.size() + in->firstnumber];
298 for(std::size_t i = 0; i < _vertices.size() + in->firstnumber; i++) {
299 setpointtype(idx2verlist[i], VOLVERTEX);
300 ver2tetarray[i] =
nullptr;
305 std::vector<triface> ts( tets.size() );
306 for(std::size_t i = 0; i < tets.size(); i++) {
309 tets[i]->tet()->forceNum(i+1);
310 p[0] = idx2verlist[tets[i]->getVertex(0)->getIndex()];
311 p[1] = idx2verlist[tets[i]->getVertex(1)->getIndex()];
312 p[2] = idx2verlist[tets[i]->getVertex(2)->getIndex()];
313 p[3] = idx2verlist[tets[i]->getVertex(3)->getIndex()];
317 for (uint64_t i = 0; i < tets.size(); i++) {
320 for (tf1.ver=0; tf1.ver<4; tf1.ver++){
321 uint64_t neigh = tets[i]->getNeigh(tf1.ver)->tet()->getNum() - 1;
322 triface tf2 = ts[neigh];
323 int iface2 = tf1.ver;
326 tets[i]->getVertex(faces_tetra(tf1.ver),0)->getIndex(),
327 tets[i]->getVertex(faces_tetra(tf1.ver),1)->getIndex(),
328 tets[i]->getVertex(faces_tetra(tf1.ver),2)->getIndex()};
330 tf2.ver = computeTetGenVersion2(faces2[0], face2, iface2);
340 for(std::size_t i = 0; i < tets.size(); i++) {
342 for(
int j = 0; j < 4; j++) {
343 p[j] = idx2verlist[tets[i]->getVertex(j)->getIndex()];
346 ori =
orient3d(p[0], p[1], p[2], p[3]);
353 else if(ori == 0.0) {
355 Msg::Warning(
"Tet #%d is degenerated", i + in->firstnumber);
359 maketetrahedron(&tetloop);
362 for(tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
363 p[3] = oppo(tetloop);
365 idx = pointmark(p[3]) - in->firstnumber;
366 tptr = ver2tetarray[idx];
368 tetloop.tet[8 + tetloop.ver] = tptr;
370 ver2tetarray[idx] = encode(tetloop);
371 decode(tptr, checktet);
372 if(checktet.tet !=
nullptr) {
374 p[1] = dest(tetloop);
375 p[2] = apex(tetloop);
376 prevchktet = tetloop;
378 q[0] = org(checktet);
379 q[1] = dest(checktet);
380 q[2] = apex(checktet);
383 for(
int j = 0; j < 3; j++) {
385 esym(checktet, face2);
386 if(face2.tet[face2.ver & 3] ==
nullptr) {
391 esym(tetloop, face1);
399 enext(tetloop, face1);
408 eprev(tetloop, face1);
421 tptr = checktet.tet[8 + checktet.ver];
425 prevchktet.tet[8 + prevchktet.ver] = tptr;
429 prevchktet = checktet;
431 decode(tptr, checktet);
432 }
while(checktet.tet !=
nullptr);
442 hullsize = tetrahedrons->items;
444 tetrahedrons->traversalinit();
445 tetloop.tet = tetrahedrontraverse();
447 tptr = encode(tetloop);
448 for(tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
449 if(tetloop.tet[tetloop.ver] ==
nullptr) {
451 maketetrahedron(&hulltet);
453 p[1] = dest(tetloop);
454 p[2] = apex(tetloop);
455 setvertices(hulltet, p[1], p[0], p[2], dummypoint);
456 bond(tetloop, hulltet);
458 for(
int j = 0; j < 3; j++) {
459 fsym(hulltet, face2);
461 if(face2.tet ==
nullptr)
break;
463 if(apex(face2) == dummypoint)
break;
466 if(face2.tet !=
nullptr) {
468 assert(face2.tet[face2.ver & 3] ==
nullptr);
469 esym(hulltet, face1);
477 setpoint2tet((point)(tetloop.tet[4 + tetloop.ver]), tptr);
479 tetloop.tet[8 + tetloop.ver] =
nullptr;
481 tetloop.tet = tetrahedrontraverse();
484 hullsize = tetrahedrons->items - hullsize;
486 delete[] ver2tetarray;
487 for(std::size_t i = 0; i < tets.size(); i++)
delete tets[i];
492 std::vector<GFace *>
const &f_list = _gr->
faces();
502 for(
auto it = f_list.begin(); it != f_list.end(); ++it) {
504 for(std::size_t i = 0; i < gf->
triangles.size(); i++) {
505 for(
int j = 0; j < 3; j++) {
506 p[j] = idx2verlist[gf->
triangles[i]->getVertex(j)->getIndex()];
507 if(pointtype(p[j]) == VOLVERTEX) {
508 setpointtype(p[j], FACETVERTEX);
511 makeshellface(subfaces, &newsh);
513 setshellmark(newsh, gf->
tag());
515 for(
int j = 0; j < 3; j++) {
516 makeshellface(subsegs, &newseg);
519 setshellmark(newseg, -1);
520 ssbond(newsh, newseg);
527 std::map<MFace, GFace *, MFaceLessThan>
f = _sqr->
getTri();
528 for(
auto it =
f.begin(); it !=
f.end(); it++) {
529 const MFace &mf = it->first;
530 for(
int j = 0; j < 3; j++) {
532 if(pointtype(p[j]) == VOLVERTEX) {
533 setpointtype(p[j], FACETVERTEX);
536 makeshellface(subfaces, &newsh);
538 setshellmark(newsh, it->second->tag());
540 for(
int j = 0; j < 3; j++) {
541 makeshellface(subsegs, &newseg);
544 setshellmark(newseg, -1);
545 ssbond(newsh, newseg);
554 Msg::Info(
" - Identifying boundary edges");
558 face searchsh, neighsh;
559 face segloop, checkseg;
563 makepoint2submap(subfaces, idx2shlist, shperverlist);
568 for(
auto it = e_list.begin(); it != e_list.end(); ++it) {
570 for(std::size_t i = 0; i < ge->
lines.size(); i++) {
571 for(
int j = 0; j < 2; j++) {
572 p[j] = idx2verlist[ge->
lines[i]->getVertex(j)->getIndex()];
573 setpointtype(p[j], RIDGEVERTEX);
581 searchsh.sh =
nullptr;
582 idx = pointmark(p[0]) - in->firstnumber;
583 for(
int j = idx2shlist[idx]; j < idx2shlist[idx + 1]; j++) {
584 checkpt = sdest(shperverlist[j]);
585 if(checkpt == p[1]) {
586 searchsh = shperverlist[j];
590 checkpt = sapex(shperverlist[j]);
591 if(checkpt == p[1]) {
592 senext2(shperverlist[j], searchsh);
598 if(searchsh.sh !=
nullptr) {
600 sspivot(searchsh, checkseg);
601 if(checkseg.sh !=
nullptr) {
607 makeshellface(subsegs, &newseg);
609 ssbond(searchsh, newseg);
610 spivot(searchsh, neighsh);
611 if(neighsh.sh !=
nullptr) { ssbond(neighsh, newseg); }
631 if(newseg.sh ==
nullptr) {
632 makeshellface(subsegs, &newseg);
636 setshellmark(newseg, ge->
tag());
640 delete[] shperverlist;
643 Msg::Debug(
" %ld (%ld) subfaces (segments)", subfaces->items,
647 insegments = subsegs->items;
649 if(0) { outmesh2medit(
"dump2"); }
652 delete[] idx2verlist;
662 if(subvertstack->objects > 0l) { suppresssteinerpoints(); }
669 if((dupverts > 0l) || (unuverts > 0l)) {
675 long tetnumber, facenumber;
678 Msg::Debug(
" Input points: %ld", _vertices.size());
680 Msg::Debug(
" Input facets: %ld", f_list.size());
681 Msg::Debug(
" Input segments: %ld", e_list.size());
684 tetnumber = tetrahedrons->items - hullsize;
685 facenumber = (tetnumber * 4l + hullsize) / 2l;
688 Msg::Debug(
" Mesh points: %ld", points->items - nonregularcount);
691 Msg::Debug(
" Mesh points: %ld", points->items);
693 Msg::Debug(
" Mesh tetrahedra: %ld", tetnumber);
695 if(meshedges > 0l) {
Msg::Debug(
" Mesh edges: %ld", meshedges); }
698 long vsize = points->items - dupverts - unuverts;
699 if(b->weighted) vsize -= nonregularcount;
700 meshedges = vsize + facenumber - tetnumber - 1;
705 if(b->plc || b->refine) {
706 Msg::Debug(
" Mesh faces on facets: %ld", subfaces->items);
707 Msg::Debug(
" Mesh edges on segments: %ld", subsegs->items);
708 if(st_volref_count > 0l) {
709 Msg::Debug(
" Steiner points inside domain: %ld", st_volref_count);
711 if(st_facref_count > 0l) {
712 Msg::Debug(
" Steiner points on facets: %ld", st_facref_count);
714 if(st_segref_count > 0l) {
715 Msg::Debug(
" Steiner points on segments: %ld", st_segref_count);
719 Msg::Debug(
" Convex hull faces: %ld", hullsize);
720 if(meshhulledges > 0l) {
721 Msg::Debug(
" Convex hull edges: %ld", meshhulledges);
725 Msg::Debug(
" Skipped non-regular points: %ld", nonregularcount);
729 if(0) { outmesh2medit(
"dump"); }
740 std::set<int> l_faces, l_edges;
742 if(points->items > (
int)_vertices.size()) {
743 face parentseg, parentsh, spinsh;
747 points->traversalinit();
748 pointloop = pointtraverse();
749 while(pointloop != (point)
nullptr) {
750 if(issteinerpoint(pointloop)) {
752 if(pointtype(pointloop) == FREESEGVERTEX) {
753 sdecode(point2sh(pointloop), parentseg);
754 assert(parentseg.sh !=
nullptr);
755 l_edges.insert(shellmark(parentseg));
759 int etag = shellmark(parentseg);
760 for(
auto it = e_list.begin(); it != e_list.end(); ++it) {
761 if((*it)->tag() == etag) {
768 pointloop[2], ge, 0);
775 _extras[pointmark(pointloop) - in->firstnumber] = v;
777 spivot(parentseg, parentsh);
778 if(parentsh.sh !=
nullptr) {
781 int ftag = shellmark(parentsh);
782 for(
auto it = f_list.begin(); it != f_list.end(); ++it) {
783 if((*it)->tag() == ftag) {
790 pointloop[0], pointloop[1], pointloop[2], gf, 0, 0);
798 _extras[pointmark(pointloop) - in->firstnumber] = v;
804 l_faces.insert(shellmark(spinsh));
806 if(spinsh.sh == parentsh.sh)
break;
809 if((ge ==
nullptr) && (gf ==
nullptr)) {
812 new MVertex(pointloop[0], pointloop[1], pointloop[2], _gr);
814 _extras[pointmark(pointloop) - in->firstnumber] = v;
818 else if(pointtype(pointloop) == FREEFACETVERTEX) {
819 sdecode(point2sh(pointloop), parentsh);
820 assert(parentsh.sh !=
nullptr);
821 l_faces.insert(shellmark(parentsh));
824 int ftag = shellmark(parentsh);
825 for(
auto it = f_list.begin(); it != f_list.end(); ++it) {
826 if((*it)->tag() == ftag) {
833 pointloop[2], gf, 0, 0);
841 _extras[pointmark(pointloop) - in->firstnumber] = v;
846 new MVertex(pointloop[0], pointloop[1], pointloop[2], _gr);
849 _extras[pointmark(pointloop) - in->firstnumber] = v;
854 new MVertex(pointloop[0], pointloop[1], pointloop[2], _gr);
857 _extras[pointmark(pointloop) - in->firstnumber] = v;
860 pointloop = pointtraverse();
866 Msg::Info(
" - Added %d Steiner point%s", _extras.size(),
867 (_extras.size() > 1) ?
"s" :
"");
869 if(l_edges.size() > 0) {
873 for(
auto it = l_edges.begin(); it != l_edges.end(); ++it) {
878 for(
auto it = e_list.begin(); it != e_list.end(); ++it) {
879 if((*it)->tag() == etag) {
885 Msg::Info(
" - Steiner points exist on curve %d", ge->
tag());
887 for(std::size_t i = 0; i < ge->
lines.size(); i++)
893 subsegs->traversalinit();
894 segloop.sh = shellfacetraverse(subsegs);
895 while(segloop.sh !=
nullptr) {
896 if(shellmark(segloop) == etag) {
897 p[0] = sorg(segloop);
898 p[1] = sdest(segloop);
899 int idx1 = pointmark(p[0]) - in->firstnumber;
900 MVertex *v1 = idx1 >= (int)_vertices.size() ? _extras[idx1] :
902 int idx2 = pointmark(p[1]) - in->firstnumber;
903 MVertex *v2 = idx2 >= (int)_vertices.size() ? _extras[idx2] :
906 ge->
lines.push_back(t);
908 segloop.sh = shellfacetraverse(subsegs);
912 Msg::Debug(
"Unknown curve %d with Steiner point(s)", etag);
917 if(l_faces.size() > 0) {
921 for(
auto it = l_faces.begin(); it != l_faces.end(); ++it) {
926 for(
auto it = f_list.begin(); it != f_list.end(); ++it) {
927 if((*it)->tag() == ftag) {
934 Msg::Info(
" - Steiner points exist on surface %d", gf->
tag());
935 for(std::size_t i = 0; i < gf->
triangles.size(); i++)
941 Msg::Warning(
"Steiner points not handled for quad surface mesh");
946 subfaces->traversalinit();
947 subloop.sh = shellfacetraverse(subfaces);
948 while(subloop.sh !=
nullptr) {
949 if(shellmark(subloop) == ftag) {
950 p[0] = sorg(subloop);
951 p[1] = sdest(subloop);
952 p[2] = sapex(subloop);
953 int idx1 = pointmark(p[0]) - in->firstnumber;
954 MVertex *v1 = idx1 >= (int)_vertices.size() ? _extras[idx1] :
956 int idx2 = pointmark(p[1]) - in->firstnumber;
957 MVertex *v2 = idx2 >= (int)_vertices.size() ? _extras[idx2] :
959 int idx3 = pointmark(p[2]) - in->firstnumber;
960 MVertex *v3 = idx3 >= (int)_vertices.size() ? _extras[idx3] :
965 subloop.sh = shellfacetraverse(subfaces);
969 Msg::Debug(
"Unknown surface %d with Steiner point(s)", ftag);
977 tetrahedrons->traversalinit();
978 tetloop.tet = tetrahedrontraverse();
982 p[1] = dest(tetloop);
983 p[2] = apex(tetloop);
984 p[3] = oppo(tetloop);
986 int idx1 = pointmark(p[0]) - in->firstnumber;
988 idx1 >= (int)_vertices.size() ? _extras[idx1] : _vertices[idx1];
989 int idx2 = pointmark(p[1]) - in->firstnumber;
991 idx2 >= (int)_vertices.size() ? _extras[idx2] : _vertices[idx2];
992 int idx3 = pointmark(p[2]) - in->firstnumber;
994 idx3 >= (int)_vertices.size() ? _extras[idx3] : _vertices[idx3];
995 int idx4 = pointmark(p[3]) - in->firstnumber;
997 idx4 >= (int)_vertices.size() ? _extras[idx4] : _vertices[idx4];
1000 tetloop.tet = tetrahedrontraverse();
1004 Msg::Info(
"Done reconstructing mesh (Wall %gs, CPU %gs)",
1009 for(
auto vIter = originalCoordinates.begin();
1010 vIter != originalCoordinates.end(); ++vIter) {
1011 const SPoint3 &coordinates = vIter->second;
1012 vIter->first->setXYZ(coordinates.
x(), coordinates.
y(), coordinates.
z());
1016 for(std::size_t i = _vertices.size() - 8; i < _vertices.size(); i++)
1017 delete _vertices[i];
1026 FILE *outfile =
nullptr;
1027 char sfilename[256];
1032 strcpy(sfilename, mfilename);
1033 strcat(sfilename,
".node");
1034 outfile = fopen(sfilename,
"w");
1035 if(!b->quiet) { printf(
"Writing %s.\n", sfilename); }
1036 fprintf(outfile,
"%ld 3 0 0\n", points->items);
1038 firstindex = b->zeroindex ? 0 : in->firstnumber;
1039 points->traversalinit();
1040 pointloop = pointtraverse();
1041 pointnumber = firstindex;
1042 while(pointloop != (point)
nullptr) {
1044 fprintf(outfile,
"%4d %.17g %.17g %.17g", pointnumber,
1045 pointloop[0], pointloop[1], pointloop[2]);
1046 fprintf(outfile,
"\n");
1047 pointloop = pointtraverse();
1053 point torg, tdest, tapex;
1054 strcpy(sfilename, mfilename);
1055 strcat(sfilename,
".smesh");
1056 outfile = fopen(sfilename,
"w");
1057 if(!b->quiet) { printf(
"Writing %s.\n", sfilename); }
1059 if((in->firstnumber == 1) && (firstindex == 0)) {
1062 fprintf(outfile,
"0 3 0 0\n");
1063 fprintf(outfile,
"%ld 1\n", subfaces->items);
1064 subfaces->traversalinit();
1065 faceloop.sh = shellfacetraverse(subfaces);
1066 while(faceloop.sh != (shellface *)
nullptr) {
1067 torg = sorg(faceloop);
1068 tdest = sdest(faceloop);
1069 tapex = sapex(faceloop);
1070 fprintf(outfile,
"3 %4d %4d %4d %d\n", pointmark(torg) - shift,
1071 pointmark(tdest) - shift, pointmark(tapex) - shift,
1072 shellmark(faceloop));
1073 faceloop.sh = shellfacetraverse(subfaces);
1075 fprintf(outfile,
"0\n");
1076 fprintf(outfile,
"0\n");
1081 strcpy(sfilename, mfilename);
1082 strcat(sfilename,
".edge");
1083 outfile = fopen(sfilename,
"w");
1084 if(!b->quiet) { printf(
"Writing %s.\n", sfilename); }
1085 fprintf(outfile,
"%ld 1\n", subsegs->items);
1086 subsegs->traversalinit();
1087 edgeloop.sh = shellfacetraverse(subsegs);
1088 edgenumber = firstindex;
1089 while(edgeloop.sh != (shellface *)
nullptr) {
1090 torg = sorg(edgeloop);
1091 tdest = sdest(edgeloop);
1092 fprintf(outfile,
"%5d %4d %4d %d\n", edgenumber,
1093 pointmark(torg) - shift, pointmark(tdest) - shift,
1094 shellmark(edgeloop));
1096 edgeloop.sh = shellfacetraverse(subsegs);
1104 char mefilename[256];
1106 triface tface, tsymface;
1107 face segloop, checkmark;
1108 point ptloop, p1, p2, p3, p4;
1113 if(mfilename != (
char *)
nullptr && mfilename[0] !=
'\0') {
1114 strcpy(mefilename, mfilename);
1117 strcpy(mefilename,
"unnamed");
1119 strcat(mefilename,
".mesh");
1121 if(!b->quiet) { printf(
"Writing %s.\n", mefilename); }
1122 outfile = fopen(mefilename,
"w");
1123 if(outfile == (FILE *)
nullptr) {
1124 Msg::Error(
"Could not open file '%s'", mefilename);
1128 fprintf(outfile,
"MeshVersionFormatted 1\n");
1129 fprintf(outfile,
"\n");
1130 fprintf(outfile,
"Dimension\n");
1131 fprintf(outfile,
"3\n");
1132 fprintf(outfile,
"\n");
1134 fprintf(outfile,
"\n# Set of mesh vertices\n");
1135 fprintf(outfile,
"Vertices\n");
1136 fprintf(outfile,
"%ld\n", points->items);
1138 points->traversalinit();
1139 ptloop = pointtraverse();
1141 while(ptloop != (point)
nullptr) {
1143 fprintf(outfile,
"%.17g %.17g %.17g", ptloop[0], ptloop[1],
1145 fprintf(outfile,
" 0\n");
1147 ptloop = pointtraverse();
1152 if(in->firstnumber == 1) { shift = 0; }
1158 ntets = tetrahedrons->items - hullsize;
1160 fprintf(outfile,
"\n# Set of Tetrahedra\n");
1161 fprintf(outfile,
"Tetrahedra\n");
1162 fprintf(outfile,
"%ld\n", ntets);
1164 tetrahedrons->traversalinit();
1165 tetptr = tetrahedrontraverse();
1167 if(!b->reversetetori) {
1168 p1 = (point)tetptr[4];
1169 p2 = (point)tetptr[5];
1172 p1 = (point)tetptr[5];
1173 p2 = (point)tetptr[4];
1175 p3 = (point)tetptr[6];
1176 p4 = (point)tetptr[7];
1177 fprintf(outfile,
"%5d %5d %5d %5d", pointmark(p1) + shift,
1178 pointmark(p2) + shift, pointmark(p3) + shift,
1179 pointmark(p4) + shift);
1180 if(numelemattrib > 0) {
1181 fprintf(outfile,
" %.17g", elemattribute(tetptr, 0));
1184 fprintf(outfile,
" 0");
1186 fprintf(outfile,
"\n");
1187 tetptr = tetrahedrontraverse();
1191 faces = subfaces->items;
1194 fprintf(outfile,
"\n# Set of Triangles\n");
1195 fprintf(outfile,
"Triangles\n");
1196 fprintf(outfile,
"%ld\n",
faces);
1198 subfaces->traversalinit();
1199 sface.sh = shellfacetraverse(subfaces);
1200 while(sface.sh !=
nullptr) {
1204 fprintf(outfile,
"%5d %5d %5d", pointmark(p1) + shift,
1205 pointmark(p2) + shift, pointmark(p3) + shift);
1206 marker = shellmark(sface);
1207 fprintf(outfile,
" %d\n", marker);
1208 sface.sh = shellfacetraverse(subfaces);
1211 fprintf(outfile,
"\nEnd\n");
1221 tetgenBR::tetgenmesh *m =
new tetgenBR::tetgenmesh();
1222 m->in =
new tetgenBR::tetgenio();
1223 m->b =
new tetgenBR::tetgenbehavior();
1224 tetgenBR::brdata data = {gr,
sqr};
1225 ret = m->reconstructmesh((
void *)&data);
1231 Msg::Error(
"Out of memory in boundary mesh recovery");
1235 std::map<int, MVertex *> all;
1236 std::vector<GFace *>
f = gr->
faces();
1237 for(
auto it =
f.begin(); it !=
f.end(); ++it) {
1239 for(std::size_t i = 0; i < gf->
triangles.size(); i++) {
1240 for(
int j = 0; j < 3; j++) {
1247 for(
auto it = e.begin(); it != e.end(); ++it) {
1249 for(std::size_t i = 0; i < ge->
lines.size(); i++) {
1250 for(
int j = 0; j < 2; j++) {
1257 for(
auto it = v.begin(); it != v.end(); ++it) {
1259 for(std::size_t i = 0; i < gv->
points.size(); i++) {
1271 case 1: what =
"segment-segment intersection";
break;
1272 case 2: what =
"segment-facet intersection";
break;
1273 case 3: what =
"facet-facet intersection";
break;
1275 what =
"overlapping segments";
1279 what =
"segment in facet";
1283 what =
"overlapping facets";
1286 case 7: what =
"vertex in segment";
break;
1287 case 8: what =
"vertex in facet";
break;
1288 default: what =
"unknown";
break;
1297 std::ostringstream pb;
1298 std::vector<double> x, y,
z, val;
1299 for(
int f = 0;
f < 2;
f++) {
1304 pb <<
" surface " << ftags[
f];
1311 pb <<
" curve " << etags[
f];
1314 for(
int i = 0; i < 3; i++) {
1318 x.push_back(v->
x());
1319 y.push_back(v->
y());
1320 z.push_back(v->
z());
1329 pb <<
", intersection (" << px <<
"," << py <<
"," << pz <<
")";
1335 Msg::Error(
"Invalid boundary mesh (%s) on%s", what.c_str(),
1337 #if defined(HAVE_POST)
1338 new PView(
"Boundary mesh issue", x, y,
z, val);
1339 #if defined(HAVE_FLTK)
1340 if(FlGui::available()) FlGui::instance()->updateViews(
true,
true);
1347 Msg::Error(
"Could not recover boundary mesh: error %d", err);