gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
BDS.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 <stack>
7 #include <cmath>
8 #include <stdio.h>
9 
10 #include "GmshMessage.h"
11 #include "OS.h"
12 #include "robustPredicates.h"
13 #include "Numeric.h"
14 #include "BDS.h"
15 #include "GFace.h"
16 #include "discreteFace.h"
18 #include "Numeric.h"
19 #include "qualityMeasures.h"
20 
21 static double _cos_N(BDS_Point *_p1, BDS_Point *_p2, BDS_Point *_p3, GFace *gf)
22 {
23  double n[3];
24  normal_triangle(_p1, _p2, _p3, n);
25  SVector3 N1 = gf->normal(SPoint2(_p1->u, _p1->v));
26  SVector3 N2 = gf->normal(SPoint2(_p2->u, _p2->v));
27  SVector3 N3 = gf->normal(SPoint2(_p3->u, _p3->v));
28  SVector3 N = N1 + N2 + N3;
29  N.normalize();
30  return N.x() * n[0] + N.y() * n[1] + N.z() * n[2];
31 }
32 
34 {
35  BDS_Point *pts[4];
36  if(!f->getNodes(pts)) return 0.;
37  if((pts[0]->degenerated ? 1 : 0) + (pts[1]->degenerated ? 1 : 0) +
38  (pts[2]->degenerated ? 1 : 0) <
39  2) {
40  double qa1 = qmTriangle::gamma(pts[0], pts[1], pts[2]);
41  return qa1 * _cos_N(pts[0], pts[1], pts[2], gf);
42  }
43  return 1.0;
44 }
45 
46 void outputScalarField(std::vector<BDS_Face *> &t, const char *iii, int param,
47  GFace *gf)
48 {
49  Msg::Info("Writing debug file '%s'", iii);
50  if(gf && 0) {
51  FILE *view_c = Fopen("param_mesh_as_it_is_in_3D.pos", "w");
52  if(!view_c) {
53  Msg::Error("Could not open file 'param_mesh_as_it_is_in_3D.pos'");
54  return;
55  }
56  fprintf(view_c, "View \"paramC\"{\n");
57  auto tit = t.begin();
58  auto tite = t.end();
59  while(tit != tite) {
60  BDS_Point *pts[4];
61  if(!(*tit)->deleted && (*tit)->getNodes(pts)) {
62  for(int j = 0; j < 3; j++) {
63  double U1 =
64  pts[j]->degenerated == 1 ? pts[(j + 1) % 3]->u : pts[j]->u;
65  double U2 = pts[(j + 1) % 3]->degenerated == 1 ? pts[j]->u :
66  pts[(j + 1) % 3]->u;
67  double V1 =
68  pts[j]->degenerated == 2 ? pts[(j + 1) % 3]->v : pts[j]->v;
69  double V2 = pts[(j + 1) % 3]->degenerated == 2 ? pts[j]->v :
70  pts[(j + 1) % 3]->v;
71  SPoint2 p1(U1, V1);
72  SPoint2 p2(U2, V2);
73  SPoint2 prev = p1;
74  for(int k = 1; k < 30; k++) {
75  double t = (double)k / 29;
76  SPoint2 p = p1 * (1. - t) + p2 * t;
77  GPoint pa = gf->point(p.x(), p.y());
78  GPoint pb = gf->point(prev.x(), prev.y());
79  fprintf(view_c, "SL(%g,%g,%g,%g,%g,%g){1,1,1};\n", pa.x(), pa.y(),
80  pa.z(), pb.x(), pb.y(), pb.z());
81  prev = p;
82  }
83  }
84  }
85  ++tit;
86  }
87  fprintf(view_c, "};\n");
88  fclose(view_c);
89  }
90 
91  FILE *f = Fopen(iii, "w");
92  if(!f) {
93  Msg::Error("Could not open file '%s'", iii);
94  return;
95  }
96  fprintf(f, "View \"scalar\" {\n");
97  auto tit = t.begin();
98  auto tite = t.end();
99  while(tit != tite) {
100  BDS_Point *pts[4];
101  if(!(*tit)->deleted && (*tit)->getNodes(pts)) {
102  if(!param) {
103  fprintf(f,
104  "ST(%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%"
105  "22.15E,%22.15E){%g,%g,%g};\n",
106  pts[0]->X, pts[0]->Y, pts[0]->Z, pts[1]->X, pts[1]->Y,
107  pts[1]->Z, pts[2]->X, pts[2]->Y, pts[2]->Z, (double)pts[0]->iD,
108  (double)pts[1]->iD, (double)pts[2]->iD);
109  }
110  if(param && gf) {
111  // FIXME --- LOOK AT THE VALUE OG DEGENERATED
112  if((pts[0]->degenerated ? 1 : 0) + (pts[1]->degenerated ? 1 : 0) +
113  (pts[2]->degenerated ? 1 : 0) >
114  1) {}
115  else if(pts[0]->degenerated == 1)
116  fprintf(f, "SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g,%g};\n",
117  pts[1]->u, pts[1]->v, 0.0, pts[2]->u, pts[2]->v, 0.0,
118  pts[2]->u, pts[0]->v, 0.0, pts[1]->u, pts[0]->v, 0.0,
119  (double)pts[1]->iD, (double)pts[2]->iD, (double)pts[0]->iD,
120  (double)pts[0]->iD);
121  else if(pts[1]->degenerated == 1)
122  fprintf(f, "SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g,%g};\n",
123  pts[2]->u, pts[2]->v, 0.0, pts[0]->u, pts[0]->v, 0.0,
124  pts[0]->u, pts[1]->v, 0.0, pts[2]->u, pts[1]->v, 0.0,
125  (double)pts[2]->iD, (double)pts[0]->iD, (double)pts[1]->iD,
126  (double)pts[1]->iD);
127  else if(pts[2]->degenerated == 1)
128  fprintf(f, "SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g,%g};\n",
129  pts[0]->u, pts[0]->v, 0.0, pts[1]->u, pts[1]->v, 0.0,
130  pts[1]->u, pts[2]->v, 0.0, pts[0]->u, pts[2]->v, 0.0,
131  (double)pts[0]->iD, (double)pts[1]->iD, (double)pts[2]->iD,
132  (double)pts[2]->iD);
133  else if(pts[0]->degenerated == 2)
134  fprintf(f, "SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g,%g};\n",
135  pts[1]->u, pts[1]->v, 0.0, pts[2]->u, pts[2]->v, 0.0,
136  pts[0]->u, pts[2]->v, 0.0, pts[0]->u, pts[1]->v, 0.0,
137  (double)pts[1]->iD, (double)pts[2]->iD, (double)pts[0]->iD,
138  (double)pts[0]->iD);
139  else if(pts[1]->degenerated == 2)
140  fprintf(f, "SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g,%g};\n",
141  pts[2]->u, pts[2]->v, 0.0, pts[0]->u, pts[0]->v, 0.0,
142  pts[1]->u, pts[0]->v, 0.0, pts[1]->u, pts[2]->v, 0.0,
143  (double)pts[2]->iD, (double)pts[0]->iD, (double)pts[1]->iD,
144  (double)pts[1]->iD);
145  else if(pts[2]->degenerated == 2)
146  fprintf(f, "SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g){%g,%g,%g,%g};\n",
147  pts[0]->u, pts[0]->v, 0.0, pts[1]->u, pts[1]->v, 0.0,
148  pts[2]->u, pts[1]->v, 0.0, pts[2]->u, pts[0]->v, 0.0,
149  (double)pts[0]->iD, (double)pts[1]->iD, (double)pts[2]->iD,
150  (double)pts[2]->iD);
151  else {
152  fprintf(f,
153  "ST(%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%22.15E,%"
154  "22.15E,%22.15E){%g,%g,%g};\n",
155  pts[0]->u, pts[0]->v, 0.0, pts[1]->u, pts[1]->v, 0.0,
156  pts[2]->u, pts[2]->v, 0.0, (double)pts[0]->iD,
157  (double)pts[1]->iD, (double)pts[2]->iD);
158  }
159  }
160  }
161  ++tit;
162  }
163  fprintf(f, "};\n");
164  fclose(f);
165 }
166 
167 static void vector_triangle(BDS_Point *p1, BDS_Point *p2, BDS_Point *p3,
168  double c[3])
169 {
170  double a[3] = {p1->X - p2->X, p1->Y - p2->Y, p1->Z - p2->Z};
171  double b[3] = {p1->X - p3->X, p1->Y - p3->Y, p1->Z - p3->Z};
172  c[2] = a[0] * b[1] - a[1] * b[0];
173  c[1] = -a[0] * b[2] + a[2] * b[0];
174  c[0] = a[1] * b[2] - a[2] * b[1];
175 }
176 
178  BDS_Point *p3)
179 {
180  double const a[2] = {p1->u - p2->u, p1->v - p2->v};
181  double const b[2] = {p1->u - p3->u, p1->v - p3->v};
182  return a[0] * b[1] - a[1] * b[0];
183 }
184 
185 void normal_triangle(BDS_Point *p1, BDS_Point *p2, BDS_Point *p3, double c[3])
186 {
187  vector_triangle(p1, p2, p3, c);
188  norme(c);
189 }
190 
192  BDS_Point *p3)
193 {
194  // FIXME
195  // THIS ASSUMES DEGENERATED EDGES ALONG AXIS U !!!
196  // SEEMS TO BE THE CASE WITH OCC
197 
198  if(!p1 || !p2 || !p3) {
199  Msg::Error("Invalid point in parametric triangle surface computation");
200  return 0;
201  }
202 
203  double c;
204  if((p1->degenerated ? 1 : 0) + (p2->degenerated ? 1 : 0) +
205  (p3->degenerated ? 1 : 0) >
206  1)
207  c = 0; // vector_triangle_parametric(p1, p2, p3, c);
208  else if(p1->degenerated == 1) {
209  double du = fabs(p3->u - p2->u);
210  c = 2 * fabs(0.5 * (p3->v + p2->v) - p1->v) * du;
211  }
212  else if(p2->degenerated == 1) {
213  double du = fabs(p3->u - p1->u);
214  c = 2 * fabs(0.5 * (p3->v + p1->v) - p2->v) * du;
215  }
216  else if(p3->degenerated == 1) {
217  double du = fabs(p2->u - p1->u);
218  c = 2 * fabs(0.5 * (p2->v + p1->v) - p3->v) * du;
219  }
220  else if(p1->degenerated == 2) {
221  double dv = fabs(p3->v - p2->v);
222  c = 2 * fabs(0.5 * (p3->u + p2->u) - p1->u) * dv;
223  }
224  else if(p2->degenerated == 2) {
225  double dv = fabs(p3->v - p1->v);
226  c = 2 * fabs(0.5 * (p3->u + p1->u) - p2->u) * dv;
227  }
228  else if(p3->degenerated == 2) {
229  double dv = fabs(p2->v - p1->v);
230  c = 2 * fabs(0.5 * (p2->u + p1->u) - p3->u) * dv;
231  }
232  else
233  c = vector_triangle_parametric(p1, p2, p3);
234  return (0.5 * c);
235 }
236 
237 std::vector<BDS_Face *> BDS_Point::getTriangles() const
238 {
239  std::vector<BDS_Face *> t;
240  t.reserve(edges.size());
241 
242  auto it = edges.begin();
243  while(it != edges.end()) {
244  std::size_t const number_of_faces = (*it)->numfaces();
245 
246  for(std::size_t i = 0; i < number_of_faces; ++i) {
247  BDS_Face *const tt = (*it)->faces(i);
248  if(tt && std::find(t.begin(), t.end(), tt) == t.end()) {
249  t.push_back(tt);
250  }
251  }
252  ++it;
253  }
254  return t;
255 }
256 
257 BDS_Point *BDS_Mesh::add_point(int const num, double const x, double const y,
258  double const z)
259 {
260  BDS_Point *pp = new BDS_Point(num, x, y, z);
261  points.insert(pp);
262  MAXPOINTNUMBER = std::max(MAXPOINTNUMBER, num);
263  return pp;
264 }
265 
266 BDS_Point *BDS_Mesh::add_point(int num, double u, double v, GFace *gf)
267 {
268  GPoint gp = gf->point(u, v);
269  BDS_Point *pp = new BDS_Point(num, gp.x(), gp.y(), gp.z());
270  pp->u = u;
271  pp->v = v;
272  points.insert(pp);
273  MAXPOINTNUMBER = std::max(MAXPOINTNUMBER, num);
274  return pp;
275 }
276 
278 {
279  BDS_Point P(p);
280  auto it = points.find(&P);
281 
282  return it != points.end() ? static_cast<BDS_Point *>(*it) : nullptr;
283 }
284 
286 {
287  auto eit = p->edges.begin();
288  while(eit != p->edges.end()) {
289  if((*eit)->p1 == p && (*eit)->p2->iD == num2) return (*eit);
290  if((*eit)->p2 == p && (*eit)->p1->iD == num2) return (*eit);
291  ++eit;
292  }
293  return nullptr;
294 }
295 
297 {
298  return find_edge(p1, p2->iD);
299 }
300 
301 BDS_Edge *BDS_Mesh::find_edge(int num1, int num2)
302 {
303  BDS_Point *p = find_point(num1);
304  return find_edge(p, num2);
305 }
306 
307 int Intersect_Edges_2d(double x1, double y1, double x2, double y2, double x3,
308  double y3, double x4, double y4, double x[2])
309 {
310  double mat[2][2];
311  double rhs[2];
312  mat[0][0] = (x2 - x1);
313  mat[0][1] = -(x4 - x3);
314  mat[1][0] = (y2 - y1);
315  mat[1][1] = -(y4 - y3);
316  rhs[0] = x3 - x1;
317  rhs[1] = y3 - y1;
318  if(!sys2x2(mat, rhs, x)) return 0;
319  if(x[0] >= 0.0 && x[0] <= 1.0 && x[1] >= 0.0 && x[1] <= 1.0) return 1;
320  return 0;
321 }
322 
324 {
325  std::vector<BDS_Face *> ts = p1->getTriangles();
326 
327  auto it = ts.begin();
328  while(it != ts.end()) {
329  BDS_Face *t = *it;
330  if(!t->e4) {
331  BDS_Edge *e = t->oppositeEdge(p1);
332  BDS_Face *f = e->otherFace(t);
333  if(!f->e4) {
334  BDS_Point *p2b = f->oppositeVertex(e);
335  if(p2b && p2 == p2b) {
336  if(swap_edge(e, BDS_SwapEdgeTestRecover(), true)) {
337  return find_edge(p1, p2->iD);
338  }
339  }
340  }
341  }
342  ++it;
343  }
344  return nullptr;
345 }
346 
347 BDS_Edge *BDS_Mesh::recover_edge(int num1, int num2, bool &_fatal,
348  std::set<EdgeToRecover> *e2r,
349  std::set<EdgeToRecover> *not_recovered)
350 {
351  BDS_Edge *e = find_edge(num1, num2);
352  _fatal = false;
353 
354  if(e) return e;
355 
356  BDS_Point *p1 = find_point(num1);
357  BDS_Point *p2 = find_point(num2);
358 
359  if(!p1 || !p2) {
360  Msg::Error("Could not find points %d or %d in BDS mesh", num1, num2);
361  return nullptr;
362  }
363 
364  Msg::Debug("Edge %d %d has to be recovered", num1, num2);
365 
366  int ix = 0;
367  double x[2];
368  while(1) {
369  std::vector<BDS_Edge *> intersected;
370 
371  bool selfIntersection = false;
372 
373  auto it = edges.begin();
374  while(it != edges.end()) {
375  e = (*it);
376  if(!e->deleted && e->p1 != p1 && e->p1 != p2 && e->p2 != p1 &&
377  e->p2 != p2)
378  if(Intersect_Edges_2d(e->p1->u, e->p1->v, e->p2->u, e->p2->v, p1->u,
379  p1->v, p2->u, p2->v, x)) {
380  // intersect
381  if(e2r && e2r->find(EdgeToRecover(e->p1->iD, e->p2->iD, nullptr)) !=
382  e2r->end()) {
383  auto itr1 = e2r->find(EdgeToRecover(e->p1->iD, e->p2->iD, nullptr));
384  auto itr2 = e2r->find(EdgeToRecover(num1, num2, nullptr));
385  Msg::Debug("edge %d %d on model edge %d cannot be recovered because"
386  " it intersects %d %d on model edge %d",
387  num1, num2, itr2->ge->tag(), e->p1->iD, e->p2->iD,
388  itr1->ge->tag());
389  // now throw a class that contains the diagnostic
390  not_recovered->insert(EdgeToRecover(num1, num2, itr2->ge));
391  not_recovered->insert(
392  EdgeToRecover(e->p1->iD, e->p2->iD, itr1->ge));
393  selfIntersection = true;
394  }
395  if(e->numfaces() != e->numTriangles()) return nullptr;
396  intersected.push_back(e);
397  }
398  ++it;
399  }
400 
401  if(selfIntersection) return nullptr;
402 
403  if(!intersected.size() || ix > 300) {
404  BDS_Edge *eee = find_edge(num1, num2);
405  if(!eee) {
406  if(Msg::GetVerbosity() > 98) {
407  outputScalarField(triangles, "debugp.pos", 1);
408  outputScalarField(triangles, "debugr.pos", 0);
409  Msg::Debug(
410  "edge %d %d cannot be recovered at all, look at debugp.pos "
411  "and debugr.pos",
412  num1, num2);
413  }
414  else {
415  Msg::Debug("edge %d %d cannot be recovered at all", num1, num2);
416  }
417  _fatal = true;
418  return nullptr;
419  }
420  return eee;
421  }
422 
423  std::vector<int>::size_type ichoice = 0;
424  bool success = false;
425  while(!success && ichoice < intersected.size()) {
426  success = swap_edge(intersected[ichoice++], BDS_SwapEdgeTestRecover());
427  }
428 
429  if(!success) {
430  Msg::Debug("edge %d %d cannot be recovered at all\n", num1, num2);
431  _fatal = true;
432  return nullptr;
433  }
434 
435  ix++;
436  }
437  return nullptr;
438 }
439 
441 {
442  BDS_Point P1(p1->iD);
443  BDS_Point P2(p2->iD);
444  BDS_Edge E(&P1, &P2);
445  if(t->e1->p1->iD == E.p1->iD && t->e1->p2->iD == E.p2->iD) return t->e1;
446  if(t->e2->p1->iD == E.p1->iD && t->e2->p2->iD == E.p2->iD) return t->e2;
447  if(t->e3->p1->iD == E.p1->iD && t->e3->p2->iD == E.p2->iD) return t->e3;
448  return nullptr;
449 }
450 
451 static bool is_equivalent(BDS_Edge *e1, BDS_Edge *e2, BDS_Edge *e3,
452  BDS_Edge *o1, BDS_Edge *o2, BDS_Edge *o3)
453 {
454  return (o1 == e1 && o2 == e2 && o3 == e3) ||
455  (o1 == e1 && o2 == e3 && o3 == e2) ||
456  (o1 == e2 && o2 == e1 && o3 == e3) ||
457  (o1 == e2 && o2 == e3 && o3 == e1) ||
458  (o1 == e3 && o2 == e1 && o3 == e2) ||
459  (o1 == e3 && o2 == e2 && o3 == e1);
460 }
461 
463 {
464  for(int i = 0; i < e1->numfaces(); i++) {
465  BDS_Face *t = e1->faces(i);
466  if(is_equivalent(e1, e2, e3, t->e1, t->e2, t->e3)) { return t; }
467  }
468  for(int i = 0; i < e2->numfaces(); i++) {
469  BDS_Face *t = e2->faces(i);
470  if(is_equivalent(e1, e2, e3, t->e1, t->e2, t->e3)) { return t; }
471  }
472  for(int i = 0; i < e3->numfaces(); i++) {
473  BDS_Face *t = e3->faces(i);
474  if(is_equivalent(e1, e2, e3, t->e1, t->e2, t->e3)) { return t; }
475  }
476  return nullptr;
477 }
478 
479 BDS_Edge *BDS_Mesh::add_edge(int const p1, int const p2)
480 {
481  BDS_Edge *efound = find_edge(p1, p2);
482  if(efound) return efound;
483 
484  BDS_Point *pp1 = find_point(p1);
485  BDS_Point *pp2 = find_point(p2);
486 
487  if(!pp1 || !pp2) {
488  Msg::Error("Could not find points %d or %d", p1, p2);
489  return nullptr;
490  }
491  edges.push_back(new BDS_Edge(pp1, pp2));
492 
493  return edges.back();
494 }
495 
496 BDS_Face *BDS_Mesh::add_triangle(int p1, int p2, int p3)
497 {
498  BDS_Edge *e1 = add_edge(p1, p2);
499  BDS_Edge *e2 = add_edge(p2, p3);
500  BDS_Edge *e3 = add_edge(p3, p1);
501  if(e1 && e2 && e3) return add_triangle(e1, e2, e3);
502  return nullptr;
503 }
504 
506 {
507  if(e1 && e2 && e3) {
508  BDS_Face *t = new BDS_Face(e1, e2, e3);
509  triangles.push_back(t);
510  return t;
511  }
512  return nullptr;
513 }
514 
516 {
517  if(!t) return;
518  t->e1->del(t);
519  t->e2->del(t);
520  t->e3->del(t);
521  if(t->e4) t->e4->del(t);
522  t->deleted = true;
523 }
524 
526 {
527  if(!e) return;
528  e->p1->del(e);
529  e->p2->del(e);
530  e->deleted = true;
531 }
532 
534 {
535  if(!p) return;
536  if(points.erase(p)) delete p;
537 }
538 
539 void BDS_Mesh::add_geom(int p1, int p2)
540 {
541  BDS_GeomEntity *e = new BDS_GeomEntity(p1, p2);
542  auto res = geom.insert(e);
543  if(!res.second) delete e;
544 }
545 
547  BDS_Point *oface[2]) const
548 {
549  oface[0] = oface[1] = nullptr;
550  pts1[0] = pts1[1] = pts1[2] = pts1[3] = nullptr;
551  pts2[0] = pts2[1] = pts2[2] = pts2[3] = nullptr;
552  if(faces(0)) {
553  if(!faces(0)->getNodes(pts1)) return;
554  if(pts1[0] != p1 && pts1[0] != p2)
555  oface[0] = pts1[0];
556  else if(pts1[1] != p1 && pts1[1] != p2)
557  oface[0] = pts1[1];
558  else
559  oface[0] = pts1[2];
560  }
561  if(faces(1)) {
562  if(!faces(1)->getNodes(pts2)) return;
563  if(pts2[0] != p1 && pts2[0] != p2)
564  oface[1] = pts2[0];
565  else if(pts2[1] != p1 && pts2[1] != p2)
566  oface[1] = pts2[1];
567  else
568  oface[1] = pts2[2];
569  }
570 }
571 
572 void BDS_Edge::oppositeof(BDS_Point *oface[2]) const
573 {
574  oface[0] = oface[1] = nullptr;
575  if(faces(0)) {
576  BDS_Point *pts[4];
577  if(!faces(0)->getNodes(pts)) return;
578  if(pts[0] != p1 && pts[0] != p2)
579  oface[0] = pts[0];
580  else if(pts[1] != p1 && pts[1] != p2)
581  oface[0] = pts[1];
582  else
583  oface[0] = pts[2];
584  }
585  if(faces(1)) {
586  BDS_Point *pts[4];
587  if(!faces(1)->getNodes(pts)) return;
588  if(pts[0] != p1 && pts[0] != p2)
589  oface[1] = pts[0];
590  else if(pts[1] != p1 && pts[1] != p2)
591  oface[1] = pts[1];
592  else
593  oface[1] = pts[2];
594  }
595 }
596 
598 {
599  BDS_GeomEntity ge(p1, p2);
600  auto it = geom.find(&ge);
601  if(it == geom.end()) return nullptr;
602  return (BDS_GeomEntity *)(*it);
603 }
604 
606 {
607  std::stack<BDS_Face *> _stack;
608  _stack.push(t);
609 
610  while(!_stack.empty()) {
611  t = _stack.top();
612  _stack.pop();
613  if(!t->g) {
614  t->g = g;
615  if(!t->e1->g && t->e1->numfaces() == 2) {
616  _stack.push(t->e1->otherFace(t));
617  }
618  if(!t->e2->g && t->e2->numfaces() == 2) {
619  _stack.push(t->e2->otherFace(t));
620  }
621  if(!t->e3->g && t->e3->numfaces() == 2) {
622  _stack.push(t->e3->otherFace(t));
623  }
624  }
625  }
626 }
627 
629 
630 template <class IT> void DESTROOOY(IT beg, IT end)
631 {
632  while(beg != end) {
633  delete *beg;
634  beg++;
635  }
636 }
637 
639  template <class T> bool operator()(T *const face) { return !face->deleted; }
640 };
641 
643 {
644  {
645  auto last =
646  std::partition(triangles.begin(), triangles.end(), is_not_deleted());
647  auto it = last;
648  while(it != triangles.end()) {
649  delete *it;
650  ++it;
651  }
652  triangles.erase(last, triangles.end());
653  }
654  {
655  auto last = std::partition(edges.begin(), edges.end(), is_not_deleted());
656  auto it = last;
657  while(it != edges.end()) {
658  delete *it;
659  ++it;
660  }
661  edges.erase(last, edges.end());
662  }
663 }
664 
666 {
667  DESTROOOY(geom.begin(), geom.end());
668  DESTROOOY(points.begin(), points.end());
669  cleanup();
670  DESTROOOY(edges.begin(), edges.end());
671  DESTROOOY(triangles.begin(), triangles.end());
672 }
673 
674 bool BDS_Mesh::split_edge(BDS_Edge *e, BDS_Point *mid, bool check_area_param)
675 {
676  /*
677  p1
678  / | \
679  / | \
680  op1/ 0mid1 \op2
681  \ | /
682  \ | /
683  \ p2/
684 
685  // p1,op1,mid -
686  // p2,op2,mid -
687  // p2,op1,mid +
688  // p1,op2,mid +
689  */
690 
691  BDS_Point *op[2];
692  BDS_Point *p1 = e->p1;
693  BDS_Point *p2 = e->p2;
694 
695  e->oppositeof(op);
696  if(!op[0] || !op[1]) return false;
697 
698  const int CHECK1 = -1, CHECK2 = -1;
699 
700  if(p1->iD == CHECK1 && p2->iD == CHECK2)
701  printf("splitting edge %d %d opp %d %d new %d\n", p1->iD, p2->iD, op[0]->iD,
702  op[1]->iD, mid->iD);
703  if(check_area_param) {
704  double area0 = fabs(surface_triangle_param(p2, p1, op[0])) +
705  fabs(surface_triangle_param(p2, p1, op[1]));
706  double area1 = fabs(surface_triangle_param(mid, p1, op[1])) +
707  fabs(surface_triangle_param(mid, op[1], p2)) +
708  fabs(surface_triangle_param(mid, p2, op[0])) +
709  fabs(surface_triangle_param(mid, op[0], p1));
710  // heuristic - abort if area changed too much
711  if(area1 > 1.1 * area0 || area1 < 0.9 * area0) { return false; }
712  }
713 
714  if(p1->iD == CHECK1 && p2->iD == CHECK2)
715  printf("%d %d %d %d\n", p1->iD, p2->iD, op[0]->iD, op[1]->iD);
716 
717  BDS_Point *pts1[4];
718  if(!e->faces(0)->getNodes(pts1)) return false;
719 
720  int orientation = 0;
721  for(int i = 0; i < 3; i++) {
722  if(pts1[i] == p1) {
723  orientation = pts1[(i + 1) % 3] == p2 ? 1 : -1;
724  break;
725  }
726  }
727 
728  BDS_GeomEntity *g1 = nullptr, *g2 = nullptr, *ge = e->g;
729 
730  BDS_Edge *p1_op1 = find_edge(p1, op[0], e->faces(0));
731  BDS_Edge *op1_p2 = find_edge(op[0], p2, e->faces(0));
732  BDS_Edge *p1_op2 = find_edge(p1, op[1], e->faces(1));
733  BDS_Edge *op2_p2 = find_edge(op[1], p2, e->faces(1));
734 
735  if(e->faces(0)) {
736  g1 = e->faces(0)->g;
737  del_face(e->faces(0));
738  }
739  // not a bug !!!
740  if(e->faces(0)) {
741  g2 = e->faces(0)->g;
742  del_face(e->faces(0));
743  }
744 
745  del_edge(e);
746 
747  BDS_Edge *p1_mid = new BDS_Edge(p1, mid);
748  edges.push_back(p1_mid);
749  BDS_Edge *mid_p2 = new BDS_Edge(mid, p2);
750  edges.push_back(mid_p2);
751  BDS_Edge *op1_mid = new BDS_Edge(op[0], mid);
752  edges.push_back(op1_mid);
753  BDS_Edge *mid_op2 = new BDS_Edge(mid, op[1]);
754  edges.push_back(mid_op2);
755 
756  BDS_Face *t1, *t2, *t3, *t4;
757  if(orientation == 1) {
758  t1 = new BDS_Face(op1_mid, p1_op1, p1_mid);
759  t2 = new BDS_Face(mid_op2, op2_p2, mid_p2);
760  t3 = new BDS_Face(op1_p2, op1_mid, mid_p2);
761  t4 = new BDS_Face(p1_op2, mid_op2, p1_mid);
762  }
763  else {
764  t1 = new BDS_Face(p1_op1, op1_mid, p1_mid);
765  t2 = new BDS_Face(op2_p2, mid_op2, mid_p2);
766  t3 = new BDS_Face(op1_mid, op1_p2, mid_p2);
767  t4 = new BDS_Face(mid_op2, p1_op2, p1_mid);
768  }
769  t1->g = g1;
770  t2->g = g2;
771  t3->g = g1;
772  t4->g = g2;
773 
774  p1_mid->g = ge;
775  mid_p2->g = ge;
776  op1_mid->g = g1;
777  mid_op2->g = g2;
778 
779  mid->g = ge;
780 
781  triangles.push_back(t1);
782  triangles.push_back(t2);
783  triangles.push_back(t3);
784  triangles.push_back(t4);
785 
786  return true;
787  // config has changed
788  p1->config_modified = true;
789  p2->config_modified = true;
790  op[0]->config_modified = true;
791  op[1]->config_modified = true;
792  return true;
793 }
794 
796  BDS_Point *_q1, BDS_Point *_q2) const
797 {
798  double p1[2] = {_p1->u, _p1->v};
799  double p2[2] = {_p2->u, _p2->v};
800  double op1[2] = {_q1->u, _q1->v};
801  double op2[2] = {_q2->u, _q2->v};
802 
803  double ori_t1 = robustPredicates::orient2d(op1, p1, op2);
804  double ori_t2 = robustPredicates::orient2d(op1, op2, p2);
805 
806  return (ori_t1 * ori_t2 > 0); // the quadrangle was strictly convex !
807 }
808 
810  BDS_Point *_p3, BDS_Point *_q1,
811  BDS_Point *_q2, BDS_Point *_q3,
812  BDS_Point *_op1, BDS_Point *_op2,
813  BDS_Point *_op3, BDS_Point *_oq1,
814  BDS_Point *_oq2, BDS_Point *_oq3) const
815 {
816  return true;
817 }
818 
819 // This function does actually the swap without taking into account
820 // the feasability of the operation. Those conditions have to be
821 // taken into account before doing the edge swap
822 
824  BDS_Point *_q1, BDS_Point *_q2) const
825 {
826  if(!testSmallTriangles) return true;
827 
828  // AVOID CREATING POINTS WITH 2 NEIGHBORING TRIANGLES
829  // std::vector<BDS_Face*> f1 = p1->getTriangles();
830  // std::vector<BDS_Face*> f2 = p2->getTriangles();
831  if(_p1->g && _p1->g->classif_degree == 2 && _p1->edges.size() <= 4)
832  return false;
833  if(_p2->g && _p2->g->classif_degree == 2 && _p2->edges.size() <= 4)
834  return false;
835  if(_p1->g && _p1->g->classif_degree < 2 && _p1->edges.size() <= 3)
836  return false;
837  if(_p2->g && _p2->g->classif_degree < 2 && _p2->edges.size() <= 3)
838  return false;
839 
840  double s1 = fabs(surface_triangle_param(_p1, _p2, _q1));
841  double s2 = fabs(surface_triangle_param(_p1, _p2, _q2));
842  double s3 = fabs(surface_triangle_param(_p1, _q1, _q2));
843  double s4 = fabs(surface_triangle_param(_p2, _q1, _q2));
844  if(fabs(s1 + s2 - s3 - s4) > 1.e-12 * (s3 + s4)) { return false; }
845 
846  return true;
847 }
848 
850  BDS_Point *_p3, BDS_Point *_q1,
851  BDS_Point *_q2, BDS_Point *_q3,
852  BDS_Point *_op1, BDS_Point *_op2,
853  BDS_Point *_op3, BDS_Point *_oq1,
854  BDS_Point *_oq2, BDS_Point *_oq3) const
855 {
856  // Check if new edge is not on a seam or degenerated
857  BDS_Point *p1 = nullptr, *p2 = nullptr;
858  if(_op1 != _oq1 && _op1 != _oq2 && _op1 != _oq3) {
859  p1 = _op2;
860  p2 = _op3;
861  }
862  else if(_op2 != _oq1 && _op2 != _oq2 && _op2 != _oq3) {
863  p1 = _op1;
864  p2 = _op3;
865  }
866  else if(_op3 != _oq1 && _op3 != _oq2 && _op3 != _oq3) {
867  p1 = _op1;
868  p2 = _op2;
869  }
870  else {
871  Msg::Warning("Unable to detect the new edge in BDS_SwapEdgeTestQuality\n");
872  }
873 
874  if(p1 && p2) {
875  if(p1->degenerated && p2->degenerated) return false;
876  if(p1->_periodicCounterpart && p2->_periodicCounterpart) return false;
877  }
878 
879  if(!testQuality) return true;
880 
881  double qa1 = qmTriangle::gamma(_p1, _p2, _p3);
882  double qa2 = qmTriangle::gamma(_q1, _q2, _q3);
883  double qb1 = qmTriangle::gamma(_op1, _op2, _op3);
884  double qb2 = qmTriangle::gamma(_oq1, _oq2, _oq3);
885 
886  // we swap for a better configuration
887  double const mina = std::min(qa1, qa2);
888  double const minb = std::min(qb1, qb2);
889 
890  return minb > mina;
891 }
892 
894  BDS_Point *_q1, BDS_Point *_q2) const
895 {
896  double s1 = fabs(surface_triangle_param(_p1, _p2, _q1));
897  double s2 = fabs(surface_triangle_param(_p1, _p2, _q2));
898  double s3 = fabs(surface_triangle_param(_p1, _q1, _q2));
899  double s4 = fabs(surface_triangle_param(_p2, _q1, _q2));
900  if(fabs(s1 + s2 - s3 - s4) > 1.e-12 * (s3 + s4)) { return false; }
901  return true;
902 }
903 
905  BDS_Point *_p3, BDS_Point *_q1,
906  BDS_Point *_q2, BDS_Point *_q3,
907  BDS_Point *_op1, BDS_Point *_op2,
908  BDS_Point *_op3, BDS_Point *_oq1,
909  BDS_Point *_oq2, BDS_Point *_oq3) const
910 {
911  double qa1 = qmTriangle::gamma(_p1, _p2, _p3);
912  double qa2 = qmTriangle::gamma(_q1, _q2, _q3);
913  double qb1 = qmTriangle::gamma(_op1, _op2, _op3);
914  double qb2 = qmTriangle::gamma(_oq1, _oq2, _oq3);
915 
916  double OLD = std::min(_ori * qa1 * _cos_N(_p1, _p2, _p3, gf),
917  _ori * qa2 * _cos_N(_q1, _q2, _q3, gf));
918 
919  double NEW = std::min(_ori * qb1 * _cos_N(_op1, _op2, _op3, gf),
920  _ori * qb2 * _cos_N(_oq1, _oq2, _oq3, gf));
921 
922  if(OLD < 0.5 && OLD < NEW) return true;
923  return false;
924 }
925 
927  bool force)
928 {
929  /*
930  p1
931  / | \
932  / | \
933  op1/ 0 | 1 \op2
934  \ | /
935  \ | /
936  \ p2/
937 
938  // op1 p1 op2
939  // op1 op2 p2
940  */
941 
942  // we test if the edge is deleted
943  // return false;
944 
945  BDS_Point *p1 = e->p1;
946  BDS_Point *p2 = e->p2;
947 
948  if(e->deleted) return false;
949 
950  int nbFaces = e->numfaces();
951  if(nbFaces != 2) return false;
952 
953  if(e->g && e->g->classif_degree == 1) return false;
954 
955  const int CHECK1 = -1, CHECK2 = -1;
956 
957  BDS_Point *op[2];
958  BDS_Point *pts1[4];
959  BDS_Point *pts2[4];
960  e->computeNeighborhood(pts1, pts2, op);
961  if(!op[0] || !op[1]) return false;
962 
963  if(p1->iD == CHECK1 && p2->iD == CHECK2) {
964  printf("- e %d %d --> %d %d\n", p1->iD, p2->iD, op[0]->iD, op[1]->iD);
965  printf("- %d %d %d\n", pts1[0]->iD, pts1[1]->iD, pts1[2]->iD);
966  printf("- %d %d %d\n", pts2[0]->iD, pts2[1]->iD, pts2[2]->iD);
967  }
968 
969  if(!force && !p1->config_modified && !p2->config_modified &&
970  !op[0]->config_modified && !op[1]->config_modified)
971  return false;
972 
973  if(p1->iD == CHECK1 && p2->iD == CHECK2) printf("topology OK \n");
974 
975  BDS_GeomEntity *g1 = nullptr, *g2 = nullptr, *ge = e->g;
976 
977  // compute the orientation of the face
978  // with respect to the edge
979  int orientation = 0;
980  for(int i = 0; i < 3; i++) {
981  if(pts1[i] == p1) {
982  orientation = pts1[(i + 1) % 3] == p2 ? 1 : -1;
983  break;
984  }
985  }
986 
987  if(orientation == 1) {
988  if(!theTest(p1, p2, op[0], p2, p1, op[1], p1, op[1], op[0], op[1], p2,
989  op[0]))
990  return false;
991  }
992  else {
993  if(!theTest(p2, p1, op[0], p1, p2, op[1], p1, op[0], op[1], op[1], op[0],
994  p2))
995  return false;
996  }
997 
998  if(p1->iD == CHECK1 && p2->iD == CHECK2) printf("TEST1 OK\n");
999 
1000  if(!theTest(p1, p2, op[0], op[1])) return false;
1001 
1002  if(p1->iD == CHECK1 && p2->iD == CHECK2) printf("TEST2 OK\n");
1003 
1004  BDS_Edge *p1_op1 = find_edge(p1, op[0], e->faces(0));
1005  BDS_Edge *op1_p2 = find_edge(op[0], p2, e->faces(0));
1006  BDS_Edge *p1_op2 = find_edge(p1, op[1], e->faces(1));
1007  BDS_Edge *op2_p2 = find_edge(op[1], p2, e->faces(1));
1008 
1009  // degenerate
1010  if(p1_op1 == p1_op2 || op2_p2 == op1_p2) return false;
1011 
1012  if(e->faces(0)) {
1013  g1 = e->faces(0)->g;
1014  del_face(e->faces(0));
1015  }
1016  // not a bug !!!
1017  if(e->faces(0)) {
1018  g2 = e->faces(0)->g;
1019  del_face(e->faces(0));
1020  }
1021  del_edge(e);
1022 
1023  edges.push_back(new BDS_Edge(op[0], op[1]));
1024 
1025  BDS_Face *t1, *t2;
1026  if(orientation == 1) {
1027  t1 = new BDS_Face(p1_op1, p1_op2, edges.back());
1028  t2 = new BDS_Face(edges.back(), op2_p2, op1_p2);
1029  }
1030  else {
1031  t1 = new BDS_Face(p1_op2, p1_op1, edges.back());
1032  t2 = new BDS_Face(op2_p2, edges.back(), op1_p2);
1033  }
1034 
1035  t1->g = g1;
1036  t2->g = g2;
1037 
1038  edges.back()->g = ge;
1039 
1040  triangles.push_back(t1);
1041  triangles.push_back(t2);
1042 
1043  p1->config_modified = true;
1044  p2->config_modified = true;
1045  op[0]->config_modified = true;
1046  op[1]->config_modified = true;
1047 
1048  return true;
1049 }
1050 
1052 {
1053  return std::count_if(
1054  begin(_faces), end(_faces),
1055  [](const BDS_Face *const face) { return face->numEdges() == 3; });
1056 }
1057 
1058 /*
1059  VERTICES C AND D LOSE ONE EDGE !!
1060  AS IF TWO EDGE SWAPS WERE DONE
1061 
1062  OTHER GAIN EDGES --> NO SOUCI
1063 
1064  C------B
1065  / \ / \
1066  / \ / \
1067  / \/ \
1068  x-------A-------D
1069  \ /\ /
1070  \ / \ /
1071  x-------x
1072  */
1073 
1075 {
1076  if(!force && e->numfaces() != 2) return false;
1077  if(!force && p->g && p->g->classif_degree == 0) return false;
1078  // not really ok but 'til now this is the best choice not to do collapses on
1079  // model edges
1080  if(!force && p->g && p->g->classif_degree == 1) return false;
1081  if(!force && e->g && p->g) {
1082  if(e->g->classif_degree == 2 && p->g != e->g) return false;
1083  }
1084 
1085  const int CHECK1 = -1, CHECK2 = -1;
1086 
1087  if(e->p1->iD == CHECK1 && e->p2->iD == CHECK2) {
1088  printf("collapsing edge %p %p onto %p\n", e->p1, e->p2, p);
1089  printf("collapsing edge %d %d onto %d\n", e->p1->iD, e->p2->iD, p->iD);
1090  }
1091 
1092  if(!force) {
1093  for(size_t i = 0; i < e->p1->edges.size(); i++) {
1094  for(size_t j = 0; j < e->p2->edges.size(); j++) {
1095  BDS_Point *p1 = e->p1->edges[i]->p1 == e->p1 ? e->p1->edges[i]->p2 :
1096  e->p1->edges[i]->p1;
1097  BDS_Point *p2 = e->p2->edges[j]->p1 == e->p2 ? e->p2->edges[j]->p2 :
1098  e->p2->edges[j]->p1;
1099  if(p1->_periodicCounterpart == p2) return false;
1100  }
1101  }
1102  }
1103 
1104  if(e->numfaces() == 2) {
1105  BDS_Point *oface[2];
1106  e->oppositeof(oface);
1107  if(!oface[0] || !oface[1]) {
1108  Msg::Error("No opposite face in edge collapse");
1109  return false;
1110  }
1111  for(size_t i = 0; i < oface[0]->edges.size(); i++) {
1112  if(oface[0]->edges[i]->p1 == oface[0] &&
1113  oface[0]->edges[i]->p2 == oface[1])
1114  return false;
1115  if(oface[0]->edges[i]->p1 == oface[1] &&
1116  oface[0]->edges[i]->p2 == oface[0])
1117  return false;
1118  }
1119  if(!force && oface[0]->g && oface[0]->g->classif_degree == 2 &&
1120  oface[0]->edges.size() <= 4)
1121  return false;
1122  if(!force && oface[1]->g && oface[1]->g->classif_degree == 2 &&
1123  oface[1]->edges.size() <= 4)
1124  return false;
1125  if(!force && oface[0]->g && oface[0]->g->classif_degree < 2 &&
1126  oface[0]->edges.size() <= 3)
1127  return false;
1128  if(!force && oface[1]->g && oface[1]->g->classif_degree < 2 &&
1129  oface[1]->edges.size() <= 3)
1130  return false;
1131  }
1132  std::vector<BDS_Face *> t = p->getTriangles();
1133  BDS_Point *o = e->othervertex(p);
1134 
1135  BDS_Point *pt[3][1024];
1136  BDS_GeomEntity *gs[1024];
1137  int ept[2][1024];
1138  BDS_GeomEntity *egs[1024];
1139  int nt = 0;
1140  double area_old = 0.0;
1141  double area_new = 0.0;
1142  {
1143  auto it = t.begin();
1144  while(it != t.end()) {
1145  BDS_Face *t = *it;
1146  BDS_Point *pts[4];
1147  if(t->getNodes(pts)) {
1148  double sold = std::abs(surface_triangle_param(pts[0], pts[1], pts[2]));
1149  area_old += sold;
1150  if(t->e1 != e && t->e2 != e && t->e3 != e) {
1151  gs[nt] = t->g;
1152  pt[0][nt] = (pts[0] == p) ? o : pts[0];
1153  pt[1][nt] = (pts[1] == p) ? o : pts[1];
1154  pt[2][nt] = (pts[2] == p) ? o : pts[2];
1155  if(!pt[0][nt] || !pt[1][nt] || !pt[2][nt]) {
1156  Msg::Error("Invalid point in edge collapse");
1157  return false;
1158  }
1159  double snew =
1160  std::abs(surface_triangle_param(pt[0][nt], pt[1][nt], pt[2][nt]));
1161  if(!force && snew < .02 * sold) { return false; }
1162  area_new += snew;
1163  ++nt;
1164  }
1165  }
1166  ++it;
1167  }
1168  }
1169 
1170  // if(!force && nt == 2) return false;
1171 
1172  if(!force && fabs(area_old - area_new) > 1.e-12 * (area_old + area_new)) {
1173  // printf("%g %g\n", fabs(area_old - area_new), 1.e-12 * (area_old +
1174  // area_new));
1175  return false;
1176  }
1177  {
1178  auto it = t.begin();
1179  while(it != t.end()) {
1180  del_face(*it);
1181  ++it;
1182  }
1183  }
1184 
1185  int kk = 0;
1186  {
1187  std::vector<BDS_Edge *> edges(p->edges);
1188  auto eit = edges.begin();
1189  while(eit != edges.end()) {
1190  (*eit)->p1->config_modified = (*eit)->p2->config_modified = true;
1191  ept[0][kk] = ((*eit)->p1 == p) ? (o ? o->iD : -1) : (*eit)->p1->iD;
1192  ept[1][kk] = ((*eit)->p2 == p) ? (o ? o->iD : -1) : (*eit)->p2->iD;
1193  if(ept[0][kk] < 0 || ept[1][kk] < 0) {
1194  Msg::Error("Something wrong in edge collapse");
1195  return false;
1196  }
1197  egs[kk++] = (*eit)->g;
1198  del_edge(*eit);
1199  ++eit;
1200  }
1201  }
1202 
1203  // FIXME
1204  // del_point(p);
1205 
1206  {
1207  for(int k = 0; k < nt; k++) {
1208  BDS_Face *t = add_triangle(pt[0][k]->iD, pt[1][k]->iD, pt[2][k]->iD);
1209  t->g = gs[k];
1210  }
1211  }
1212 
1213  for(int i = 0; i < kk; ++i) {
1214  BDS_Edge *e = find_edge(ept[0][i], ept[1][i]);
1215  if(e && !e->g) e->g = egs[i];
1216  }
1217 
1218  return true;
1219 }
1220 
1221 // Tutte's simple smoothing
1222 // other implementations are coming
1223 
1224 static inline bool validityOfCavity(const BDS_Point *p,
1225  const std::vector<BDS_Point *> &nbg)
1226 {
1227  double p_[2] = {p->u, p->v};
1228  double q_[2] = {nbg[0]->degenerated == 1 ? nbg[1]->u : nbg[0]->u,
1229  nbg[0]->degenerated == 2 ? nbg[1]->v : nbg[0]->v};
1230  double r_[2] = {nbg[1]->degenerated == 1 ? nbg[0]->u : nbg[1]->u,
1231  nbg[1]->degenerated == 2 ? nbg[0]->v : nbg[1]->v};
1232  double sign = robustPredicates::orient2d(p_, q_, r_);
1233  for(size_t i = 1; i < nbg.size(); ++i) {
1234  BDS_Point *p0 = nbg[i];
1235  BDS_Point *p1 = nbg[(i + 1) % nbg.size()];
1236  double qq_[2] = {p0->degenerated == 1 ? p1->u : p0->u,
1237  p0->degenerated == 2 ? p1->v : p0->v};
1238  double rr_[2] = {p1->degenerated == 1 ? p0->u : p1->u,
1239  p1->degenerated == 2 ? p0->v : p1->v};
1240  double sign_ = robustPredicates::orient2d(p_, qq_, rr_);
1241  if(sign * sign_ <= 0) return false;
1242  }
1243  return true;
1244 }
1245 
1247  std::vector<BDS_Point *> &nbg,
1248  std::vector<BDS_Face *> &ts,
1249  int CHECK)
1250 {
1251  if(p->iD == CHECK) {
1252  printf("LISTING THE TRIANGLES\n");
1253  for(size_t i = 0; i < ts.size(); i++) {
1254  BDS_Point *pts[4];
1255  if(ts[i]->getNodes(pts)) {
1256  printf("TR %lu : %p %p %p\n", i, pts[0], pts[1], pts[2]);
1257  printf("TR %lu : %d %d - %d %d - %d %d\n", i, ts[i]->e1->p1->iD,
1258  ts[i]->e1->p2->iD, ts[i]->e2->p1->iD, ts[i]->e2->p2->iD,
1259  ts[i]->e3->p1->iD, ts[i]->e3->p2->iD);
1260  }
1261  }
1262  }
1263 
1264  if(ts.empty()) return false;
1265  while(1) {
1266  bool found = false;
1267  for(size_t i = 0; i < ts.size(); i++) {
1268  BDS_Point *pts[4];
1269  if(!ts[i]->getNodes(pts)) continue;
1270  BDS_Point *pp[2];
1271  if(pts[0] == p) {
1272  pp[0] = pts[1];
1273  pp[1] = pts[2];
1274  }
1275  else if(pts[1] == p) {
1276  pp[0] = pts[0];
1277  pp[1] = pts[2];
1278  }
1279  else {
1280  pp[0] = pts[0];
1281  pp[1] = pts[1];
1282  }
1283  if(nbg.empty()) {
1284  nbg.push_back(pp[0]);
1285  nbg.push_back(pp[1]);
1286  found = true;
1287  break;
1288  }
1289  else {
1290  BDS_Point *p0 = nbg[nbg.size() - 2];
1291  BDS_Point *p1 = nbg[nbg.size() - 1];
1292  if(p1 == pp[0] && p0 != pp[1]) {
1293  nbg.push_back(pp[1]);
1294  found = true;
1295  break;
1296  }
1297  else if(p1 == pp[1] && p0 != pp[0]) {
1298  nbg.push_back(pp[0]);
1299  found = true;
1300  break;
1301  }
1302  }
1303  }
1304 
1305  if(nbg.size() == ts.size()) break;
1306  if(!found) return false;
1307  }
1308 
1309  if(p->iD == CHECK) {
1310  printf("FINALLY : ");
1311  for(size_t i = 0; i < nbg.size(); i++) { printf("%d ", nbg[i]->iD); }
1312  printf("\n");
1313  }
1314  return true;
1315 }
1316 
1317 static inline double getTutteEnergy(const BDS_Point *p,
1318  const std::vector<BDS_Point *> &nbg,
1319  double &RATIO)
1320 {
1321  if(nbg.empty()) return 1.e22;
1322  double E = 0;
1323  double MAX = 0., MIN = 0.;
1324  for(size_t i = 0; i < nbg.size(); ++i) {
1325  const double dx = p->X - nbg[i]->X;
1326  const double dy = p->Y - nbg[i]->Y;
1327  const double dz = p->Z - nbg[i]->Z;
1328  const double l2 = dx * dx + dy * dy + dz * dz;
1329  MAX = i ? std::max(MAX, l2) : l2;
1330  MIN = i ? std::min(MIN, l2) : l2;
1331  E += l2;
1332  }
1333  if(!MAX) return 1.e22;
1334  RATIO = MIN / MAX;
1335  return E;
1336 }
1337 
1338 static inline void getCentroidUV(const BDS_Point *p, GFace *gf,
1339  const std::vector<SPoint2> &kernel,
1340  const std::vector<double> &lc, double &U,
1341  double &V, double &LC)
1342 {
1343  U = V = LC = 0.;
1344  double factSum = 0;
1345  for(size_t i = 0; i < kernel.size(); ++i) {
1346  GPoint gp = gf->point(kernel[i]);
1347  double du = p->u - gp.u();
1348  double dv = p->v - gp.v();
1349  double denom = (du * du + dv * dv);
1350  if(denom) {
1351  double dx = p->X - gp.x();
1352  double dy = p->Y - gp.y();
1353  double dz = p->Z - gp.z();
1354  double fact = sqrt((dx * dx + dy * dy + dz * dz) / denom);
1355  factSum += fact;
1356  U += kernel[i].x() * fact;
1357  V += kernel[i].y() * fact;
1358  LC += lc[i] * fact;
1359  }
1360  }
1361  if(factSum) {
1362  U /= factSum;
1363  V /= factSum;
1364  LC /= factSum;
1365  }
1366 }
1367 
1368 static inline void getCentroidUV(const std::vector<SPoint2> &kernel,
1369  const std::vector<double> &lc, double &U,
1370  double &V, double &LC)
1371 {
1372  U = V = LC = 0.;
1373  for(size_t i = 0; i < kernel.size(); ++i) {
1374  U += kernel[i].x();
1375  V += kernel[i].y();
1376  LC += lc[i];
1377  }
1378  U /= kernel.size();
1379  V /= kernel.size();
1380  LC /= kernel.size();
1381 }
1382 
1383 static inline void getIntersection(const SPoint2 &p1, const SPoint2 &p2,
1384  const SPoint2 &q1, const SPoint2 &q2,
1385  double x[2])
1386 {
1387  double A[2][2];
1388  A[0][0] = p2.x() - p1.x();
1389  A[0][1] = q1.x() - q2.x();
1390  A[1][0] = p2.y() - p1.y();
1391  A[1][1] = q1.y() - q2.y();
1392  double b[2] = {q1.x() - p1.x(), q1.y() - p1.y()};
1393  sys2x2(A, b, x);
1394 }
1395 
1396 static inline void computeSomeKindOfKernel(const BDS_Point *p,
1397  const std::vector<BDS_Point *> &nbg,
1398  std::vector<SPoint2> &kernel,
1399  std::vector<double> &lc, int check)
1400 {
1401  FILE *f = nullptr;
1402  if(p->iD == check) f = fopen("kernel.pos", "w");
1403 
1404  SPoint2 pp(p->u, p->v);
1405  if(p->iD == check) {
1406  fprintf(f, "View \"kernel\"{\n");
1407  fprintf(f, "SP(%g,%g,0){2};\n", p->u, p->v);
1408  }
1409 
1410  double ll = p->lc();
1411  kernel.clear();
1412  lc.clear();
1413  for(size_t i = 0; i < nbg.size(); i++) {
1414  if(nbg[i]->degenerated == 1) {
1415  kernel.push_back(SPoint2(p->u, nbg[i]->v));
1416  kernel.push_back(SPoint2(nbg[(i + 1) % nbg.size()]->u, nbg[i]->v));
1417 
1418  lc.push_back(nbg[i]->lc());
1419  lc.push_back(nbg[i]->lc());
1420  }
1421  else if(nbg[i]->degenerated == 2) {
1422  kernel.push_back(SPoint2(nbg[i]->u, p->v));
1423  kernel.push_back(SPoint2(nbg[i]->u, nbg[(i + 1) % nbg.size()]->v));
1424 
1425  lc.push_back(nbg[i]->lc());
1426  lc.push_back(nbg[i]->lc());
1427  }
1428  else if(nbg[(i + 1) % nbg.size()]->degenerated == 1) {
1429  kernel.push_back(SPoint2(nbg[i]->u, nbg[i]->v));
1430  kernel.push_back(SPoint2(nbg[i]->u, nbg[(i + 1) % nbg.size()]->v));
1431  lc.push_back(nbg[i]->lc());
1432  lc.push_back(nbg[i]->lc());
1433  }
1434  else if(nbg[(i + 1) % nbg.size()]->degenerated == 2) {
1435  kernel.push_back(SPoint2(nbg[i]->u, nbg[i]->v));
1436  kernel.push_back(SPoint2(nbg[(i + 1) % nbg.size()]->u, nbg[i]->v));
1437  lc.push_back(nbg[i]->lc());
1438  lc.push_back(nbg[i]->lc());
1439  }
1440  else {
1441  kernel.push_back(SPoint2(nbg[i]->u, nbg[i]->v));
1442  lc.push_back(nbg[i]->lc());
1443  }
1444  }
1445  // return;
1446  if(p->iD == check) {
1447  for(size_t i = 0; i < kernel.size(); i++) {
1448  fprintf(f, "SL(%g,%g,0,%g,%g,0){4,4};\n", kernel[i].x(), kernel[i].y(),
1449  kernel[(i + 1) % kernel.size()].x(),
1450  kernel[(i + 1) % kernel.size()].y());
1451  }
1452  }
1453 
1454  // bool changed = false;
1455  // we should compute the true kernel
1456  for(size_t i = 0; i < kernel.size(); i++) {
1457  SPoint2 p_now = kernel[i];
1458  double lc_now = lc[i];
1459  for(size_t j = 0; j < kernel.size(); j++) {
1460  if(i != j && i != (j + 1) % kernel.size()) {
1461  const SPoint2 &p0 = kernel[j];
1462  const SPoint2 &p1 = kernel[(j + 1) % kernel.size()];
1463  double x[2];
1464  getIntersection(pp, p_now, p0, p1, x);
1465  if(x[0] > 0 && x[0] < 1.0) {
1466  p_now = (pp * (1. - x[0])) + (p_now * x[0]);
1467  lc_now = ll * (1. - x[0]) + lc_now * x[0];
1468  // changed = true;
1469  }
1470  }
1471  }
1472  kernel[i] = p_now;
1473  lc[i] = lc_now;
1474  }
1475 
1476  if(p->iD == check) {
1477  fprintf(f, "};\n");
1478  fclose(f);
1479  }
1480  // if (changed)getchar();
1481 }
1482 
1484  const std::vector<SPoint2> &kernel, SPoint3 &target,
1485  int N)
1486 {
1487  double minDist = 1.e22;
1488  SPoint2 p0(p->u, p->v);
1489  SPoint2 pMin = p0;
1490  for(size_t i = 0; i < kernel.size(); ++i) {
1491  SPoint2 p1(kernel[i].x(), kernel[i].y());
1492  SPoint2 p2(kernel[(i + 1) % kernel.size()].x(),
1493  kernel[(i + 1) % kernel.size()].y());
1494  for(int j = 1; j < N; j++) {
1495  for(int k = 1; k < N - j; k++) {
1496  double xi = (double)j / (2 * N);
1497  double eta = (double)k / (2 * N);
1498  SPoint2 p = p0 * (1 - xi - eta) + p1 * xi + p2 * eta;
1499  GPoint gp = gf->point(p);
1500  double d = ((target.x() - gp.x()) * (target.x() - gp.x()) +
1501  (target.y() - gp.y()) * (target.y() - gp.y()) +
1502  (target.z() - gp.z()) * (target.z() - gp.z()));
1503  if(d < minDist) {
1504  pMin = p;
1505  minDist = d;
1506  }
1507  }
1508  }
1509  }
1510 
1511  return gf->point(pMin);
1512 }
1513 
1514 static inline bool minimizeTutteEnergyProj(BDS_Point *p, double E_unmoved,
1515  double RATIO,
1516  const std::vector<BDS_Point *> &nbg,
1517  const std::vector<SPoint2> &kernel,
1518  const std::vector<double> &lc,
1519  GFace *gf, int check)
1520 {
1521  SPoint3 x;
1522  double oldX = p->X, oldY = p->Y, oldZ = p->Z, oldU = p->u, oldV = p->v;
1523  double sum = 0;
1524  SPoint3 p0(oldX, oldY, oldZ);
1525  for(size_t i = 0; i < nbg.size(); ++i) {
1526  SPoint3 pi(nbg[i]->X, nbg[i]->Y, nbg[i]->Z);
1527  SPoint3 pip(nbg[(i + 1) % nbg.size()]->X, nbg[(i + 1) % nbg.size()]->Y,
1528  nbg[(i + 1) % nbg.size()]->Z);
1529  SVector3 v1 = pi - p0;
1530  SVector3 v2 = pip - p0;
1531  SVector3 pv = crossprod(v1, v2);
1532  double nrm = pv.norm();
1533  x += (pi + p0 + pip) * (nrm / 3.0);
1534  sum += nrm;
1535  }
1536  x /= sum;
1537  if(p->iD == check) printf("%12.5E %12.5E %12.5E\n", x.x(), x.y(), x.z());
1538  GPoint gp;
1539  if(gf->geomType() == GEntity::BSplineSurface ||
1540  gf->geomType() == GEntity::BezierSurface ||
1541  gf->geomType() == GEntity::Unknown) {
1542  gp = _closestPoint(p, gf, kernel, x, 5);
1543  }
1544  else {
1545  double U, V, LC;
1546  getCentroidUV(kernel, lc, U, V, LC);
1547  double uv[2] = {U, V};
1548  gp = gf->closestPoint(x, uv);
1549  }
1550  p->u = gp.u();
1551  p->v = gp.v();
1552  if(p->iD == check) {
1553  printf("%g %g %d\n", p->u, p->v, validityOfCavity(p, nbg));
1554  }
1555 
1556  if(validityOfCavity(p, nbg)) {
1557  p->X = gp.x();
1558  p->Y = gp.y();
1559  p->Z = gp.z();
1560  double E_moved = getTutteEnergy(p, nbg, RATIO);
1561  if(E_moved < E_unmoved) { return true; }
1562  }
1563 
1564  p->X = oldX;
1565  p->Y = oldY;
1566  p->Z = oldZ;
1567  p->u = oldU;
1568  p->v = oldV;
1569  if(p->iD == check) printf("NO WAY\n");
1570  return false;
1571 }
1572 
1573 static inline bool minimizeTutteEnergyParam(BDS_Point *p, double E_unmoved,
1574  double RATIO1,
1575  const std::vector<BDS_Point *> &nbg,
1576  const std::vector<SPoint2> &kernel,
1577  const std::vector<double> &lc,
1578  GFace *gf, int check)
1579 {
1580  double U, V, LC, oldX = p->X, oldY = p->Y, oldZ = p->Z, oldU = p->u,
1581  oldV = p->v;
1582  double RATIO2 = 0;
1583  getCentroidUV(p, gf, kernel, lc, U, V, LC);
1584  GPoint gp = gf->point(U, V);
1585  if(!gp.succeeded()) return false;
1586  p->X = gp.x();
1587  p->Y = gp.y();
1588  p->Z = gp.z();
1589  double E_moved = getTutteEnergy(p, nbg, RATIO2);
1590 
1591  if(p->iD == check) printf("%g vs %g\n", E_unmoved, E_moved);
1592 
1593  if(E_moved < E_unmoved) {
1594  p->u = U;
1595  p->v = V;
1596  if(!validityOfCavity(p, nbg)) {
1597  p->X = oldX;
1598  p->Y = oldY;
1599  p->Z = oldZ;
1600  p->u = oldU;
1601  p->v = oldV;
1602  return false;
1603  }
1604  p->lc() = LC;
1605  return RATIO2 > .25;
1606  }
1607  p->X = oldX;
1608  p->Y = oldY;
1609  p->Z = oldZ;
1610  return false;
1611 }
1612 
1613 bool BDS_Mesh::smooth_point_centroid(BDS_Point *p, GFace *gf, double threshold)
1614 {
1615  if(p->degenerated) return false;
1616  if(p->g && p->g->classif_degree <= 1) return false;
1617  if(p->g && p->g->classif_tag < 0) {
1618  p->config_modified = true;
1619  return true;
1620  }
1621 
1622  int CHECK = -1;
1623 
1624  if(p->iD == CHECK)
1625  printf("VERTEX %d TRYING TO MOVE from its initial position %g %g\n", CHECK,
1626  p->u, p->v);
1627 
1628  std::vector<BDS_Point *> nbg;
1629  std::vector<double> lc;
1630  std::vector<SPoint2> kernel;
1631  std::vector<BDS_Face *> ts = p->getTriangles();
1632 
1633  if(p->iD == CHECK) printf("%d adjacent triangles\n", (int)ts.size());
1634 
1635  if(!getOrderedNeighboringVertices(p, nbg, ts, CHECK)) return false;
1636 
1637  if(p->iD == CHECK) printf("%d adjacent vertices\n", (int)nbg.size());
1638 
1639  double RATIO = 0;
1640  double E_unmoved = getTutteEnergy(p, nbg, RATIO);
1641  if(RATIO > threshold) return false;
1642 
1643  computeSomeKindOfKernel(p, nbg, kernel, lc, CHECK);
1644 
1645  if(!minimizeTutteEnergyParam(p, E_unmoved, RATIO, nbg, kernel, lc, gf,
1646  CHECK)) {
1647  if(!minimizeTutteEnergyProj(p, E_unmoved, RATIO, nbg, kernel, lc, gf,
1648  CHECK)) {
1649  return false;
1650  }
1651  else {
1652  p->config_modified = true;
1653  E_unmoved = getTutteEnergy(p, nbg, RATIO);
1654  minimizeTutteEnergyProj(p, E_unmoved, RATIO, nbg, kernel, lc, gf, CHECK);
1655  }
1656  }
1657  else {
1658  p->config_modified = true;
1659  }
1660 
1661  return true;
1662 }
BDS_Face::deleted
bool deleted
Definition: BDS.h:222
crossprod
SVector3 crossprod(const SVector3 &a, const SVector3 &b)
Definition: SVector3.h:150
GPoint::succeeded
bool succeeded() const
Definition: GPoint.h:63
BDS_Mesh::smooth_point_centroid
bool smooth_point_centroid(BDS_Point *p, GFace *gf, double thresh)
Definition: BDS.cpp:1613
qualityMeasures.h
BDS_Mesh::find_triangle
BDS_Face * find_triangle(BDS_Edge *e1, BDS_Edge *e2, BDS_Edge *e3)
Definition: BDS.cpp:462
BDS_Edge::p1
BDS_Point * p1
Definition: BDS.h:160
vector_triangle_parametric
static double vector_triangle_parametric(BDS_Point *p1, BDS_Point *p2, BDS_Point *p3)
Definition: BDS.cpp:177
BDS_Edge::deleted
bool deleted
Definition: BDS.h:159
Msg::GetVerbosity
static int GetVerbosity()
Definition: GmshMessage.cpp:254
surface_triangle_param
static double surface_triangle_param(BDS_Point *p1, BDS_Point *p2, BDS_Point *p3)
Definition: BDS.cpp:191
GPoint::y
double y() const
Definition: GPoint.h:22
GFace.h
BDS_SwapEdgeTestNormals::gf
GFace * gf
Definition: BDS.h:303
_cos_N
static double _cos_N(BDS_Point *_p1, BDS_Point *_p2, BDS_Point *_p3, GFace *gf)
Definition: BDS.cpp:21
GFace
Definition: GFace.h:33
vector_triangle
static void vector_triangle(BDS_Point *p1, BDS_Point *p2, BDS_Point *p3, double c[3])
Definition: BDS.cpp:167
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
SPoint2
Definition: SPoint2.h:12
OS.h
MAX
#define MAX(a, b)
Definition: libol1.c:81
BDS_Edge::computeNeighborhood
void computeNeighborhood(BDS_Point *oface[2], BDS_Point *t1[4], BDS_Point *t2[4]) const
Definition: BDS.cpp:546
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
BDS_Face::e4
BDS_Edge * e4
Definition: BDS.h:223
BDS_Mesh::find_point
BDS_Point * find_point(int num)
Definition: BDS.cpp:277
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
BDS_Edge::numTriangles
int numTriangles() const
Definition: BDS.cpp:1051
getTutteEnergy
static double getTutteEnergy(const BDS_Point *p, const std::vector< BDS_Point * > &nbg, double &RATIO)
Definition: BDS.cpp:1317
BDS_SwapEdgeTestQuality::testSmallTriangles
bool testSmallTriangles
Definition: BDS.h:286
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
BDS_Mesh::split_edge
bool split_edge(BDS_Edge *, BDS_Point *, bool check_area_param=false)
Definition: BDS.cpp:674
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
getCentroidUV
static void getCentroidUV(const BDS_Point *p, GFace *gf, const std::vector< SPoint2 > &kernel, const std::vector< double > &lc, double &U, double &V, double &LC)
Definition: BDS.cpp:1338
BDS_Edge::g
BDS_GeomEntity * g
Definition: BDS.h:161
BDS_Mesh::get_geom
BDS_GeomEntity * get_geom(int p1, int p2)
Definition: BDS.cpp:597
Intersect_Edges_2d
int Intersect_Edges_2d(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, double x[2])
Definition: BDS.cpp:307
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
GFace::point
virtual GPoint point(double par1, double par2) const =0
SVector3
Definition: SVector3.h:16
BDS_Face::e3
BDS_Edge * e3
Definition: BDS.h:223
BDS_Point::g
BDS_GeomEntity * g
Definition: BDS.h:62
BDS_Face::numEdges
int numEdges() const
Definition: BDS.h:174
BDS_Mesh::del_face
void del_face(BDS_Face *t)
Definition: BDS.cpp:515
BDS_SwapEdgeTest
Definition: BDS.h:261
BDS_Point::config_modified
bool config_modified
Definition: BDS.h:58
BDS_Mesh::triangles
std::vector< BDS_Face * > triangles
Definition: BDS.h:349
GmshMessage.h
BDS_Point::edges
std::vector< BDS_Edge * > edges
Definition: BDS.h:63
BDS_Face::e2
BDS_Edge * e2
Definition: BDS.h:223
BDS_GeomEntity::classif_degree
int classif_degree
Definition: BDS.h:34
validityOfCavity
static bool validityOfCavity(const BDS_Point *p, const std::vector< BDS_Point * > &nbg)
Definition: BDS.cpp:1224
GPoint
Definition: GPoint.h:13
BDS_Edge::_faces
std::vector< BDS_Face * > _faces
Definition: BDS.h:86
GFace::closestPoint
virtual GPoint closestPoint(const SPoint3 &queryPoint, const double initialGuess[2]) const
Definition: GFace.cpp:1323
BDS_Mesh::collapse_edge_parametric
bool collapse_edge_parametric(BDS_Edge *, BDS_Point *, bool=false)
Definition: BDS.cpp:1074
BDS_Edge::oppositeof
void oppositeof(BDS_Point *oface[2]) const
Definition: BDS.cpp:572
BDS_Edge::p2
BDS_Point * p2
Definition: BDS.h:160
BDS_Edge::otherFace
BDS_Face * otherFace(const BDS_Face *f) const
Definition: BDS.h:135
Fopen
FILE * Fopen(const char *f, const char *mode)
Definition: OS.cpp:273
BDS_GeomEntity::classif_tag
int classif_tag
Definition: BDS.h:33
GPoint::z
double z() const
Definition: GPoint.h:23
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
BDS_Mesh::geom
std::set< BDS_GeomEntity *, GeomLessThan > geom
Definition: BDS.h:346
computeSomeKindOfKernel
static void computeSomeKindOfKernel(const BDS_Point *p, const std::vector< BDS_Point * > &nbg, std::vector< SPoint2 > &kernel, std::vector< double > &lc, int check)
Definition: BDS.cpp:1396
BDS_SwapEdgeTestRecover::operator()
virtual bool operator()(BDS_Point *p1, BDS_Point *p2, BDS_Point *q1, BDS_Point *q2) const
Definition: BDS.cpp:795
BDS_SwapEdgeTestRecover
Definition: BDS.h:273
BDS_Point::X
double X
Definition: BDS.h:56
EdgeToRecover
Definition: BDS.h:316
GPoint::u
double u() const
Definition: GPoint.h:27
BDS_Mesh::points
std::set< BDS_Point *, PointLessThan > points
Definition: BDS.h:347
BDS_GeomEntity
Definition: BDS.h:31
GEntity::BSplineSurface
@ BSplineSurface
Definition: GEntity.h:113
BDS_Face_Validity
double BDS_Face_Validity(GFace *gf, BDS_Face *f)
Definition: BDS.cpp:33
recur_tag
void recur_tag(BDS_Face *t, BDS_GeomEntity *g)
Definition: BDS.cpp:605
qmTriangle::gamma
static double gamma(MTriangle *f)
Definition: qualityMeasures.cpp:146
Numeric.h
BDS_Point::v
double v
Definition: BDS.h:57
BDS_Point::degenerated
short degenerated
Definition: BDS.h:59
BDS_Mesh::recover_edge_fast
BDS_Edge * recover_edge_fast(BDS_Point *p1, BDS_Point *p2)
Definition: BDS.cpp:323
meshGFaceDelaunayInsertion.h
BDS_Mesh::cleanup
void cleanup()
Definition: BDS.cpp:642
GEntity::geomType
virtual GeomType geomType() const
Definition: GEntity.h:238
SVector3::norm
double norm() const
Definition: SVector3.h:33
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
minimizeTutteEnergyParam
static bool minimizeTutteEnergyParam(BDS_Point *p, double E_unmoved, double RATIO1, const std::vector< BDS_Point * > &nbg, const std::vector< SPoint2 > &kernel, const std::vector< double > &lc, GFace *gf, int check)
Definition: BDS.cpp:1573
is_equivalent
static bool is_equivalent(BDS_Edge *e1, BDS_Edge *e2, BDS_Edge *e3, BDS_Edge *o1, BDS_Edge *o2, BDS_Edge *o3)
Definition: BDS.cpp:451
BDS_Face::e1
BDS_Edge * e1
Definition: BDS.h:223
BDS_SwapEdgeTestQuality::operator()
virtual bool operator()(BDS_Point *p1, BDS_Point *p2, BDS_Point *q1, BDS_Point *q2) const
Definition: BDS.cpp:823
BDS.h
discreteFace.h
BDS_Point::iD
int iD
Definition: BDS.h:61
SVector3::x
double x(void) const
Definition: SVector3.h:30
_closestPoint
static GPoint _closestPoint(BDS_Point *p, GFace *gf, const std::vector< SPoint2 > &kernel, SPoint3 &target, int N)
Definition: BDS.cpp:1483
BDS_Edge::faces
BDS_Face * faces(std::size_t const i) const
Definition: BDS.h:103
normal_triangle
void normal_triangle(BDS_Point *p1, BDS_Point *p2, BDS_Point *p3, double c[3])
Definition: BDS.cpp:185
BDS_Edge::numfaces
int numfaces() const
Definition: BDS.h:110
DESTROOOY
void DESTROOOY(IT beg, IT end)
Definition: BDS.cpp:630
BDS_Face
Definition: BDS.h:164
BDS_Mesh::add_geom
void add_geom(int degree, int tag)
Definition: BDS.cpp:539
BDS_Edge::del
void del(BDS_Face *t)
Definition: BDS.h:147
GEntity::BezierSurface
@ BezierSurface
Definition: GEntity.h:114
BDS_Face::getNodes
bool getNodes(BDS_Point *_n[4]) const
Definition: BDS.h:201
BDS_Edge::othervertex
BDS_Point * othervertex(const BDS_Point *p) const
Definition: BDS.h:120
outputScalarField
void outputScalarField(std::vector< BDS_Face * > &t, const char *iii, int param, GFace *gf)
Definition: BDS.cpp:46
SPoint2::x
double x(void) const
Definition: SPoint2.h:86
sys2x2
int sys2x2(double mat[2][2], double b[2], double res[2])
Definition: Numeric.cpp:101
BDS_SwapEdgeTestNormals::operator()
virtual bool operator()(BDS_Point *p1, BDS_Point *p2, BDS_Point *q1, BDS_Point *q2) const
Definition: BDS.cpp:893
BDS_Point::del
void del(BDS_Edge *e)
Definition: BDS.h:71
SVector3::y
double y(void) const
Definition: SVector3.h:31
z
const double z
Definition: GaussQuadratureQuad.cpp:56
BDS_Mesh::recover_edge
BDS_Edge * recover_edge(int p1, int p2, bool &_fatal, std::set< EdgeToRecover > *e2r=nullptr, std::set< EdgeToRecover > *not_recovered=nullptr)
Definition: BDS.cpp:347
BDS_Mesh::add_point
BDS_Point * add_point(int num, double x, double y, double z)
Definition: BDS.cpp:257
BDS_Point::Y
double Y
Definition: BDS.h:56
BDS_Mesh::del_edge
void del_edge(BDS_Edge *e)
Definition: BDS.cpp:525
getIntersection
static void getIntersection(const SPoint2 &p1, const SPoint2 &p2, const SPoint2 &q1, const SPoint2 &q2, double x[2])
Definition: BDS.cpp:1383
BDS_Point::getTriangles
std::vector< BDS_Face * > getTriangles() const
Definition: BDS.cpp:237
BDS_Mesh::del_point
void del_point(BDS_Point *p)
Definition: BDS.cpp:533
SVector3::z
double z(void) const
Definition: SVector3.h:32
BDS_SwapEdgeTestQuality::testQuality
bool testQuality
Definition: BDS.h:286
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
BDS_Mesh::~BDS_Mesh
virtual ~BDS_Mesh()
Definition: BDS.cpp:665
GPoint::v
double v() const
Definition: GPoint.h:28
BDS_SwapEdgeTestNormals::_ori
double _ori
Definition: BDS.h:304
BDS_Edge
Definition: BDS.h:85
BDS_Point::u
double u
Definition: BDS.h:57
MIN
#define MIN(a, b)
Definition: libol1.c:80
is_not_deleted
Definition: BDS.cpp:638
BDS_Point
Definition: BDS.h:49
BDS_Mesh::edges
std::vector< BDS_Edge * > edges
Definition: BDS.h:348
GFace::normal
virtual SVector3 normal(const SPoint2 &param) const
Definition: GFace.cpp:1416
getOrderedNeighboringVertices
static bool getOrderedNeighboringVertices(BDS_Point *p, std::vector< BDS_Point * > &nbg, std::vector< BDS_Face * > &ts, int CHECK)
Definition: BDS.cpp:1246
BDS_Point::lc
double & lc()
Definition: BDS.h:66
BDS_Mesh::add_edge
BDS_Edge * add_edge(int p1, int p2)
Definition: BDS.cpp:479
norme
double norme(double a[3])
Definition: Numeric.h:123
PointLessThanLexicographic::t
static double t
Definition: BDS.h:242
GPoint::x
double x() const
Definition: GPoint.h:21
minimizeTutteEnergyProj
static bool minimizeTutteEnergyProj(BDS_Point *p, double E_unmoved, double RATIO, const std::vector< BDS_Point * > &nbg, const std::vector< SPoint2 > &kernel, const std::vector< double > &lc, GFace *gf, int check)
Definition: BDS.cpp:1514
BDS_Face::g
BDS_GeomEntity * g
Definition: BDS.h:224
BDS_Face::oppositeEdge
BDS_Edge * oppositeEdge(BDS_Point *p)
Definition: BDS.h:175
is_not_deleted::operator()
bool operator()(T *const face)
Definition: BDS.cpp:639
BDS_Mesh::swap_edge
bool swap_edge(BDS_Edge *, const BDS_SwapEdgeTest &theTest, bool force=false)
Can invalidate the iterators for edge.
Definition: BDS.cpp:926
robustPredicates::orient2d
REAL orient2d(REAL *pa, REAL *pb, REAL *pc)
Definition: robustPredicates.cpp:1633
BDS_Point::_periodicCounterpart
BDS_Point * _periodicCounterpart
Definition: BDS.h:60
BDS_Mesh::MAXPOINTNUMBER
int MAXPOINTNUMBER
Definition: BDS.h:341
BDS_Mesh::find_edge
BDS_Edge * find_edge(int p1, int p2)
Definition: BDS.cpp:301
BDS_Mesh::add_triangle
BDS_Face * add_triangle(int p1, int p2, int p3)
Definition: BDS.cpp:496
SVector3::normalize
double normalize()
Definition: SVector3.h:38
BDS_Point::Z
double Z
Definition: BDS.h:56
SPoint2::y
double y(void) const
Definition: SPoint2.h:88