gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
meshGFaceDelaunayInsertion.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 <limits>
7 #include <set>
8 #include <map>
9 #include <algorithm>
10 #include <numeric>
11 #include "GmshConfig.h"
12 #include "GmshMessage.h"
13 #include "OS.h"
14 #include "robustPredicates.h"
15 #include "BackgroundMesh.h"
17 #include "meshGFaceOptimize.h"
18 #include "meshGFace.h"
19 #include "GModel.h"
20 #include "GFace.h"
21 #include "Numeric.h"
22 #include "STensor3.h"
23 #include "Context.h"
24 #include "discreteFace.h"
25 #include "intersectCurveSurface.h"
26 #include "HilbertCurve.h"
27 #include "fullMatrix.h"
28 
29 #if defined(HAVE_DOMHEX)
30 #include "pointInsertion.h"
31 #include "surfaceFiller.h"
32 #endif
33 
34 static double LIMIT_ = 0.5 * std::sqrt(2.0) * 1;
35 int MTri3::radiusNorm = 2;
36 
37 static void getDegeneratedVertices(GFace *gf, std::set<GEntity *> &degenerated)
38 {
39  degenerated.clear();
40  const std::vector<GEdge *> &ed = gf->edges();
41  for(size_t i = 0; i < ed.size(); i++) {
42  GEdge *e = ed[i];
43  if(e->getBeginVertex() && e->getBeginVertex() == e->getEndVertex()) {
44  if(e->geomType() == GEntity::Unknown) {
45  degenerated.insert(e->getBeginVertex());
46  }
47  }
48  }
49 }
50 
51 static inline bool intersection_segments_2(double *p1, double *p2, double *q1,
52  double *q2)
53 {
54  double a = robustPredicates::orient2d(p1, p2, q1);
55  double b = robustPredicates::orient2d(p1, p2, q2);
56  if(a * b > 0) return 0;
57  a = robustPredicates::orient2d(q1, q2, p1);
58  b = robustPredicates::orient2d(q1, q2, p2);
59  if(a * b > 0) return 0;
60  return 1;
61 }
62 
63 template <class ITERATOR>
64 void _printTris(char *name, ITERATOR it, ITERATOR end, bidimMeshData *data,
65  GFace *gf = nullptr, std::set<GEntity *> *degenerated = nullptr)
66 {
67  FILE *ff = Fopen(name, "w");
68  if(!ff) {
69  Msg::Error("Could not open file '%s'", name);
70  return;
71  }
72  fprintf(ff, "View\"test\"{\n");
73 
74  if(data && gf && degenerated) {
75  const int N = 100;
76  while(it != end) {
77  MTri3 *worst = *it;
78  if(!worst->isDeleted()) {
79  for(int i = 0; i < 3; i++) {
80  int whatever =
81  (degenerated->find((worst)->tri()->getVertex(i)->onWhat()) !=
82  degenerated->end()) +
83  (degenerated->find(
84  (worst)->tri()->getVertex((i + 1) % 3)->onWhat()) !=
85  degenerated->end());
86  if(whatever == 1) {
87  double u1 = data->Us[data->getIndex((worst)->tri()->getVertex(i))];
88  double u2 =
89  data->Us[data->getIndex((worst)->tri()->getVertex((i + 1) % 3))];
90  double v1 = data->Vs[data->getIndex((worst)->tri()->getVertex(i))];
91  double v2 =
92  data->Vs[data->getIndex((worst)->tri()->getVertex((i + 1) % 3))];
93  GPoint p_prec;
94  for(int j = 0; j < N; j++) {
95  double t = (double)j / (N - 1);
96  double u = u1 + t * (u2 - u1);
97  double v = v1 + t * (v2 - v1);
98  GPoint p = gf->point(SPoint2(u, v));
99  if(j) {
100  fprintf(ff, "SL(%g,%g,%g,%g,%g,%g){1,1};\n", p_prec.x(),
101  p_prec.y(), p_prec.z(), p.x(), p.y(), p.z());
102  }
103  p_prec = p;
104  }
105  }
106  }
107  }
108  ++it;
109  }
110  }
111  else {
112  while(it != end) {
113  MTri3 *worst = *it;
114  if(!worst->isDeleted()) {
115  if(data) {
116  double u1 = data->Us[data->getIndex((worst)->tri()->getVertex(0))];
117  double v1 = data->Vs[data->getIndex((worst)->tri()->getVertex(0))];
118  double u2 = data->Us[data->getIndex((worst)->tri()->getVertex(1))];
119  double v2 = data->Vs[data->getIndex((worst)->tri()->getVertex(1))];
120  double u3 = data->Us[data->getIndex((worst)->tri()->getVertex(2))];
121  double v3 = data->Vs[data->getIndex((worst)->tri()->getVertex(2))];
122 
123  if(degenerated) {
124  bool deg[3];
125  deg[0] =
126  degenerated->find((worst)->tri()->getVertex(0)->onWhat()) !=
127  degenerated->end();
128  deg[1] =
129  degenerated->find((worst)->tri()->getVertex(1)->onWhat()) !=
130  degenerated->end();
131  deg[2] =
132  degenerated->find((worst)->tri()->getVertex(2)->onWhat()) !=
133  degenerated->end();
134  if(deg[0] && !deg[1] && !deg[2]) {
135  fprintf(
136  ff, "SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d,%d};\n",
137  u3, v1, 0., u2, v1, 0., u2, v2, 0., u3, v3, 0.,
138  (worst)->tri()->getVertex(0)->getNum(),
139  (worst)->tri()->getVertex(0)->getNum(),
140  (worst)->tri()->getVertex(1)->getNum(),
141  (worst)->tri()->getVertex(2)->getNum());
142  }
143  else if(!deg[0] && deg[1] && !deg[2]) {
144  fprintf(
145  ff, "SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d,%d};\n",
146  u1, v2, 0., u3, v2, 0., u3, v3, 0., u1, v1, 0.,
147  (worst)->tri()->getVertex(1)->getNum(),
148  (worst)->tri()->getVertex(1)->getNum(),
149  (worst)->tri()->getVertex(2)->getNum(),
150  (worst)->tri()->getVertex(0)->getNum());
151  }
152  else if(!deg[0] && !deg[1] && deg[2]) {
153  fprintf(
154  ff, "SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d,%d};\n",
155  u2, v3, 0., u1, v3, 0., u1, v1, 0., u2, v2, 0.,
156  (worst)->tri()->getVertex(2)->getNum(),
157  (worst)->tri()->getVertex(2)->getNum(),
158  (worst)->tri()->getVertex(0)->getNum(),
159  (worst)->tri()->getVertex(1)->getNum());
160  }
161  else if(!deg[0] && !deg[1] && !deg[2]) {
162  fprintf(ff, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d};\n", u1,
163  v1, 0., u2, v2, 0., u3, v3, 0.,
164  (worst)->tri()->getVertex(0)->getNum(),
165  (worst)->tri()->getVertex(1)->getNum(),
166  (worst)->tri()->getVertex(2)->getNum());
167  }
168  }
169  else {
170  fprintf(ff, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d};\n", u1, v1,
171  0., u2, v2, 0., u3, v3, 0.,
172  (worst)->tri()->getVertex(0)->getNum(),
173  (worst)->tri()->getVertex(1)->getNum(),
174  (worst)->tri()->getVertex(2)->getNum());
175  }
176  }
177  else
178  fprintf(ff, "ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d};\n",
179  (worst)->tri()->getVertex(0)->x(),
180  (worst)->tri()->getVertex(0)->y(),
181  (worst)->tri()->getVertex(0)->z(),
182  (worst)->tri()->getVertex(1)->x(),
183  (worst)->tri()->getVertex(1)->y(),
184  (worst)->tri()->getVertex(1)->z(),
185  (worst)->tri()->getVertex(2)->x(),
186  (worst)->tri()->getVertex(2)->y(),
187  (worst)->tri()->getVertex(2)->z(),
188  (worst)->tri()->getVertex(0)->getNum(),
189  (worst)->tri()->getVertex(1)->getNum(),
190  (worst)->tri()->getVertex(2)->getNum());
191  }
192  ++it;
193  }
194  }
195  fprintf(ff, "};\n");
196  fclose(ff);
197 }
198 
199 static bool isActive(MTri3 *t, double limit_, int &active)
200 {
201  if(t->isDeleted()) return false;
202  for(active = 0; active < 3; active++) {
203  MTri3 *neigh = t->getNeigh(active);
204  if(!neigh || (neigh->getRadius() < limit_ && neigh->getRadius() > 0)) {
205  // int ip1 = active - 1 < 0 ? 2 : active - 1;
206  // int ip2 = active;
207  // if(distance(t->tri()->getVertex(ip1), t->tri()->getVertex(ip2))
208  // > 1.e-12)
209  return true;
210  }
211  }
212  return false;
213 }
214 
215 static bool isActive(MTri3 *t, double limit_, int &i,
216  std::set<MEdge, MEdgeLessThan> *front)
217 {
218  if(t->isDeleted()) return false;
219  for(i = 0; i < 3; i++) {
220  MTri3 *neigh = t->getNeigh(i);
221  if(!neigh || (neigh->getRadius() < limit_ && neigh->getRadius() > 0)) {
222  int ip1 = i - 1 < 0 ? 2 : i - 1;
223  int ip2 = i;
224  MEdge me(t->tri()->getVertex(ip1), t->tri()->getVertex(ip2));
225  if(front->find(me) != front->end()) { return true; }
226  }
227  }
228  return false;
229 }
230 
231 static void updateActiveEdges(MTri3 *t, double limit_,
232  std::set<MEdge, MEdgeLessThan> &front)
233 {
234  if(t->isDeleted()) return;
235  for(int active = 0; active < 3; active++) {
236  MTri3 *neigh = t->getNeigh(active);
237  if(!neigh || (neigh->getRadius() < limit_ && neigh->getRadius() > 0)) {
238  int ip1 = active - 1 < 0 ? 2 : active - 1;
239  int ip2 = active;
240  MEdge me(t->tri()->getVertex(ip1), t->tri()->getVertex(ip2));
241  front.insert(me);
242  }
243  }
244 }
245 
246 static void circumCenterMetric(double *pa, double *pb, double *pc,
247  const double *metric, double *x, double &Radius2)
248 {
249  // d = (u2-u1) M (u2-u1) = u2 M u2 + u1 M u1 - 2 u2 M u1
250  double sys[2][2];
251  double rhs[2];
252 
253  const double a = metric[0];
254  const double b = metric[1];
255  const double d = metric[2];
256 
257  sys[0][0] = 2. * a * (pa[0] - pb[0]) + 2. * b * (pa[1] - pb[1]);
258  sys[0][1] = 2. * d * (pa[1] - pb[1]) + 2. * b * (pa[0] - pb[0]);
259  sys[1][0] = 2. * a * (pa[0] - pc[0]) + 2. * b * (pa[1] - pc[1]);
260  sys[1][1] = 2. * d * (pa[1] - pc[1]) + 2. * b * (pa[0] - pc[0]);
261 
262  rhs[0] = a * (pa[0] * pa[0] - pb[0] * pb[0]) +
263  d * (pa[1] * pa[1] - pb[1] * pb[1]) +
264  2. * b * (pa[0] * pa[1] - pb[0] * pb[1]);
265  rhs[1] = a * (pa[0] * pa[0] - pc[0] * pc[0]) +
266  d * (pa[1] * pa[1] - pc[1] * pc[1]) +
267  2. * b * (pa[0] * pa[1] - pc[0] * pc[1]);
268 
269  if(!sys2x2(sys, rhs, x)) {
270  // printf("%g %g %g\n",a,b,d);
271  }
272 
273  Radius2 = (x[0] - pa[0]) * (x[0] - pa[0]) * a +
274  (x[1] - pa[1]) * (x[1] - pa[1]) * d +
275  2. * (x[0] - pa[0]) * (x[1] - pa[1]) * b;
276 }
277 
278 static void circumCenterMetricXYZ(double *p1, double *p2, double *p3,
279  SMetric3 &metric, double *res, double *uv,
280  double &radius)
281 {
282  double v1[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
283  double v2[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
284  double vx[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
285  double vy[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
286  double vz[3];
287  prodve(vx, vy, vz);
288  prodve(vz, vx, vy);
289  norme(vx);
290  norme(vy);
291  norme(vz);
292  double p1P[2] = {0.0, 0.0};
293  double p2P[2] = {prosca(v1, vx), prosca(v1, vy)};
294  double p3P[2] = {prosca(v2, vx), prosca(v2, vy)};
295 
296  double resP[2];
297 
298  fullMatrix<double> T(3, 3);
299  for(int i = 0; i < 3; i++) T(0, i) = vx[i];
300  for(int i = 0; i < 3; i++) T(1, i) = vy[i];
301  for(int i = 0; i < 3; i++) T(2, i) = vz[i];
302  SMetric3 tra = metric.transform(T);
303  double mm[3] = {tra(0, 0), tra(0, 1), tra(1, 1)};
304 
305  circumCenterMetric(p1P, p2P, p3P, mm, resP, radius);
306 
307  if(uv) {
308  double mat[2][2] = {{p2P[0] - p1P[0], p3P[0] - p1P[0]},
309  {p2P[1] - p1P[1], p3P[1] - p1P[1]}};
310  double rhs[2] = {resP[0] - p1P[0], resP[1] - p1P[1]};
311  sys2x2(mat, rhs, uv);
312  }
313 
314  res[0] = p1[0] + resP[0] * vx[0] + resP[1] * vy[0];
315  res[1] = p1[1] + resP[0] * vx[1] + resP[1] * vy[1];
316  res[2] = p1[2] + resP[0] * vx[2] + resP[1] * vy[2];
317 }
318 
319 static void circumCenterMetric(MTriangle *base, const double *metric,
320  bidimMeshData &data, double *x, double &Radius2)
321 {
322  // d = (u2-u1) M (u2-u1) = u2 M u2 + u1 M u1 - 2 u2 M u1
323  int index0 = data.getIndex(base->getVertex(0));
324  int index1 = data.getIndex(base->getVertex(1));
325  int index2 = data.getIndex(base->getVertex(2));
326  double pa[2] = {data.Us[index0], data.Vs[index0]};
327  double pb[2] = {data.Us[index1], data.Vs[index1]};
328  double pc[2] = {data.Us[index2], data.Vs[index2]};
329  circumCenterMetric(pa, pb, pc, metric, x, Radius2);
330 }
331 
332 void buildMetric(GFace *gf, double *uv, double *metric)
333 {
334  Pair<SVector3, SVector3> der = gf->firstDer(SPoint2(uv[0], uv[1]));
335 
336  metric[0] = dot(der.first(), der.first());
337  metric[1] = dot(der.second(), der.first());
338  metric[2] = dot(der.second(), der.second());
339 }
340 
341 static double computeTolerance(const double radius)
342 {
343  if(radius <= 1e3) return 1e-12;
344  if(radius <= 1e5) return 1e-11;
345  return 1e-9;
346 }
347 
348 int inCircumCircleAniso(GFace *gf, double *p1, double *p2, double *p3,
349  double *uv, double *metric)
350 {
351  double x[2], Radius2;
352  circumCenterMetric(p1, p2, p3, metric, x, Radius2);
353  const double a = metric[0];
354  const double b = metric[1];
355  const double d = metric[2];
356  const double d0 = (x[0] - uv[0]);
357  const double d1 = (x[1] - uv[1]);
358  const double d3 = d0 * d0 * a + d1 * d1 * d + 2.0 * d0 * d1 * b;
359  const double tolerance = computeTolerance(Radius2);
360  return d3 < Radius2 - tolerance;
361 }
362 
363 int inCircumCircleAniso(GFace *gf, MTriangle *base, const double *uv,
364  const double *metricb, bidimMeshData &data)
365 {
366  SPoint3 c;
367  double x[2], Radius2;
368  double metric[3];
369  if(!metricb) {
370  int index0 = data.getIndex(base->getVertex(0));
371  int index1 = data.getIndex(base->getVertex(1));
372  int index2 = data.getIndex(base->getVertex(2));
373  double pa[2] = {(data.Us[index0] + data.Us[index1] + data.Us[index2]) / 3.,
374  (data.Vs[index0] + data.Vs[index1] + data.Vs[index2]) / 3.};
375  buildMetric(gf, pa, metric);
376  }
377  else {
378  metric[0] = metricb[0];
379  metric[1] = metricb[1];
380  metric[2] = metricb[2];
381  };
382  circumCenterMetric(base, metric, data, x, Radius2);
383 
384  const double a = metric[0];
385  const double b = metric[1];
386  const double d = metric[2];
387 
388  const double d0 = (x[0] - uv[0]);
389  const double d1 = (x[1] - uv[1]);
390  const double d3 = d0 * d0 * a + d1 * d1 * d + 2.0 * d0 * d1 * b;
391  return d3 < Radius2;
392 }
393 
394 static void fourthPoint(double *p1, double *p2, double *p3, double *p4)
395 {
396  double c[3];
397  circumCenterXYZ(p1, p2, p3, c);
398  double vx[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
399  double vy[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
400  double vz[3];
401  prodve(vx, vy, vz);
402  norme(vz);
403  double R =
404  sqrt((p1[0] - c[0]) * (p1[0] - c[0]) + (p1[1] - c[1]) * (p1[1] - c[1]) +
405  (p1[2] - c[2]) * (p1[2] - c[2]));
406  p4[0] = c[0] + R * vz[0];
407  p4[1] = c[1] + R * vz[1];
408  p4[2] = c[2] + R * vz[2];
409 }
410 
411 MTri3::MTri3(MTriangle *t, double lc, SMetric3 *metric, bidimMeshData *data,
412  GFace *gf)
413  : deleted(false), base(t)
414 {
415  neigh[0] = neigh[1] = neigh[2] = nullptr;
416  double center[3];
417  double pa[3] = {base->getVertex(0)->x(), base->getVertex(0)->y(),
418  base->getVertex(0)->z()};
419  double pb[3] = {base->getVertex(1)->x(), base->getVertex(1)->y(),
420  base->getVertex(1)->z()};
421  double pc[3] = {base->getVertex(2)->x(), base->getVertex(2)->y(),
422  base->getVertex(2)->z()};
423 
424  if(!metric) {
425  if(radiusNorm == 3) { circum_radius = 1. / base->gammaShapeMeasure(); }
426  else if(radiusNorm == 2) {
427  circumCenterXYZ(pa, pb, pc, center);
428  const double dx = base->getVertex(0)->x() - center[0];
429  const double dy = base->getVertex(0)->y() - center[1];
430  const double dz = base->getVertex(0)->z() - center[2];
431  circum_radius = std::sqrt(dx * dx + dy * dy + dz * dz) / lc;
432  }
433  else {
434  int const index0 = data->getIndex(base->getVertex(0));
435  int const index1 = data->getIndex(base->getVertex(1));
436  int const index2 = data->getIndex(base->getVertex(2));
437  double const p1[2] = {data->Us[index0], data->Vs[index0]};
438  double const p2[2] = {data->Us[index1], data->Vs[index1]};
439  double const p3[2] = {data->Us[index2], data->Vs[index2]};
440 
441  double midpoint[2] = {(p1[0] + p2[0] + p3[0]) / 3.0,
442  (p1[1] + p2[1] + p3[1]) / 3.0};
443 
444  double quadAngle =
446  backgroundMesh::current()->getAngle(midpoint[0], midpoint[1], 0) :
447  0.0;
448 
449  double x0 = p1[0] * std::cos(quadAngle) + p1[1] * std::sin(quadAngle);
450  double y0 = -p1[0] * std::sin(quadAngle) + p1[1] * std::cos(quadAngle);
451  double x1 = p2[0] * std::cos(quadAngle) + p2[1] * std::sin(quadAngle);
452  double y1 = -p2[0] * std::sin(quadAngle) + p2[1] * std::cos(quadAngle);
453  double x2 = p3[0] * std::cos(quadAngle) + p3[1] * std::sin(quadAngle);
454  double y2 = -p3[0] * std::sin(quadAngle) + p3[1] * std::cos(quadAngle);
455  double xmax = std::max(std::max(x0, x1), x2);
456  double ymax = std::max(std::max(y0, y1), y2);
457  double xmin = std::min(std::min(x0, x1), x2);
458  double ymin = std::min(std::min(y0, y1), y2);
459 
460  double metric[3];
461  buildMetric(gf, midpoint, metric);
462  double RATIO =
463  std::pow(metric[0] * metric[2] - metric[1] * metric[1], -0.25);
464 
465  circum_radius = std::max(xmax - xmin, ymax - ymin) / (RATIO * lc);
466  }
467  }
468  else {
469  double uv[2];
470  circumCenterMetricXYZ(pa, pb, pc, *metric, center, uv, circum_radius);
471  }
472 
473  if(gf) {
474  BoundaryLayerColumns *_columns = gf->getColumns();
475  if(_columns) {
476  if(_columns->_toFirst.find(t) != _columns->_toFirst.end()) {
477  circum_radius = 0;
478  }
479  }
480  }
481 }
482 
483 int MTri3::inCircumCircle(const double *p) const
484 {
485  double pa[3] = {base->getVertex(0)->x(), base->getVertex(0)->y(),
486  base->getVertex(0)->z()};
487  double pb[3] = {base->getVertex(1)->x(), base->getVertex(1)->y(),
488  base->getVertex(1)->z()};
489  double pc[3] = {base->getVertex(2)->x(), base->getVertex(2)->y(),
490  base->getVertex(2)->z()};
491  double fourth[3];
492  fourthPoint(pa, pb, pc, fourth);
493 
494  double result = robustPredicates::insphere(pa, pb, pc, fourth, (double *)p) *
495  robustPredicates::orient3d(pa, pb, pc, fourth);
496  return (result > 0) ? 1 : 0;
497 }
498 
499 int inCircumCircle(MTriangle *base, const double *p, const double *param,
500  bidimMeshData &data)
501 {
502  int index0 = data.getIndex(base->getVertex(0));
503  int index1 = data.getIndex(base->getVertex(1));
504  int index2 = data.getIndex(base->getVertex(2));
505  double pa[2] = {data.Us[index0], data.Vs[index0]};
506  double pb[2] = {data.Us[index1], data.Vs[index1]};
507  double pc[2] = {data.Us[index2], data.Vs[index2]};
508 
509  double result = robustPredicates::incircle(pa, pb, pc, (double *)param) *
510  robustPredicates::orient2d(pa, pb, pc);
511  return (result > 0) ? 1 : 0;
512 }
513 
514 template <class Iterator>
515 static void connectTris(Iterator beg, Iterator end,
516  std::vector<edgeXface> &conn)
517 {
518  conn.clear();
519 
520  while(beg != end) {
521  if(!(*beg)->isDeleted()) {
522  for(int j = 0; j < 3; j++) { conn.push_back(edgeXface(*beg, j)); }
523  }
524  ++beg;
525  }
526 
527  if(conn.empty()) return;
528 
529  std::sort(conn.begin(), conn.end());
530 
531  for(std::size_t i = 0; i < conn.size() - 1; i++) {
532  edgeXface &f1 = conn[i];
533  edgeXface &f2 = conn[i + 1];
534 
535  if(f1 == f2 && f1.t1 != f2.t1) {
536  f1.t1->setNeigh(f1.i1, f2.t1);
537  f2.t1->setNeigh(f2.i1, f1.t1);
538  ++i;
539  }
540  }
541 }
542 
543 void connectTriangles(std::list<MTri3 *> &l)
544 {
545  std::vector<edgeXface> conn;
546  connectTris(l.begin(), l.end(), conn);
547 }
548 
549 void connectTriangles(std::vector<MTri3 *> &l)
550 {
551  std::vector<edgeXface> conn;
552  connectTris(l.begin(), l.end(), conn);
553 }
554 
555 void connectTriangles(std::set<MTri3 *, compareTri3Ptr> &l)
556 {
557  std::vector<edgeXface> conn;
558  connectTris(l.begin(), l.end(), conn);
559 }
560 
562 {
563  MVertex *v1 = t->getVertex(0);
564  MVertex *v2 = t->getVertex(1);
565  MVertex *v3 = t->getVertex(2);
566  double p1[2] = {v1->x(), v1->y()};
567  double p2[2] = {v2->x(), v2->y()};
568  double p3[2] = {v3->x(), v3->y()};
569  double pp[2] = {v->x(), v->y()};
570  double result = robustPredicates::incircle(p1, p2, p3, pp) *
571  robustPredicates::orient2d(p1, p2, p3);
572  return (result > 0) ? 1 : 0;
573 }
574 
575 static void recurFindCavity(std::vector<edgeXface> &shell,
576  std::vector<MTri3 *> &cavity, MVertex *v, MTri3 *t)
577 {
578  t->setDeleted(true);
579  // the cavity that has to be removed because it violates delaunay
580  // criterion
581  cavity.push_back(t);
582 
583  for(int i = 0; i < 3; i++) {
584  MTri3 *neigh = t->getNeigh(i);
585  if(!neigh)
586  shell.push_back(edgeXface(t, i));
587  else if(!neigh->isDeleted()) {
588  int circ = inCircumCircleXY(neigh->tri(), v);
589  if(circ)
590  recurFindCavity(shell, cavity, v, neigh);
591  else
592  shell.push_back(edgeXface(t, i));
593  }
594  }
595 }
596 
597 static void recurFindCavityAniso(GFace *gf, std::list<edgeXface> &shell,
598  std::list<MTri3 *> &cavity, double *metric,
599  double *param, MTri3 *t, bidimMeshData &data)
600 {
601  t->setDeleted(true);
602  // the cavity that has to be removed because it violates delaunay
603  // criterion
604  cavity.push_back(t);
605 
606  for(int i = 0; i < 3; i++) {
607  MTri3 *neigh = t->getNeigh(i);
608  edgeXface exf(t, i);
609  // take care of untouchable internal edges
610  auto it = data.internalEdges.find(MEdge(exf._v(0), exf._v(1)));
611  if(!neigh || it != data.internalEdges.end())
612  shell.push_back(exf);
613  else if(!neigh->isDeleted()) {
614  int circ = inCircumCircleAniso(gf, neigh->tri(), param, metric, data);
615  if(circ)
616  recurFindCavityAniso(gf, shell, cavity, metric, param, neigh, data);
617  else
618  shell.push_back(exf);
619  }
620  }
621 }
622 
623 static bool circUV(MTriangle *t, bidimMeshData &data, double *res, GFace *gf)
624 {
625  int index0 = data.getIndex(t->getVertex(0));
626  int index1 = data.getIndex(t->getVertex(1));
627  int index2 = data.getIndex(t->getVertex(2));
628  double u1[3] = {data.Us[index0], data.Vs[index0], 0};
629  double u2[3] = {data.Us[index1], data.Vs[index1], 0};
630  double u3[3] = {data.Us[index2], data.Vs[index2], 0};
631  circumCenterXY(u1, u2, u3, res);
632  return true;
633 }
634 
635 static bool invMapUV(MTriangle *t, double *p, bidimMeshData &data, double *uv,
636  double tol)
637 {
638  double mat[2][2];
639  double b[2];
640 
641  int index0 = data.getIndex(t->getVertex(0));
642  int index1 = data.getIndex(t->getVertex(1));
643  int index2 = data.getIndex(t->getVertex(2));
644 
645  double u0 = data.Us[index0];
646  double v0 = data.Vs[index0];
647  double u1 = data.Us[index1];
648  double v1 = data.Vs[index1];
649  double u2 = data.Us[index2];
650  double v2 = data.Vs[index2];
651 
652  mat[0][0] = u1 - u0;
653  mat[0][1] = u2 - u0;
654  mat[1][0] = v1 - v0;
655  mat[1][1] = v2 - v0;
656 
657  b[0] = p[0] - u0;
658  b[1] = p[1] - v0;
659  sys2x2(mat, b, uv);
660 
661  return uv[0] >= -tol && uv[1] >= -tol && uv[0] <= 1. + tol &&
662  uv[1] <= 1. + tol && 1. - uv[0] - uv[1] > -tol;
663 }
664 
665 inline double getSurfUV(MTriangle *t, bidimMeshData &data)
666 {
667  int index0 = data.getIndex(t->getVertex(0));
668  int index1 = data.getIndex(t->getVertex(1));
669  int index2 = data.getIndex(t->getVertex(2));
670 
671  double u1 = data.Us[index0];
672  double v1 = data.Vs[index0];
673  double u2 = data.Us[index1];
674  double v2 = data.Vs[index1];
675  double u3 = data.Us[index2];
676  double v3 = data.Vs[index2];
677 
678  const double vv1[2] = {u2 - u1, v2 - v1};
679  const double vv2[2] = {u3 - u1, v3 - v1};
680 
681  return 0.5 * (vv1[0] * vv2[1] - vv1[1] * vv2[0]);
682 }
683 
684 static int insertVertexB(std::list<edgeXface> &shell,
685  std::list<MTri3 *> &cavity, bool force, GFace *gf,
686  MVertex *v, double *param, MTri3 *t,
687  std::set<MTri3 *, compareTri3Ptr> &allTets,
688  std::set<MTri3 *, compareTri3Ptr> *activeTets,
689  bidimMeshData &data, double *metric,
690  MTri3 **oneNewTriangle,
691  bool verifyStarShapeness = true)
692 {
693  if(cavity.size() == 1) return -1;
694 
695  if(shell.size() != cavity.size() + 2) return -2;
696 
697  double EPS = verifyStarShapeness ? 1.e-12 : 1.e12;
698 
699  // check that volume is conserved
700  double newVolume = 0.0;
701  double newMinQuality = 2.0;
702 
703  double oldVolume = std::accumulate(
704  begin(cavity), end(cavity), 0.0, [&](double volume, MTri3 *const triangle) {
705  return volume + std::abs(getSurfUV(triangle->tri(), data));
706  });
707 
708  MTri3 **newTris = new MTri3 *[shell.size()];
709 
710  std::vector<MTri3 *> new_cavity;
711 
712  int k = 0;
713 
714  auto it = shell.begin();
715 
716  bool onePointIsTooClose = false;
717 
718  while(it != shell.end()) {
719  MVertex *v0, *v1;
720  if(it->ori > 0) {
721  v0 = it->_v(0);
722  v1 = it->_v(1);
723  }
724  else {
725  v0 = it->_v(1);
726  v1 = it->_v(0);
727  }
728  MTriangle *t = new MTriangle(v0, v1, v);
729  int index0 = data.getIndex(t->getVertex(0));
730  int index1 = data.getIndex(t->getVertex(1));
731  int index2 = data.getIndex(t->getVertex(2));
732  constexpr double ONE_THIRD = 1. / 3.;
733  double lc = ONE_THIRD * (data.vSizes[index0] + data.vSizes[index1] +
734  data.vSizes[index2]);
735  double lcBGM =
736  ONE_THIRD * (data.vSizesBGM[index0] + data.vSizesBGM[index1] +
737  data.vSizesBGM[index2]);
738  double LL = std::min(lc, lcBGM);
739 
740  MTri3 *t4 = new MTri3(t, Extend1dMeshIn2dSurfaces(gf) ? LL : lcBGM, nullptr,
741  &data, gf);
742 
743  if(oneNewTriangle) {
744  force = true;
745  *oneNewTriangle = t4;
746  }
747 
748  double d1 = distance(v0, v);
749  double d2 = distance(v1, v);
750  double d3 = distance(v0, v1);
751  double d4 = 1.e22;
752  // avoid angles that are too obtuse
753  double cosv = ((d1 * d1 + d2 * d2 - d3 * d3) / (2. * d1 * d2));
754 
755  if(v0->onWhat()->dim() != 2 && v1->onWhat()->dim() != 2) {
756  SVector3 v0v1(v1->x() - v0->x(), v1->y() - v0->y(), v1->z() - v0->z());
757  SVector3 v0v(v->x() - v0->x(), v->y() - v0->y(), v->z() - v0->z());
758  SVector3 pv = crossprod(v0v1, v0v);
759  d4 = pv.norm() / d3;
760  }
761 
762  if((d1 < LL * .5 || d2 < LL * .5 || d4 < LL * .4 || cosv < -.9999) &&
763  !force) {
764  onePointIsTooClose = true;
765  }
766 
767  newTris[k++] = t4;
768  // all new triangles are pushed front in order to be able to destroy them if
769  // the cavity is not star shaped around the new vertex.
770  new_cavity.push_back(t4);
771 
772  MTri3 *otherSide = it->t1->getNeigh(it->i1);
773  if(otherSide) new_cavity.push_back(otherSide);
774 
775  double ss = std::abs(getSurfUV(t4->tri(), data));
776  if(ss < 1.e-25) ss = 1.e22;
777 
778  newVolume += ss;
779  newMinQuality = std::min(newMinQuality, t4->tri()->gammaShapeMeasure());
780 
781  ++it;
782  }
783 
784  std::vector<edgeXface> conn;
785 
786  // for adding a point we require that the area remains the same after addition
787  // of the point, and that the point is not too close to an edge
788  if(std::abs(oldVolume - newVolume) < EPS * oldVolume && !onePointIsTooClose) {
789  connectTris(new_cavity.begin(), new_cavity.end(), conn);
790  // 30 % of the time is spent here!
791  allTets.insert(newTris, newTris + shell.size());
792  if(activeTets) {
793  for(auto i = new_cavity.begin(); i != new_cavity.end(); ++i) {
794  int active_edge;
795  if(isActive(*i, LIMIT_, active_edge) && (*i)->getRadius() > LIMIT_) {
796  if((*activeTets).find(*i) == (*activeTets).end())
797  (*activeTets).insert(*i);
798  }
799  }
800  }
801  delete[] newTris;
802  return 1;
803  }
804  else {
805  // the cavity is NOT star shaped
806  std::for_each(begin(cavity), end(cavity),
807  [](MTri3 *triangle) { triangle->setDeleted(false); });
808  // _printTris("cavity.pos", cavity.begin(), cavity.end(), Us, Vs, false);
809  // _printTris("new_cavity.pos", new_cavity.begin(), new_cavity.end(), Us,
810  // Vs, false); _printTris("newTris.pos", &newTris[0], newTris+shell.size(),
811  // Us, Vs, false); _printTris("allTris.pos", allTets.begin(),allTets.end(),
812  // Us, Vs, false);
813  for(std::size_t i = 0; i < shell.size(); i++) {
814  delete newTris[i]->tri();
815  delete newTris[i];
816  }
817  delete[] newTris;
818 
819  if(std::abs(oldVolume - newVolume) > EPS * oldVolume) return -3;
820  if(onePointIsTooClose) return -4;
821  return -5;
822  }
823 }
824 
825 static bool invMapXY(MTriangle *t, MVertex *v)
826 {
827  MVertex *v0 = t->getVertex(0);
828  MVertex *v1 = t->getVertex(1);
829  MVertex *v2 = t->getVertex(2);
830  double mat[2][2], b[2], uv[2], tol = 1.e-6;
831  mat[0][0] = v1->x() - v0->x();
832  mat[0][1] = v2->x() - v0->x();
833  mat[1][0] = v1->y() - v0->y();
834  mat[1][1] = v2->y() - v0->y();
835 
836  b[0] = v->x() - v0->x();
837  b[1] = v->y() - v0->y();
838  sys2x2(mat, b, uv);
839 
840  if(uv[0] >= -tol && uv[1] >= -tol && uv[0] <= 1. + tol && uv[1] <= 1. + tol &&
841  1. - uv[0] - uv[1] > -tol) {
842  return true;
843  }
844  return false;
845 }
846 
847 static MTri3 *search4Triangle(MTri3 *t, MVertex *v, int maxx, int &ITER)
848 {
849  bool inside = invMapXY(t->tri(), v);
850  SPoint3 q1(v->x(), v->y(), 0);
851  if(inside) return t;
852  while(1) {
853  SPoint3 q2 = t->tri()->barycenter();
854  int i;
855  for(i = 0; i < 3; i++) {
856  int i1 = i == 0 ? 2 : i - 1;
857  int i2 = i;
858  MVertex *v1 = t->tri()->getVertex(i1);
859  MVertex *v2 = t->tri()->getVertex(i2);
860  SPoint3 p1(v1->x(), v1->y(), 0);
861  SPoint3 p2(v2->x(), v2->y(), 0);
862  if(intersection_segments_2(p1, p2, q1, q2)) break;
863  }
864  if(i >= 3) break;
865  t = t->getNeigh(i);
866  if(!t) break;
867  bool inside = invMapXY(t->tri(), v);
868  if(inside) return t;
869  if(ITER++ > .5 * maxx) break;
870  }
871  return nullptr;
872 }
873 
874 static MTri3 *search4Triangle(MTri3 *t, double pt[2], bidimMeshData &data,
875  std::set<MTri3 *, compareTri3Ptr> &AllTris,
876  double uv[2], bool force = false)
877 {
878  // bool inside = t->inCircumCircle(pt);
879  bool inside = invMapUV(t->tri(), pt, data, uv, 1.e-8);
880 
881  if(inside) return t;
882  SPoint3 q1(pt[0], pt[1], 0);
883  int ITER = 0;
884  while(1) {
885  int index0 = data.getIndex(t->tri()->getVertex(0));
886  int index1 = data.getIndex(t->tri()->getVertex(1));
887  int index2 = data.getIndex(t->tri()->getVertex(2));
888  SPoint3 q2((data.Us[index0] + data.Us[index1] + data.Us[index2]) / 3.0,
889  (data.Vs[index0] + data.Vs[index1] + data.Vs[index2]) / 3.0, 0);
890  int i;
891  for(i = 0; i < 3; i++) {
892  int i1 = data.getIndex(t->tri()->getVertex(i == 0 ? 2 : i - 1));
893  int i2 = data.getIndex(t->tri()->getVertex(i));
894  SPoint3 p1(data.Us[i1], data.Vs[i1], 0);
895  SPoint3 p2(data.Us[i2], data.Vs[i2], 0);
896  if(intersection_segments_2(p1, p2, q1, q2)) break;
897  }
898  if(i >= 3) {
899  printf("impossible\n");
900  break;
901  }
902  t = t->getNeigh(i);
903  if(!t) break;
904  bool inside = invMapUV(t->tri(), pt, data, uv, 1.e-8);
905  if(inside) return t;
906  if(ITER++ > (int)AllTris.size()) break;
907  }
908 
909  if(!force)
910  return nullptr; // FIXME: removing this leads to horrible performance
911 
912  for(auto itx = AllTris.begin(); itx != AllTris.end(); ++itx) {
913  if(!(*itx)->isDeleted()) {
914  inside = invMapUV((*itx)->tri(), pt, data, uv, 1.e-8);
915  if(inside) { return *itx; }
916  }
917  }
918  // printf("argh %g %g!!!!\n", pt[0], pt[1]);
919  return nullptr;
920 }
921 
922 static bool
923 insertAPoint(GFace *gf, std::set<MTri3 *, compareTri3Ptr>::iterator it,
924  double center[2], double metric[3], bidimMeshData &data,
925  std::set<MTri3 *, compareTri3Ptr> &AllTris,
926  std::set<MTri3 *, compareTri3Ptr> *ActiveTris = nullptr,
927  MTri3 *worst = nullptr, MTri3 **oneNewTriangle = nullptr,
928  bool testStarShapeness = false)
929 {
930  if(worst) {
931  it = AllTris.find(worst);
932  if(worst != *it) {
933  Msg::Error("Could not insert point");
934  return false;
935  }
936  }
937  else
938  worst = *it;
939 
940  MTri3 *ptin = nullptr;
941  std::list<edgeXface> shell;
942  std::list<MTri3 *> cavity;
943  double uv[2];
944 
945  // if the point is able to break the bad triangle "worst"
946  if(inCircumCircleAniso(gf, worst->tri(), center, metric, data)) {
947  recurFindCavityAniso(gf, shell, cavity, metric, center, worst, data);
948  for(auto itc = cavity.begin(); itc != cavity.end(); ++itc) {
949  if(invMapUV((*itc)->tri(), center, data, uv, 1.e-8)) {
950  ptin = *itc;
951  break;
952  }
953  }
954  }
955  else {
956  ptin = search4Triangle(worst, center, data, AllTris, uv,
957  oneNewTriangle ? true : false);
958  if(ptin) {
959  recurFindCavityAniso(gf, shell, cavity, metric, center, ptin, data);
960  }
961  }
962 
963  if(ptin) {
964  // we use here local coordinates as real coordinates x,y and z will be
965  // computed hereafter
966  GPoint p = gf->point(center[0], center[1]);
967 
968  MVertex *v = new MFaceVertex(p.x(), p.y(), p.z(), gf, center[0], center[1]);
969 
970  double lc1, lc;
971  int index0 = data.getIndex(ptin->tri()->getVertex(0));
972  int index1 = data.getIndex(ptin->tri()->getVertex(1));
973  int index2 = data.getIndex(ptin->tri()->getVertex(2));
974  lc1 = (1. - uv[0] - uv[1]) * data.vSizes[index0] +
975  uv[0] * data.vSizes[index1] + uv[1] * data.vSizes[index2];
977  lc = 1.;
978  else
979  lc = BGM_MeshSize(gf, center[0], center[1], p.x(), p.y(), p.z());
980 
981  data.addVertex(v, center[0], center[1], lc1, lc);
982 
983  int result = -9;
984  if(p.succeeded()) {
985  result = insertVertexB(shell, cavity, false, gf, v, center, ptin, AllTris,
986  ActiveTris, data, metric, oneNewTriangle,
987  testStarShapeness);
988  }
989  if(result != 1) {
990  if(result == -1)
991  Msg::Debug("Point %g %g cannot be inserted because cavity if of size 1",
992  center[0], center[1]);
993  if(result == -2)
994  Msg::Debug("Point %g %g cannot be inserted because euler formula is "
995  "not fulfilled",
996  center[0], center[1]);
997  if(result == -3)
998  Msg::Debug(
999  "Point %g %g cannot be inserted because cavity is not star shaped",
1000  center[0], center[1]);
1001  if(result == -4)
1002  Msg::Debug("Point %g %g cannot be inserted because it is too close to "
1003  "another point)",
1004  center[0], center[1]);
1005  if(result == -5)
1006  Msg::Debug("Point %g %g cannot be inserted because it is out of the "
1007  "parametric domain)",
1008  center[0], center[1]);
1009 
1010  AllTris.erase(it);
1011  worst->forceRadius(-1);
1012  AllTris.insert(worst);
1013  delete v;
1014  for(auto itc = cavity.begin(); itc != cavity.end(); ++itc)
1015  (*itc)->setDeleted(false);
1016  return false;
1017  }
1018  else {
1019  gf->mesh_vertices.push_back(v);
1020  return true;
1021  }
1022  }
1023  else {
1024  for(auto itc = cavity.begin(); itc != cavity.end(); ++itc)
1025  (*itc)->setDeleted(false);
1026  AllTris.erase(it);
1027  worst->forceRadius(0);
1028  AllTris.insert(worst);
1029  return false;
1030  }
1031 }
1032 
1033 void bowyerWatson(GFace *gf, int MAXPNT,
1034  std::map<MVertex *, MVertex *> *equivalence,
1035  std::map<MVertex *, SPoint2> *parametricCoordinates)
1036 {
1037  std::set<MTri3 *, compareTri3Ptr> AllTris;
1038  bidimMeshData DATA(equivalence, parametricCoordinates);
1039 
1040  if(!buildMeshGenerationDataStructures(gf, AllTris, DATA)) {
1041  Msg::Error("Invalid meshing data structure");
1042  return;
1043  }
1044 
1045  if(AllTris.empty()) {
1046  Msg::Error("No triangles in initial mesh");
1047  return;
1048  }
1049 
1050  int ITER = 0;
1051  int NBDELETED = 0;
1052  while(1) {
1053  MTri3 *worst = *AllTris.begin();
1054  if(worst->isDeleted()) {
1055  delete worst->tri();
1056  delete worst;
1057  AllTris.erase(AllTris.begin());
1058  NBDELETED++;
1059  }
1060  else {
1061  if(ITER++ % 5000 == 0) {
1062  Msg::Debug("%7d points created -- Worst tri radius is %8.3f",
1063  DATA.vSizes.size(), worst->getRadius());
1064  }
1065  // VERIFY STOP !!!
1066  if(worst->getRadius() < 0.5 * std::sqrt(2.0) ||
1067  (int)DATA.vSizes.size() > MAXPNT) {
1068  break;
1069  }
1070 
1071  double center[2], metric[3], r2;
1072  circUV(worst->tri(), DATA, center, gf);
1073  MTriangle *base = worst->tri();
1074  int index0 = DATA.getIndex(base->getVertex(0));
1075  int index1 = DATA.getIndex(base->getVertex(1));
1076  int index2 = DATA.getIndex(base->getVertex(2));
1077  double pa[2] = {
1078  (DATA.Us[index0] + DATA.Us[index1] + DATA.Us[index2]) / 3.,
1079  (DATA.Vs[index0] + DATA.Vs[index1] + DATA.Vs[index2]) / 3.};
1080 
1081  buildMetric(gf, pa, metric);
1082  circumCenterMetric(worst->tri(), metric, DATA, center, r2);
1083  insertAPoint(gf, AllTris.begin(), center, metric, DATA, AllTris);
1084  }
1085  }
1087  transferDataStructure(gf, AllTris, DATA);
1088 }
1089 
1090 // Let's try a frontal delaunay approach now that the delaunay mesher is stable.
1091 // We use the approach of Rebay (JCP 1993) that we extend to anisotropic
1092 // metrics. The point isertion is done on the Voronoi Edges.
1093 
1094 static double lengthInfniteNorm(const double p[2], const double q[2],
1095  const double quadAngle)
1096 {
1097  double const xp = p[0] * std::cos(quadAngle) + p[1] * std::sin(quadAngle);
1098  double const yp = -p[0] * std::sin(quadAngle) + p[1] * std::cos(quadAngle);
1099  double const xq = q[0] * std::cos(quadAngle) + q[1] * std::sin(quadAngle);
1100  double const yq = -q[0] * std::sin(quadAngle) + q[1] * std::cos(quadAngle);
1101  double const xmax = std::max(xp, xq);
1102  double const xmin = std::min(xp, xq);
1103  double const ymax = std::max(yp, yq);
1104  double const ymin = std::min(yp, yq);
1105  return std::max(xmax - xmin, ymax - ymin);
1106 }
1107 
1108 static void circumCenterInfinite(MTriangle *base, double quadAngle,
1109  bidimMeshData &data, double *x)
1110 {
1111  int const index0 = data.getIndex(base->getVertex(0));
1112  int const index1 = data.getIndex(base->getVertex(1));
1113  int const index2 = data.getIndex(base->getVertex(2));
1114  double const pa[2] = {data.Us[index0], data.Vs[index0]};
1115  double const pb[2] = {data.Us[index1], data.Vs[index1]};
1116  double const pc[2] = {data.Us[index2], data.Vs[index2]};
1117  double const xa = pa[0] * std::cos(quadAngle) - pa[1] * std::sin(quadAngle);
1118  double const ya = pa[0] * std::sin(quadAngle) + pa[1] * std::cos(quadAngle);
1119  double const xb = pb[0] * std::cos(quadAngle) - pb[1] * std::sin(quadAngle);
1120  double const yb = pb[0] * std::sin(quadAngle) + pb[1] * std::cos(quadAngle);
1121  double const xc = pc[0] * std::cos(quadAngle) - pc[1] * std::sin(quadAngle);
1122  double const yc = pc[0] * std::sin(quadAngle) + pc[1] * std::cos(quadAngle);
1123  double const xmax = std::max(std::max(xa, xb), xc);
1124  double const ymax = std::max(std::max(ya, yb), yc);
1125  double const xmin = std::min(std::min(xa, xb), xc);
1126  double const ymin = std::min(std::min(ya, yb), yc);
1127  x[0] = 0.5 * (xmax - xmin);
1128  x[1] = 0.5 * (ymax - ymin);
1129 }
1130 
1131 static double lengthMetric(const double p[2], const double q[2],
1132  const double metric[3])
1133 {
1134  return std::sqrt((p[0] - q[0]) * metric[0] * (p[0] - q[0]) +
1135  2 * (p[0] - q[0]) * metric[1] * (p[1] - q[1]) +
1136  (p[1] - q[1]) * metric[2] * (p[1] - q[1]));
1137 }
1138 
1139 /*
1140  /|
1141  / |
1142  / |
1143  / |
1144  lc / | r
1145  / |
1146  / |
1147  / x
1148  / |
1149  / | r/2
1150 / |
1151 -----------+
1152  lc/2
1153 
1154  (3 r/2)^2 = lc^2 - lc^2/4
1155  -> lc^2 3/4 = 9r^2/4
1156  -> lc^2 = 3 r^2
1157 
1158  r^2 /4 + lc^2/4 = r^2
1159  -> lc^2 = 3 r^2
1160 
1161 */
1162 
1163 static double optimalPointFrontal(GFace *gf, MTri3 *worst, int active_edge,
1164  bidimMeshData &data, double newPoint[2],
1165  double metric[3])
1166 {
1167  double center[2], r2;
1168  MTriangle *base = worst->tri();
1169  circUV(base, data, center, gf);
1170  int index0 = data.getIndex(base->getVertex(0));
1171  int index1 = data.getIndex(base->getVertex(1));
1172  int index2 = data.getIndex(base->getVertex(2));
1173  double pa[2] = {(data.Us[index0] + data.Us[index1] + data.Us[index2]) / 3.,
1174  (data.Vs[index0] + data.Vs[index1] + data.Vs[index2]) / 3.};
1175  buildMetric(gf, pa, metric);
1176  circumCenterMetric(worst->tri(), metric, data, center, r2);
1177  // compute the middle point of the edge
1178  int ip1 = active_edge - 1 < 0 ? 2 : active_edge - 1;
1179  int ip2 = active_edge;
1180 
1181  index0 = data.getIndex(base->getVertex(ip1));
1182  index1 = data.getIndex(base->getVertex(ip2));
1183  double P[2] = {data.Us[index0], data.Vs[index0]};
1184  double Q[2] = {data.Us[index1], data.Vs[index1]};
1185  double midpoint[2] = {0.5 * (P[0] + Q[0]), 0.5 * (P[1] + Q[1])};
1186 
1187  // now we have the edge center and the center of the circumcircle, we try to
1188  // find a point that would produce a perfect triangle while connecting the 2
1189  // points of the active edge
1190  double dir[2] = {center[0] - midpoint[0], center[1] - midpoint[1]};
1191  double norm = std::sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
1192  dir[0] /= norm;
1193  dir[1] /= norm;
1194  const double RATIO =
1195  std::sqrt(dir[0] * dir[0] * metric[0] + 2 * dir[1] * dir[0] * metric[1] +
1196  dir[1] * dir[1] * metric[2]);
1197 
1198  const double rhoM1 =
1199  0.5 * (data.vSizes[index0] + data.vSizes[index1]); // * RATIO;
1200  const double rhoM2 =
1201  0.5 * (data.vSizesBGM[index0] + data.vSizesBGM[index1]); // * RATIO;
1202  const double rhoM =
1203  Extend1dMeshIn2dSurfaces(gf) ? std::min(rhoM1, rhoM2) : rhoM2;
1204  const double rhoM_hat = rhoM;
1205 
1206  const double q = lengthMetric(center, midpoint, metric);
1207  const double d = rhoM_hat * std::sqrt(3.0) * 0.5;
1208 
1209  // d is corrected in a way that the mesh size is computed at point newPoint
1210 
1211  const double L = std::min(d, q);
1212 
1213  newPoint[0] = midpoint[0] + L * dir[0] / RATIO;
1214  newPoint[1] = midpoint[1] + L * dir[1] / RATIO;
1215 
1216  return L;
1217 }
1218 
1219 /*
1220  x
1221  |
1222  |
1223  | d = 3^{1/2}/2 h
1224  |
1225  |
1226  ------p-------> n
1227  h
1228 
1229  x point of the plane
1230 
1231  h being some kind of average between the size field
1232  and the edge length
1233 */
1234 
1235 static bool optimalPointFrontalB(GFace *gf, MTri3 *worst, int active_edge,
1236  bidimMeshData &data, double newPoint[2],
1237  double metric[3])
1238 {
1239  // as a starting point, let us use the "fast algo"
1240  double d =
1241  optimalPointFrontal(gf, worst, active_edge, data, newPoint, metric);
1242  int ip1 = (active_edge + 2) % 3;
1243  int ip2 = active_edge;
1244  int ip3 = (active_edge + 1) % 3;
1245  MVertex *v1 = worst->tri()->getVertex(ip1);
1246  MVertex *v2 = worst->tri()->getVertex(ip2);
1247  MVertex *v3 = worst->tri()->getVertex(ip3);
1248  SVector3 middle((v1->x() + v2->x()) * .5, (v1->y() + v2->y()) * .5,
1249  (v1->z() + v2->z()) * .5);
1250  SVector3 v1v2(v2->x() - v1->x(), v2->y() - v1->y(), v2->z() - v1->z());
1251  SVector3 tmp(v3->x() - middle.x(), v3->y() - middle.y(),
1252  v3->z() - middle.z());
1253  SVector3 n1 = crossprod(v1v2, tmp);
1254  if(n1.norm() < 1.e-12) return true;
1255  SVector3 n2 = crossprod(n1, v1v2);
1256  n1.normalize();
1257  n2.normalize();
1258  // we look for a point that is
1259  // P = d * (n1 std::cos(t) + n2 std::sin(t)) that is on the surface
1260  // so we have to find t, starting with t = 0
1261  // return true;
1262 
1263 #if defined(HAVE_HXT)
1264  if(gf->geomType() == GEntity::DiscreteSurface) {
1265  discreteFace *ddf = dynamic_cast<discreteFace *>(gf);
1266  if(ddf) {
1267  GPoint gp = ddf->intersectionWithCircle(n1, n2, middle, d, newPoint);
1268  if(gp.succeeded()) return true;
1269  return false;
1270  }
1271  }
1272 #endif
1273 
1274  double uvt[3] = {newPoint[0], newPoint[1], 0.0};
1275  curveFunctorCircle cc(n2, n1, middle, d);
1276  surfaceFunctorGFace ss(gf);
1277 
1278  if(intersectCurveSurface(cc, ss, uvt, d * 1.e-8)) {
1279  // if(gf->containsParam(SPoint2(uvt[0], uvt[1]))) {
1280  newPoint[0] = uvt[0];
1281  newPoint[1] = uvt[1];
1282  return true;
1283  // }
1284  }
1285 
1286  return true;
1287 }
1288 
1289 void bowyerWatsonFrontal(GFace *gf, std::map<MVertex *, MVertex *> *equivalence,
1290  std::map<MVertex *, SPoint2> *parametricCoordinates,
1291  std::vector<SPoint2> *true_boundary)
1292 {
1293  std::set<MTri3 *, compareTri3Ptr> AllTris;
1294  std::set<MTri3 *, compareTri3Ptr> ActiveTris;
1295  bidimMeshData DATA(equivalence, parametricCoordinates);
1296  bool testStarShapeness = true;
1297  SPoint3 c;
1298  std::set<GEntity *> degenerated;
1300 
1301  if(!buildMeshGenerationDataStructures(gf, AllTris, DATA)) {
1302  Msg::Error("Invalid meshing data structure");
1303  return;
1304  }
1305 
1306  int ITER = 0, active_edge;
1307  // compute active triangle
1308  auto it = AllTris.begin();
1309  for(; it != AllTris.end(); ++it) {
1310  if(isActive(*it, LIMIT_, active_edge))
1311  ActiveTris.insert(*it);
1312  else if((*it)->getRadius() < LIMIT_)
1313  break;
1314  }
1315 
1316  Range<double> RU = gf->parBounds(0);
1317  Range<double> RV = gf->parBounds(1);
1318  SPoint2 FAR(2 * RU.high(), 2 * RV.high());
1319 
1320 
1321  // insert points
1322  int ITERATION = 0;
1323  while(1) {
1324  ++ITERATION;
1325  // if(ITERATION % 1 == 0 && Msg::GetVerbosity() == 99){
1326  // char name[245];
1327  // sprintf(name,"delFrontal_GFace_%d_Layer_%d.pos",gf->tag(),ITERATION);
1328  // _printTris (name, AllTris.begin(), AllTris.end(), &DATA);
1329  // sprintf(name,"delFrontal_GFace_%d_Layer_Real%d.pos",gf->tag(),ITERATION);
1330  // _printTris (name, AllTris.begin(), AllTris.end(),NULL);
1331  // sprintf(name,"delFrontal_GFace_%d_Layer_%d_Active.pos",gf->tag(),ITERATION);
1332  // _printTris (name, ActiveTris.begin(), ActiveTris.end(), &DATA);
1333  // }
1334 
1335  // printf("%d active tris \n",ActiveTris.size());
1336  if(!ActiveTris.size()) break;
1337  MTri3 *worst = (*ActiveTris.begin());
1338  ActiveTris.erase(ActiveTris.begin());
1339 
1340  if(!worst->isDeleted() && isActive(worst, LIMIT_, active_edge) &&
1341  worst->getRadius() > LIMIT_) {
1342  if(ITER++ % 5000 == 0)
1343  Msg::Debug("%7d points created -- Worst tri radius is %8.3f",
1344  gf->mesh_vertices.size(), worst->getRadius());
1345  double newPoint[2], metric[3];
1346  if(optimalPointFrontalB(gf, worst, active_edge, DATA, newPoint, metric)) {
1347  SPoint2 NP(newPoint[0], newPoint[1]);
1348  int nnnn;
1349  if(!true_boundary ||
1350  pointInsideParametricDomain(*true_boundary, NP, FAR, nnnn))
1351  insertAPoint(gf, AllTris.end(), newPoint, metric, DATA, AllTris,
1352  &ActiveTris, worst, nullptr, testStarShapeness);
1353  }
1354  }
1355  }
1356 
1357  // char name[245];
1358  // sprintf(name,"delFrontal_GFace_%d_Layer_%d_Active.pos",gf->tag(),ITERATION);
1359  // _printTris (name, AllTris.begin(), AllTris.end(), &DATA);
1360  transferDataStructure(gf, AllTris, DATA);
1361 
1363 
1364 }
1365 
1366 static void optimalPointFrontalQuad(GFace *gf, MTri3 *worst, int active_edge,
1367  bidimMeshData &data, double newPoint[2],
1368  double metric[3])
1369 {
1370  MTriangle *base = worst->tri();
1371  int ip1 = active_edge - 1 < 0 ? 2 : active_edge - 1;
1372  int ip2 = active_edge;
1373  int ip3 = (active_edge + 1) % 3;
1374 
1375  int index1 = data.getIndex(base->getVertex(ip1));
1376  int index2 = data.getIndex(base->getVertex(ip2));
1377  int index3 = data.getIndex(base->getVertex(ip3));
1378 
1379  double P[2] = {data.Us[index1], data.Vs[index1]};
1380  double Q[2] = {data.Us[index2], data.Vs[index2]};
1381  double O[2] = {data.Us[index3], data.Vs[index3]};
1382  double midpoint[2] = {0.5 * (P[0] + Q[0]), 0.5 * (P[1] + Q[1])};
1383 
1384  // compute background mesh data
1385  double quadAngle =
1386  backgroundMesh::current()->getAngle(midpoint[0], midpoint[1], 0);
1387  double center[2];
1388  circumCenterInfinite(base, quadAngle, data, center);
1389 
1390  // rotate the points with respect to the angle
1391  double XP1 = 0.5 * (Q[0] - P[0]);
1392  double YP1 = 0.5 * (Q[1] - P[1]);
1393  double xp = XP1 * std::cos(quadAngle) + YP1 * std::sin(quadAngle);
1394  double yp = -XP1 * std::sin(quadAngle) + YP1 * std::cos(quadAngle);
1395  // ensure xp > yp
1396  bool exchange = false;
1397  if(std::abs(xp) < std::abs(yp)) {
1398  double temp = xp;
1399  xp = yp;
1400  yp = temp;
1401  exchange = true;
1402  }
1403 
1404  buildMetric(gf, midpoint, metric);
1405  double RATIO = std::pow(metric[0] * metric[2] - metric[1] * metric[1], -0.25);
1406 
1407  const double p = 0.5 * lengthInfniteNorm(P, Q, quadAngle);
1408  const double q = lengthInfniteNorm(center, midpoint, quadAngle);
1409 
1410  const double rhoM1 =
1411  0.5 * RATIO * (data.vSizes[index1] + data.vSizes[index2]) / std::sqrt(3.0);
1412  const double rhoM2 = 0.5 * RATIO *
1413  (data.vSizesBGM[index1] + data.vSizesBGM[index2]) /
1414  std::sqrt(3.);
1415  const double rhoM =
1416  Extend1dMeshIn2dSurfaces(gf) ? std::min(rhoM1, rhoM2) : rhoM2;
1417 
1418  const double rhoM_hat =
1419  std::min(std::max(rhoM, p), (p * p + q * q) / (2 * q));
1420  const double factor =
1421  (rhoM_hat + std::sqrt(rhoM_hat * rhoM_hat - p * p)) / (std::sqrt(3.) * p);
1422 
1423  double npx, npy;
1424  if(xp * yp > 0) {
1425  npx = -std::abs(xp) * factor;
1426  npy = std::abs(xp) * (1. + factor) - std::abs(yp);
1427  }
1428  else {
1429  npx = std::abs(xp) * factor;
1430  npy = (1. + factor) * std::abs(xp) - std::abs(yp);
1431  }
1432  if(exchange) {
1433  double temp = npx;
1434  npx = npy;
1435  npy = temp;
1436  }
1437 
1438  newPoint[0] =
1439  midpoint[0] + std::cos(quadAngle) * npx - std::sin(quadAngle) * npy;
1440  newPoint[1] =
1441  midpoint[1] + std::sin(quadAngle) * npx + std::cos(quadAngle) * npy;
1442 
1443  if((midpoint[0] - newPoint[0]) * (midpoint[0] - O[0]) +
1444  (midpoint[1] - newPoint[1]) * (midpoint[1] - O[1]) <
1445  0) {
1446  newPoint[0] =
1447  midpoint[0] - std::cos(quadAngle) * npx + std::sin(quadAngle) * npy;
1448  newPoint[1] =
1449  midpoint[1] - std::sin(quadAngle) * npx - std::cos(quadAngle) * npy;
1450  }
1451 }
1452 
1453 void buildBackgroundMesh(GFace *gf, bool crossFieldClosestPoint,
1454  std::map<MVertex *, MVertex *> *equivalence,
1455  std::map<MVertex *, SPoint2> *parametricCoordinates)
1456 {
1457 #if defined(HAVE_DOMHEX)
1458  if(!old_algo_hexa()) return;
1459 #endif
1460  Msg::Debug("build background mesh (Bowyer Watson, fixed size) ...");
1461 
1462  quadsToTriangles(gf, 100000);
1463 
1464  if(!backgroundMesh::current()) {
1465  std::vector<MTriangle *> TR;
1466  for(std::size_t i = 0; i < gf->triangles.size(); i++) {
1467  TR.push_back(new MTriangle(gf->triangles[i]->getVertex(0),
1468  gf->triangles[i]->getVertex(1),
1469  gf->triangles[i]->getVertex(2)));
1470  }
1471  // avoid computing curvatures on the fly : only on the BGM computes once
1472  // curvatures at each node
1473 
1474  // disable curvature control
1475  int CurvControl = CTX::instance()->mesh.lcFromCurvature;
1477  // do a background mesh
1478  bowyerWatson(gf, 40000, equivalence, parametricCoordinates);
1479  // re-enable curv control if asked
1480  CTX::instance()->mesh.lcFromCurvature = CurvControl;
1481  // apply this to the BGM
1482  if(crossFieldClosestPoint)
1483  backgroundMesh::setCrossFieldsByDistance(gf); // faster for delquad
1484  else
1485  backgroundMesh::set(gf); // will solve PDE
1486  if(Msg::GetVerbosity() == 99) {
1487  char name[256];
1488  sprintf(name, "bgm-%d.pos", gf->tag());
1489  backgroundMesh::current()->print(name, gf);
1490  sprintf(name, "cross-%d.pos", gf->tag());
1491  backgroundMesh::current()->print(name, gf, 1);
1492  }
1493  gf->triangles = TR;
1494  }
1495 }
1496 
1498  GFace *gf, bool quad, std::map<MVertex *, MVertex *> *equivalence,
1499  std::map<MVertex *, SPoint2> *parametricCoordinates)
1500 {
1501  std::set<MTri3 *, compareTri3Ptr> AllTris;
1502  std::set<MTri3 *, compareTri3Ptr> ActiveTris;
1503  bidimMeshData DATA(equivalence, parametricCoordinates);
1504 
1505  if(quad) {
1506  LIMIT_ = std::sqrt(2.0) * 0.99;
1507  // LIMIT_ = 4./3.;//std::sqrt(2.) * .99;
1508  MTri3::radiusNorm = -1;
1509  }
1510 
1511  if(!buildMeshGenerationDataStructures(gf, AllTris, DATA)) {
1512  Msg::Error("Invalid meshing data structure");
1513  return;
1514  }
1515 
1516  int ITER = 0, active_edge;
1517  // compute active triangle
1518  auto it = AllTris.begin();
1519  std::set<MEdge, MEdgeLessThan> _front;
1520  for(; it != AllTris.end(); ++it) {
1521  if(isActive(*it, LIMIT_, active_edge)) {
1522  ActiveTris.insert(*it);
1523  updateActiveEdges(*it, LIMIT_, _front);
1524  }
1525  else if((*it)->getRadius() < LIMIT_)
1526  break;
1527  }
1528 
1529  // insert points
1530  int ITERATION = 1;
1531  int max_layers = quad ? 10000 : 4;
1532  while(1) {
1533  ITERATION++;
1534  // if(ITERATION % 1 == 0 && Msg::GetVerbosity() == 99){
1535  // char name[245];
1536  // sprintf(name,"delInfinite_GFace_%d_Layer_%d.pos",gf->tag(),ITERATION);
1537  // _printTris (name, AllTris.begin(), AllTris.end(), DATA,true);
1538  // sprintf(name,"delInfinite_GFace_%d_Layer_%d_Active.pos",gf->tag(),ITERATION);
1539  // _printTris (name, ActiveTris.begin(), ActiveTris.end(),DATA,true);
1540  // }
1541 
1542  std::set<MTri3 *, compareTri3Ptr> ActiveTrisNotInFront;
1543 
1544  // printf("%d active triangles\n",ActiveTris.size());
1545 
1546  while(1) {
1547  if(!ActiveTris.size()) break;
1548 
1549  /* if (1 || gf->tag() == 1900){
1550  char name[245];
1551  sprintf(name,"x_GFace_%d_Layer_%d.pos",gf->tag(),ITER);
1552  _printTris (name, AllTris, Us,Vs,true);
1553  }
1554  */
1555  auto WORST_ITER = ActiveTris.begin();
1556 
1557  MTri3 *worst = (*WORST_ITER);
1558  ActiveTris.erase(WORST_ITER);
1559  if(!worst->isDeleted() &&
1560  (ITERATION > max_layers ?
1561  isActive(worst, LIMIT_, active_edge) :
1562  isActive(worst, LIMIT_, active_edge, &_front)) &&
1563  worst->getRadius() > LIMIT_) {
1564  // for (active_edge = 0 ; active_edge < 0 ; active_edge ++){
1565  // if (active_edges[active_edge])break;
1566  // }
1567  if(ITER++ % 5000 == 0)
1568  Msg::Debug(
1569  "%7d points created -- Worst tri infinite radius is %8.3f -- "
1570  "front size %6d",
1571  DATA.vSizes.size(), worst->getRadius(), _front.size());
1572 
1573  // compute the middle point of the edge
1574  double newPoint[2], metric[3] = {1, 0, 1};
1575  if(quad)
1576  optimalPointFrontalQuad(gf, worst, active_edge, DATA, newPoint,
1577  metric);
1578  else
1579  optimalPointFrontalB(gf, worst, active_edge, DATA, newPoint, metric);
1580 
1581  insertAPoint(gf, AllTris.end(), newPoint, nullptr, DATA, AllTris,
1582  &ActiveTris, worst);
1583  // else if (!worst->isDeleted() && worst->getRadius() > LIMIT_){
1584  // ActiveTrisNotInFront.insert(worst);
1585  // }
1586 
1587  /*
1588  if(ITER % 1== 0){
1589  char name[245];
1590  sprintf(name,"frontal%d-ITER%d.pos",gf->tag(),ITER);
1591  _printTris (name, AllTris, Us,Vs,false);
1592  }
1593  */
1594  }
1595  else if(!worst->isDeleted() && worst->getRadius() > LIMIT_) {
1596  ActiveTrisNotInFront.insert(worst);
1597  }
1598  }
1599  _front.clear();
1600  it = ActiveTrisNotInFront.begin();
1601  for(; it != ActiveTrisNotInFront.end(); ++it) {
1602  if((*it)->getRadius() > LIMIT_ && isActive(*it, LIMIT_, active_edge)) {
1603  ActiveTris.insert(*it);
1604  updateActiveEdges(*it, LIMIT_, _front);
1605  }
1606  }
1607  // Msg::Info("%d active tris %d front edges %d not in front",
1608  // ActiveTris.size(),_front.size(),ActiveTrisNotInFront.size());
1609  if(!ActiveTris.size()) break;
1610  }
1611 
1612  transferDataStructure(gf, AllTris, DATA);
1613  MTri3::radiusNorm = 2;
1614  LIMIT_ = 0.5 * std::sqrt(2.0) * 1;
1615 
1617 
1619 }
1620 
1622  GFace *gf, std::map<MVertex *, MVertex *> *equivalence,
1623  std::map<MVertex *, SPoint2> *parametricCoordinates)
1624 {
1625  std::set<MTri3 *, compareTri3Ptr> AllTris;
1626  bidimMeshData DATA(equivalence, parametricCoordinates);
1627  std::vector<MVertex *> packed;
1628  std::vector<SMetric3> metrics;
1629 
1630  Msg::Debug("- Face %i: bowyerWatsonParallelograms ...", gf->tag());
1631  if(!gf->haveParametrization()) {
1632  Msg::Error(
1633  "- Face %i: no CAD parametrization available, cannot mesh with algo PACK",
1634  gf->tag());
1635  return;
1636  }
1637 
1638 #if defined(HAVE_DOMHEX)
1639  if(old_algo_hexa()) {
1640  Msg::Debug("bowyerWatsonParallelograms: call packingOfParallelograms()");
1641  packingOfParallelograms(gf, packed, metrics);
1642  }
1643  else {
1644  Msg::Debug("bowyerWatsonParallelograms: call Filler2D::pointInsertion2D()");
1645  Filler2D f;
1646  f.pointInsertion2D(gf, packed, metrics);
1647  }
1648 #else
1649  Msg::Error("Packing of parallelograms algorithm requires DOMHEX");
1650 #endif
1651 
1652  Msg::Info("%lu Nodes created --> now staring insertion", packed.size());
1653 
1654  if(!buildMeshGenerationDataStructures(gf, AllTris, DATA)) {
1655  Msg::Error("Invalid meshing data structure");
1656  return;
1657  }
1658 
1659  // std::sort(packed.begin(), packed.end(), MVertexPtrLessThanLexicographic());
1660  SortHilbert(packed);
1661  Msg::Debug("bowyerWatsonParallelograms: %li candidate points to insert in "
1662  "the triangulation",
1663  packed.size());
1664 
1665  MTri3 *oneNewTriangle = nullptr;
1666  for(std::size_t i = 0; i < packed.size();) {
1667  MTri3 *worst = *AllTris.begin();
1668  if(worst->isDeleted()) {
1669  delete worst->tri();
1670  delete worst;
1671  AllTris.erase(AllTris.begin());
1672  }
1673  else {
1674  double newPoint[2];
1675  packed[i]->getParameter(0, newPoint[0]);
1676  packed[i]->getParameter(1, newPoint[1]);
1677  delete packed[i];
1678  double metric[3];
1679  buildMetric(gf, newPoint, metric);
1680 
1681  bool success =
1682  insertAPoint(gf, AllTris.begin(), newPoint, metric, DATA, AllTris,
1683  nullptr, oneNewTriangle, &oneNewTriangle);
1684  if(!success) oneNewTriangle = nullptr;
1685  i++;
1686  }
1687 
1688  if(1.0 * AllTris.size() > 2.5 * DATA.vSizes.size()) {
1689  auto itd = AllTris.begin();
1690  while(itd != AllTris.end()) {
1691  if((*itd)->isDeleted()) {
1692  delete *itd;
1693  AllTris.erase(itd++);
1694  }
1695  else
1696  itd++;
1697  }
1698  }
1699  }
1700 
1701  transferDataStructure(gf, AllTris, DATA);
1703 
1704  Msg::Debug(
1705  "bowyerWatsonParallelograms: %li candidate points -> %li inserted vertices",
1706  packed.size(), gf->mesh_vertices.size());
1707 
1709 }
1710 
1712  GFace *gf, const std::set<MVertex *> &constr_vertices,
1713  std::map<MVertex *, MVertex *> *equivalence,
1714  std::map<MVertex *, SPoint2> *parametricCoordinates)
1715 {
1716  Msg::Error("bowyerWatsonParallelogramsConstrained deprecated");
1717  return;
1718 
1719  std::set<MTri3 *, compareTri3Ptr> AllTris;
1720  bidimMeshData DATA(equivalence, parametricCoordinates);
1721  std::vector<MVertex *> packed;
1722  std::vector<SMetric3> metrics;
1723 
1724 #if defined(HAVE_DOMHEX)
1725  // packingOfParallelogramsConstrained no longer exists
1726  // packingOfParallelogramsConstrained(gf, constr_vertices, packed, metrics);
1727 #else
1728  Msg::Error("Packing of parallelograms algorithm requires DOMHEX");
1729 #endif
1730 
1731  if(!buildMeshGenerationDataStructures(gf, AllTris, DATA)) {
1732  Msg::Error("Invalid meshing data structure");
1733  return;
1734  }
1735 
1736  std::sort(packed.begin(), packed.end(), MVertexPtrLessThanLexicographic());
1737 
1738  MTri3 *oneNewTriangle = nullptr;
1739  for(std::size_t i = 0; i < packed.size();) {
1740  MTri3 *worst = *AllTris.begin();
1741  if(worst->isDeleted()) {
1742  delete worst->tri();
1743  delete worst;
1744  AllTris.erase(AllTris.begin());
1745  }
1746  else {
1747  double newPoint[2];
1748  packed[i]->getParameter(0, newPoint[0]);
1749  packed[i]->getParameter(1, newPoint[1]);
1750  delete packed[i];
1751  double metric[3];
1752  buildMetric(gf, newPoint, metric);
1753 
1754  bool success =
1755  insertAPoint(gf, AllTris.begin(), newPoint, metric, DATA, AllTris,
1756  nullptr, oneNewTriangle, &oneNewTriangle);
1757  if(!success) oneNewTriangle = nullptr;
1758  i++;
1759  }
1760 
1761  if(1.0 * AllTris.size() > 2.5 * DATA.vSizes.size()) {
1762  auto itd = AllTris.begin();
1763  while(itd != AllTris.end()) {
1764  if((*itd)->isDeleted()) {
1765  delete *itd;
1766  AllTris.erase(itd++);
1767  }
1768  else
1769  itd++;
1770  }
1771  }
1772  }
1773 
1774  transferDataStructure(gf, AllTris, DATA);
1775  for(std::size_t i = 0; i < gf->getNumMeshVertices(); i++) {
1776  MVertex *vtest = gf->getMeshVertex(i);
1777  double para0, para1;
1778  vtest->getParameter(0, para0);
1779  vtest->getParameter(1, para1);
1780  }
1782 
1784 }
1785 
1786 static void initialSquare(std::vector<MVertex *> &v, MVertex *box[4],
1787  std::vector<MTri3 *> &t)
1788 {
1789  SBoundingBox3d bbox;
1790  for(std::size_t i = 0; i < v.size(); i++) {
1791  MVertex *pv = v[i];
1792  bbox += SPoint3(pv->x(), pv->y(), pv->z());
1793  }
1794  bbox *= 1.3;
1795  box[0] = new MVertex(bbox.min().x(), bbox.min().y(), 0);
1796  box[1] = new MVertex(bbox.max().x(), bbox.min().y(), 0);
1797  box[2] = new MVertex(bbox.max().x(), bbox.max().y(), 0);
1798  box[3] = new MVertex(bbox.min().x(), bbox.max().y(), 0);
1799  MTriangle *t0 = new MTriangle(box[0], box[1], box[2]);
1800  MTriangle *t1 = new MTriangle(box[2], box[3], box[0]);
1801  t.push_back(new MTri3(t0, 0.0));
1802  t.push_back(new MTri3(t1, 0.0));
1803  connectTriangles(t);
1804 }
1805 
1806 static MTri3 *getTriToBreak(MVertex *v, std::vector<MTri3 *> &t, int &ITER)
1807 {
1808  // last inserted is used as starting point we know it is not deleted
1809  std::size_t k = t.size() - 1;
1810  while(t[k]->isDeleted()) { k--; }
1811  MTri3 *start = t[k];
1812  start = search4Triangle(start, v, (int)t.size(), ITER);
1813  if(start) return start;
1814  for(size_t i = 0; i < t.size(); i++) {
1815  if(!t[i]->isDeleted() && inCircumCircleXY(t[i]->tri(), v)) return t[i];
1816  }
1817  return nullptr;
1818 }
1819 
1820 static bool triOnBox(MTriangle *t, MVertex *box[4])
1821 {
1822  for(size_t i = 0; i < 3; i++) {
1823  for(size_t j = 0; j < 4; j++) {
1824  if(t->getVertex(i) == box[j]) return true;
1825  }
1826  }
1827  return false;
1828 }
1829 
1830 // vertices are supposed to be sitting in the XY plane !
1831 
1832 void recoverEdges(std::vector<MTri3 *> &t, std::vector<MEdge> &edges);
1833 
1834 void delaunayMeshIn2D(std::vector<MVertex *> &v,
1835  std::vector<MTriangle *> &result, bool removeBox,
1836  std::vector<MEdge> *edgesToRecover, bool hilbertSort)
1837 {
1838  std::vector<MTri3 *> t;
1839  t.reserve(v.size() * 2);
1840  std::vector<edgeXface> conn;
1841  std::vector<edgeXface> shell;
1842  std::vector<MTri3 *> cavity;
1843  MVertex *box[4];
1844  initialSquare(v, box, t);
1845 
1846  if(hilbertSort) SortHilbert(v);
1847 
1848  for(size_t i = 0; i < v.size(); i++) {
1849  MVertex *pv = v[i];
1850 
1851  int NITER = 0;
1852  MTri3 *found = getTriToBreak(pv, t, NITER);
1853  if(!found) {
1854  Msg::Error("Cannot insert a point in 2D Delaunay");
1855  continue;
1856  }
1857  shell.clear();
1858  cavity.clear();
1859 
1860  recurFindCavity(shell, cavity, pv, found);
1861 
1862  std::vector<MTri3 *> extended_cavity;
1863  for(std::size_t count = 0; count < shell.size(); count++) {
1864  const edgeXface &fxt = shell[count];
1865  MTriangle *tr;
1866  MTri3 *t3;
1867  MVertex *v0 = fxt._v(0);
1868  MVertex *v1 = fxt._v(1);
1869  MTri3 *otherSide = fxt.t1->getNeigh(fxt.i1);
1870  if(count < cavity.size()) {
1871  t3 = cavity[count];
1872  tr = t3->tri();
1873  tr->setVertex(0, v0);
1874  tr->setVertex(1, v1);
1875  tr->setVertex(2, pv);
1876  }
1877  else {
1878  tr = new MTriangle(v0, v1, pv);
1879  t3 = new MTri3(tr, 0.0);
1880  t.push_back(t3);
1881  }
1882  extended_cavity.push_back(t3);
1883  if(otherSide) extended_cavity.push_back(otherSide);
1884  }
1885 
1886  for(std::size_t k = 0; k < std::min(cavity.size(), shell.size()); k++) {
1887  cavity[k]->setDeleted(false);
1888  for(std::size_t l = 0; l < 3; l++) { cavity[k]->setNeigh(l, nullptr); }
1889  }
1890  connectTris(extended_cavity.begin(), extended_cavity.end(), conn);
1891  }
1892 
1893  if(edgesToRecover) recoverEdges(t, *edgesToRecover);
1894 
1895  for(size_t i = 0; i < t.size(); i++) {
1896  if(t[i]->isDeleted() || (removeBox && triOnBox(t[i]->tri(), box)))
1897  delete t[i]->tri();
1898  else {
1899  result.push_back(t[i]->tri());
1900  }
1901  delete t[i];
1902  }
1903 
1904  if(removeBox) {
1905  for(int i = 0; i < 4; i++) delete box[i];
1906  }
1907  else {
1908  for(int i = 0; i < 4; i++) v.push_back(box[i]);
1909  }
1910 }
1911 
1912 bool swapedge(MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, MTri3 *t1,
1913  int iLocalEdge)
1914 {
1915  MTri3 *t2 = t1->getNeigh(iLocalEdge);
1916  if(!t2) return false;
1917 
1918  MTriangle *t1b = new MTriangle(v2, v3, v4);
1919  MTriangle *t2b = new MTriangle(v4, v3, v1);
1920  double BEFORE = t1->tri()->getVolume() + t2->tri()->getVolume();
1921  double AFTER = t1b->getVolume() + t2b->getVolume();
1922  // printf("swapping %d %d %d %d %g %g\n",
1923  // v1->getNum(),v2->getNum(),v3->getNum(),v4->getNum(),BEFORE,AFTER);
1924  if(std::abs(BEFORE - AFTER) / BEFORE > 1.e-8) {
1925  delete t1b;
1926  delete t2b;
1927  return false;
1928  }
1929 
1930  delete t1->tri();
1931  delete t2->tri();
1932  t1->setTri(t1b);
1933  t2->setTri(t2b);
1934 
1935  std::set<MTri3 *> cavity;
1936  cavity.insert(t1);
1937  cavity.insert(t2);
1938  for(int i = 0; i < 3; i++) {
1939  if(t1->getNeigh(i)) cavity.insert(t1->getNeigh(i));
1940  if(t2->getNeigh(i)) cavity.insert(t2->getNeigh(i));
1941  }
1942  std::vector<edgeXface> conn;
1943  connectTris(cavity.begin(), cavity.end(), conn);
1944  return true;
1945 }
1946 
1947 bool diffend(MVertex *v1, MVertex *v2, MVertex *p1, MVertex *p2)
1948 {
1949  if(v1 == p1 || v2 == p1 || v1 == p2 || v2 == p2) return false;
1950  return true;
1951 }
1952 
1953 static bool recoverEdgeBySwaps(std::vector<MTri3 *> &t, MVertex *mv1,
1954  MVertex *mv2, std::vector<MEdge> &edges)
1955 {
1956  SPoint3 pv1(mv1->x(), mv1->y(), 0);
1957  SPoint3 pv2(mv2->x(), mv2->y(), 0);
1958  double xcc[2];
1959  for(std::size_t i = 0; i < t.size(); i++) {
1960  for(std::size_t j = 0; j < 3; j++) {
1961  MVertex *v1 = t[i]->tri()->getVertex((j + 2) % 3);
1962  MVertex *v2 = t[i]->tri()->getVertex(j);
1963  MVertex *v3 = t[i]->tri()->getVertex((j + 1) % 3);
1964  MVertex *o = t[i]->otherSide(j);
1965  if(o) {
1966  SPoint3 p1(v1->x(), v1->y(), 0);
1967  SPoint3 p2(v2->x(), v2->y(), 0);
1968  SPoint3 p3(v3->x(), v3->y(), 0);
1969  SPoint3 po(o->x(), o->y(), 0);
1970  if(diffend(v1, v2, mv1, mv2)) {
1971  if(intersection_segments(p1, p2, pv1, pv2, xcc)) {
1972  // if
1973  // (std::binary_search(edges.begin(),edges.end(),MEdge(v1,v2),MEdgeLessThan)){
1974  // Msg::Error("1D mesh self intersects");
1975  // }
1976  if(!intersection_segments(po, p3, pv1, pv2, xcc) ||
1977  (v3 == mv1 || o == mv1 || v3 == mv2 || o == mv2)) {
1978  if(swapedge(v1, v2, v3, o, t[i], j)) return true;
1979  }
1980  }
1981  }
1982  }
1983  }
1984  }
1985  return false;
1986 }
1987 
1988 // recover the edges by edge swapping in the triangulation.
1989 // edges are not supposed to
1990 
1991 void recoverEdges(std::vector<MTri3 *> &t, std::vector<MEdge> &edges)
1992 {
1993  MEdgeLessThan le;
1994  std::sort(edges.begin(), edges.end(), le);
1995  std::set<MEdge, MEdgeLessThan> setOfMeshEdges;
1996  for(size_t i = 0; i < t.size(); i++) {
1997  for(int j = 0; j < 3; j++) {
1998  setOfMeshEdges.insert(t[i]->tri()->getEdge(j));
1999  }
2000  }
2001 
2002  std::vector<MEdge> edgesToRecover;
2003  for(std::size_t i = 0; i < edges.size(); i++) {
2004  if(setOfMeshEdges.find(edges[i]) == setOfMeshEdges.end())
2005  edgesToRecover.push_back(edges[i]);
2006  }
2007 
2008  Msg::Info("%d edges to recover among %d edges", edgesToRecover.size(),
2009  edges.size());
2010  // int iter = 0;
2011  // char name[256];
2012  // sprintf(name,"iter%d.pos",iter++);
2013  // _printTris (name, t.begin(),t.end(),0);
2014  for(std::size_t i = 0; i < edgesToRecover.size(); i++) {
2015  MVertex *mstart = edgesToRecover[i].getVertex(0);
2016  MVertex *mend = edgesToRecover[i].getVertex(1);
2017  Msg::Info("recovering edge %d %d", mstart->getNum(), mend->getNum());
2018  // int iter;
2019  while(recoverEdgeBySwaps(t, mstart, mend, edges)) {
2020  // iter ++;
2021  }
2022  }
2023 }
edgeXface::i1
int i1
Definition: meshGFaceDelaunayInsertion.h:180
parametricCoordinates
static void parametricCoordinates(MElement *t, GFace *gf, double u[4], double v[4], MVertex *close=nullptr)
Definition: meshGFaceOptimize.cpp:472
isActive
static bool isActive(MTri3 *t, double limit_, int &active)
Definition: meshGFaceDelaunayInsertion.cpp:199
crossprod
SVector3 crossprod(const SVector3 &a, const SVector3 &b)
Definition: SVector3.h:150
GPoint::succeeded
bool succeeded() const
Definition: GPoint.h:63
triangle
Definition: shapeFunctions.h:414
GFace::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GFace.h:121
GFace::firstDer
virtual Pair< SVector3, SVector3 > firstDer(const SPoint2 &param) const =0
MEdge
Definition: MEdge.h:14
updateActiveEdges
static void updateActiveEdges(MTri3 *t, double limit_, std::set< MEdge, MEdgeLessThan > &front)
Definition: meshGFaceDelaunayInsertion.cpp:231
dot
double dot(const SVector3 &a, const SMetric3 &m, const SVector3 &b)
Definition: STensor3.h:71
circumCenterMetricXYZ
static void circumCenterMetricXYZ(double *p1, double *p2, double *p3, SMetric3 &metric, double *res, double *uv, double &radius)
Definition: meshGFaceDelaunayInsertion.cpp:278
splitElementsInBoundaryLayerIfNeeded
void splitElementsInBoundaryLayerIfNeeded(GFace *gf)
Definition: meshGFaceOptimize.cpp:1457
SMetric3
Definition: STensor3.h:17
backgroundMesh::print
void print(const std::string &filename, GFace *gf, const std::map< MVertex *, double > &, int smooth=0)
Definition: BackgroundMesh.cpp:672
Msg::GetVerbosity
static int GetVerbosity()
Definition: GmshMessage.cpp:254
contextMeshOptions::lcFromCurvature
int lcFromCurvature
Definition: Context.h:27
GPoint::y
double y() const
Definition: GPoint.h:22
GFace.h
SortHilbert
static void SortHilbert(std::vector< Vert * > &v, std::vector< int > &indices)
Definition: delaunay3d.cpp:592
circumCenterXY
void circumCenterXY(double *p1, double *p2, double *p3, double *res)
Definition: Numeric.cpp:317
distance
double distance(MVertex *v1, MVertex *v2)
Definition: MVertex.h:245
bowyerWatsonParallelograms
void bowyerWatsonParallelograms(GFace *gf, std::map< MVertex *, MVertex * > *equivalence, std::map< MVertex *, SPoint2 > *parametricCoordinates)
Definition: meshGFaceDelaunayInsertion.cpp:1621
MTri3::tri
MTriangle * tri() const
Definition: meshGFaceDelaunayInsertion.h:105
GEntity::getMeshVertex
MVertex * getMeshVertex(std::size_t index)
Definition: GEntity.h:379
bowyerWatsonFrontalLayers
void bowyerWatsonFrontalLayers(GFace *gf, bool quad, std::map< MVertex *, MVertex * > *equivalence, std::map< MVertex *, SPoint2 > *parametricCoordinates)
Definition: meshGFaceDelaunayInsertion.cpp:1497
GFace
Definition: GFace.h:33
GFace::triangles
std::vector< MTriangle * > triangles
Definition: GFace.h:428
MTri3::neigh
MTri3 * neigh[3]
Definition: meshGFaceDelaunayInsertion.h:83
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
SPoint2
Definition: SPoint2.h:12
MTri3::base
MTriangle * base
Definition: meshGFaceDelaunayInsertion.h:82
quadsToTriangles
void quadsToTriangles(GFace *gf, double minqual)
Definition: meshGFaceOptimize.cpp:1374
OS.h
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
robustPredicates.h
c
static double c(int i, int j, fullMatrix< double > &CA, const std::vector< SPoint3 > &P, const std::vector< SPoint3 > &Q)
Definition: discreteFrechetDistance.cpp:15
MVertex
Definition: MVertex.h:24
MTriangle::gammaShapeMeasure
virtual double gammaShapeMeasure()
Definition: MTriangle.cpp:115
bidimMeshData
Definition: meshGFaceDelaunayInsertion.h:23
optimalPointFrontal
static double optimalPointFrontal(GFace *gf, MTri3 *worst, int active_edge, bidimMeshData &data, double newPoint[2], double metric[3])
Definition: meshGFaceDelaunayInsertion.cpp:1163
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
search4Triangle
static MTri3 * search4Triangle(MTri3 *t, MVertex *v, int maxx, int &ITER)
Definition: meshGFaceDelaunayInsertion.cpp:847
triOnBox
static bool triOnBox(MTriangle *t, MVertex *box[4])
Definition: meshGFaceDelaunayInsertion.cpp:1820
MVertex::z
double z() const
Definition: MVertex.h:62
BackgroundMesh.h
bidimMeshData::addVertex
void addVertex(MVertex *mv, double u, double v, double size, double sizeBGM)
Definition: meshGFaceDelaunayInsertion.h:31
box
Definition: gl2gif.cpp:311
GEntity::Unknown
@ Unknown
Definition: GEntity.h:89
SPoint3
Definition: SPoint3.h:14
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
recoverEdges
void recoverEdges(std::vector< MTri3 * > &t, std::vector< MEdge > &edges)
Definition: meshGFaceDelaunayInsertion.cpp:1991
MVertex::getNum
std::size_t getNum() const
Definition: MVertex.h:86
circumCenterMetric
static void circumCenterMetric(double *pa, double *pb, double *pc, const double *metric, double *x, double &Radius2)
Definition: meshGFaceDelaunayInsertion.cpp:246
SBoundingBox3d::min
SPoint3 min() const
Definition: SBoundingBox3d.h:90
Range::high
T high() const
Definition: Range.h:20
GFace::point
virtual GPoint point(double par1, double par2) const =0
SVector3
Definition: SVector3.h:16
meshGFaceOptimize.h
MTriangle::getVertex
virtual MVertex * getVertex(int num)
Definition: MTriangle.h:62
MVertex::onWhat
GEntity * onWhat() const
Definition: MVertex.h:82
BoundaryLayerColumns
Definition: boundaryLayersData.h:51
transferDataStructure
void transferDataStructure(GFace *gf, std::set< MTri3 *, compareTri3Ptr > &AllTris, bidimMeshData &data)
Definition: meshGFaceOptimize.cpp:348
GmshMessage.h
recurFindCavityAniso
static void recurFindCavityAniso(GFace *gf, std::list< edgeXface > &shell, std::list< MTri3 * > &cavity, double *metric, double *param, MTri3 *t, bidimMeshData &data)
Definition: meshGFaceDelaunayInsertion.cpp:597
edges
static int edges[6][2]
Definition: meshGRegionLocalMeshMod.cpp:23
MTri3::MTri3
MTri3(MTriangle *t, double lc, SMetric3 *m=nullptr, bidimMeshData *data=nullptr, GFace *gf=nullptr)
Definition: meshGFaceDelaunayInsertion.cpp:411
MEdgeLessThan
Definition: MEdge.h:122
diffend
bool diffend(MVertex *v1, MVertex *v2, MVertex *p1, MVertex *p2)
Definition: meshGFaceDelaunayInsertion.cpp:1947
connectTriangles
void connectTriangles(std::list< MTri3 * > &l)
Definition: meshGFaceDelaunayInsertion.cpp:543
GPoint
Definition: GPoint.h:13
GEntity::getNumMeshVertices
std::size_t getNumMeshVertices()
Definition: GEntity.h:376
BDS_Point::lcBGM
double & lcBGM()
Definition: BDS.h:65
buildMetric
void buildMetric(GFace *gf, double *uv, double *metric)
Definition: meshGFaceDelaunayInsertion.cpp:332
Extend1dMeshIn2dSurfaces
bool Extend1dMeshIn2dSurfaces(GFace *gf)
Definition: BackgroundMeshTools.cpp:339
computeTolerance
static double computeTolerance(const double radius)
Definition: meshGFaceDelaunayInsertion.cpp:341
surfaceFunctorGFace
Definition: intersectCurveSurface.h:29
MTri3::getNeigh
MTri3 * getNeigh(int iN) const
Definition: meshGFaceDelaunayInsertion.h:107
Fopen
FILE * Fopen(const char *f, const char *mode)
Definition: OS.cpp:273
backgroundMesh::setCrossFieldsByDistance
static void setCrossFieldsByDistance(GFace *)
Definition: BackgroundMesh.cpp:52
GPoint::z
double z() const
Definition: GPoint.h:23
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
Pair::first
L first() const
Definition: Pair.h:22
bowyerWatsonParallelogramsConstrained
void bowyerWatsonParallelogramsConstrained(GFace *gf, const std::set< MVertex * > &constr_vertices, std::map< MVertex *, MVertex * > *equivalence, std::map< MVertex *, SPoint2 > *parametricCoordinates)
Definition: meshGFaceDelaunayInsertion.cpp:1711
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
fullMatrix< double >
conn
Definition: delaunay3d.cpp:257
MTri3
Definition: meshGFaceDelaunayInsertion.h:78
Range
Definition: Range.h:10
Pair::second
R second() const
Definition: Pair.h:23
intersection_segments
int intersection_segments(const SPoint2 &p1, const SPoint2 &p2, const SPoint2 &q1, const SPoint2 &q2, double x[2])
Definition: Numeric.cpp:1331
GEntity::mesh_vertices
std::vector< MVertex * > mesh_vertices
Definition: GEntity.h:56
circUV
static bool circUV(MTriangle *t, bidimMeshData &data, double *res, GFace *gf)
Definition: meshGFaceDelaunayInsertion.cpp:623
MTri3::radiusNorm
static int radiusNorm
2 is euclidian norm, -1 is infinite norm , 3 quality
Definition: meshGFaceDelaunayInsertion.h:87
MTri3::setTri
void setTri(MTriangle *t)
Definition: meshGFaceDelaunayInsertion.h:104
invMapXY
static bool invMapXY(MTriangle *t, MVertex *v)
Definition: meshGFaceDelaunayInsertion.cpp:825
tolerance
#define tolerance
Definition: curvature.cpp:11
norm
void norm(const double *vec, double *norm)
Definition: gmshLevelset.cpp:202
MTriangle::getVolume
virtual double getVolume()
Definition: MTriangle.cpp:59
Numeric.h
LIMIT_
static double LIMIT_
Definition: meshGFaceDelaunayInsertion.cpp:34
BDS_Point::v
double v
Definition: BDS.h:57
initialSquare
static void initialSquare(std::vector< MVertex * > &v, MVertex *box[4], std::vector< MTri3 * > &t)
Definition: meshGFaceDelaunayInsertion.cpp:1786
getSurfUV
double getSurfUV(MTriangle *t, bidimMeshData &data)
Definition: meshGFaceDelaunayInsertion.cpp:665
BDS_Point::degenerated
short degenerated
Definition: BDS.h:59
edgeXface::t1
MTri3 * t1
Definition: meshGFaceDelaunayInsertion.h:179
circumCenterInfinite
static void circumCenterInfinite(MTriangle *base, double quadAngle, bidimMeshData &data, double *x)
Definition: meshGFaceDelaunayInsertion.cpp:1108
BGM_MeshSize
double BGM_MeshSize(GEntity *ge, double U, double V, double X, double Y, double Z)
Definition: BackgroundMeshTools.cpp:255
bowyerWatson
void bowyerWatson(GFace *gf, int MAXPNT, std::map< MVertex *, MVertex * > *equivalence, std::map< MVertex *, SPoint2 > *parametricCoordinates)
Definition: meshGFaceDelaunayInsertion.cpp:1033
GEdge::getBeginVertex
virtual GVertex * getBeginVertex() const
Definition: GEdge.h:63
discreteFace::intersectionWithCircle
GPoint intersectionWithCircle(const SVector3 &n1, const SVector3 &n2, const SVector3 &p, const double &R, double uv[2])
Definition: discreteFace.cpp:692
meshGFaceDelaunayInsertion.h
robustPredicates::insphere
REAL insphere(REAL *pa, REAL *pb, REAL *pc, REAL *pd, REAL *pe)
Definition: robustPredicates.cpp:4200
GEntity::geomType
virtual GeomType geomType() const
Definition: GEntity.h:238
lengthInfniteNorm
static double lengthInfniteNorm(const double p[2], const double q[2], const double quadAngle)
Definition: meshGFaceDelaunayInsertion.cpp:1094
SVector3::norm
double norm() const
Definition: SVector3.h:33
inCircumCircleXY
static int inCircumCircleXY(MTriangle *t, MVertex *v)
Definition: meshGFaceDelaunayInsertion.cpp:561
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
MVertexPtrLessThanLexicographic
Definition: MVertex.h:210
prosca
double prosca(double const a[3], double const b[3])
Definition: Numeric.h:112
intersection_segments_2
static bool intersection_segments_2(double *p1, double *p2, double *q1, double *q2)
Definition: meshGFaceDelaunayInsertion.cpp:51
CTX::mesh
contextMeshOptions mesh
Definition: Context.h:313
optimalPointFrontalB
static bool optimalPointFrontalB(GFace *gf, MTri3 *worst, int active_edge, bidimMeshData &data, double newPoint[2], double metric[3])
Definition: meshGFaceDelaunayInsertion.cpp:1235
swapedge
bool swapedge(MVertex *v1, MVertex *v2, MVertex *v3, MVertex *v4, MTri3 *t1, int iLocalEdge)
Definition: meshGFaceDelaunayInsertion.cpp:1912
GEntity::tag
int tag() const
Definition: GEntity.h:280
MFaceVertex
Definition: MVertex.h:168
discreteFace.h
bidimMeshData::internalEdges
std::set< MEdge, MEdgeLessThan > internalEdges
Definition: meshGFaceDelaunayInsertion.h:29
prodve
void prodve(double a[3], double b[3], double c[3])
Definition: Numeric.h:105
bidimMeshData::getIndex
int getIndex(MVertex *mv)
Definition: meshGFaceDelaunayInsertion.h:51
SVector3::x
double x(void) const
Definition: SVector3.h:30
MTri3::inCircumCircle
int inCircumCircle(const double *p) const
Definition: meshGFaceDelaunayInsertion.cpp:483
GEntity::parBounds
virtual Range< double > parBounds(int i) const
Definition: GEntity.h:259
insertAPoint
static bool insertAPoint(GFace *gf, std::set< MTri3 *, compareTri3Ptr >::iterator it, double center[2], double metric[3], bidimMeshData &data, std::set< MTri3 *, compareTri3Ptr > &AllTris, std::set< MTri3 *, compareTri3Ptr > *ActiveTris=nullptr, MTri3 *worst=nullptr, MTri3 **oneNewTriangle=nullptr, bool testStarShapeness=false)
Definition: meshGFaceDelaunayInsertion.cpp:923
MTriangle
Definition: MTriangle.h:26
GEntity::DiscreteSurface
@ DiscreteSurface
Definition: GEntity.h:117
edgeXface::_v
MVertex * _v(int i) const
Definition: meshGFaceDelaunayInsertion.h:193
delaunayMeshIn2D
void delaunayMeshIn2D(std::vector< MVertex * > &v, std::vector< MTriangle * > &result, bool removeBox, std::vector< MEdge > *edgesToRecover, bool hilbertSort)
Definition: meshGFaceDelaunayInsertion.cpp:1834
insertVertexB
static int insertVertexB(std::list< edgeXface > &shell, std::list< MTri3 * > &cavity, bool force, GFace *gf, MVertex *v, double *param, MTri3 *t, std::set< MTri3 *, compareTri3Ptr > &allTets, std::set< MTri3 *, compareTri3Ptr > *activeTets, bidimMeshData &data, double *metric, MTri3 **oneNewTriangle, bool verifyStarShapeness=true)
Definition: meshGFaceDelaunayInsertion.cpp:684
GFace::getColumns
BoundaryLayerColumns * getColumns()
Definition: GFace.h:453
recurFindCavity
static void recurFindCavity(std::vector< edgeXface > &shell, std::vector< MTri3 * > &cavity, MVertex *v, MTri3 *t)
Definition: meshGFaceDelaunayInsertion.cpp:575
intersectCurveSurface.h
BoundaryLayerColumns::_toFirst
std::map< MElement *, MElement * > _toFirst
Definition: boundaryLayersData.h:56
MVertex::getParameter
virtual bool getParameter(int i, double &par) const
Definition: MVertex.h:97
meshGFace.h
Context.h
sys2x2
int sys2x2(double mat[2][2], double b[2], double res[2])
Definition: Numeric.cpp:101
lengthMetric
static double lengthMetric(const double p[2], const double q[2], const double metric[3])
Definition: meshGFaceDelaunayInsertion.cpp:1131
backgroundMesh::unset
static void unset()
Definition: BackgroundMesh.cpp:60
SVector3::y
double y(void) const
Definition: SVector3.h:31
MTri3::setDeleted
void setDeleted(bool d)
Definition: meshGFaceDelaunayInsertion.h:118
MTri3::isDeleted
bool isDeleted() const
Definition: meshGFaceDelaunayInsertion.h:88
buildBackgroundMesh
void buildBackgroundMesh(GFace *gf, bool crossFieldClosestPoint, std::map< MVertex *, MVertex * > *equivalence, std::map< MVertex *, SPoint2 > *parametricCoordinates)
Definition: meshGFaceDelaunayInsertion.cpp:1453
pointInsideParametricDomain
bool pointInsideParametricDomain(std::vector< SPoint2 > &bnd, SPoint2 &p, SPoint2 &out, int &N)
Definition: meshGFace.cpp:43
z
const double z
Definition: GaussQuadratureQuad.cpp:56
contextMeshOptions::algo2d
int algo2d
Definition: Context.h:29
circumCenterXYZ
void circumCenterXYZ(double *p1, double *p2, double *p3, double *res, double *uv)
Definition: Numeric.cpp:342
_printTris
void _printTris(char *name, ITERATOR it, ITERATOR end, bidimMeshData *data, GFace *gf=nullptr, std::set< GEntity * > *degenerated=nullptr)
Definition: meshGFaceDelaunayInsertion.cpp:64
O
#define O
Definition: DefaultOptions.h:22
Pair
Definition: Pair.h:10
STensor3.h
GEdge
Definition: GEdge.h:26
SVector3::z
double z(void) const
Definition: SVector3.h:32
MTri3::getRadius
double getRadius() const
Definition: meshGFaceDelaunayInsertion.h:90
MElement::barycenter
virtual SPoint3 barycenter(bool primary=false) const
Definition: MElement.cpp:520
backgroundMesh::current
static backgroundMesh * current()
Definition: BackgroundMesh.cpp:68
inCircumCircle
int inCircumCircle(MTriangle *base, const double *p, const double *param, bidimMeshData &data)
Definition: meshGFaceDelaunayInsertion.cpp:499
connectTris
static void connectTris(Iterator beg, Iterator end, std::vector< edgeXface > &conn)
Definition: meshGFaceDelaunayInsertion.cpp:515
BDS_Point::u
double u
Definition: BDS.h:57
robustPredicates::orient3d
REAL orient3d(REAL *pa, REAL *pb, REAL *pc, REAL *pd)
Definition: robustPredicates.cpp:2321
GModel.h
fourthPoint
static void fourthPoint(double *p1, double *p2, double *p3, double *p4)
Definition: meshGFaceDelaunayInsertion.cpp:394
edgeXface
Definition: meshGFaceDelaunayInsertion.h:177
SMetric3::transform
SMetric3 transform(fullMatrix< double > &V)
Definition: STensor3.cpp:92
MVertex::y
double y() const
Definition: MVertex.h:61
inCircumCircleAniso
int inCircumCircleAniso(GFace *gf, double *p1, double *p2, double *p3, double *uv, double *metric)
Definition: meshGFaceDelaunayInsertion.cpp:348
recoverEdgeBySwaps
static bool recoverEdgeBySwaps(std::vector< MTri3 * > &t, MVertex *mv1, MVertex *mv2, std::vector< MEdge > &edges)
Definition: meshGFaceDelaunayInsertion.cpp:1953
GEdge::getEndVertex
virtual GVertex * getEndVertex() const
Definition: GEdge.h:64
getTriToBreak
static MTri3 * getTriToBreak(MVertex *v, std::vector< MTri3 * > &t, int &ITER)
Definition: meshGFaceDelaunayInsertion.cpp:1806
BDS_Point::lc
double & lc()
Definition: BDS.h:66
backgroundMesh::getAngle
double getAngle(double u, double v, double w) const
Definition: BackgroundMesh.cpp:603
bidimMeshData::Vs
std::vector< double > Vs
Definition: meshGFaceDelaunayInsertion.h:25
norme
double norme(double a[3])
Definition: Numeric.h:123
MTriangle::setVertex
virtual void setVertex(int num, MVertex *v)
Definition: MTriangle.h:64
bidimMeshData::Us
std::vector< double > Us
Definition: meshGFaceDelaunayInsertion.h:25
SBoundingBox3d::max
SPoint3 max() const
Definition: SBoundingBox3d.h:91
MTri3::circum_radius
double circum_radius
Definition: meshGFaceDelaunayInsertion.h:81
GEntity::dim
virtual int dim() const
Definition: GEntity.h:196
MTri3::setNeigh
void setNeigh(int iN, MTri3 *n)
Definition: meshGFaceDelaunayInsertion.h:106
GPoint::x
double x() const
Definition: GPoint.h:21
getDegeneratedVertices
static void getDegeneratedVertices(GFace *gf, std::set< GEntity * > &degenerated)
Definition: meshGFaceDelaunayInsertion.cpp:37
invMapUV
static bool invMapUV(MTriangle *t, double *p, bidimMeshData &data, double *uv, double tol)
Definition: meshGFaceDelaunayInsertion.cpp:635
bidimMeshData::vSizesBGM
std::vector< double > vSizesBGM
Definition: meshGFaceDelaunayInsertion.h:25
robustPredicates::orient2d
REAL orient2d(REAL *pa, REAL *pb, REAL *pc)
Definition: robustPredicates.cpp:1633
buildMeshGenerationDataStructures
bool buildMeshGenerationDataStructures(GFace *gf, std::set< MTri3 *, compareTri3Ptr > &AllTris, bidimMeshData &data)
Definition: meshGFaceOptimize.cpp:174
bidimMeshData::vSizes
std::vector< double > vSizes
Definition: meshGFaceDelaunayInsertion.h:25
SBoundingBox3d
Definition: SBoundingBox3d.h:21
ALGO_2D_BAMG
#define ALGO_2D_BAMG
Definition: GmshDefines.h:243
curveFunctorCircle
Definition: intersectCurveSurface.h:53
fullMatrix.h
HilbertCurve.h
optimalPointFrontalQuad
static void optimalPointFrontalQuad(GFace *gf, MTri3 *worst, int active_edge, bidimMeshData &data, double newPoint[2], double metric[3])
Definition: meshGFaceDelaunayInsertion.cpp:1366
intersectCurveSurface
int intersectCurveSurface(curveFunctor &c, surfaceFunctor &s, double uvt[3], double epsilon)
Definition: intersectCurveSurface.cpp:62
GEntity::haveParametrization
virtual bool haveParametrization()
Definition: GEntity.h:251
MVertex::x
double x() const
Definition: MVertex.h:60
bowyerWatsonFrontal
void bowyerWatsonFrontal(GFace *gf, std::map< MVertex *, MVertex * > *equivalence, std::map< MVertex *, SPoint2 > *parametricCoordinates, std::vector< SPoint2 > *true_boundary)
Definition: meshGFaceDelaunayInsertion.cpp:1289
SVector3::normalize
double normalize()
Definition: SVector3.h:38
discreteFace
Definition: discreteFace.h:18
robustPredicates::incircle
REAL incircle(REAL *pa, REAL *pb, REAL *pc, REAL *pd)
Definition: robustPredicates.cpp:3245
backgroundMesh::set
static void set(GFace *)
Definition: BackgroundMesh.cpp:40