gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
meshGRegionBoundaryRecovery.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include <stdio.h>
7 #include <string.h>
8 #include <assert.h>
9 #include <sstream>
10 #include "GmshConfig.h"
12 
13 #if defined(HAVE_TETGENBR)
14 
15 #include "meshGRegion.h"
17 #include "robustPredicates.h"
18 #include "GModel.h"
19 #include "GRegion.h"
20 #include "GFace.h"
21 #include "MVertex.h"
22 #include "MLine.h"
23 #include "MPoint.h"
24 #include "MTriangle.h"
25 #include "MQuadrangle.h"
26 #include "MTetrahedron.h"
27 #include "Context.h"
28 #include "OS.h"
29 #if !defined(HAVE_NO_STDINT_H)
30 #include <stdint.h>
31 #elif defined(HAVE_NO_INTPTR_T)
32 typedef unsigned long intptr_t;
33 #endif
34 
35 #if defined(HAVE_POST)
36 #include "PView.h"
37 #endif
38 
39 #if defined(HAVE_FLTK)
40 #include "FlGui.h"
41 #include "drawContext.h"
42 #endif
43 
44 #if 0
45 static int computeTetGenVersion2(uint32_t v1, uint32_t* v2Choices,
46  const int iface2)
47 {
48  int i;
49  for (i = 0; i < 3; i++) {
50  if(v1 == v2Choices[i]){
51  break;
52  }
53  }
54 
55  if(i == 3)
56  Msg::Error("Should never happen (file:%s line:%d)", __FILE__, __LINE__);
57 
58  // version%4 : corresponding face in adjacent tet
59  // version/4 : which of the 3 rotation of the facet the tetrahedra has...
60  return 4 * i + iface2;
61 }
62 #endif
63 
64 namespace tetgenBR {
65 
66 #define REAL double
67 
68  struct brdata {
69  GRegion *gr;
71  };
72 
73  // dummy tetgenio class
74  class tetgenio {
75  public:
76  int firstnumber;
77  int numberofpointattributes;
78  int numberoftetrahedronattributes;
79  int numberofsegmentconstraints;
80  REAL *segmentconstraintlist;
81  int numberoffacetconstraints;
82  REAL *facetconstraintlist;
83  int numberofpoints;
84  int *pointlist;
85  int *pointattributelist;
86  int numberofpointmakers;
87  int *pointmarkerlist;
88  int numberofpointmtrs;
89  int *pointmtrlist;
90  int numberofedges;
91  int *edgelist;
92  int *edgemarkerlist;
93  int numberofholes;
94  REAL *holelist;
95  int numberofregions;
96  REAL *regionlist;
97  int mesh_dim;
98  tetgenio()
99  {
100  firstnumber = 1;
101  numberofpointattributes = 0;
102  numberoftetrahedronattributes = 0;
103  numberofsegmentconstraints = 0;
104  segmentconstraintlist = nullptr;
105  numberoffacetconstraints = 0;
106  facetconstraintlist = nullptr;
107  numberofpoints = 0;
108  pointlist = nullptr;
109  pointattributelist = nullptr;
110  numberofpointmakers = 0;
111  pointmarkerlist = nullptr;
112  numberofpointmtrs = 0;
113  pointmtrlist = nullptr;
114  numberofedges = 0;
115  edgelist = nullptr;
116  edgemarkerlist = nullptr;
117  numberofholes = 0;
118  holelist = nullptr;
119  numberofregions = 0;
120  regionlist = nullptr;
121  mesh_dim = 0;
122  }
123  };
124 
125 // redefinition of predicates using our own
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)
130  {
131  return 0.;
132  }
133  static int clock() { return 0; }
134 #define clock_t int
135 #if !defined(TETLIBRARY)
136 #define TETLIBRARY
137 #endif
138 #define printf Msg::Auto
139 #include "tetgenBR.h"
140 #include "tetgenBR.cxx"
141 #undef printf
142 
143  bool tetgenmesh::reconstructmesh(void *p)
144  {
145  GRegion *_gr = ((brdata *)p)->gr;
146  splitQuadRecovery *_sqr = ((brdata *)p)->sqr;
147 
148  char opts[128];
149  sprintf(opts, "YpeQT%gp/%g", CTX::instance()->mesh.toleranceInitialDelaunay,
151  b->parse_commandline(opts);
152 
153  double t_start = Cpu(), w_start = TimeOfDay();
154  std::vector<MVertex *> _vertices;
155  std::map<int, MVertex *> _extras;
156  // Get the set of vertices from GRegion.
157  {
158  std::set<MVertex *, MVertexPtrLessThan> all;
159  std::vector<GFace *> const &f = _gr->faces();
160  for(auto it = f.begin(); it != f.end(); ++it) {
161  GFace *gf = *it;
162  for(std::size_t i = 0; i < gf->triangles.size(); i++) {
163  MVertex *v0 = gf->triangles[i]->getVertex(0);
164  MVertex *v1 = gf->triangles[i]->getVertex(1);
165  MVertex *v2 = gf->triangles[i]->getVertex(2);
166  all.insert(v0);
167  all.insert(v1);
168  all.insert(v2);
169  }
170  if(_sqr) {
171  for(std::size_t i = 0; i < gf->quadrangles.size(); i++) {
172  MVertex *v0 = gf->quadrangles[i]->getVertex(0);
173  MVertex *v1 = gf->quadrangles[i]->getVertex(1);
174  MVertex *v2 = gf->quadrangles[i]->getVertex(2);
175  MVertex *v3 = gf->quadrangles[i]->getVertex(3);
176  MVertex *newv =
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);
180  // the extra vertex will be added in a GRegion (and reclassified
181  // correctly on that GRegion) when the pyramid is generated
182  MFace mf = gf->quadrangles[i]->getFace(0);
183  _sqr->add(mf, newv, gf);
184  all.insert(v0);
185  all.insert(v1);
186  all.insert(v2);
187  all.insert(v3);
188  all.insert(newv);
189  }
190  }
191  }
192  std::vector<GEdge *> const &e = _gr->embeddedEdges();
193  for(auto it = e.begin(); it != e.end(); ++it) {
194  GEdge *ge = *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));
198  }
199  }
200  std::vector<GVertex *> const &v = _gr->embeddedVertices();
201  for(auto it = v.begin(); it != v.end(); ++it) {
202  GVertex *gv = *it;
203  for(std::size_t i = 0; i < gv->points.size(); i++) {
204  all.insert(gv->points[i]->getVertex(0));
205  }
206  }
207  all.insert(_gr->mesh_vertices.begin(), _gr->mesh_vertices.end());
208 
209  _vertices.insert(_vertices.begin(), all.begin(), all.end());
210  }
211 
212  initializepools();
213 
214  // Store all coordinates of the vertices as these will be pertubated in
215  // function delaunayTriangulation
216  std::map<MVertex *, SPoint3> originalCoordinates;
217  for(std::size_t i = 0; i < _vertices.size(); i++) {
218  MVertex *v = _vertices[i];
219  originalCoordinates[v] = v->point();
220  }
221 
222  std::vector<MTetrahedron *> tets;
223 
224  delaunayMeshIn3D(_vertices,
225  tets); // will add 8 MVertices at the end of _vertices
226  if(Msg::GetErrorCount()) return false;
227 
228  Msg::Debug("Points have been tetrahedralized");
229 
230  {
231  point pointloop;
232  REAL x, y, z;
233 
234  // Read the points.
235  for(std::size_t i = 0; i < _vertices.size(); i++) {
236  makepoint(&pointloop, UNUSEDVERTEX);
237  // Read the point coordinates.
238  x = pointloop[0] = _vertices[i]->x();
239  y = pointloop[1] = _vertices[i]->y();
240  z = pointloop[2] = _vertices[i]->z();
241  // Determine the smallest and largest x, y and z coordinates.
242  if(i == 0) {
243  xmin = xmax = x;
244  ymin = ymax = y;
245  zmin = zmax = z;
246  }
247  else {
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;
254  }
255  }
256 
257  // 'longest' is the largest possible edge length formed by input vertices.
258  x = xmax - xmin;
259  y = ymax - ymin;
260  z = zmax - zmin;
261  longest = sqrt(x * x + y * y + z * z);
262  if(longest == 0.0) {
263  Msg::Warning("The point set is trivial");
264  return true;
265  }
266 
267  // Two identical points are distinguished by 'lengthlimit'.
268  if(minedgelength == 0.0) { minedgelength = longest * b->epsilon; }
269  }
270 
271  point *idx2verlist;
272 
273  // Create a map from indices to vertices.
274  makeindex2pointmap(idx2verlist);
275  // 'idx2verlist' has length 'in->numberofpoints + 1'.
276  idx2verlist[0] = dummypoint; // Let 0th-entry be dummypoint.
277  // Index the vertices, starting at 1 (vertex index 0 is used as special code
278  // in tetgenBR in case of failure)
279  for(std::size_t i = 0; i < _vertices.size(); i++) {
280  _vertices[i]->setIndex(i + 1);
281  }
282 
283  {
284  tetrahedron *ver2tetarray;
285  triface tetloop, checktet, prevchktet;
286  triface hulltet, face1, face2;
287  tetrahedron tptr;
288  point p[4], q[3];
289  REAL ori; //, attrib, volume;
290  int bondflag;
291  int t1ver;
292  int idx, k;
293 
294  Msg::Info("Reconstructing mesh...");
295 
296  // Allocate an array that maps each vertex to its adjacent tets.
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); // initial type.
300  ver2tetarray[i] = nullptr;
301  }
302 
303 #if 0
304  /* N E W V E R S I O N */
305  std::vector<triface> ts( tets.size() );
306  for(std::size_t i = 0; i < tets.size(); i++) {
307  point p[4];
308  // index tetrahedra in order to have access to neighbors ids.
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()];
314  setvertices(ts[i], p[0], p[1], p[2], p[3]);
315  }
316  // we can make this in parallel, iterations are totally independent
317  for (uint64_t i = 0; i < tets.size(); i++) {
318  triface tf1 = ts[i];
319 
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;
324 
325  int face2[3] = {
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()};
329 
330  tf2.ver = computeTetGenVersion2(faces2[0], face2, iface2);
331  bond(tf1,tf2);
332  }
333  }
334 
335 #else
336 
337  /* N E W V E R S I O N */
338 
339  // Create the tetrahedra and connect those that share a common face.
340  for(std::size_t i = 0; i < tets.size(); i++) {
341  // Get the four vertices.
342  for(int j = 0; j < 4; j++) {
343  p[j] = idx2verlist[tets[i]->getVertex(j)->getIndex()];
344  }
345  // Check the orientation.
346  ori = orient3d(p[0], p[1], p[2], p[3]);
347  if(ori > 0.0) {
348  // Swap the first two vertices.
349  q[0] = p[0];
350  p[0] = p[1];
351  p[1] = q[0];
352  }
353  else if(ori == 0.0) {
354  if(!b->quiet) {
355  Msg::Warning("Tet #%d is degenerated", i + in->firstnumber);
356  }
357  }
358  // Create a new tetrahedron.
359  maketetrahedron(&tetloop); // tetloop.ver = 11.
360  setvertices(tetloop, p[0], p[1], p[2], p[3]);
361  // Try connecting this tet to others that share the common faces.
362  for(tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
363  p[3] = oppo(tetloop);
364  // Look for other tets having this vertex.
365  idx = pointmark(p[3]) - in->firstnumber;
366  tptr = ver2tetarray[idx];
367  // Link the current tet to the next one in the stack.
368  tetloop.tet[8 + tetloop.ver] = tptr;
369  // Push the current tet onto the stack.
370  ver2tetarray[idx] = encode(tetloop);
371  decode(tptr, checktet);
372  if(checktet.tet != nullptr) {
373  p[0] = org(tetloop); // a
374  p[1] = dest(tetloop); // b
375  p[2] = apex(tetloop); // c
376  prevchktet = tetloop;
377  do {
378  q[0] = org(checktet); // a'
379  q[1] = dest(checktet); // b'
380  q[2] = apex(checktet); // c'
381  // Check the three faces at 'd' in 'checktet'.
382  bondflag = 0;
383  for(int j = 0; j < 3; j++) {
384  // Go to the face [b',a',d], or [c',b',d], or [a',c',d].
385  esym(checktet, face2);
386  if(face2.tet[face2.ver & 3] == nullptr) {
387  k = ((j + 1) % 3);
388  if(q[k] == p[0]) { // b', c', a' = a
389  if(q[j] == p[1]) { // a', b', c' = b
390  // [#,#,d] is matched to [b,a,d].
391  esym(tetloop, face1);
392  bond(face1, face2);
393  bondflag++;
394  }
395  }
396  if(q[k] == p[1]) { // b',c',a' = b
397  if(q[j] == p[2]) { // a',b',c' = c
398  // [#,#,d] is matched to [c,b,d].
399  enext(tetloop, face1);
400  esymself(face1);
401  bond(face1, face2);
402  bondflag++;
403  }
404  }
405  if(q[k] == p[2]) { // b',c',a' = c
406  if(q[j] == p[0]) { // a',b',c' = a
407  // [#,#,d] is matched to [a,c,d].
408  eprev(tetloop, face1);
409  esymself(face1);
410  bond(face1, face2);
411  bondflag++;
412  }
413  }
414  }
415  else {
416  bondflag++;
417  }
418  enextself(checktet);
419  } // j
420  // Go to the next tet in the link.
421  tptr = checktet.tet[8 + checktet.ver];
422  if(bondflag == 3) {
423  // All three faces at d in 'checktet' have been connected.
424  // It can be removed from the link.
425  prevchktet.tet[8 + prevchktet.ver] = tptr;
426  }
427  else {
428  // Bakup the previous tet in the link.
429  prevchktet = checktet;
430  }
431  decode(tptr, checktet);
432  } while(checktet.tet != nullptr);
433  } // if(checktet.tet != nullptr)
434  } // for(tetloop.ver = 0; ...
435  } // i
436 
437  // Remember a tet of the mesh.
438  recenttet = tetloop;
439 
440  // Create hull tets, create the point-to-tet map, and clean up the
441  // temporary spaces used in each tet.
442  hullsize = tetrahedrons->items;
443 
444  tetrahedrons->traversalinit();
445  tetloop.tet = tetrahedrontraverse();
446  while(tetloop.tet != (tetrahedron *)nullptr) {
447  tptr = encode(tetloop);
448  for(tetloop.ver = 0; tetloop.ver < 4; tetloop.ver++) {
449  if(tetloop.tet[tetloop.ver] == nullptr) {
450  // Create a hull tet.
451  maketetrahedron(&hulltet);
452  p[0] = org(tetloop);
453  p[1] = dest(tetloop);
454  p[2] = apex(tetloop);
455  setvertices(hulltet, p[1], p[0], p[2], dummypoint);
456  bond(tetloop, hulltet);
457  // Try connecting this to others that share common hull edges.
458  for(int j = 0; j < 3; j++) {
459  fsym(hulltet, face2);
460  while(1) {
461  if(face2.tet == nullptr) break;
462  esymself(face2);
463  if(apex(face2) == dummypoint) break;
464  fsymself(face2);
465  }
466  if(face2.tet != nullptr) {
467  // Found an adjacent hull tet.
468  assert(face2.tet[face2.ver & 3] == nullptr);
469  esym(hulltet, face1);
470  bond(face1, face2);
471  }
472  enextself(hulltet);
473  }
474  // hullsize++;
475  }
476  // Create the point-to-tet map.
477  setpoint2tet((point)(tetloop.tet[4 + tetloop.ver]), tptr);
478  // Clean the temporary used space.
479  tetloop.tet[8 + tetloop.ver] = nullptr;
480  }
481  tetloop.tet = tetrahedrontraverse();
482  }
483 
484  hullsize = tetrahedrons->items - hullsize;
485 
486  delete[] ver2tetarray;
487  for(std::size_t i = 0; i < tets.size(); i++) delete tets[i];
488  tets.clear(); // Release all memory in this vector.
489  }
490 #endif
491 
492  std::vector<GFace *> const &f_list = _gr->faces();
493  std::vector<GEdge *> const &e_list = _gr->embeddedEdges();
494 
495  {
496  Msg::Info(" - Creating surface mesh");
497  face newsh;
498  face newseg;
499  point p[4];
500  int idx;
501 
502  for(auto it = f_list.begin(); it != f_list.end(); ++it) {
503  GFace *gf = *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);
509  }
510  }
511  makeshellface(subfaces, &newsh);
512  setshvertices(newsh, p[0], p[1], p[2]);
513  setshellmark(newsh, gf->tag()); // the GFace's tag.
514  recentsh = newsh;
515  for(int j = 0; j < 3; j++) {
516  makeshellface(subsegs, &newseg);
517  setshvertices(newseg, sorg(newsh), sdest(newsh), nullptr);
518  // Set the default segment marker '-1'.
519  setshellmark(newseg, -1);
520  ssbond(newsh, newseg);
521  senextself(newsh);
522  }
523  }
524  } // it
525 
526  if(_sqr) {
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++) {
531  p[j] = idx2verlist[mf.getVertex(j)->getIndex()];
532  if(pointtype(p[j]) == VOLVERTEX) {
533  setpointtype(p[j], FACETVERTEX);
534  }
535  }
536  makeshellface(subfaces, &newsh);
537  setshvertices(newsh, p[0], p[1], p[2]);
538  setshellmark(newsh, it->second->tag());
539  recentsh = newsh;
540  for(int j = 0; j < 3; j++) {
541  makeshellface(subsegs, &newseg);
542  setshvertices(newseg, sorg(newsh), sdest(newsh), nullptr);
543  // Set the default segment marker '-1'.
544  setshellmark(newseg, -1);
545  ssbond(newsh, newseg);
546  senextself(newsh);
547  }
548  }
549  }
550 
551  // Connecting triangles, removing redundant segments.
552  unifysegments();
553 
554  Msg::Info(" - Identifying boundary edges");
555 
556  face *shperverlist;
557  int *idx2shlist;
558  face searchsh, neighsh;
559  face segloop, checkseg;
560  point checkpt;
561 
562  // Construct a map from points to subfaces.
563  makepoint2submap(subfaces, idx2shlist, shperverlist);
564 
565  // Process the set of PSC edges.
566  // Remeber that all segments have default marker '-1'.
567  // int COUNTER = 0;
568  for(auto it = e_list.begin(); it != e_list.end(); ++it) {
569  GEdge *ge = *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);
574  }
575  if(p[0] == p[1]) {
576  // This is a potential problem in surface mesh.
577  continue; // Skip this edge.
578  }
579  // Find a face contains the edge p[0], p[1].
580  newseg.sh = nullptr;
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];
587  break; // Found.
588  }
589  else {
590  checkpt = sapex(shperverlist[j]);
591  if(checkpt == p[1]) {
592  senext2(shperverlist[j], searchsh);
593  sesymself(searchsh);
594  break;
595  }
596  }
597  } // j
598  if(searchsh.sh != nullptr) {
599  // Check if this edge is already a segment of the mesh.
600  sspivot(searchsh, checkseg);
601  if(checkseg.sh != nullptr) {
602  // This segment already exist.
603  newseg = checkseg;
604  }
605  else {
606  // Create a new segment at this edge.
607  makeshellface(subsegs, &newseg);
608  setshvertices(newseg, p[0], p[1], nullptr);
609  ssbond(searchsh, newseg);
610  spivot(searchsh, neighsh);
611  if(neighsh.sh != nullptr) { ssbond(neighsh, newseg); }
612  }
613  }
614  else {
615  // It is a dangling segment (not belong to any facets).
616  // Check if segment [p[0],p[1]] already exists.
617  // TODO: Change the brute-force search. Slow!
618  /* point *ppt;
619  subsegs->traversalinit();
620  segloop.sh = shellfacetraverse(subsegs);
621  while (segloop.sh != nullptr){
622  ppt = (point *) &(segloop.sh[3]);
623  if(((ppt[0] == p[0]) && (ppt[1] == p[1])) ||
624  ((ppt[0] == p[1]) && (ppt[1] == p[0]))){
625  // Found!
626  newseg = segloop;
627  break;
628  }
629  segloop.sh = shellfacetraverse(subsegs);
630  }*/
631  if(newseg.sh == nullptr) {
632  makeshellface(subsegs, &newseg);
633  setshvertices(newseg, p[0], p[1], nullptr);
634  }
635  }
636  setshellmark(newseg, ge->tag());
637  } // i
638  } // e_list
639 
640  delete[] shperverlist;
641  delete[] idx2shlist;
642 
643  Msg::Debug(" %ld (%ld) subfaces (segments)", subfaces->items,
644  subsegs->items);
645 
646  // The total number of iunput segments.
647  insegments = subsegs->items;
648 
649  if(0) { outmesh2medit("dump2"); }
650  }
651 
652  delete[] idx2verlist;
653 
654  // Boundary recovery.
655 
656  clock_t t;
657  Msg::Info(" - Recovering boundary");
658  recoverboundary(t);
659 
660  carveholes();
661 
662  if(subvertstack->objects > 0l) { suppresssteinerpoints(); }
663 
664  recoverdelaunay();
665 
666  // let's try
667  optimizemesh();
668 
669  if((dupverts > 0l) || (unuverts > 0l)) {
670  // Remove hanging nodes.
671  // cannot call this here due to 8 additional exterior vertices we
672  // inserted jettisonnodes();
673  }
674 
675  long tetnumber, facenumber;
676 
677  Msg::Debug("Statistics:\n");
678  Msg::Debug(" Input points: %ld", _vertices.size());
679  if(b->plc) {
680  Msg::Debug(" Input facets: %ld", f_list.size());
681  Msg::Debug(" Input segments: %ld", e_list.size());
682  }
683 
684  tetnumber = tetrahedrons->items - hullsize;
685  facenumber = (tetnumber * 4l + hullsize) / 2l;
686 
687  if(b->weighted) { // -w option
688  Msg::Debug(" Mesh points: %ld", points->items - nonregularcount);
689  }
690  else {
691  Msg::Debug(" Mesh points: %ld", points->items);
692  }
693  Msg::Debug(" Mesh tetrahedra: %ld", tetnumber);
694  Msg::Debug(" Mesh faces: %ld", facenumber);
695  if(meshedges > 0l) { Msg::Debug(" Mesh edges: %ld", meshedges); }
696  else {
697  if(!nonconvex) {
698  long vsize = points->items - dupverts - unuverts;
699  if(b->weighted) vsize -= nonregularcount;
700  meshedges = vsize + facenumber - tetnumber - 1;
701  Msg::Debug(" Mesh edges: %ld", meshedges);
702  }
703  }
704 
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);
710  }
711  if(st_facref_count > 0l) {
712  Msg::Debug(" Steiner points on facets: %ld", st_facref_count);
713  }
714  if(st_segref_count > 0l) {
715  Msg::Debug(" Steiner points on segments: %ld", st_segref_count);
716  }
717  }
718  else {
719  Msg::Debug(" Convex hull faces: %ld", hullsize);
720  if(meshhulledges > 0l) {
721  Msg::Debug(" Convex hull edges: %ld", meshhulledges);
722  }
723  }
724  if(b->weighted) { // -w option
725  Msg::Debug(" Skipped non-regular points: %ld", nonregularcount);
726  }
727 
728  // Debug
729  if(0) { outmesh2medit("dump"); }
730 
731  {
732  // Write mesh into to GRegion.
733 
734  Msg::Debug("Writing to GRegion...");
735 
736  point p[4];
737 
738  // In some hard cases, the surface mesh may be modified.
739  // Find the list of GFaces, GEdges that have been modified.
740  std::set<int> l_faces, l_edges;
741 
742  if(points->items > (int)_vertices.size()) {
743  face parentseg, parentsh, spinsh;
744  point pointloop;
745  // Create newly added mesh vertices.
746  // The new vertices must be added at the end of the point list.
747  points->traversalinit();
748  pointloop = pointtraverse();
749  while(pointloop != (point)nullptr) {
750  if(issteinerpoint(pointloop)) {
751  // Check if this Steiner point locates on boundary.
752  if(pointtype(pointloop) == FREESEGVERTEX) {
753  sdecode(point2sh(pointloop), parentseg);
754  assert(parentseg.sh != nullptr);
755  l_edges.insert(shellmark(parentseg));
756  // Get the GEdge containing this vertex.
757  GEdge *ge = nullptr;
758  GFace *gf = nullptr;
759  int etag = shellmark(parentseg);
760  for(auto it = e_list.begin(); it != e_list.end(); ++it) {
761  if((*it)->tag() == etag) {
762  ge = *it;
763  break;
764  }
765  }
766  if(ge != nullptr) {
767  MEdgeVertex *v = new MEdgeVertex(pointloop[0], pointloop[1],
768  pointloop[2], ge, 0);
769  double uu = 0;
770  if(reparamMeshVertexOnEdge(v, ge, uu)) {
771  v->setParameter(0, uu);
772  }
773  v->setIndex(pointmark(pointloop));
774  _gr->mesh_vertices.push_back(v);
775  _extras[pointmark(pointloop) - in->firstnumber] = v;
776  }
777  spivot(parentseg, parentsh);
778  if(parentsh.sh != nullptr) {
779  if(ge == nullptr) {
780  // We treat this vertex a facet vertex.
781  int ftag = shellmark(parentsh);
782  for(auto it = f_list.begin(); it != f_list.end(); ++it) {
783  if((*it)->tag() == ftag) {
784  gf = *it;
785  break;
786  }
787  }
788  if(gf != nullptr) {
789  MFaceVertex *v = new MFaceVertex(
790  pointloop[0], pointloop[1], pointloop[2], gf, 0, 0);
791  SPoint2 param;
792  if(reparamMeshVertexOnFace(v, gf, param)) {
793  v->setParameter(0, param.x());
794  v->setParameter(1, param.y());
795  }
796  v->setIndex(pointmark(pointloop));
797  _gr->mesh_vertices.push_back(v);
798  _extras[pointmark(pointloop) - in->firstnumber] = v;
799  }
800  }
801  // Record all the GFaces' tag at this segment.
802  spinsh = parentsh;
803  while(1) {
804  l_faces.insert(shellmark(spinsh));
805  spivotself(spinsh);
806  if(spinsh.sh == parentsh.sh) break;
807  }
808  }
809  if((ge == nullptr) && (gf == nullptr)) {
810  // Create an interior mesh vertex.
811  MVertex *v =
812  new MVertex(pointloop[0], pointloop[1], pointloop[2], _gr);
813  v->setIndex(pointmark(pointloop));
814  _extras[pointmark(pointloop) - in->firstnumber] = v;
815  _gr->mesh_vertices.push_back(v);
816  }
817  }
818  else if(pointtype(pointloop) == FREEFACETVERTEX) {
819  sdecode(point2sh(pointloop), parentsh);
820  assert(parentsh.sh != nullptr);
821  l_faces.insert(shellmark(parentsh));
822  // Get the GFace containing this vertex.
823  GFace *gf = nullptr;
824  int ftag = shellmark(parentsh);
825  for(auto it = f_list.begin(); it != f_list.end(); ++it) {
826  if((*it)->tag() == ftag) {
827  gf = *it;
828  break;
829  }
830  }
831  if(gf != nullptr) {
832  MFaceVertex *v = new MFaceVertex(pointloop[0], pointloop[1],
833  pointloop[2], gf, 0, 0);
834  SPoint2 param;
835  if(reparamMeshVertexOnFace(v, gf, param)) {
836  v->setParameter(0, param.x());
837  v->setParameter(1, param.y());
838  }
839  v->setIndex(pointmark(pointloop));
840  _gr->mesh_vertices.push_back(v);
841  _extras[pointmark(pointloop) - in->firstnumber] = v;
842  }
843  else {
844  // Create a mesh vertex.
845  MVertex *v =
846  new MVertex(pointloop[0], pointloop[1], pointloop[2], _gr);
847  v->setIndex(pointmark(pointloop));
848  _gr->mesh_vertices.push_back(v);
849  _extras[pointmark(pointloop) - in->firstnumber] = v;
850  }
851  }
852  else {
853  MVertex *v =
854  new MVertex(pointloop[0], pointloop[1], pointloop[2], _gr);
855  v->setIndex(pointmark(pointloop));
856  _gr->mesh_vertices.push_back(v);
857  _extras[pointmark(pointloop) - in->firstnumber] = v;
858  }
859  }
860  pointloop = pointtraverse();
861  }
862  // assert((int)_vertices.size() == points->items);
863  }
864 
865  if(!_extras.empty())
866  Msg::Info(" - Added %d Steiner point%s", _extras.size(),
867  (_extras.size() > 1) ? "s" : "");
868 
869  if(l_edges.size() > 0) {
870  // There are Steiner points on segments!
871  face segloop;
872  // Re-create the segment mesh in the corresponding GEdges.
873  for(auto it = l_edges.begin(); it != l_edges.end(); ++it) {
874  // Find the GEdge with tag = *it.
875 
876  int etag = *it;
877  GEdge *ge = nullptr;
878  for(auto it = e_list.begin(); it != e_list.end(); ++it) {
879  if((*it)->tag() == etag) {
880  ge = *it;
881  break;
882  }
883  }
884  if(ge != nullptr) {
885  Msg::Info(" - Steiner points exist on curve %d", ge->tag());
886  // Delete the old triangles.
887  for(std::size_t i = 0; i < ge->lines.size(); i++)
888  delete ge->lines[i];
889  ge->lines.clear();
890  ge->deleteVertexArrays();
891  // Create the new triangles.
892  segloop.shver = 0;
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] :
901  _vertices[idx1];
902  int idx2 = pointmark(p[1]) - in->firstnumber;
903  MVertex *v2 = idx2 >= (int)_vertices.size() ? _extras[idx2] :
904  _vertices[idx2];
905  MLine *t = new MLine(v1, v2);
906  ge->lines.push_back(t);
907  }
908  segloop.sh = shellfacetraverse(subsegs);
909  }
910  }
911  else {
912  Msg::Debug("Unknown curve %d with Steiner point(s)", etag);
913  }
914  } // it
915  }
916 
917  if(l_faces.size() > 0) {
918  // There are Steiner points on facets!
919  face subloop;
920  // Re-create the surface mesh in the corresponding GFaces.
921  for(auto it = l_faces.begin(); it != l_faces.end(); ++it) {
922  // Find the GFace with tag = *it.
923 
924  int ftag = *it;
925  GFace *gf = nullptr;
926  for(auto it = f_list.begin(); it != f_list.end(); ++it) {
927  if((*it)->tag() == ftag) {
928  gf = *it;
929  break;
930  }
931  }
932  if(gf != nullptr) {
933  // Delete the old triangles.
934  Msg::Info(" - Steiner points exist on surface %d", gf->tag());
935  for(std::size_t i = 0; i < gf->triangles.size(); i++)
936  delete gf->triangles[i];
937  gf->triangles.clear();
938  gf->deleteVertexArrays();
939 
940  if(gf->quadrangles.size()) {
941  Msg::Warning("Steiner points not handled for quad surface mesh");
942  }
943 
944  // Create the new triangles.
945  subloop.shver = 0;
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] :
955  _vertices[idx1];
956  int idx2 = pointmark(p[1]) - in->firstnumber;
957  MVertex *v2 = idx2 >= (int)_vertices.size() ? _extras[idx2] :
958  _vertices[idx2];
959  int idx3 = pointmark(p[2]) - in->firstnumber;
960  MVertex *v3 = idx3 >= (int)_vertices.size() ? _extras[idx3] :
961  _vertices[idx3];
962  MTriangle *t = new MTriangle(v1, v2, v3);
963  gf->triangles.push_back(t);
964  }
965  subloop.sh = shellfacetraverse(subfaces);
966  }
967  }
968  else {
969  Msg::Debug("Unknown surface %d with Steiner point(s)", ftag);
970  }
971  } // it
972  }
973 
974  triface tetloop;
975 
976  tetloop.ver = 11;
977  tetrahedrons->traversalinit();
978  tetloop.tet = tetrahedrontraverse();
979 
980  while(tetloop.tet != (tetrahedron *)nullptr) {
981  p[0] = org(tetloop);
982  p[1] = dest(tetloop);
983  p[2] = apex(tetloop);
984  p[3] = oppo(tetloop);
985 
986  int idx1 = pointmark(p[0]) - in->firstnumber;
987  MVertex *v1 =
988  idx1 >= (int)_vertices.size() ? _extras[idx1] : _vertices[idx1];
989  int idx2 = pointmark(p[1]) - in->firstnumber;
990  MVertex *v2 =
991  idx2 >= (int)_vertices.size() ? _extras[idx2] : _vertices[idx2];
992  int idx3 = pointmark(p[2]) - in->firstnumber;
993  MVertex *v3 =
994  idx3 >= (int)_vertices.size() ? _extras[idx3] : _vertices[idx3];
995  int idx4 = pointmark(p[3]) - in->firstnumber;
996  MVertex *v4 =
997  idx4 >= (int)_vertices.size() ? _extras[idx4] : _vertices[idx4];
998  MTetrahedron *t = new MTetrahedron(v1, v2, v3, v4);
999  _gr->tetrahedra.push_back(t);
1000  tetloop.tet = tetrahedrontraverse();
1001  }
1002  } // mesh output
1003 
1004  Msg::Info("Done reconstructing mesh (Wall %gs, CPU %gs)",
1005  TimeOfDay() - w_start, Cpu() - t_start);
1006 
1007  // Put all coordinates back so they are not pertubated anymore
1008  // (pertubation done in delaunayTriangulation)
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());
1013  }
1014 
1015  // delete 8 new enclosing box vertices added in delaunayMeshIn3d
1016  for(std::size_t i = _vertices.size() - 8; i < _vertices.size(); i++)
1017  delete _vertices[i];
1018 
1019  return true;
1020  }
1021 
1022  // Dump the input surface mesh.
1023  // 'mfilename' is a filename without suffix.
1024  void tetgenmesh::outsurfacemesh(const char *mfilename)
1025  {
1026  FILE *outfile = nullptr;
1027  char sfilename[256];
1028  int firstindex;
1029 
1030  point pointloop;
1031  int pointnumber;
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);
1037  // Determine the first index (0 or 1).
1038  firstindex = b->zeroindex ? 0 : in->firstnumber;
1039  points->traversalinit();
1040  pointloop = pointtraverse();
1041  pointnumber = firstindex; // in->firstnumber;
1042  while(pointloop != (point)nullptr) {
1043  // Point number, x, y and z coordinates.
1044  fprintf(outfile, "%4d %.17g %.17g %.17g", pointnumber,
1045  pointloop[0], pointloop[1], pointloop[2]);
1046  fprintf(outfile, "\n");
1047  pointloop = pointtraverse();
1048  pointnumber++;
1049  }
1050  fclose(outfile);
1051 
1052  face faceloop;
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); }
1058  int shift = 0; // Default no shiftment.
1059  if((in->firstnumber == 1) && (firstindex == 0)) {
1060  shift = 1; // Shift the output indices by 1.
1061  }
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);
1074  }
1075  fprintf(outfile, "0\n");
1076  fprintf(outfile, "0\n");
1077  fclose(outfile);
1078 
1079  face edgeloop;
1080  int edgenumber;
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; // in->firstnumber;
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));
1095  edgenumber++;
1096  edgeloop.sh = shellfacetraverse(subsegs);
1097  }
1098  fclose(outfile);
1099  }
1100 
1101  void tetgenmesh::outmesh2medit(const char *mfilename)
1102  {
1103  FILE *outfile;
1104  char mefilename[256];
1105  tetrahedron *tetptr;
1106  triface tface, tsymface;
1107  face segloop, checkmark;
1108  point ptloop, p1, p2, p3, p4;
1109  long ntets, faces;
1110  int shift = 0;
1111  int marker;
1112 
1113  if(mfilename != (char *)nullptr && mfilename[0] != '\0') {
1114  strcpy(mefilename, mfilename);
1115  }
1116  else {
1117  strcpy(mefilename, "unnamed");
1118  }
1119  strcat(mefilename, ".mesh");
1120 
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);
1125  return;
1126  }
1127 
1128  fprintf(outfile, "MeshVersionFormatted 1\n");
1129  fprintf(outfile, "\n");
1130  fprintf(outfile, "Dimension\n");
1131  fprintf(outfile, "3\n");
1132  fprintf(outfile, "\n");
1133 
1134  fprintf(outfile, "\n# Set of mesh vertices\n");
1135  fprintf(outfile, "Vertices\n");
1136  fprintf(outfile, "%ld\n", points->items);
1137 
1138  points->traversalinit();
1139  ptloop = pointtraverse();
1140  // pointnumber = 1;
1141  while(ptloop != (point)nullptr) {
1142  // Point coordinates.
1143  fprintf(outfile, "%.17g %.17g %.17g", ptloop[0], ptloop[1],
1144  ptloop[2]);
1145  fprintf(outfile, " 0\n");
1146  // setpointmark(ptloop, pointnumber);
1147  ptloop = pointtraverse();
1148  // pointnumber++;
1149  }
1150 
1151  // Medit need start number form 1.
1152  if(in->firstnumber == 1) { shift = 0; }
1153  else {
1154  shift = 1;
1155  }
1156 
1157  // Compute the number of faces.
1158  ntets = tetrahedrons->items - hullsize;
1159 
1160  fprintf(outfile, "\n# Set of Tetrahedra\n");
1161  fprintf(outfile, "Tetrahedra\n");
1162  fprintf(outfile, "%ld\n", ntets);
1163 
1164  tetrahedrons->traversalinit();
1165  tetptr = tetrahedrontraverse();
1166  while(tetptr != (tetrahedron *)nullptr) {
1167  if(!b->reversetetori) {
1168  p1 = (point)tetptr[4];
1169  p2 = (point)tetptr[5];
1170  }
1171  else {
1172  p1 = (point)tetptr[5];
1173  p2 = (point)tetptr[4];
1174  }
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));
1182  }
1183  else {
1184  fprintf(outfile, " 0");
1185  }
1186  fprintf(outfile, "\n");
1187  tetptr = tetrahedrontraverse();
1188  }
1189 
1190  // faces = (ntets * 4l + hullsize) / 2l;
1191  faces = subfaces->items;
1192  face sface;
1193 
1194  fprintf(outfile, "\n# Set of Triangles\n");
1195  fprintf(outfile, "Triangles\n");
1196  fprintf(outfile, "%ld\n", faces);
1197 
1198  subfaces->traversalinit();
1199  sface.sh = shellfacetraverse(subfaces);
1200  while(sface.sh != nullptr) {
1201  p1 = sorg(sface);
1202  p2 = sdest(sface);
1203  p3 = sapex(sface);
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);
1209  }
1210 
1211  fprintf(outfile, "\nEnd\n");
1212  fclose(outfile);
1213  }
1214 
1215  } // namespace tetgenBR
1216 
1218  {
1219  bool ret = false;
1220  try {
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);
1226  delete m->in;
1227  delete m->b;
1228  delete m;
1229  } catch(int err) {
1230  if(err == 1) {
1231  Msg::Error("Out of memory in boundary mesh recovery");
1232  ret = false;
1233  }
1234  else if(err == 3) {
1235  std::map<int, MVertex *> all;
1236  std::vector<GFace *> f = gr->faces();
1237  for(auto it = f.begin(); it != f.end(); ++it) {
1238  GFace *gf = *it;
1239  for(std::size_t i = 0; i < gf->triangles.size(); i++) {
1240  for(int j = 0; j < 3; j++) {
1241  MVertex *v = gf->triangles[i]->getVertex(j);
1242  all[v->getIndex()] = v;
1243  }
1244  }
1245  }
1246  std::vector<GEdge *> const &e = gr->embeddedEdges();
1247  for(auto it = e.begin(); it != e.end(); ++it) {
1248  GEdge *ge = *it;
1249  for(std::size_t i = 0; i < ge->lines.size(); i++) {
1250  for(int j = 0; j < 2; j++) {
1251  MVertex *v = ge->lines[i]->getVertex(j);
1252  all[v->getIndex()] = v;
1253  }
1254  }
1255  }
1256  std::vector<GVertex *> const &v = gr->embeddedVertices();
1257  for(auto it = v.begin(); it != v.end(); ++it) {
1258  GVertex *gv = *it;
1259  for(std::size_t i = 0; i < gv->points.size(); i++) {
1260  MVertex *v = gv->points[i]->getVertex(0);
1261  all[v->getIndex()] = v;
1262  }
1263  }
1264  for(std::size_t i = 0; i < gr->mesh_vertices.size(); i++) {
1265  MVertex *v = gr->mesh_vertices[i];
1266  all[v->getIndex()] = v;
1267  }
1268  std::string what;
1269  bool pnt = true;
1270  switch(tetgenBR::sevent.e_type) {
1271  case 1: what = "segment-segment intersection"; break;
1272  case 2: what = "segment-facet intersection"; break;
1273  case 3: what = "facet-facet intersection"; break;
1274  case 4:
1275  what = "overlapping segments";
1276  pnt = false;
1277  break;
1278  case 5:
1279  what = "segment in facet";
1280  pnt = false;
1281  break;
1282  case 6:
1283  what = "overlapping facets";
1284  pnt = false;
1285  break;
1286  case 7: what = "vertex in segment"; break;
1287  case 8: what = "vertex in facet"; break;
1288  default: what = "unknown"; break;
1289  }
1290  int vtags[2][3] = {
1297  std::ostringstream pb;
1298  std::vector<double> x, y, z, val;
1299  for(int f = 0; f < 2; f++) {
1300  if(ftags[f] > 0) {
1301  GFace *gf = gr->model()->getFaceByTag(ftags[f]);
1302  if(gf) {
1303  gr->model()->addLastMeshEntityError(gf);
1304  pb << " surface " << ftags[f];
1305  }
1306  }
1307  if(etags[f] > 0) {
1308  GEdge *ge = gr->model()->getEdgeByTag(etags[f]);
1309  if(ge) {
1310  gr->model()->addLastMeshEntityError(ge);
1311  pb << " curve " << etags[f];
1312  }
1313  }
1314  for(int i = 0; i < 3; i++) {
1315  MVertex *v = all[vtags[f][i]];
1316  if(v) {
1317  gr->model()->addLastMeshVertexError(v);
1318  x.push_back(v->x());
1319  y.push_back(v->y());
1320  z.push_back(v->z());
1321  val.push_back(f);
1322  }
1323  }
1324  }
1325  if(pnt) {
1326  double px = tetgenBR::sevent.int_point[0];
1327  double py = tetgenBR::sevent.int_point[1];
1328  double pz = tetgenBR::sevent.int_point[2];
1329  pb << ", intersection (" << px << "," << py << "," << pz << ")";
1330  x.push_back(px);
1331  y.push_back(py);
1332  z.push_back(pz);
1333  val.push_back(3.);
1334  }
1335  Msg::Error("Invalid boundary mesh (%s) on%s", what.c_str(),
1336  pb.str().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);
1342 #endif
1343 #endif
1344  ret = false;
1345  }
1346  else {
1347  Msg::Error("Could not recover boundary mesh: error %d", err);
1348  ret = false;
1349  }
1350  }
1351  return ret;
1352  }
1353 
1354 #else
1355 
1357 {
1358  return false;
1359 }
1360 
1361 #endif
sevent
static selfint_event sevent
Definition: tetgenBR.h:1537
MTriangle.h
TimeOfDay
double TimeOfDay()
Definition: OS.cpp:399
sqr
static int sqr(int x)
Definition: gl2gif.cpp:266
PView
Definition: PView.h:27
selfint_event::f_marker2
int f_marker2
Definition: tetgenBR.h:1525
meshGRegionDelaunayInsertion.h
GFace.h
MTetrahedron
Definition: MTetrahedron.h:34
GFace
Definition: GFace.h:33
GFace::triangles
std::vector< MTriangle * > triangles
Definition: GFace.h:428
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
GEdge::lines
std::vector< MLine * > lines
Definition: GEdge.h:42
GEntity::model
GModel * model() const
Definition: GEntity.h:277
SPoint2
Definition: SPoint2.h:12
OS.h
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
contextMeshOptions::angleToleranceFacetOverlap
double angleToleranceFacetOverlap
Definition: Context.h:47
selfint_event::int_point
REAL int_point[3]
Definition: tetgenBR.h:1528
robustPredicates.h
MVertex
Definition: MVertex.h:24
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
MVertex::z
double z() const
Definition: MVertex.h:62
reparamMeshVertexOnFace
bool reparamMeshVertexOnFace(MVertex const *v, const GFace *gf, SPoint2 &param, bool onSurface, bool failOnSeam, int dir)
Definition: MVertex.cpp:522
SPoint3
Definition: SPoint3.h:14
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
GModel::getFaceByTag
GFace * getFaceByTag(int n) const
Definition: GModel.cpp:326
PView.h
REAL
#define REAL
Definition: robustPredicates.cpp:141
MPoint.h
tetgenmesh::outsurfacemesh
void outsurfacemesh(const char *mfilename)
MVertex::point
SPoint3 point() const
Definition: MVertex.h:67
GModel::getEdgeByTag
GEdge * getEdgeByTag(int n) const
Definition: GModel.cpp:336
MLine.h
meshGRegionBoundaryRecovery
bool meshGRegionBoundaryRecovery(GRegion *gr, splitQuadRecovery *sqr)
Definition: meshGRegionBoundaryRecovery.cpp:1356
reparamMeshVertexOnEdge
bool reparamMeshVertexOnEdge(MVertex *v, const GEdge *ge, double &param)
Definition: MVertex.cpp:592
drawContext::global
static drawContextGlobal * global()
Definition: drawContext.cpp:85
GFace::quadrangles
std::vector< MQuadrangle * > quadrangles
Definition: GFace.h:429
MLine
Definition: MLine.h:21
drawContextGlobal::draw
virtual void draw(bool rateLimited=true)
Definition: drawContext.h:97
GVertex::points
std::vector< MPoint * > points
Definition: GVertex.h:120
tetgenBR.cxx
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
GRegion::faces
virtual std::vector< GFace * > faces() const
Definition: GRegion.h:64
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
GModel::addLastMeshVertexError
void addLastMeshVertexError(MVertex *v)
Definition: GModel.h:591
MFace
Definition: MFace.h:20
GRegion.h
selfint_event::f_vertices1
int f_vertices1[3]
Definition: tetgenBR.h:1524
MVertex::setIndex
void setIndex(long int index)
Definition: MVertex.h:94
delaunayMeshIn3D
void delaunayMeshIn3D(std::vector< MVertex * > &v, std::vector< MTetrahedron * > &result, bool removeBox)
Definition: meshGRegionDelaunayInsertion.cpp:1559
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
tetgenmesh::reconstructmesh
bool reconstructmesh(void *)
MEdgeVertex
Definition: MVertex.h:137
MEdgeVertex::setParameter
virtual bool setParameter(int i, double par)
Definition: MVertex.h:159
GVertex
Definition: GVertex.h:23
meshGRegionBoundaryRecovery.h
MVertex.h
fsymself
#define fsymself(t)
Definition: tetgenBR.h:1707
Cpu
double Cpu()
Definition: OS.cpp:366
splitQuadRecovery::add
void add(const MFace &f, MVertex *v, GFace *gf)
Definition: meshGRegion.cpp:33
MFace::getVertex
MVertex * getVertex(std::size_t i) const
Definition: MFace.h:30
selfint_event::f_marker1
int f_marker1
Definition: tetgenBR.h:1522
MFaceVertex::setParameter
virtual bool setParameter(int i, double par)
Definition: MVertex.h:196
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
selfint_event::s_marker1
int s_marker1
Definition: tetgenBR.h:1523
CTX::mesh
contextMeshOptions mesh
Definition: Context.h:313
GEntity::tag
int tag() const
Definition: GEntity.h:280
MFaceVertex
Definition: MVertex.h:168
splitQuadRecovery
Definition: meshGRegion.h:72
GRegion
Definition: GRegion.h:28
splitQuadRecovery::getTri
std::map< MFace, GFace *, MFaceLessThan > & getTri()
Definition: meshGRegion.h:80
MTriangle
Definition: MTriangle.h:26
selfint_event::s_marker2
int s_marker2
Definition: tetgenBR.h:1526
tetgenBR.h
selfint_event::f_vertices2
int f_vertices2[3]
Definition: tetgenBR.h:1527
SPoint2::x
double x(void) const
Definition: SPoint2.h:86
MVertex::getIndex
long int getIndex() const
Definition: MVertex.h:93
Context.h
GRegion::embeddedEdges
std::vector< GEdge * > & embeddedEdges()
Definition: GRegion.h:80
MTetrahedron.h
setvertices
#define setvertices(t, torg, tdest, tapex, toppo)
Definition: tetgenBR.h:1770
tetgenmesh::outmesh2medit
void outmesh2medit(const char *mfilename)
z
const double z
Definition: GaussQuadratureQuad.cpp:56
MQuadrangle.h
tetrahedron
Definition: shapeFunctions.h:682
GEdge
Definition: GEdge.h:26
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
meshGRegion.h
robustPredicates::orient3d
REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd)
Definition: robustPredicates.cpp:2321
setshvertices
#define setshvertices(s, pa, pb, pc)
Definition: tetgenBR.h:2069
GModel.h
MVertex::y
double y() const
Definition: MVertex.h:61
GModel::addLastMeshEntityError
void addLastMeshEntityError(GEntity *e)
Definition: GModel.h:585
GEntity::deleteVertexArrays
void deleteVertexArrays()
Definition: GEntity.cpp:27
robustPredicates::orient4d
REAL orient4d(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe, REAL aheight, REAL bheight, REAL cheight, REAL dheight, REAL eheight)
Definition: robustPredicates.cpp:4739
Msg::GetErrorCount
static int GetErrorCount()
Definition: GmshMessage.cpp:347
GRegion::tetrahedra
std::vector< MTetrahedron * > tetrahedra
Definition: GRegion.h:163
GRegion::embeddedVertices
std::vector< GVertex * > & embeddedVertices()
Definition: GRegion.h:79
MVertex::x
double x() const
Definition: MVertex.h:60
faces
static int faces[4][3]
Definition: meshGRegionDelaunayInsertion.cpp:165
SPoint2::y
double y(void) const
Definition: SPoint2.h:88
drawContext.h