gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
meshGRegionBoundaryLayer.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 "GRegion.h"
7 #include "GModel.h"
8 #include "GFace.h"
9 #include "MVertex.h"
10 #include "MTetrahedron.h"
11 #include "MQuadrangle.h"
12 #include "MTriangle.h"
13 #include "MPrism.h"
14 #include "MLine.h"
15 #include "SVector3.h"
16 #include "xyFace.h"
17 #include "xyEdge.h"
18 #include "Numeric.h"
19 
20 /*
21 
22  EDGES : both faces BL --> EDGE = RIDGE
23  EDGES : one face BL --> FACE = BOUNDARY, EDGE = RIDGE
24 
25 --> VERTICES
26 
27  VERTICES : all edges RIDGE --> corner
28 
29 */
30 
31 static GFace *haveTowGEdges(std::vector<GFace *> &faces, GEdge *ge1, GEdge *ge2)
32 {
33  for(size_t i = 0; i < faces.size(); i++) {
34  std::vector<GEdge *> e = faces[i]->edges();
35  if(std::find(e.begin(), e.end(), ge1) != e.end() &&
36  std::find(e.begin(), e.end(), ge2) != e.end())
37  return faces[i];
38  }
39  return nullptr;
40 }
41 
42 static void meshPolygon(GRegion *gr, std::vector<MLine *> &poly,
43  std::vector<MTriangle *> &mesh,
44  std::vector<MVertex *> &new_vertices)
45 {
46  // we want to mesh a simple polygon
47  // Create a planar surface
48  xyEdge e(gr->model(), 1111);
49  e.lines = poly;
50  xyFace f(gr->model(), 1111, &e);
51  f.mesh(true);
52  // printf("mesh done %d triangles %d
53  // size\n",f.triangles.size(),f.mesh_vertices.size());
54  new_vertices = f.mesh_vertices;
55  mesh = f.triangles;
56  f.mesh_vertices.clear();
57  f.triangles.clear();
58 }
59 
60 class blyr_ridge {
61 public:
62  enum type { INTERNAL, EXTERNAL, FLAT };
66  GFace *_f[2];
68  std::size_t N_SUBNORMALS;
69 
70  void computeType(double angle)
71  {
72  if(max_angle > angle)
73  _t = EXTERNAL;
74  else if(min_angle < -angle)
75  _t = INTERNAL;
76  else
77  _t = FLAT;
78  }
79 
80  void setType(type t) { _t = t; }
81 
82  type getType() const { return _t; }
83 
84  blyr_ridge(GEdge *ge, GRegion *gr, GFace *f0, GFace *f1)
85  : _ge(ge), _gr(gr), N_SUBNORMALS(0)
86  {
87  _f[0] = f0;
88  _f[1] = f1;
89  }
90  GEdge *getEdge() const { return _ge; }
91  bool operator<(const blyr_ridge &other)
92  {
93  return _ge->tag() < other._ge->tag();
94  }
95 };
96 
97 class blyr_mvertex {
98 public:
100  // all triangles connected to that vertex
101 
102  mutable std::vector<MTriangle *> _triangles;
103  mutable std::vector<SVector3> _normals;
104  mutable std::vector<GFace *> _gfaces;
105 
106  // all mesh edges connected to that vertex
107 
108  mutable std::vector<MLine *> _lines;
109  mutable std::vector<GEdge *> _gedges;
110 
111  // one extruded vertex per face ...
112  mutable std::vector<MVertex *> _v_per_face;
113  mutable std::vector<SVector3> _n_per_vertex;
114  mutable std::vector<GFace *> _f_per_normal;
115 
116  // ridge points
117  mutable std::map<std::pair<GFace *, GFace *>, std::vector<MVertex *> >
119 
120  // triangles for external corners
121  mutable std::vector<MTriangle *> _triangles_at_corner;
122 
123  bool operator<(const blyr_mvertex &other) const
124  {
125  return _v->getNum() < other._v->getNum();
126  }
127  blyr_mvertex(MVertex *v) : _v(v) {}
128 
130  {
131  if(_f_per_normal.size() == 1) return _v_per_face[0];
132  for(size_t i = 0; i < _f_per_normal.size(); i++) {
133  if(gf == _f_per_normal[i]) return _v_per_face[i];
134  }
135  // if (gf) printf("NONE for face %d\n",gf->tag());
136  return nullptr;
137  }
138 
139  SVector3 average_normal(GFace *gf = nullptr) const
140  {
141  SVector3 n(0, 0, 0);
142  // printf("%d %d\n",_normals.size(),_f_per_normal.size());
143  for(size_t i = 0; i < _normals.size(); i++) {
144  if(!gf || gf == _gfaces[i]) n += _normals[i];
145  }
146  n.normalize();
147  return n;
148  }
149 
150  void add_triangle(MTriangle *t, SVector3 &n, GFace *gf) const
151  {
152  if(std::find(_triangles.begin(), _triangles.end(), t) == _triangles.end()) {
153  _triangles.push_back(t);
154  _normals.push_back(n);
155  _gfaces.push_back(gf);
156  }
157  }
158  void add_line(MLine *l, GEdge *ge) const
159  {
160  if(std::find(_lines.begin(), _lines.end(), l) == _lines.end()) {
161  _lines.push_back(l);
162  _gedges.push_back(ge);
163  }
164  }
165 };
166 
168  // blayer thickness (this could change
169  // by imposing a function)...
170 
171  double _thickness;
172 
173  // threshold for angles
175 
176  // the 3D region where the fluid is flowing
178 
179  // one face BL --> FACE = BOUNDARY, EDGE = RIDGE
180  std::vector<GFace *> _faces;
181 
182  // both faces BL --> RIDGE
183  std::vector<blyr_ridge> _ridges;
184 
185  // vertices of the surface
186  std::set<blyr_mvertex> _vertices;
187 
188 public:
189  blyr_manager(GRegion *gr, std::vector<GFace *> &bls, double t)
190  : _thickness(t), _gr(gr), _faces(bls)
191  {
192  std::map<MFace, SVector3, MFaceLessThan> t_normals;
193  for(size_t i = 0; i < _gr->tetrahedra.size(); i++) {
194  for(int j = 0; j < 4; j++) {
195  MFace f = _gr->tetrahedra[i]->getFace(j);
196  auto it = t_normals.find(f);
197  if(it == t_normals.end()) {
198  SVector3 n = f.normal();
199  MVertex *v = _gr->tetrahedra[i]->getVertex(3 - j);
200  SPoint3 b = f.barycenter();
201  SVector3 t(v->x() - b.x(), v->y() - b.y(), v->z() - b.z());
202  if(dot(t, n) < 0) n *= -1.0;
203  t_normals[f] = n;
204  }
205  else
206  t_normals.erase(it);
207  }
208  }
209 
210  // printf("%d triangles are ok\n",t_normals.size());
211 
212  _threshold_angle = M_PI / 6; // one normal per vertex for now
213  // compute all vertices
214  for(size_t i = 0; i < bls.size(); i++) {
215  for(size_t j = 0; j < bls[i]->triangles.size(); j++) {
216  for(int k = 0; k < 3; k++) {
217  _vertices.insert(blyr_mvertex(bls[i]->triangles[j]->getVertex(k)));
218  }
219  }
220  }
221 
222  Msg::Debug("Boundary layer manager computes extruded elements in region %d",
223  gr->tag());
224 
225  // compute ridges and boundaries
226  std::vector<GEdge *> edges = gr->edges();
227  std::vector<GFace *> faces = gr->faces();
228  for(size_t i = 0; i < edges.size(); i++) {
229  GFace *f[2] = {nullptr, nullptr};
230  std::vector<GFace *> efaces = edges[i]->faces();
231  int count = 0;
232  bool seam = false;
233  for(size_t j = 0; j < efaces.size(); j++) {
234  if(edges[i]->isSeam(efaces[j])) seam = true;
235  if(std::find(faces.begin(), faces.end(), efaces[j]) != faces.end()) {
236  f[count++] = efaces[j];
237  }
238  }
239  // seams are virtual so NO ridge is present
240  // also remove flat ridges
241  if(!seam) {
242  if(count >= 1) {
243  _ridges.push_back(blyr_ridge(edges[i], gr, f[0], f[1]));
244  }
245  for(size_t j = 0; j < edges[i]->lines.size(); j++) {
246  for(int k = 0; k < 2; k++) {
247  MVertex *v = edges[i]->lines[j]->getVertex(k);
248  auto it = _vertices.find(v);
249  if(it == _vertices.end())
250  Msg::Error("Unknown node in boundary layer");
251  it->add_line(edges[i]->lines[j], edges[i]);
252  }
253  }
254  }
255  }
256 
257  Msg::Debug("Boundary layer manager : %d ridges", _ridges.size());
258 
259  // then compute normals
260 
261  for(size_t i = 0; i < bls.size(); i++) {
262  for(size_t j = 0; j < bls[i]->triangles.size(); j++) {
263  MTriangle *t = bls[i]->triangles[j];
264  auto it = t_normals.find(t->getFace(0));
265  SVector3 n;
266  if(it == t_normals.end())
267  Msg::Error("Unknown face in boundary layer");
268  else
269  n = it->second;
270  for(int k = 0; k < 3; k++) {
271  MVertex *v = t->getVertex(k);
272  auto it = _vertices.find(v);
273  if(it == _vertices.end())
274  Msg::Error("Unknown node in boundary layer");
275  it->add_triangle(t, n, bls[i]);
276  }
277  }
278  }
279  }
280 
282  {
283  for(size_t i = 0; i < _ridges.size(); i++) {
284  if(_ridges[i]._ge == ge) return &_ridges[i];
285  }
286  Msg::Error("Unknown ridge %d", ge->tag());
287  return nullptr;
288  }
289 
291  {
292  for(size_t i = 0; i < _ridges.size(); i++) {
293  GEdge *ge = _ridges[i].getEdge();
294  GFace *f0 = _ridges[i]._f[0];
295  GFace *f1 = _ridges[i]._f[1];
296  _ridges[i].max_angle = -2 * M_PI;
297  _ridges[i].min_angle = 2 * M_PI;
298  for(size_t j = 0; j < ge->lines.size(); j++) {
299  MLine *l = ge->lines[j];
300  MVertex *l0 = l->getVertex(0);
301  MVertex *l1 = l->getVertex(1);
302  MVertex *op1 = nullptr;
303  SVector3 N[2];
304  auto it = _vertices.find(l->getVertex(0));
305  for(size_t k = 0; k < it->_triangles.size(); k++) {
306  MVertex *v0 = it->_triangles[k]->getVertex(0);
307  MVertex *v1 = it->_triangles[k]->getVertex(1);
308  MVertex *v2 = it->_triangles[k]->getVertex(2);
309  GFace *gf = it->_gfaces[k];
310  if((v0 == l0 && v1 == l1) || (v0 == l1 && v1 == l0)) {
311  if(gf == f0) { N[0] = it->_normals[k]; }
312  if(gf == f1) {
313  N[1] = it->_normals[k];
314  op1 = v2;
315  }
316  }
317  if((v0 == l0 && v2 == l1) || (v0 == l1 && v2 == l0)) {
318  if(gf == f0) { N[0] = it->_normals[k]; }
319  if(gf == f1) {
320  N[1] = it->_normals[k];
321  op1 = v1;
322  }
323  }
324  if((v1 == l0 && v2 == l1) || (v1 == l1 && v2 == l0)) {
325  if(gf == f0) { N[0] = it->_normals[k]; }
326  if(gf == f1) {
327  N[1] = it->_normals[k];
328  op1 = v0;
329  }
330  }
331  }
332  double alpha = angle(N[0], N[1]);
333  if(op1) {
334  SVector3 dir(0.5 * (l0->x() + l1->x()) - op1->x(),
335  0.5 * (l0->y() + l1->y()) - op1->y(),
336  0.5 * (l0->z() + l1->z()) - op1->z());
337  dir.normalize();
338  // sign < 0 ---> re-intrant corner
339  double sign = dot(dir, N[0]);
340  if(sign < 0) alpha = -alpha;
341  }
342 
343  _ridges[i].max_angle = std::max(alpha, _ridges[i].max_angle);
344  _ridges[i].min_angle = std::min(alpha, _ridges[i].min_angle);
345  _ridges[i].computeType(_threshold_angle);
346  }
347  // nice "outer" ridge
348  if(_ridges[i].min_angle > 0 && _ridges[i].max_angle > 0) {
349  while(_ridges[i].max_angle / (_ridges[i].N_SUBNORMALS + 1) >
351  _ridges[i].N_SUBNORMALS++;
352  }
353  }
354  if(_ridges[i].min_angle < 0 && _ridges[i].max_angle < 0) {
355  _ridges[i].N_SUBNORMALS = 0;
356  }
357  }
358  }
359 
361  {
362  auto it = _vertices.begin();
363  for(; it != _vertices.end(); ++it) {}
364  }
365 
366  void add_fan(const blyr_mvertex &v)
367  {
368  std::vector<GFace *> _unique;
369  for(size_t i = 0; i < v._gfaces.size(); i++) {
370  if(std::find(_unique.begin(), _unique.end(), v._gfaces[i]) ==
371  _unique.end())
372  _unique.push_back(v._gfaces[i]);
373  }
374 
375  double t = blyr_thickness(v._v->x(), v._v->y(), v._v->z());
376  for(size_t i = 0; i < _unique.size(); i++) {
377  SVector3 n = v.average_normal(_unique[i]);
378  MVertex *new_v = new MVertex(v._v->x() + n.x() * t, v._v->y() + n.y() * t,
379  v._v->z() + n.z() * t, _gr);
380  v._v_per_face.push_back(new_v);
381  v._n_per_vertex.push_back(n);
382  v._f_per_normal.push_back(_unique[i]);
383  _gr->mesh_vertices.push_back(new_v);
384  }
385 
386  for(size_t i = 0; i < _unique.size(); i++) {
387  for(size_t j = i + 1; j < _unique.size(); j++) {
388  int num_subnormals = 0;
389  for(size_t k = 0; k < _ridges.size(); k++) {
390  if((_ridges[k]._f[0] == _unique[i] &&
391  _ridges[k]._f[1] == _unique[j]) ||
392  (_ridges[k]._f[1] == _unique[i] &&
393  _ridges[k]._f[0] == _unique[j])) {
394  num_subnormals = _ridges[k].N_SUBNORMALS;
395  }
396  }
397 
398  SVector3 n0 = v._n_per_vertex[i];
399  SVector3 n1 = v._n_per_vertex[j];
400  std::vector<MVertex *> fan;
401  for(int k = 0; k < num_subnormals; k++) {
402  double u = (double)(k + 1) / (num_subnormals + 1);
403  SVector3 n = n0 * (1. - u) + n1 * u;
404  n.normalize();
405  MVertex *new_v =
406  new MVertex(v._v->x() + n.x() * t, v._v->y() + n.y() * t,
407  v._v->z() + n.z() * t, _gr);
408  fan.push_back(new_v);
409  _gr->mesh_vertices.push_back(new_v);
410  }
411  std::pair<GFace *, GFace *> pa = std::make_pair(_unique[i], _unique[j]);
412  v._v_per_ridge[pa] = fan;
413  }
414  }
415  }
416 
418  {
419  std::vector<SPoint3> aaa;
420  for(size_t i = 0; i < v._v_per_face.size(); i++) {
421  aaa.push_back(SPoint3(v._v_per_face[i]->x(), v._v_per_face[i]->y(),
422  v._v_per_face[i]->z()));
423  }
424  mean_plane plane;
425  computeMeanPlaneSimple(aaa, plane);
426 
427  auto it = v._v_per_ridge.begin();
428 
429  std::vector<MLine *> plane_lines;
430  std::map<MVertex *, MVertex *> plane_vertices;
431 
432  for(; it != v._v_per_ridge.end(); ++it) {
433  GFace *f0 = it->first.first;
434  GFace *f1 = it->first.second;
435  std::vector<MVertex *> &verts = it->second;
436  MVertex *v0 = nullptr;
437  MVertex *v1 = nullptr;
438  for(size_t i = 0; i < v._v_per_face.size(); i++) {
439  if(f0 == v._f_per_normal[i]) v0 = v._v_per_face[i];
440  if(f1 == v._f_per_normal[i]) v1 = v._v_per_face[i];
441  }
442 
443  SPoint3 p0, p1;
444  projectPointToPlane(SPoint3(v0->x(), v0->y(), v0->z()), p0, plane);
445  projectPointToPlane(SPoint3(v1->x(), v1->y(), v1->z()), p1, plane);
446  SPoint2 P0((p0.x() - plane.x) * plane.plan[0][0] +
447  (p0.y() - plane.y) * plane.plan[0][1] +
448  (p0.z() - plane.z) * plane.plan[0][2],
449  (p0.x() - plane.x) * plane.plan[1][0] +
450  (p0.y() - plane.y) * plane.plan[1][1] +
451  (p0.z() - plane.z) * plane.plan[1][2]);
452  SPoint2 P1((p1.x() - plane.x) * plane.plan[0][0] +
453  (p1.y() - plane.y) * plane.plan[0][1] +
454  (p1.z() - plane.z) * plane.plan[0][2],
455  (p1.x() - plane.x) * plane.plan[1][0] +
456  (p1.y() - plane.y) * plane.plan[1][1] +
457  (p1.z() - plane.z) * plane.plan[1][2]);
458 
459  MVertex *v_plane_0 = nullptr;
460  auto itp = plane_vertices.find(v0);
461  if(itp != plane_vertices.end())
462  v_plane_0 = itp->second;
463  else {
464  v_plane_0 = new MVertex(P0.x(), P0.y(), 0, _gr);
465  plane_vertices[v0] = v_plane_0;
466  }
467  MVertex *v_plane_1 = nullptr;
468  itp = plane_vertices.find(v1);
469  if(itp != plane_vertices.end())
470  v_plane_1 = itp->second;
471  else {
472  v_plane_1 = new MVertex(P1.x(), P1.y(), 0, _gr);
473  plane_vertices[v1] = v_plane_1;
474  }
475 
476  for(size_t i = 0; i < verts.size(); i++) {
477  MVertex *vv = verts[i];
478  SPoint3 pp;
479  projectPointToPlane(SPoint3(vv->x(), vv->y(), vv->z()), pp, plane);
480  SPoint2 PP((pp.x() - plane.x) * plane.plan[0][0] +
481  (pp.y() - plane.y) * plane.plan[0][1] +
482  (pp.z() - plane.z) * plane.plan[0][2],
483  (pp.x() - plane.x) * plane.plan[1][0] +
484  (pp.y() - plane.y) * plane.plan[1][1] +
485  (pp.z() - plane.z) * plane.plan[1][2]);
486  MVertex *v_plane = new MVertex(PP.x(), PP.y(), 0, _gr);
487  plane_vertices[vv] = v_plane;
488  if(i == 0)
489  plane_lines.push_back(new MLine(v_plane_0, v_plane));
490  else if(i == verts.size() - 1) {
491  plane_lines.push_back(new MLine(
492  plane_lines[plane_lines.size() - 1]->getVertex(1), v_plane));
493  plane_lines.push_back(new MLine(v_plane, v_plane_1));
494  }
495  else {
496  MVertex *vV = plane_lines[plane_lines.size() - 1]->getVertex(1);
497  plane_lines.push_back(new MLine(vV, v_plane));
498  }
499  }
500  }
501 
502  std::vector<MTriangle *> mesh;
503  std::vector<MVertex *> new_vertices;
504  meshPolygon(_gr, plane_lines, mesh, new_vertices);
505 
506  for(size_t i = 0; i < new_vertices.size(); i++) {
507  MVertex *vv = new_vertices[i];
508  SPoint3 pp(
509  plane.x + plane.plan[0][0] * vv->x() + plane.plan[1][0] * vv->y(),
510  plane.y + plane.plan[0][1] * vv->x() + plane.plan[1][1] * vv->y(),
511  plane.z + plane.plan[0][2] * vv->x() + plane.plan[1][2] * vv->y());
512  SVector3 dx(pp.x() - v._v->x(), pp.y() - v._v->y(), pp.z() - v._v->z());
513  dx.normalize();
514  MVertex *newv = new MVertex(
515  v._v->x() + dx.x() * blyr_thickness(v._v->x(), v._v->y(), v._v->z()),
516  v._v->y() + dx.y() * blyr_thickness(v._v->x(), v._v->y(), v._v->z()),
517  v._v->z() + dx.z() * blyr_thickness(v._v->x(), v._v->y(), v._v->z()),
518  _gr);
519  _gr->mesh_vertices.push_back(newv);
520  plane_vertices[newv] = vv;
521  }
522 
523  std::map<int, MVertex *> plane_vertices_inv;
524  for(auto it = plane_vertices.begin(); it != plane_vertices.end(); ++it)
525  plane_vertices_inv[it->second->getNum()] = it->first;
526  // printf("%d vertices there\n",plane_vertices_inv.size());
527  // printf("%d triangles\n",mesh.size());
528  for(size_t i = 0; i < mesh.size(); i++) {
529  MVertex *v0 = plane_vertices_inv[mesh[i]->getVertex(0)->getNum()];
530  MVertex *v1 = plane_vertices_inv[mesh[i]->getVertex(1)->getNum()];
531  MVertex *v2 = plane_vertices_inv[mesh[i]->getVertex(2)->getNum()];
532  //
533  v._triangles_at_corner.push_back(new MTriangle(v0, v1, v2));
534  delete mesh[i];
535  }
536 
537  for(size_t i = 0; i < new_vertices.size(); i++) delete new_vertices[i];
538 
539  // printf("%d new vertices\n",new_vertices.size());
540  }
541 
543  {
544  SVector3 n = v.average_normal();
545  double t = blyr_thickness(v._v->x(), v._v->y(), v._v->z());
546  MVertex *new_v = new MVertex(v._v->x() + n.x() * t, v._v->y() + n.y() * t,
547  v._v->z() + n.z() * t, _gr);
548  v._v_per_face.push_back(new_v);
549  v._n_per_vertex.push_back(n);
550  v._f_per_normal.push_back(v._gfaces[0]);
551  _gr->mesh_vertices.push_back(new_v);
552  }
553 
555  const blyr_mvertex &v, blyr_ridge *ridge,
556  std::vector<blyr_mvertex> &new_vertices)
557  {
558  MVertex *vs[2];
559 
560  double t = blyr_thickness(v._v->x(), v._v->y(), v._v->z());
561  SVector3 n = v.average_normal();
562  SPoint3 newp(v._v->x() + t * sqrt(2.0) * n.x(),
563  v._v->y() + t * sqrt(2.0) * n.y(),
564  v._v->z() + t * sqrt(2.0) * n.z());
565  MVertex *vmid = new MVertex(newp.x(), newp.y(), newp.z(), _gr);
566  _gr->mesh_vertices.push_back(vmid);
567 
568  for(int i = 0; i < 2; i++) {
569  GFace *f = ridge->_f[i];
570  GFace *f_other = ridge->_f[(i + 1) % 2];
571  n = v.average_normal(f_other);
572  newp = SPoint3(v._v->x() + t * n.x(), v._v->y() + t * n.y(),
573  v._v->z() + t * n.z());
574  double initialGuess[2] = {0, 0};
575  GPoint p = f->closestPoint(newp, initialGuess);
576  vs[i] = new MFaceVertex(p.x(), p.y(), p.z(), f, p.u(), p.v());
577  f->mesh_vertices.push_back(vs[i]);
578  ridge->N_SUBNORMALS = 1;
579  v._v_per_face.push_back(vs[i]);
580  v._n_per_vertex.push_back(n);
581  v._f_per_normal.push_back(f);
582  for(size_t j = 0; j < v._triangles.size(); j++) {
583  if(v._gfaces[j] == f) {
584  for(int k = 0; k < 3; k++)
585  if(v._triangles[j]->getVertex(k) == v._v)
586  v._triangles[j]->setVertex(k, vs[i]);
587  }
588  }
589  blyr_mvertex bv(vs[i]);
590  bv._v_per_face.push_back(vmid);
591  bv._f_per_normal.push_back(f);
592  bv._n_per_vertex.push_back(v.average_normal(f));
593  new_vertices.push_back(bv);
594  }
595  std::pair<GFace *, GFace *> pa = std::make_pair(ridge->_f[0], ridge->_f[1]);
596  std::vector<MVertex *> fan;
597  fan.push_back(vmid);
598 
599  v._v_per_ridge[pa] = fan;
600  v._triangles.clear();
601  v._normals.clear();
602  v._gfaces.clear();
603  }
604 
606  {
607  for(size_t i = 0; i < _ridges.size(); i++) {
608  blyr_ridge &r = _ridges[i];
609  GFace *f0 = r._f[0];
610  GFace *f1 = r._f[1];
611  if(r.getType() == blyr_ridge::INTERNAL) {
612  for(size_t j = 0; j < r._ge->lines.size(); j++) {
613  MLine *l = r._ge->lines[j];
614  MVertex *v0 = l->getVertex(0);
615  MVertex *v1 = l->getVertex(1);
616  auto it0 = _vertices.find(v0);
617  auto it1 = _vertices.find(v1);
618 
619  MVertex *o00 = it0->extruded_vertex(f0);
620  MVertex *o01 = it0->extruded_vertex(f1);
621  MVertex *o10 = it1->extruded_vertex(f0);
622  MVertex *o11 = it1->extruded_vertex(f1);
623  if(o10 && o00)
624  f0->quadrangles.push_back(new MQuadrangle(v0, v1, o10, o00));
625  if(o01 && o11)
626  f1->quadrangles.push_back(new MQuadrangle(v0, v1, o11, o01));
627  }
628  }
629  }
630  }
631 
633  {
634  std::vector<blyr_mvertex> new_vertices;
635  auto it = _vertices.begin();
636  for(; it != _vertices.end(); ++it) {
637  // printf ("%d has %d lines %d tris\n",it->_v->getNum(),
638  // it->_lines.size(), it->_triangles.size());
639  if(it->_lines.size() == 2) {
640  GEdge *ge0 = it->_gedges[0];
641  GEdge *ge1 = it->_gedges[1];
642  blyr_ridge *ridge0 = getRidge(ge0);
643  blyr_ridge *ridge1 = getRidge(ge1);
644  if(ridge0 == nullptr && ridge1 == nullptr) // not a ridge
645  continue;
646  else {
647  if(ridge0->getType() == blyr_ridge::INTERNAL) {
648  if(ridge0 == ridge1) {
650  new_vertices);
651  }
652  else {
653  Msg::Warning(
654  "there is a seam... and we should extrude on that seam");
655  }
656  }
657  }
658  }
659  }
660  // printf("-------------- %d new vertices \n",new_vertices.size());
661  _vertices.insert(new_vertices.begin(), new_vertices.end());
662  }
663 
665  {
666  std::vector<blyr_mvertex> vplus;
667  auto it = _vertices.begin();
668  for(; it != _vertices.end(); ++it) {
669  if(it->_lines.size() > 2) {
670  std::vector<blyr_ridge *> _internals;
671  std::vector<blyr_ridge *> _externals;
672  std::vector<MVertex *> _externals_v;
673  std::vector<MVertex *> _internals_v;
674  for(size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
675  GEdge *ge = it->_gedges[iGe];
676  MLine *ml = it->_lines[iGe];
677  MVertex *o =
678  ml->getVertex(0) == it->_v ? ml->getVertex(1) : ml->getVertex(0);
679  blyr_ridge *ridge = getRidge(ge);
680  if(ridge->getType() == blyr_ridge::EXTERNAL) {
681  _externals.push_back(ridge);
682  _externals_v.push_back(o);
683  }
684  else if(ridge->getType() == blyr_ridge::INTERNAL) {
685  _internals.push_back(ridge);
686  _internals_v.push_back(o);
687  }
688  }
689  size_t nINTERNAL = _internals.size();
690  size_t nEXTERNAL = _externals.size();
691 
692  // printf("%d %d\n",nINTERNAL,nEXTERNAL);
693 
694  if(nINTERNAL == (it->_gedges.size() - 1) && nEXTERNAL == 1) {
695  // add one normal on the face that is incident to the external ridge
696  // we could add a FAN (commented below) on the face, quite
697  // complicated indeed ... if users really want it, we may code that
698  // feature. Yet, I beleive that fans
699  // should only be "embedded" to close a O mesh.
700 
701  double initialGuess[2] = {0, 0};
702  blyr_ridge *ridge = _externals[0];
703  printf("average normals --> %d %d\n", ridge->_f[0]->tag(),
704  ridge->_f[1]->tag());
705  SVector3 n1 = it->average_normal(ridge->_f[0]);
706  SVector3 n2 = it->average_normal(ridge->_f[1]);
707  double thk = blyr_thickness(it->_v->x(), it->_v->y(), it->_v->z());
708  SVector3 n = (n1 + n2) * thk;
709  printf("%g %g %g -- %g %g %g\n", n1.x(), n1.y(), n1.z(), n2.x(),
710  n2.y(), n2.z());
711  SPoint3 p(it->_v->x() + n.x(), it->_v->y() + n.y(),
712  it->_v->z() + n.z());
713  GFace *gf = nullptr;
714  for(size_t k = 0; k < it->_gfaces.size(); k++) {
715  std::vector<GEdge *> e = it->_gfaces[k]->edges();
716  if(std::find(e.begin(), e.end(), ridge->_ge) == e.end()) {
717  gf = it->_gfaces[k];
718  break;
719  }
720  }
721  if(!gf)
722  Msg::Error("Topological error in 3D boundary layer generation");
723  GPoint gp = gf->closestPoint(p, initialGuess);
724  printf("adding a point %g %g %g in face %d\n", n.x(), n.y(), n.z(),
725  gf->tag());
726  MVertex *vf =
727  new MFaceVertex(gp.x(), gp.y(), gp.z(), gf, gp.u(), gp.v());
728  gf->mesh_vertices.push_back(vf);
729  blyr_mvertex blv(vf);
730  for(size_t j = 0; j < it->_triangles.size(); j++) {
731  MTriangle *t = it->_triangles[j];
732  blv._gfaces.push_back(gf);
733  blv._triangles.push_back(t);
734  blv._normals.push_back(it->_normals[j]);
735  if(it->_gfaces[j] == gf) {
736  for(int k = 0; k < 3; k++) {
737  if(t->getVertex(k) == it->_v) { t->setVertex(k, vf); }
738  }
739  }
740  }
741  auto ite = _vertices.find(blyr_mvertex(_externals_v[0]));
742  if(ite != _vertices.end()) {
743  blv._v_per_face.push_back(ite->_v_per_face[0]);
744  blv._n_per_vertex.push_back(n);
745  blv._f_per_normal.push_back(_externals[0]->_f[0]);
746  // add the corner info
747  std::vector<MVertex *> fan;
748  fan.push_back(ite->_v_per_face[0]);
749 
750  it->_v_per_face.push_back(vf);
751  it->_n_per_vertex.push_back(n);
752  it->_f_per_normal.push_back(gf);
753  it->_v_per_face.push_back(ite->_v);
754  it->_n_per_vertex.push_back(n);
755  it->_f_per_normal.push_back(_externals[0]->_f[0]);
756  it->_v_per_face.push_back(ite->_v);
757  it->_n_per_vertex.push_back(n);
758  it->_f_per_normal.push_back(_externals[0]->_f[1]);
759 
760  for(size_t k = 0; k < _internals.size(); k++) {
761  std::pair<GFace *, GFace *> pa =
762  std::make_pair(_internals[k]->_f[0], _internals[k]->_f[1]);
763  it->_v_per_ridge[pa] = fan;
764  auto iti = _vertices.find(blyr_mvertex(_internals_v[k]));
765  MVertex *o = iti->_v_per_face[0];
766  gf->quadrangles.push_back(
767  new MQuadrangle(it->_v, iti->_v, o, vf));
768  if(_externals[0]->_f[0] == _internals[k]->_f[0] ||
769  _externals[0]->_f[0] == _internals[k]->_f[1]) {
770  MVertex *l = iti->extruded_vertex(_externals[0]->_f[0]);
771  _externals[0]->_f[0]->quadrangles.push_back(
772  new MQuadrangle(it->_v, ite->_v, l, iti->_v));
773  }
774  else if(_externals[0]->_f[1] == _internals[k]->_f[0] ||
775  _externals[0]->_f[1] == _internals[k]->_f[1]) {
776  MVertex *l = iti->extruded_vertex(_externals[0]->_f[1]);
777  _externals[0]->_f[1]->quadrangles.push_back(
778  new MQuadrangle(it->_v, ite->_v, l, iti->_v));
779  }
780  }
781  }
782 
783  vplus.push_back(blv);
784  }
785  }
786  }
787  for(size_t i = 0; i < vplus.size(); i++)
788  if(vplus[i]._v) _vertices.insert(vplus[i]);
789  }
790 
792  {
793  auto it = _vertices.begin();
794  for(; it != _vertices.end(); ++it) {
795  if(!it->_triangles.empty()) add_one_normal(*it);
796  }
797  }
798 
800  {
801  auto it = _vertices.begin();
802  for(; it != _vertices.end(); ++it) {
803  if(it->_lines.empty()) {
804  // simple vertex that is extruded along the average of face normals
805  // printf("simple %d\n",it->_v->getNum());
806  if(!it->_triangles.empty()) add_one_normal(*it);
807  // printf("simple done\n");
808  }
809  else if(it->_lines.size() == 2) {
810  // simple ridge, look if more than one normal is necessary
811  // internal vertex to a model edge
812  GEdge *ge0 = it->_gedges[0];
813  GEdge *ge1 = it->_gedges[1];
814  // normal case
815  blyr_ridge *ridge0 = getRidge(ge0);
816  blyr_ridge *ridge1 = getRidge(ge1);
817  // printf("%d %d %g %g %d
818  //%d\n",ge0->tag(),ge1->tag(),ridge0->min_angle,ridge0->max_angle,ridge0->getType(),blyr_ridge::FLAT);
819  if(ridge0 == nullptr && ridge1 == nullptr) { // not a ridge
820  if(!it->_triangles.empty()) add_one_normal(*it);
821  }
822  else {
823  if(ridge0->getType() == blyr_ridge::FLAT) {
824  if(!it->_triangles.empty()) add_one_normal(*it);
825  }
826  else if(ridge0->getType() == blyr_ridge::EXTERNAL) {
827  // printf("verex %d has 2 lines (%d
828  //%d)\n",it->_v->getNum(),ge0->tag(), ge1->tag());
829  if(!it->_triangles.empty()) add_one_normal(*it);
830  // add_fan (*it);
831  }
832  }
833  }
834  // standard corner
835  else {
836  std::vector<blyr_ridge *> _internals;
837  std::vector<blyr_ridge *> _externals;
838  std::vector<blyr_ridge *> _flats;
839  for(size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
840  GEdge *ge = it->_gedges[iGe];
841  blyr_ridge *ridge = getRidge(ge);
842  if(ridge->getType() == blyr_ridge::EXTERNAL)
843  _externals.push_back(ridge);
844  else if(ridge->getType() == blyr_ridge::INTERNAL)
845  _internals.push_back(ridge);
846  else if(ridge->getType() == blyr_ridge::FLAT)
847  _flats.push_back(ridge);
848  }
849  size_t nINTERNAL = _internals.size();
850  size_t nEXTERNAL = _externals.size();
851 
852  if(nEXTERNAL == it->_gedges.size()) {
853  if(!it->_triangles.empty()) add_one_normal(*it);
854  // CAN BE DONE TOO BUT NOT SURE THIS "FAN" COMPLEXITY IS USEFUL
855  // add_fan (*it);
856  // add_external_corner(*it);
857  }
858  // internal corner
859  else if(nINTERNAL == it->_gedges.size()) {
860  // ALREADY DONE (see function below)
861  }
862  else if(nINTERNAL == 0 && nEXTERNAL == 0) {
863  // ALL IS FLAT ...
864  if(!it->_triangles.empty()) add_one_normal(*it);
865  }
866  else if(nINTERNAL == (it->_gedges.size() - 1) && nEXTERNAL == 1) {
867  // ALREADY DONE (see function above)
868  }
869  else {
870  Msg::Error("Corner with %d internal ridges and %d external ridges "
871  "should be coded",
872  nINTERNAL, nEXTERNAL);
873  printf("EXTERNALS :");
874  for(size_t i = 0; i < _externals.size(); i++)
875  printf("%d ", _externals[i]->_ge->tag());
876  printf("\n");
877  printf("INTERNALS :");
878  for(size_t i = 0; i < _internals.size(); i++)
879  printf("%d ", _internals[i]->_ge->tag());
880  printf("\n");
881  }
882  }
883  }
884  // printf("done\n");
885  }
886 
887  //---------------+---------------+---------------+---------------+---------------+
888  // I N T E R N A L C O R N E R S
889  //---------------+---------------+---------------+---------------+---------------+
890  // -------- extrude vertices on model edges
891  // --------------------------------
892  // MOST COMPLICATED PART OF THAT CODE
893  // ------------------------------------------------------------------------------+
894 
896  {
897  std::vector<blyr_mvertex> additional_vertices;
898  auto it = _vertices.begin();
899  for(; it != _vertices.end(); ++it) {
900  MVertex *v = it->_v;
901 
902  // create a new vertex for every internal ridges
903  std::map<GEdge *, MVertex *> e2v;
904 
905  std::vector<blyr_ridge *> _internals;
906  std::vector<blyr_ridge *> _externals;
907  std::vector<blyr_ridge *> _flats;
908  for(size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
909  GEdge *ge = it->_gedges[iGe];
910  blyr_ridge *ridge = getRidge(ge);
911  if(ridge->getType() == blyr_ridge::EXTERNAL)
912  _externals.push_back(ridge);
913  else if(ridge->getType() == blyr_ridge::INTERNAL)
914  _internals.push_back(ridge);
915  else if(ridge->getType() == blyr_ridge::FLAT)
916  _flats.push_back(ridge);
917  }
918 
919  if(_internals.empty()) continue;
920  if(it->_lines.size() <= 2) continue;
921 
922  SVector3 NR(0, 0, 0);
923  double thk = blyr_thickness(v->x(), v->y(), v->z());
924  std::vector<blyr_mvertex> vplus;
925  std::vector<blyr_mvertex> vplusf;
926  for(size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
927  GEdge *ge = it->_gedges[iGe];
928  Range<double> bounds = ge->parBounds(0);
929  blyr_ridge *ridge = getRidge(ge);
930  bool create_vertices_on_edge =
931  _externals.empty() || ridge->getType() == blyr_ridge::EXTERNAL;
932  if(create_vertices_on_edge) {
933  double t = 0.0;
934  if(ge->getBeginVertex() &&
935  v == ge->getBeginVertex()->mesh_vertices[0]) {
936  SVector3 tgt = ge->firstDer(bounds.low());
937  t = bounds.low() + thk / tgt.norm();
938  }
939  else if(ge->getEndVertex() &&
940  v == ge->getEndVertex()->mesh_vertices[0]) {
941  SVector3 tgt = ge->firstDer(bounds.high());
942  t = bounds.high() - thk / tgt.norm();
943  }
944  else
945  Msg::Error("Topological error in boundary layer");
946  GPoint gp = ge->point(t);
947  MEdgeVertex *mev = new MEdgeVertex(gp.x(), gp.y(), gp.z(), ge, t);
948  ge->mesh_vertices.push_back(mev);
949  e2v[ge] = mev;
950  vplus.push_back(blyr_mvertex(mev));
951  NR +=
952  SVector3(mev->x() - v->x(), mev->y() - v->y(), mev->z() - v->z());
953  }
954  else {
955  vplus.push_back(blyr_mvertex(nullptr));
956  }
957  }
958 
959  // CREATE A VOLUME VERTEX IN CASE OF A FULL INTERNAL CORNER
960  MVertex *vr = nullptr;
961  if(_externals.empty()) {
962  vr =
963  new MVertex(v->x() + NR.x(), v->y() + NR.y(), v->z() + NR.z(), _gr);
964  _gr->mesh_vertices.push_back(vr);
965  }
966 
967  // ADD POINTS ON BOTH NEIGHBORING FACES IF RIDGE IS INTERNAL
968  for(size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
969  if(vplus[iGe]._v != nullptr) {
970  GEdge *gei = it->_gedges[iGe];
971  blyr_ridge *ridgei = getRidge(gei);
972 
973  for(size_t jGe = 0; jGe < it->_gedges.size(); jGe++) {
974  if(jGe != iGe) {
975  GEdge *gej = it->_gedges[jGe];
976  blyr_ridge *ridgej = getRidge(gej);
977  GFace *gf = haveTowGEdges(_faces, gei, gej);
978  if(gf) {
979  MVertex *vf = nullptr;
980  // printf("s %d %d %d -- %d %d -- %d -- %p
981  //%p\n",v->getNum(),iGe,jGe,gei->tag(),gej->tag(),gf->tag(),vplus[iGe]._v,vplus[jGe]._v);
982 
983  SVector3 dx1(vplus[iGe]._v->x() - v->x(),
984  vplus[iGe]._v->y() - v->y(),
985  vplus[iGe]._v->z() - v->z());
986  if((vplus[jGe]._v != nullptr) && (jGe > iGe)) {
987  SVector3 dx2(vplus[jGe]._v->x() - v->x(),
988  vplus[jGe]._v->y() - v->y(),
989  vplus[jGe]._v->z() - v->z());
990  SPoint3 PNEW(v->x() + dx1.x() + dx2.x(),
991  v->y() + dx1.y() + dx2.y(),
992  v->z() + dx1.z() + dx2.z());
993 
994  // NEW POINT IS IN THE VOLUME
995  if(ridgei->getType() == blyr_ridge::EXTERNAL &&
996  ridgej->getType() == blyr_ridge::EXTERNAL &&
997  !_internals.empty()) {
998  printf("ON VOLUME %d\n", gf->tag());
999  vf = new MVertex(PNEW.x(), PNEW.y(), PNEW.z(), _gr);
1000  _gr->mesh_vertices.push_back(vf);
1001 
1002  it->_n_per_vertex.push_back(dx1);
1003  it->_n_per_vertex.push_back(dx2);
1004  it->_v_per_face.push_back(vplus[iGe]._v);
1005  it->_v_per_face.push_back(vplus[jGe]._v);
1006  std::vector<GEdge *> e0 = _internals[0]->_f[0]->edges();
1007  if(std::find(e0.begin(), e0.end(), gei) != e0.end()) {
1008  it->_f_per_normal.push_back(_internals[0]->_f[0]);
1009  it->_f_per_normal.push_back(_internals[0]->_f[1]);
1010  }
1011  else {
1012  it->_f_per_normal.push_back(_internals[0]->_f[1]);
1013  it->_f_per_normal.push_back(_internals[0]->_f[0]);
1014  }
1015  std::vector<MVertex *> fan;
1016  fan.push_back(vf);
1017  std::pair<GFace *, GFace *> pa = std::make_pair(
1018  _internals[0]->_f[0], _internals[0]->_f[1]);
1019  it->_v_per_ridge[pa] = fan;
1020 
1021  vplus[iGe]._v_per_face.push_back(vf);
1022  vplus[jGe]._v_per_face.push_back(vf);
1023  vplus[iGe]._n_per_vertex.push_back(dx1);
1024  vplus[jGe]._n_per_vertex.push_back(dx2);
1025  vplus[iGe]._f_per_normal.push_back(_internals[0]->_f[0]);
1026  vplus[jGe]._f_per_normal.push_back(_internals[0]->_f[1]);
1027  }
1028  else {
1029  double initialGuess[2];
1030  GPoint p = gf->closestPoint(PNEW, initialGuess);
1031  vf = new MFaceVertex(p.x(), p.y(), p.z(), gf, p.u(), p.v());
1032 
1033  if(_externals.empty()) {
1034  blyr_mvertex blv(vf);
1035  blv._v_per_face.push_back(vr);
1036  blv._f_per_normal.push_back(gf);
1037  blv._n_per_vertex.push_back(dx1); // wrong but who cares
1038  vplusf.push_back(blv);
1039  }
1040 
1041  gf->mesh_vertices.push_back(vf);
1042  gf->quadrangles.push_back(
1043  new MQuadrangle(v, vplus[iGe]._v, vf, vplus[jGe]._v));
1044 
1045  dx1.normalize();
1046  dx2.normalize();
1047  vplus[iGe]._v_per_face.push_back(vf);
1048  vplus[jGe]._v_per_face.push_back(vf);
1049  vplus[iGe]._n_per_vertex.push_back(dx1);
1050  vplus[jGe]._n_per_vertex.push_back(dx2);
1051  vplus[iGe]._f_per_normal.push_back(gf);
1052  vplus[jGe]._f_per_normal.push_back(gf);
1053  }
1054  }
1055  else if(vplus[jGe]._v == nullptr) {
1056  // printf("-------------------------------------->%d
1057  //%d %d -- %d %d -- %d -- %p
1058  //%p\n",v->getNum(),iGe,jGe,gei->tag(),gej->tag(),gf->tag(),vplus[iGe]._v,vplus[jGe]._v);
1059  // printf("-------------------------------------- >
1060  //%d -- %d %d -- %d %d\n",gf->tag(), gei->tag(),
1061  // gej->tag(),iGe,jGe);
1062  vf = vplus[iGe]._v;
1063  }
1064  if(!vf || vf->onWhat() != _gr) {
1065  if(!vf) printf("a bon\n");
1066  std::vector<MTriangle *> remaining_t;
1067  std::vector<GFace *> remaining_f;
1068  std::vector<SVector3> remaining_n;
1069  for(size_t j = 0; j < it->_triangles.size(); j++) {
1070  MTriangle *t = it->_triangles[j];
1071  if(it->_gfaces[j] == gf) {
1072  for(int k = 0; k < 3; k++) {
1073  if(vf && t->getVertex(k) == v) t->setVertex(k, vf);
1074  }
1075  vplus[iGe]._triangles.push_back(t);
1076  vplus[iGe]._gfaces.push_back(it->_gfaces[j]);
1077  vplus[iGe]._normals.push_back(it->_normals[j]);
1078  }
1079  else {
1080  remaining_t.push_back(t);
1081  remaining_f.push_back(it->_gfaces[j]);
1082  remaining_n.push_back(it->_normals[j]);
1083  }
1084  }
1085  }
1086  // printf("AFTER2 %d %d %d -- %d %d -- %d -- %p
1087  //%p\n",v->getNum(),iGe,jGe,gei->tag(),gej->tag(),gf->tag(),vplus[iGe]._v,vplus[jGe]._v);
1088  }
1089  }
1090  }
1091  }
1092  if(vr) {
1093  std::vector<MVertex *> fan;
1094  fan.push_back(vr);
1095  for(size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
1096  if(vplus[iGe]._v) {
1097  GEdge *gei = it->_gedges[iGe];
1098  blyr_ridge *ridgei = getRidge(gei);
1099  std::pair<GFace *, GFace *> pa =
1100  std::make_pair(ridgei->_f[0], ridgei->_f[1]);
1101  vplus[iGe]._v_per_ridge[pa] = fan;
1102  }
1103  }
1104  }
1105  }
1106  std::vector<MLine *> update_lines;
1107  std::vector<GEdge *> update_gedges;
1108  // update on mesh edges
1109  for(size_t iGe = 0; iGe < it->_gedges.size(); iGe++) {
1110  GEdge *ge = it->_gedges[iGe];
1111  MLine *ml = it->_lines[iGe];
1112  auto itev = e2v.find(ge);
1113  if(itev != e2v.end()) {
1114  MVertex *mev = itev->second;
1115  if(ml->getVertex(0) == v)
1116  ml->setVertex(0, mev);
1117  else
1118  ml->setVertex(1, mev);
1119  MLine *newl = new MLine(v, mev);
1120  update_lines.push_back(newl);
1121  update_gedges.push_back(ge);
1122  if(vplus[iGe]._v) {
1123  vplus[iGe]._lines.push_back(ml);
1124  vplus[iGe]._gedges.push_back(ge);
1125  vplus[iGe]._lines.push_back(newl);
1126  vplus[iGe]._gedges.push_back(ge);
1127  }
1128  ge->lines.push_back(newl);
1129  }
1130  else {
1131  update_lines.push_back(ml);
1132  update_gedges.push_back(ge);
1133  }
1134  }
1135 
1136  // it->_triangles.clear();
1137  // it->_gfaces.clear();
1138  // it->_normals.clear();
1139 
1140  it->_lines = update_lines;
1141  it->_gedges = update_gedges;
1142  for(size_t i = 0; i < vplus.size(); i++)
1143  if(vplus[i]._v) additional_vertices.push_back(vplus[i]);
1144  if(vplusf.size())
1145  additional_vertices.insert(additional_vertices.end(), vplusf.begin(),
1146  vplusf.end());
1147  }
1148  // printf("%d additional vertices\n",additional_vertices.size());
1149 
1150  _vertices.insert(additional_vertices.begin(), additional_vertices.end());
1151  // printf("lous\n");
1152  }
1153  //---------------+---------------+---------------+---------------+---------------+
1154 
1156  {
1157  for(size_t i = 0; i < _faces.size(); i++) {
1158  for(size_t j = 0; j < _faces[i]->triangles.size(); j++) {
1159  MVertex *v0 = _faces[i]->triangles[j]->getVertex(0);
1160  MVertex *v1 = _faces[i]->triangles[j]->getVertex(1);
1161  MVertex *v2 = _faces[i]->triangles[j]->getVertex(2);
1162  auto it0 = _vertices.find(v0);
1163  auto it1 = _vertices.find(v1);
1164  auto it2 = _vertices.find(v2);
1165  MVertex *o0 = it0->extruded_vertex(_faces[i]);
1166  MVertex *o1 = it1->extruded_vertex(_faces[i]);
1167  MVertex *o2 = it2->extruded_vertex(_faces[i]);
1168  // printf("%p %p %p\n",o0,o1,o2);
1169  if(o0 && o1 && o2)
1170  _gr->prisms.push_back(new MPrism(v0, v1, v2, o0, o1, o2));
1171  }
1172  }
1173  // printf("a\n");
1174  }
1175 
1177  {
1178  for(size_t i = 0; i < _ridges.size(); i++) {
1179  blyr_ridge &r = _ridges[i];
1180  GFace *f0 = r._f[0];
1181  GFace *f1 = r._f[1];
1182  std::pair<GFace *, GFace *> pa_pos = std::make_pair(f0, f1);
1183  std::pair<GFace *, GFace *> pa_neg = std::make_pair(f1, f0);
1184 
1185  // printf("ridge %d %d\n",f0->tag(),f1->tag());
1186 
1187  if(r.N_SUBNORMALS) {
1188  for(size_t j = 0; j < r._ge->lines.size(); j++) {
1189  MLine *l = r._ge->lines[j];
1190  MVertex *v0 = l->getVertex(0);
1191  MVertex *v1 = l->getVertex(1);
1192  auto it0 = _vertices.find(v0);
1193  auto it1 = _vertices.find(v1);
1194 
1195  MVertex *o00 = it0->extruded_vertex(f0);
1196  MVertex *o01 = it0->extruded_vertex(f1);
1197  MVertex *o10 = it1->extruded_vertex(f0);
1198  MVertex *o11 = it1->extruded_vertex(f1);
1199 
1200  // printf("%d %d %p %p %p
1201  //%p\n",v0->getNum(),v1->getNum(),o00,o01,o10,o11);
1202 
1203  std::vector<MVertex *> fan0;
1204  std::vector<MVertex *> fan1;
1205 
1206  auto it = it0->_v_per_ridge.find(pa_pos);
1207  if(it != it0->_v_per_ridge.end())
1208  fan0 = it->second;
1209  else {
1210  it = it0->_v_per_ridge.find(pa_neg);
1211  if(it != it0->_v_per_ridge.end()) {
1212  fan0 = it->second;
1213  std::reverse(fan0.begin(), fan0.end());
1214  }
1215  }
1216  it = it1->_v_per_ridge.find(pa_pos);
1217  if(it != it1->_v_per_ridge.end())
1218  fan1 = it->second;
1219  else {
1220  it = it1->_v_per_ridge.find(pa_neg);
1221  if(it != it1->_v_per_ridge.end()) {
1222  fan1 = it->second;
1223  std::reverse(fan1.begin(), fan1.end());
1224  }
1225  }
1226 
1227  // printf("%d %d %d\n",fan0.size(),fan1.size(),r.N_SUBNORMALS);
1228  if(fan0.size() == r.N_SUBNORMALS && fan1.size() == r.N_SUBNORMALS) {
1229  for(std::size_t k = 0; k <= r.N_SUBNORMALS; k++) {
1230  MVertex *v00 = (k == 0 ? o00 : fan0[k - 1]);
1231  MVertex *v10 = (k == 0 ? o10 : fan1[k - 1]);
1232  MVertex *v01 = (k == r.N_SUBNORMALS ? o01 : fan0[k]);
1233  MVertex *v11 = (k == r.N_SUBNORMALS ? o11 : fan1[k]);
1234  // printf("%p %p %p %p\n",v00,v01,v10,v11);
1235  _gr->prisms.push_back(new MPrism(v0, v00, v01, v1, v10, v11));
1236  }
1237  }
1238  }
1239  }
1240  }
1241  // printf("gasp\n");
1242  }
1243 
1245  {
1246  auto it = _vertices.begin();
1247  for(; it != _vertices.end(); ++it) {
1248  const blyr_mvertex &v = *it;
1249  for(size_t j = 0; j < v._triangles_at_corner.size(); j++) {
1250  MTriangle *t = v._triangles_at_corner[j];
1252  // printf("%p %p %p\n",
1253  // t->getVertex(0),t->getVertex(1),t->getVertex(2));
1254  _gr->prisms.push_back(new MPrism(v._v, v._v, v._v, t->getVertex(0),
1255  t->getVertex(1), t->getVertex(2)));
1256  }
1257  }
1258  }
1259 
1260  double blyr_thickness(double x, double y, double z) { return _thickness; }
1261 };
1262 
1263 bool createBoundaryLayerOneLayer(GRegion *gr, std::vector<GFace *> &bls)
1264 {
1265  Msg::Info("Computing boundary layer mesh of volume %d", gr->tag());
1266 
1267  bool basic = false;
1268 
1269  blyr_manager mgr(gr, bls, 0.015);
1270 
1271  // for (size_t i=0;i<gr->tetrahedra.size();i++)delete gr->tetrahedra[i];
1272  gr->tetrahedra.clear();
1273  // for (size_t i=0;i<gr->mesh_vertices.size();i++)delete
1274  // gr->mesh_vertices[i];
1275  gr->mesh_vertices.clear();
1276 
1277  if(basic) { mgr.extrude_vertices_basic(); }
1278  else {
1279  Msg::Info("Classifying ridges (INTERNAL / EXTERNAL / FLAT)");
1280  mgr.classify_ridges();
1281  Msg::Info("Extrusion of vertices for internal corners");
1283  Msg::Info("Extrusion of vertices for internal edges");
1285  Msg::Info("Extruding ridges on faces");
1287  Msg::Info("Treating REGULAR vertices");
1288  mgr.extrude_vertices();
1289  Msg::Info("Treating corners with one external ridge and others internal");
1290  mgr.extrude_one_external();
1291 
1292  Msg::Info("Generating ONLE LAYER of 3D elements");
1294  mgr.extrude_ridges();
1295  }
1296  mgr.extrude_triangles();
1297 
1298  return true;
1299 }
MTriangle.h
blyr_manager::_threshold_angle
double _threshold_angle
Definition: meshGRegionBoundaryLayer.cpp:174
blyr_mvertex::_triangles_at_corner
std::vector< MTriangle * > _triangles_at_corner
Definition: meshGRegionBoundaryLayer.cpp:121
blyr_mvertex::_normals
std::vector< SVector3 > _normals
Definition: meshGRegionBoundaryLayer.cpp:103
MTriangle::getFace
virtual MFace getFace(int num) const
Definition: MTriangle.h:91
GFace::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GFace.h:121
blyr_mvertex
Definition: meshGRegionBoundaryLayer.cpp:97
blyr_manager
Definition: meshGRegionBoundaryLayer.cpp:167
dot
double dot(const SVector3 &a, const SMetric3 &m, const SVector3 &b)
Definition: STensor3.h:71
blyr_manager::extrude_vertices
void extrude_vertices()
Definition: meshGRegionBoundaryLayer.cpp:799
blyr_mvertex::blyr_mvertex
blyr_mvertex(MVertex *v)
Definition: meshGRegionBoundaryLayer.cpp:127
blyr_ridge::operator<
bool operator<(const blyr_ridge &other)
Definition: meshGRegionBoundaryLayer.cpp:91
GPoint::y
double y() const
Definition: GPoint.h:22
blyr_ridge::min_angle
double min_angle
Definition: meshGRegionBoundaryLayer.cpp:67
GFace.h
mean_plane::x
double x
Definition: Numeric.h:36
blyr_manager::classify_ridges
void classify_ridges()
Definition: meshGRegionBoundaryLayer.cpp:290
MLine::getVertex
virtual MVertex * getVertex(int num)
Definition: MLine.h:45
GFace
Definition: GFace.h:33
blyr_ridge::type
type
Definition: meshGRegionBoundaryLayer.cpp:62
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
GEdge::lines
std::vector< MLine * > lines
Definition: GEdge.h:42
blyr_ridge::getType
type getType() const
Definition: meshGRegionBoundaryLayer.cpp:82
GEntity::model
GModel * model() const
Definition: GEntity.h:277
blyr_ridge::_gr
GRegion * _gr
Definition: meshGRegionBoundaryLayer.cpp:65
angle
double angle(const SVector3 &a, const SVector3 &b)
Definition: SVector3.h:157
SPoint2
Definition: SPoint2.h:12
blyr_ridge
Definition: meshGRegionBoundaryLayer.cpp:60
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
blyr_manager::add_fan
void add_fan(const blyr_mvertex &v)
Definition: meshGRegionBoundaryLayer.cpp:366
MVertex
Definition: MVertex.h:24
blyr_ridge::getEdge
GEdge * getEdge() const
Definition: meshGRegionBoundaryLayer.cpp:90
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
blyr_ridge::computeType
void computeType(double angle)
Definition: meshGRegionBoundaryLayer.cpp:70
blyr_manager::extrude_external_corners
void extrude_external_corners()
Definition: meshGRegionBoundaryLayer.cpp:1244
SPoint3
Definition: SPoint3.h:14
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
MVertex::getNum
std::size_t getNum() const
Definition: MVertex.h:86
blyr_manager::_gr
GRegion * _gr
Definition: meshGRegionBoundaryLayer.cpp:177
Range::high
T high() const
Definition: Range.h:20
SVector3
Definition: SVector3.h:16
blyr_ridge::FLAT
@ FLAT
Definition: meshGRegionBoundaryLayer.cpp:62
blyr_manager::extrude_vertex_on_both_surfaces_of_a_ridge
void extrude_vertex_on_both_surfaces_of_a_ridge(const blyr_mvertex &v, blyr_ridge *ridge, std::vector< blyr_mvertex > &new_vertices)
Definition: meshGRegionBoundaryLayer.cpp:554
projectPointToPlane
void projectPointToPlane(const SPoint3 &pt, SPoint3 &ptProj, const mean_plane &meanPlane)
Definition: Numeric.cpp:1497
MTriangle::getVertex
virtual MVertex * getVertex(int num)
Definition: MTriangle.h:62
MVertex::onWhat
GEntity * onWhat() const
Definition: MVertex.h:82
blyr_manager::blyr_thickness
double blyr_thickness(double x, double y, double z)
Definition: meshGRegionBoundaryLayer.cpp:1260
SVector3.h
MPrism
Definition: MPrism.h:34
blyr_ridge::max_angle
double max_angle
Definition: meshGRegionBoundaryLayer.cpp:67
meshPolygon
static void meshPolygon(GRegion *gr, std::vector< MLine * > &poly, std::vector< MTriangle * > &mesh, std::vector< MVertex * > &new_vertices)
Definition: meshGRegionBoundaryLayer.cpp:42
blyr_mvertex::_triangles
std::vector< MTriangle * > _triangles
Definition: meshGRegionBoundaryLayer.cpp:102
MLine.h
edges
static int edges[6][2]
Definition: meshGRegionLocalMeshMod.cpp:23
blyr_mvertex::_gfaces
std::vector< GFace * > _gfaces
Definition: meshGRegionBoundaryLayer.cpp:104
mean_plane
Definition: Numeric.h:33
blyr_mvertex::_v_per_face
std::vector< MVertex * > _v_per_face
Definition: meshGRegionBoundaryLayer.cpp:112
GPoint
Definition: GPoint.h:13
blyr_manager::blyr_manager
blyr_manager(GRegion *gr, std::vector< GFace * > &bls, double t)
Definition: meshGRegionBoundaryLayer.cpp:189
GFace::closestPoint
virtual GPoint closestPoint(const SPoint3 &queryPoint, const double initialGuess[2]) const
Definition: GFace.cpp:1323
MLine::setVertex
virtual void setVertex(int num, MVertex *v)
Definition: MLine.h:47
GFace::quadrangles
std::vector< MQuadrangle * > quadrangles
Definition: GFace.h:429
MLine
Definition: MLine.h:21
createBoundaryLayerOneLayer
bool createBoundaryLayerOneLayer(GRegion *gr, std::vector< GFace * > &bls)
Definition: meshGRegionBoundaryLayer.cpp:1263
blyr_mvertex::_f_per_normal
std::vector< GFace * > _f_per_normal
Definition: meshGRegionBoundaryLayer.cpp:114
GPoint::z
double z() const
Definition: GPoint.h:23
blyr_mvertex::add_line
void add_line(MLine *l, GEdge *ge) const
Definition: meshGRegionBoundaryLayer.cpp:158
GRegion::faces
virtual std::vector< GFace * > faces() const
Definition: GRegion.h:64
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
blyr_manager::extrude_vertices_on_edges
void extrude_vertices_on_edges()
Definition: meshGRegionBoundaryLayer.cpp:895
blyr_manager::extrude_ridges_on_faces
void extrude_ridges_on_faces()
Definition: meshGRegionBoundaryLayer.cpp:605
MFace
Definition: MFace.h:20
blyr_manager::extrude_vertices_on_faces
void extrude_vertices_on_faces()
Definition: meshGRegionBoundaryLayer.cpp:632
GEdge::firstDer
virtual SVector3 firstDer(double par) const =0
GRegion.h
Range
Definition: Range.h:10
blyr_mvertex::extruded_vertex
MVertex * extruded_vertex(GFace *gf) const
Definition: meshGRegionBoundaryLayer.cpp:129
blyr_ridge::INTERNAL
@ INTERNAL
Definition: meshGRegionBoundaryLayer.cpp:62
GPoint::u
double u() const
Definition: GPoint.h:27
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
xyEdge
Definition: xyEdge.h:11
MEdgeVertex
Definition: MVertex.h:137
blyr_ridge::N_SUBNORMALS
std::size_t N_SUBNORMALS
Definition: meshGRegionBoundaryLayer.cpp:68
MVertex.h
blyr_mvertex::_v_per_ridge
std::map< std::pair< GFace *, GFace * >, std::vector< MVertex * > > _v_per_ridge
Definition: meshGRegionBoundaryLayer.cpp:118
haveTowGEdges
static GFace * haveTowGEdges(std::vector< GFace * > &faces, GEdge *ge1, GEdge *ge2)
Definition: meshGRegionBoundaryLayer.cpp:31
blyr_mvertex::operator<
bool operator<(const blyr_mvertex &other) const
Definition: meshGRegionBoundaryLayer.cpp:123
blyr_manager::getRidge
blyr_ridge * getRidge(GEdge *ge)
Definition: meshGRegionBoundaryLayer.cpp:281
Numeric.h
GEdge::getBeginVertex
virtual GVertex * getBeginVertex() const
Definition: GEdge.h:63
blyr_ridge::_t
type _t
Definition: meshGRegionBoundaryLayer.cpp:63
mean_plane::z
double z
Definition: Numeric.h:36
SVector3::norm
double norm() const
Definition: SVector3.h:33
blyr_mvertex::_gedges
std::vector< GEdge * > _gedges
Definition: meshGRegionBoundaryLayer.cpp:109
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
GRegion::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GRegion.cpp:459
blyr_manager::extrude_vertices_basic
void extrude_vertices_basic()
Definition: meshGRegionBoundaryLayer.cpp:791
blyr_ridge::_f
GFace * _f[2]
Definition: meshGRegionBoundaryLayer.cpp:66
efaces
static int efaces[6][2]
Definition: meshGRegionLocalMeshMod.cpp:24
GEntity::tag
int tag() const
Definition: GEntity.h:280
MFaceVertex
Definition: MVertex.h:168
blyr_mvertex::_n_per_vertex
std::vector< SVector3 > _n_per_vertex
Definition: meshGRegionBoundaryLayer.cpp:113
SVector3::x
double x(void) const
Definition: SVector3.h:30
GRegion
Definition: GRegion.h:28
GRegion::prisms
std::vector< MPrism * > prisms
Definition: GRegion.h:165
MTriangle
Definition: MTriangle.h:26
mean_plane::y
double y
Definition: Numeric.h:36
blyr_manager::_ridges
std::vector< blyr_ridge > _ridges
Definition: meshGRegionBoundaryLayer.cpp:183
SPoint2::x
double x(void) const
Definition: SPoint2.h:86
MTetrahedron.h
mean_plane::plan
double plan[3][3]
Definition: Numeric.h:34
GEdge::parBounds
virtual Range< double > parBounds(int i) const =0
SVector3::y
double y(void) const
Definition: SVector3.h:31
z
const double z
Definition: GaussQuadratureQuad.cpp:56
MQuadrangle.h
GEdge::point
virtual GPoint point(double p) const =0
xyFace
Definition: xyFace.h:14
GEdge
Definition: GEdge.h:26
SVector3::z
double z(void) const
Definition: SVector3.h:32
blyr_ridge::blyr_ridge
blyr_ridge(GEdge *ge, GRegion *gr, GFace *f0, GFace *f1)
Definition: meshGRegionBoundaryLayer.cpp:84
MPrism.h
blyr_ridge::setType
void setType(type t)
Definition: meshGRegionBoundaryLayer.cpp:80
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
GPoint::v
double v() const
Definition: GPoint.h:28
blyr_manager::_vertices
std::set< blyr_mvertex > _vertices
Definition: meshGRegionBoundaryLayer.cpp:186
blyr_manager::extrude_ridges
void extrude_ridges()
Definition: meshGRegionBoundaryLayer.cpp:1176
GModel.h
MVertex::y
double y() const
Definition: MVertex.h:61
blyr_mvertex::average_normal
SVector3 average_normal(GFace *gf=nullptr) const
Definition: meshGRegionBoundaryLayer.cpp:139
GEdge::getEndVertex
virtual GVertex * getEndVertex() const
Definition: GEdge.h:64
xyFace.h
Range::low
T low() const
Definition: Range.h:18
blyr_ridge::_ge
GEdge * _ge
Definition: meshGRegionBoundaryLayer.cpp:64
blyr_manager::add_external_corner
void add_external_corner(const blyr_mvertex &v)
Definition: meshGRegionBoundaryLayer.cpp:417
MTriangle::setVertex
virtual void setVertex(int num, MVertex *v)
Definition: MTriangle.h:64
blyr_ridge::EXTERNAL
@ EXTERNAL
Definition: meshGRegionBoundaryLayer.cpp:62
xyEdge.h
blyr_manager::classify_corners
void classify_corners()
Definition: meshGRegionBoundaryLayer.cpp:360
blyr_manager::extrude_one_external
void extrude_one_external()
Definition: meshGRegionBoundaryLayer.cpp:664
GPoint::x
double x() const
Definition: GPoint.h:21
blyr_mvertex::_v
MVertex * _v
Definition: meshGRegionBoundaryLayer.cpp:99
MQuadrangle
Definition: MQuadrangle.h:26
blyr_manager::extrude_triangles
void extrude_triangles()
Definition: meshGRegionBoundaryLayer.cpp:1155
blyr_mvertex::add_triangle
void add_triangle(MTriangle *t, SVector3 &n, GFace *gf) const
Definition: meshGRegionBoundaryLayer.cpp:150
blyr_manager::_thickness
double _thickness
Definition: meshGRegionBoundaryLayer.cpp:171
GRegion::tetrahedra
std::vector< MTetrahedron * > tetrahedra
Definition: GRegion.h:163
computeMeanPlaneSimple
void computeMeanPlaneSimple(const std::vector< SPoint3 > &points, mean_plane &meanPlane)
Definition: Numeric.cpp:1438
blyr_manager::add_one_normal
void add_one_normal(const blyr_mvertex &v)
Definition: meshGRegionBoundaryLayer.cpp:542
blyr_mvertex::_lines
std::vector< MLine * > _lines
Definition: meshGRegionBoundaryLayer.cpp:108
MVertex::x
double x() const
Definition: MVertex.h:60
SVector3::normalize
double normalize()
Definition: SVector3.h:38
blyr_manager::_faces
std::vector< GFace * > _faces
Definition: meshGRegionBoundaryLayer.cpp:180
faces
static int faces[4][3]
Definition: meshGRegionDelaunayInsertion.cpp:165
SPoint2::y
double y(void) const
Definition: SPoint2.h:88