gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
Geo.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 <stdlib.h>
7 #include <string.h>
8 #include "GmshMessage.h"
9 #include "GmshConfig.h"
10 #include "Numeric.h"
11 #include "GModel.h"
12 #include "GModelIO_GEO.h"
13 #include "GModelIO_OCC.h"
14 #include "Geo.h"
15 #include "GeoInterpolation.h"
16 #include "Context.h"
17 #include "MVertexRTree.h"
18 #include "fullMatrix.h"
19 
20 #if defined(HAVE_MESH)
21 #include "Field.h"
22 #endif
23 
24 #if defined(HAVE_PARSER)
25 #include "Parser.h"
26 #endif
27 
28 static List_T *ListOfTransformedPoints = nullptr;
29 
30 int CompareVertex(const void *a, const void *b)
31 {
32  Vertex *q = *(Vertex **)a;
33  Vertex *w = *(Vertex **)b;
34  return abs(q->Num) - abs(w->Num);
35 }
36 
37 static int ComparePosition(const void *a, const void *b)
38 {
39  Vertex *q = *(Vertex **)a;
40  Vertex *w = *(Vertex **)b;
41 
42  if(!q || !w) {
43  Msg::Error("Cannot compare position of null points");
44  return 99;
45  }
46 
47  // Warning: tolerance (before 1.61, it was set to 1.e-10 *
48  // CTX::instance()->lc)
49  double eps = CTX::instance()->geom.tolerance * CTX::instance()->lc;
50 
51  if(q->Pos.X - w->Pos.X > eps) return 1;
52  if(q->Pos.X - w->Pos.X < -eps) return -1;
53  if(q->Pos.Y - w->Pos.Y > eps) return 1;
54  if(q->Pos.Y - w->Pos.Y < -eps) return -1;
55  if(q->Pos.Z - w->Pos.Z > eps) return 1;
56  if(q->Pos.Z - w->Pos.Z < -eps) return -1;
57  return 0;
58 }
59 
60 int CompareSurfaceLoop(const void *a, const void *b)
61 {
62  SurfaceLoop *q = *(SurfaceLoop **)a;
63  SurfaceLoop *w = *(SurfaceLoop **)b;
64  return q->Num - w->Num;
65 }
66 
67 int CompareEdgeLoop(const void *a, const void *b)
68 {
69  EdgeLoop *q = *(EdgeLoop **)a;
70  EdgeLoop *w = *(EdgeLoop **)b;
71  return q->Num - w->Num;
72 }
73 
74 int CompareCurve(const void *a, const void *b)
75 {
76  Curve *q = *(Curve **)a;
77  Curve *w = *(Curve **)b;
78  return q->Num - w->Num;
79 }
80 
81 int CompareSurface(const void *a, const void *b)
82 {
83  Surface *q = *(Surface **)a;
84  Surface *w = *(Surface **)b;
85  return q->Num - w->Num;
86 }
87 
88 int CompareVolume(const void *a, const void *b)
89 {
90  Volume *q = *(Volume **)a;
91  Volume *w = *(Volume **)b;
92  return q->Num - w->Num;
93 }
94 
95 int ComparePhysicalGroup(const void *a, const void *b)
96 {
97  PhysicalGroup *q = *(PhysicalGroup **)a;
98  PhysicalGroup *w = *(PhysicalGroup **)b;
99  int cmp = q->Typ - w->Typ;
100  if(cmp)
101  return cmp;
102  else
103  return q->Num - w->Num;
104 }
105 
106 Vertex *CreateVertex(int Num, double X, double Y, double Z, double lc, double u)
107 {
108  Vertex *pV = new Vertex(X, Y, Z, lc);
109  pV->w = 1.0;
110  pV->Num = Num;
112  0, std::max(GModel::current()->getGEOInternals()->getMaxTag(0), Num));
113  pV->u = u;
114  pV->geometry = nullptr;
115  return pV;
116 }
117 
118 Vertex *CreateVertex(int Num, double u, double v, gmshSurface *surf, double lc)
119 {
120  SPoint3 p = surf->point(u, v);
121  Vertex *pV = new Vertex(p.x(), p.y(), p.z(), lc);
122  pV->w = 1.0;
123  pV->Num = Num;
125  0, std::max(GModel::current()->getGEOInternals()->getMaxTag(0), Num));
126  pV->u = u;
127  pV->geometry = surf;
128  pV->pntOnGeometry = SPoint2(u, v);
129  surf->vertex_defined_on_surface = true;
130  return pV;
131 }
132 
133 void FreeVertex(void *a, void *b)
134 {
135  Vertex *v = *(Vertex **)a;
136  if(v) {
137  delete v;
138  v = nullptr;
139  }
140 }
141 
142 PhysicalGroup *CreatePhysicalGroup(int Num, int typ, List_T *intlist)
143 {
144  PhysicalGroup *p = new PhysicalGroup;
145  p->Entities = List_Create(List_Nbr(intlist), 1, sizeof(int));
146  p->Num = Num;
148  std::max(GModel::current()->getGEOInternals()->getMaxPhysicalTag(), Num));
149  p->Typ = typ;
150  for(int i = 0; i < List_Nbr(intlist); i++) {
151  int j;
152  List_Read(intlist, i, &j);
153  List_Add(p->Entities, &j);
154  }
155  return p;
156 }
157 
158 void FreePhysicalGroup(void *a, void *b)
159 {
160  PhysicalGroup *p = *(PhysicalGroup **)a;
161  if(p) {
162  List_Delete(p->Entities);
163  delete p;
164  p = nullptr;
165  }
166 }
167 
168 EdgeLoop *CreateEdgeLoop(int Num, List_T *intlist)
169 {
170  EdgeLoop *l = new EdgeLoop;
171  l->Curves = List_Create(List_Nbr(intlist), 1, sizeof(int));
172  l->Num = Num;
174  -1, std::max(GModel::current()->getGEOInternals()->getMaxTag(-1), Num));
175  for(int i = 0; i < List_Nbr(intlist); i++) {
176  int j;
177  List_Read(intlist, i, &j);
178  List_Add(l->Curves, &j);
179  }
180  return l;
181 }
182 
183 void FreeEdgeLoop(void *a, void *b)
184 {
185  EdgeLoop *l = *(EdgeLoop **)a;
186  if(l) {
187  List_Delete(l->Curves);
188  delete l;
189  l = nullptr;
190  }
191 }
192 
194 {
195  SurfaceLoop *l = new SurfaceLoop;
196  l->Surfaces = List_Create(List_Nbr(intlist), 1, sizeof(int));
197  l->Num = Num;
199  -2, std::max(GModel::current()->getGEOInternals()->getMaxTag(-2), Num));
200  for(int i = 0; i < List_Nbr(intlist); i++) {
201  int j;
202  List_Read(intlist, i, &j);
203  List_Add(l->Surfaces, &j);
204  }
205  return l;
206 }
207 
208 void FreeSurfaceLoop(void *a, void *b)
209 {
210  SurfaceLoop *l = *(SurfaceLoop **)a;
211  if(l) {
212  List_Delete(l->Surfaces);
213  delete l;
214  l = nullptr;
215  }
216 }
217 
218 static void direction(Vertex *v1, Vertex *v2, double d[3])
219 {
220  d[0] = v2->Pos.X - v1->Pos.X;
221  d[1] = v2->Pos.Y - v1->Pos.Y;
222  d[2] = v2->Pos.Z - v1->Pos.Z;
223 }
224 
226 {
227  bool ok = true;
228 
229  // if all control points of a curve are on the same geometry, then the curve
230  // is also on the geometry
231  int NN = List_Nbr(c->Control_Points);
232  if(NN) {
233  Vertex *pV;
234  List_Read(c->Control_Points, 0, &pV);
235  c->geometry = pV->geometry;
236  for(int i = 1; i < NN; i++) {
237  List_Read(c->Control_Points, i, &pV);
238  if(c->geometry != pV->geometry) {
239  c->geometry = nullptr;
240  break;
241  }
242  }
243  }
244 
245  if((c->Typ == MSH_SEGM_CIRC || c->Typ == MSH_SEGM_CIRC_INV ||
246  c->Typ == MSH_SEGM_ELLI || c->Typ == MSH_SEGM_ELLI_INV) &&
247  (NN == 3 || NN == 4)) {
248  // v[0] = first point
249  // v[1] = center
250  // v[2] = last point
251  // v[3] = major axis point
252  Vertex *v[4];
253  if(List_Nbr(c->Control_Points) == 4)
254  List_Read(c->Control_Points, 2, &v[3]);
255  else
256  v[3] = nullptr;
257  if(c->Typ == MSH_SEGM_CIRC_INV || c->Typ == MSH_SEGM_ELLI_INV) {
258  List_Read(c->Control_Points, 0, &v[2]);
259  List_Read(c->Control_Points, 1, &v[1]);
260  if(!v[3])
261  List_Read(c->Control_Points, 2, &v[0]);
262  else
263  List_Read(c->Control_Points, 3, &v[0]);
264  }
265  else {
266  List_Read(c->Control_Points, 0, &v[0]);
267  List_Read(c->Control_Points, 1, &v[1]);
268  if(!v[3])
269  List_Read(c->Control_Points, 2, &v[2]);
270  else
271  List_Read(c->Control_Points, 3, &v[2]);
272  }
273  double dir12[3], dir32[3], dir42[3] = {0., 0., 0.};
274  direction(v[1], v[0], dir12);
275  direction(v[1], v[2], dir32);
276  if(v[3]) direction(v[1], v[3], dir42);
277  // v0 = vector center->first pt
278  // v2 = vector center->last pt
279  // v3 = vector center->major axis pt
280  Vertex v0, v2, v3;
281  v0.Pos.X = dir12[0];
282  v0.Pos.Y = dir12[1];
283  v0.Pos.Z = dir12[2];
284  v2.Pos.X = dir32[0];
285  v2.Pos.Y = dir32[1];
286  v2.Pos.Z = dir32[2];
287  if(v[3]) {
288  v3.Pos.X = dir42[0];
289  v3.Pos.Y = dir42[1];
290  v3.Pos.Z = dir42[2];
291  }
292  norme(dir12);
293  norme(dir32);
294  double n[3];
295  prodve(dir12, dir32, n);
296  bool isValid = true;
297  if(norm3(n) < 1.e-15) { isValid = false; }
298  else {
299  norme(n);
300  if((fabs(n[0]) < 1.e-5 && fabs(n[1]) < 1.e-5 && fabs(n[2]) < 1.e-5)) {
301  isValid = false;
302  }
303  }
304  // use provided plane if unable to compute it from input points...
305  if(!isValid) {
306  n[0] = c->Circle.n[0];
307  n[1] = c->Circle.n[1];
308  n[2] = c->Circle.n[2];
309  norme(n);
310  }
311  double m[3];
312  prodve(n, dir12, m);
313  norme(m);
314  double mat[3][3];
315  mat[2][0] = c->Circle.invmat[0][2] = n[0];
316  mat[2][1] = c->Circle.invmat[1][2] = n[1];
317  mat[2][2] = c->Circle.invmat[2][2] = n[2];
318  mat[1][0] = c->Circle.invmat[0][1] = m[0];
319  mat[1][1] = c->Circle.invmat[1][1] = m[1];
320  mat[1][2] = c->Circle.invmat[2][1] = m[2];
321  mat[0][0] = c->Circle.invmat[0][0] = dir12[0];
322  mat[0][1] = c->Circle.invmat[1][0] = dir12[1];
323  mat[0][2] = c->Circle.invmat[2][0] = dir12[2];
324  // assume circle in z=0 plane
325  if(CTX::instance()->geom.oldCircle) {
326  if(n[0] == 0.0 && n[1] == 0.0) {
327  mat[2][0] = c->Circle.invmat[0][2] = 0;
328  mat[2][1] = c->Circle.invmat[1][2] = 0;
329  mat[2][2] = c->Circle.invmat[2][2] = 1;
330  mat[1][0] = c->Circle.invmat[0][1] = 0;
331  mat[1][1] = c->Circle.invmat[1][1] = 1;
332  mat[1][2] = c->Circle.invmat[2][1] = 0;
333  mat[0][0] = c->Circle.invmat[0][0] = 1;
334  mat[0][1] = c->Circle.invmat[1][0] = 0;
335  mat[0][2] = c->Circle.invmat[2][0] = 0;
336  }
337  }
338  Projette(&v0, mat);
339  Projette(&v2, mat);
340  if(v[3]) Projette(&v3, mat);
341  double R = sqrt(v0.Pos.X * v0.Pos.X + v0.Pos.Y * v0.Pos.Y);
342  double R2 = sqrt(v2.Pos.X * v2.Pos.X + v2.Pos.Y * v2.Pos.Y);
343  if(!R || !R2) {
344  // check radius
345  Msg::Error("Zero radius in circle or ellipse with tag %d", c->Num);
346  ok = false;
347  }
348  else if(!v[3] && fabs((R - R2) / (R + R2)) > 0.1) {
349  // check cocircular pts (allow 10% error)
350  Msg::Error("Control points of circle with tag %d are not cocircular: "
351  "R1=%g, R2=%g, n=[%g,%g,%g]",
352  c->Num, R, R2, n[0], n[1], n[2]);
353  ok = false;
354  }
355  // A1 = angle first pt
356  // A3 = angle last pt
357  // A4 = angle major axis
358  double A3, A1, A4;
359  double f1, f2;
360  if(v[3]) {
361  A4 = myatan2(v3.Pos.Y, v3.Pos.X);
362  A4 = angle_02pi(A4);
363  double x1 = v0.Pos.X * cos(A4) + v0.Pos.Y * sin(A4);
364  double y1 = -v0.Pos.X * sin(A4) + v0.Pos.Y * cos(A4);
365  double x3 = v2.Pos.X * cos(A4) + v2.Pos.Y * sin(A4);
366  double y3 = -v2.Pos.X * sin(A4) + v2.Pos.Y * cos(A4);
367  double sys[2][2], rhs[2], sol[2];
368  sys[0][0] = x1 * x1;
369  sys[0][1] = y1 * y1;
370  sys[1][0] = x3 * x3;
371  sys[1][1] = y3 * y3;
372  rhs[0] = 1;
373  rhs[1] = 1;
374  sys2x2(sys, rhs, sol);
375  if(sol[0] <= 0 || sol[1] <= 0) {
376  Msg::Error("Ellipse with tag %d is wrong", c->Num);
377  ok = false;
378  A1 = A3 = 0.;
379  f1 = f2 = R;
380  }
381  else {
382  f1 = sqrt(1. / sol[0]);
383  f2 = sqrt(1. / sol[1]);
384  // myasin() permet de contourner les problemes de precision
385  // sur y1/f2 ou y3/f2, qui peuvent legerement etre hors de
386  // [-1,1]
387  if(x1 < 0)
388  A1 = -myasin(y1 / f2) + A4 + M_PI;
389  else
390  A1 = myasin(y1 / f2) + A4;
391  if(x3 < 0)
392  A3 = -myasin(y3 / f2) + A4 + M_PI;
393  else
394  A3 = myasin(y3 / f2) + A4;
395  }
396  }
397  else {
398  A1 = myatan2(v0.Pos.Y, v0.Pos.X);
399  A3 = myatan2(v2.Pos.Y, v2.Pos.X);
400  A4 = 0.;
401  f1 = f2 = R;
402  }
403  A1 = angle_02pi(A1);
404  A3 = angle_02pi(A3);
405  if(A1 >= A3) A3 += 2 * M_PI;
406  c->Circle.t1 = A1;
407  c->Circle.t2 = A3;
408  c->Circle.incl = A4;
409  c->Circle.f1 = f1;
410  c->Circle.f2 = f2;
411  if(!CTX::instance()->expertMode && c->Num > 0 && A3 - A1 > 1.01 * M_PI) {
412  Msg::Error("Circle or ellipse arc %d greater than Pi (angle=%g)", c->Num,
413  A3 - A1);
414  Msg::Error(
415  "(If you understand what this implies, you can disable this error");
416  Msg::Error(
417  "message by selecting `Enable expert mode' in the option dialog.");
418  Msg::Error("Otherwise, please subdivide the arc in smaller pieces.)");
419  ok = false;
420  }
421  }
422 
423  return ok;
424 }
425 
427 {
428  // if all generatrices of a surface are on the same geometry, then
429  // the surface is also on the geometry
430  if(List_Nbr(s->Generatrices)) {
431  Curve *c;
432  int NN = List_Nbr(s->Generatrices);
433  List_Read(s->Generatrices, 0, &c);
434  s->geometry = c->geometry;
435  for(int i = 1; i < NN; i++) {
436  List_Read(s->Generatrices, i, &c);
437  if(c->geometry != s->geometry) {
438  s->geometry = nullptr;
439  break;
440  }
441  }
442  }
443 }
444 
445 Curve *CreateCurve(int Num, int Typ, int Order, List_T *Liste, List_T *Knots,
446  int p1, int p2, double u1, double u2, bool &ok)
447 {
448  ok = true;
449  double matcr[4][4] = {{-0.5, 1.5, -1.5, 0.5},
450  {1.0, -2.5, 2.0, -0.5},
451  {-0.5, 0.0, 0.5, 0.0},
452  {0.0, 1.0, 0.0, 0.0}};
453  double matbs[4][4] = {
454  {-1, 3, -3, 1}, {3, -6, 3, 0}, {-3, 0, 3, 0}, {1, 4, 1, 0}};
455  double matbez[4][4] = {
456  {-1, 3, -3, 1}, {3, -6, 3, 0}, {-3, 3, 0, 0}, {1, 0, 0, 0}};
457 
458  Curve *pC = new Curve;
459  pC->Extrude = nullptr;
460  pC->Typ = Typ;
461  pC->Num = Num;
463  1, std::max(GModel::current()->getGEOInternals()->getMaxTag(1), Num));
465  pC->degre = Order;
466  pC->Circle.n[0] = 0.0;
467  pC->Circle.n[1] = 0.0;
468  pC->Circle.n[2] = 1.0;
469  pC->geometry = nullptr;
470  pC->nbPointsTransfinite = 0;
471  pC->typeTransfinite = 0;
472  pC->coeffTransfinite = 0.;
473  pC->ReverseMesh = 0;
474  pC->beg = nullptr;
475  pC->end = nullptr;
476  pC->begByTag = 0;
477  pC->endByTag = 0;
478  pC->Control_Points = nullptr;
479  pC->degenerated = false;
480 
481  if(Typ == MSH_SEGM_SPLN) {
482  for(int i = 0; i < 4; i++)
483  for(int j = 0; j < 4; j++) pC->mat[i][j] = matcr[i][j];
484  }
485  else if(Typ == MSH_SEGM_BSPLN) {
486  for(int i = 0; i < 4; i++)
487  for(int j = 0; j < 4; j++) pC->mat[i][j] = matbs[i][j] / 6.0;
488  }
489  else if(Typ == MSH_SEGM_BEZIER) {
490  for(int i = 0; i < 4; i++)
491  for(int j = 0; j < 4; j++) pC->mat[i][j] = matbez[i][j];
492  }
493 
494  pC->ubeg = u1;
495  pC->uend = u2;
496 
497  if(Knots && List_Nbr(Knots)) {
498  pC->k = new float[List_Nbr(Knots)];
499  double kmin = .0, kmax = 1.;
500  List_Read(Knots, 0, &kmin);
501  List_Read(Knots, List_Nbr(Knots) - 1, &kmax);
502  pC->ubeg = kmin;
503  pC->uend = kmax;
504  for(int i = 0; i < List_Nbr(Knots); i++) {
505  double d;
506  List_Read(Knots, i, &d);
507  pC->k[i] = (float)d;
508  }
509  }
510  else
511  pC->k = nullptr;
512 
513  if(List_Nbr(Liste)) {
514  pC->Control_Points = List_Create(List_Nbr(Liste), 1, sizeof(Vertex *));
515  for(int j = 0; j < List_Nbr(Liste); j++) {
516  int iPnt;
517  List_Read(Liste, j, &iPnt);
518  Vertex *v;
519  if((v = FindPoint(iPnt)))
520  List_Add(pC->Control_Points, &v);
521  else {
522  Msg::Error("Unknown control point %d in GEO curve %d", iPnt, pC->Num);
523  ok = false;
524  }
525  }
526  if(p1 < 0) {
527  if(List_Nbr(pC->Control_Points)) {
528  List_Read(pC->Control_Points, 0, &pC->beg);
530  &pC->end);
531  }
532  }
533  else {
534  Vertex *v;
535  if((v = FindPoint(p1))) {
536  Msg::Info("Curve %d first control point %d ", pC->Num, v->Num);
537  pC->beg = v;
538  }
539  else {
540  Msg::Error("Unknown control point %d in GEO curve %d", p1, pC->Num);
541  ok = false;
542  }
543  if((v = FindPoint(p2))) {
544  Msg::Info("Curve %d first control point %d ", pC->Num, v->Num);
545  pC->end = v;
546  }
547  else {
548  Msg::Error("Unknown control point %d in GEO curve %d", p2, pC->Num);
549  ok = false;
550  }
551  }
552  if(!EndCurve(pC)) ok = false;
553  }
554 
555  if(pC->Typ == MSH_SEGM_LINE && pC->beg && pC->end &&
556  List_Nbr(pC->Control_Points) <= 2) {
557  if(!ComparePosition(&pC->beg, &pC->end))
558  Msg::Warning("Start point %d and end point %d of GEO line %d are closer "
559  "than the geometrical tolerance, at position (%g, %g, %g)",
560  pC->beg->Num, pC->end->Num, pC->Num, pC->beg->Pos.X,
561  pC->beg->Pos.Y, pC->beg->Pos.Z);
562  }
563 
564  return pC;
565 }
566 
567 void FreeCurve(void *a, void *b)
568 {
569  Curve *pC = *(Curve **)a;
570  if(pC) {
571  if(pC->k) delete[] pC->k;
573  if(pC->Extrude) delete pC->Extrude;
574  delete pC;
575  pC = nullptr;
576  }
577 }
578 
579 Surface *CreateSurface(int Num, int Typ)
580 {
581  Surface *pS = new Surface;
582  pS->Num = Num;
584  2, std::max(GModel::current()->getGEOInternals()->getMaxTag(2), Num));
585  pS->geometry = nullptr;
586  pS->InSphereCenter = nullptr;
587  pS->Typ = Typ;
589  pS->Recombine = 0;
590  pS->RecombineAngle = 45;
591  pS->Recombine_Dir = -1;
592  pS->TransfiniteSmoothing = -1;
593  pS->TrsfPoints = List_Create(4, 4, sizeof(Vertex *));
594  pS->Generatrices = nullptr;
595  pS->GeneratricesByTag = nullptr;
596  pS->Extrude = nullptr;
597  pS->geometry = nullptr;
598  pS->ReverseMesh = 0;
599  pS->MeshAlgorithm = 0;
600  pS->MeshSizeFromBoundary = -1;
601  return (pS);
602 }
603 
604 void FreeSurface(void *a, void *b)
605 {
606  Surface *pS = *(Surface **)a;
607  if(pS) {
608  List_Delete(pS->TrsfPoints);
611  if(pS->Extrude) delete pS->Extrude;
612  delete pS;
613  pS = nullptr;
614  }
615 }
616 
617 Volume *CreateVolume(int Num, int Typ)
618 {
619  Volume *pV = new Volume;
620  pV->Recombine3D = 0;
621  pV->Num = Num;
623  3, std::max(GModel::current()->getGEOInternals()->getMaxTag(3), Num));
624  pV->Typ = Typ;
626  pV->QuadTri = NO_QUADTRI;
627  pV->TrsfPoints = List_Create(6, 6, sizeof(Vertex *));
628  pV->Surfaces = List_Create(1, 2, sizeof(Surface *));
629  pV->SurfacesOrientations = List_Create(1, 2, sizeof(int));
630  pV->SurfacesByTag = List_Create(1, 2, sizeof(int));
631  pV->Extrude = nullptr;
632  return pV;
633 }
634 
635 void FreeVolume(void *a, void *b)
636 {
637  Volume *pV = *(Volume **)a;
638  if(pV) {
639  List_Delete(pV->TrsfPoints);
640  List_Delete(pV->Surfaces);
643  if(pV->Extrude) delete pV->Extrude;
644  delete pV;
645  pV = nullptr;
646  }
647 }
648 
649 static int Compare2Lists(List_T *List1, List_T *List2,
650  int (*fcmp)(const void *a, const void *b))
651 {
652  int i, found;
653 
654  if(!List_Nbr(List1) && !List_Nbr(List2)) return 0;
655 
656  if(!List_Nbr(List1) || !List_Nbr(List2) ||
657  (List_Nbr(List1) != List_Nbr(List2)))
658  return List_Nbr(List1) - List_Nbr(List2);
659 
660  List_T *List1Prime = List_Create(List_Nbr(List1), 1, List1->size);
661  List_T *List2Prime = List_Create(List_Nbr(List2), 1, List2->size);
662  List_Copy(List1, List1Prime);
663  List_Copy(List2, List2Prime);
664  List_Sort(List1Prime, fcmp);
665  List_Sort(List2Prime, fcmp);
666 
667  for(i = 0; i < List_Nbr(List1Prime); i++) {
668  found = fcmp(List_Pointer(List1Prime, i), List_Pointer(List2Prime, i));
669  if(found != 0) {
670  List_Delete(List1Prime);
671  List_Delete(List2Prime);
672  return found;
673  }
674  }
675  List_Delete(List1Prime);
676  List_Delete(List2Prime);
677  return 0;
678 }
679 
680 static Vertex *FindPoint(int inum, Tree_T *t)
681 {
682  Vertex C, *pc;
683  pc = &C;
684  pc->Num = inum;
685  if(Tree_Query(t, &pc)) { return pc; }
686  return nullptr;
687 }
688 
689 Vertex *FindPoint(int inum)
690 {
691  return FindPoint(inum, GModel::current()->getGEOInternals()->Points);
692 }
693 
694 static Curve *FindCurve(int inum, Tree_T *t)
695 {
696  Curve C, *pc;
697  pc = &C;
698  pc->Num = inum;
699  if(Tree_Query(t, &pc)) { return pc; }
700  return nullptr;
701 }
702 
703 Curve *FindCurve(int inum)
704 {
705  return FindCurve(inum, GModel::current()->getGEOInternals()->Curves);
706 }
707 
708 static Surface *FindSurface(int inum, Tree_T *t)
709 {
710  Surface S, *ps;
711  ps = &S;
712  ps->Num = inum;
713  if(Tree_Query(t, &ps)) { return ps; }
714  return nullptr;
715 }
716 
718 {
719  return FindSurface(inum, GModel::current()->getGEOInternals()->Surfaces);
720 }
721 
722 Volume *FindVolume(int inum)
723 {
724  Volume V, *pv;
725  pv = &V;
726  pv->Num = inum;
727  if(Tree_Query(GModel::current()->getGEOInternals()->Volumes, &pv)) {
728  return pv;
729  }
730  return nullptr;
731 }
732 
734 {
735  EdgeLoop S, *ps;
736  ps = &S;
737  ps->Num = inum;
738  if(Tree_Query(GModel::current()->getGEOInternals()->EdgeLoops, &ps)) {
739  return ps;
740  }
741  return nullptr;
742 }
743 
745 {
746  SurfaceLoop S, *ps;
747  ps = &S;
748  ps->Num = inum;
749  if(Tree_Query(GModel::current()->getGEOInternals()->SurfaceLoops, &ps)) {
750  return ps;
751  }
752  return nullptr;
753 }
754 
755 PhysicalGroup *FindPhysicalGroup(int num, int type)
756 {
757  PhysicalGroup P, *pp, **ppp;
758  pp = &P;
759  pp->Num = num;
760  pp->Typ = type;
761  if((ppp = (PhysicalGroup **)List_PQuery(
762  GModel::current()->getGEOInternals()->PhysicalGroups, &pp,
764  return *ppp;
765  }
766  return nullptr;
767 }
768 
769 static void CopyVertex(Vertex *v, Vertex *vv)
770 {
771  vv->lc = v->lc;
772  vv->u = v->u;
773  vv->Pos.X = v->Pos.X;
774  vv->Pos.Y = v->Pos.Y;
775  vv->Pos.Z = v->Pos.Z;
776 }
777 
779 {
780  if(!v) return nullptr;
781  Vertex *pv = CreateVertex(NEWPOINT(), 0, 0, 0, 0, 0);
782  CopyVertex(v, pv);
783  Tree_Insert(GModel::current()->getGEOInternals()->Points, &pv);
784  return pv;
785 }
786 
788 {
789  // dummy version to handle generic GModel entities for boundary layers
790  if(!gv) return nullptr;
791  Vertex *pv = CreateVertex(NEWPOINT(), gv->x(), gv->y(), gv->z(),
792  gv->prescribedMeshSizeAtVertex(), 0);
793  Tree_Insert(GModel::current()->getGEOInternals()->Points, &pv);
794  return pv;
795 }
796 
797 static int CompareAbsCurve(const void *a, const void *b)
798 {
799  Curve *q = *(Curve **)a;
800  Curve *w = *(Curve **)b;
801  return abs(q->Num) - abs(w->Num);
802 }
803 
804 static void CopyCurve(Curve *c, Curve *cc)
805 {
806  cc->Typ = c->Typ;
807  if(CTX::instance()->geom.copyMeshingMethod) {
808  cc->Method = c->Method;
809  cc->nbPointsTransfinite = c->nbPointsTransfinite;
810  cc->typeTransfinite = c->typeTransfinite;
811  cc->coeffTransfinite = c->coeffTransfinite;
812  cc->ReverseMesh = c->ReverseMesh;
813  }
814  cc->l = c->l;
815  for(int i = 0; i < 4; i++)
816  for(int j = 0; j < 4; j++) cc->mat[i][j] = c->mat[i][j];
817  cc->beg = c->beg;
818  cc->end = c->end;
819  cc->begByTag = c->begByTag;
820  cc->endByTag = c->endByTag;
821  cc->ubeg = c->ubeg;
822  cc->uend = c->uend;
823  cc->degenerated = c->degenerated;
824  cc->Control_Points =
825  List_Create(List_Nbr(c->Control_Points), 1, sizeof(Vertex *));
826  List_Copy(c->Control_Points, cc->Control_Points);
827  EndCurve(cc);
828 }
829 
831 {
832  bool ok = true;
833  Curve *pc =
834  CreateCurve(NEWCURVE(), 0, 1, nullptr, nullptr, -1, -1, 0., 1., ok);
835  CopyCurve(c, pc);
836  Tree_Insert(GModel::current()->getGEOInternals()->Curves, &pc);
837  for(int i = 0; i < List_Nbr(c->Control_Points); i++) {
838  Vertex *v;
839  List_Read(pc->Control_Points, i, &v);
840  Vertex *newv = DuplicateVertex(v);
841  List_Write(pc->Control_Points, i, &newv);
842  }
843  pc->beg = DuplicateVertex(c->beg);
844  pc->end = DuplicateVertex(c->end);
846  return pc;
847 }
848 
850 {
851  // dummy version to handle generic GModel entities for boundary layers
852  bool ok = true;
853  Curve *pc =
854  CreateCurve(NEWCURVE(), MSH_SEGM_BND_LAYER , 1, nullptr, nullptr, -1, -1, 0., 1., ok);
855  Tree_Insert(GModel::current()->getGEOInternals()->Curves, &pc);
856  pc->Control_Points = List_Create(2, 1, sizeof(Vertex *));
857  pc->beg = DuplicateVertex(ge->getBeginVertex());
858  if(ge->getBeginVertex() != ge->getEndVertex())
859  pc->end = DuplicateVertex(ge->getEndVertex());
860  else
861  pc->end = pc->beg;
862  List_Add(pc->Control_Points, &pc->beg);
863  List_Add(pc->Control_Points, &pc->end);
864  if(ge->degenerate(0)) pc->degenerated = true;
866  return pc;
867 }
868 
869 static void CopySurface(Surface *s, Surface *ss)
870 {
871  ss->Typ = s->Typ;
872  if(CTX::instance()->geom.copyMeshingMethod) {
873  ss->Method = s->Method;
874  ss->Recombine = s->Recombine;
876  ss->ReverseMesh = s->ReverseMesh;
877  ss->MeshAlgorithm = s->MeshAlgorithm;
879  if(List_Nbr(s->TrsfPoints))
880  Msg::Warning(
881  "Only automatic transfinite surface specifications can be copied");
882  }
883  ss->Generatrices =
884  List_Create(List_Nbr(s->Generatrices) + 1, 1, sizeof(Curve *));
885  ss->GeneratricesByTag =
886  List_Create(List_Nbr(s->GeneratricesByTag) + 1, 1, sizeof(int));
887  // after copy (and subsequent transformation), the sphere center does not make
888  // sense anymore
889  ss->InSphereCenter = nullptr;
892  EndSurface(ss);
893 }
894 
896 {
897  Surface *ps = CreateSurface(NEWSURFACE(), 0);
898  CopySurface(s, ps);
899  Tree_Insert(GModel::current()->getGEOInternals()->Surfaces, &ps);
900  for(int i = 0; i < List_Nbr(ps->Generatrices); i++) {
901  Curve *c;
902  List_Read(ps->Generatrices, i, &c);
903  Curve *newc = DuplicateCurve(c);
904  List_Write(ps->Generatrices, i, &newc);
905  }
906  return ps;
907 }
908 
909 Surface *DuplicateSurface(GFace *gf, std::map<int, int> &source)
910 {
911  // dummy version to handle generic GModel entities for boundary layers
912  Surface *ps = CreateSurface(NEWSURFACE(), MSH_SURF_PLAN); // dummy
913  Tree_Insert(GModel::current()->getGEOInternals()->Surfaces, &ps);
914  std::vector<GEdge *> edges = gf->edges();
915  ps->Generatrices = List_Create(edges.size() + 1, 1, sizeof(Curve *));
916  for(std::size_t i = 0; i < edges.size(); i++) {
917  if(!edges[i]->degenerate(0)) {
918  Curve *newc = DuplicateCurve(edges[i]);
919  List_Add(ps->Generatrices, &newc);
920  source[newc->Num] = edges[i]->tag();
921  }
922  }
923  return ps;
924 }
925 
926 static void CopyVolume(Volume *v, Volume *vv)
927 {
928  vv->Typ = v->Typ;
929  if(CTX::instance()->geom.copyMeshingMethod) {
930  vv->Method = v->Method;
931  vv->QuadTri = v->QuadTri;
932  vv->Recombine3D = v->Recombine3D;
933  if(List_Nbr(v->TrsfPoints))
934  Msg::Warning(
935  "Only automatic transfinite volume specifications can be copied");
936  }
937  List_Copy(v->Surfaces, vv->Surfaces);
940 }
941 
943 {
944  Volume *pv = CreateVolume(NEWVOLUME(), 0);
945  CopyVolume(v, pv);
946  Tree_Insert(GModel::current()->getGEOInternals()->Volumes, &pv);
947  for(int i = 0; i < List_Nbr(pv->Surfaces); i++) {
948  Surface *s;
949  List_Read(pv->Surfaces, i, &s);
950  Surface *news = DuplicateSurface(s);
951  List_Write(pv->Surfaces, i, &news);
952  }
953  return pv;
954 }
955 
956 void DeletePoint(int ip, bool recursive)
957 {
958  Vertex *v = FindPoint(ip);
959  if(!v) return;
960  List_T *Curves = Tree2List(GModel::current()->getGEOInternals()->Curves);
961  for(int i = 0; i < List_Nbr(Curves); i++) {
962  Curve *c;
963  List_Read(Curves, i, &c);
964  for(int j = 0; j < List_Nbr(c->Control_Points); j++) {
965  if(!CompareVertex(List_Pointer(c->Control_Points, j), &v)) {
966  List_Delete(Curves);
967  // cannot delete: it's a control point of a curve
968  return;
969  }
970  }
971  }
972  List_Delete(Curves);
973 
974  int tmax = GModel::current()->getGEOInternals()->getMaxTag(0);
975  if(v->Num == tmax)
976  GModel::current()->getGEOInternals()->setMaxTag(0, tmax - 1);
977  Tree_Suppress(GModel::current()->getGEOInternals()->Points, &v);
978  Tree_Add(GModel::current()->getGEOInternals()->DelPoints, &v);
979 }
980 
981 void DeleteCurve(int ip, bool recursive)
982 {
983  Curve *c = FindCurve(ip);
984  if(!c) return;
985  List_T *Surfs = Tree2List(GModel::current()->getGEOInternals()->Surfaces);
986  for(int i = 0; i < List_Nbr(Surfs); i++) {
987  Surface *s;
988  List_Read(Surfs, i, &s);
989  for(int j = 0; j < List_Nbr(s->Generatrices); j++) {
990  if(!CompareAbsCurve(List_Pointer(s->Generatrices, j), &c)) {
991  List_Delete(Surfs);
992  // cannot delete: it's on the boundary of a surface
993  return;
994  }
995  }
996  }
997  List_Delete(Surfs);
998 
999  int tmax = GModel::current()->getGEOInternals()->getMaxTag(1);
1000  if(c->Num == tmax)
1001  GModel::current()->getGEOInternals()->setMaxTag(1, tmax - 1);
1002  Tree_Suppress(GModel::current()->getGEOInternals()->Curves, &c);
1003  Tree_Add(GModel::current()->getGEOInternals()->DelCurves, &c);
1004 
1005  if(recursive) {
1006  std::set<int> vv;
1007  for(int k = 0; k < List_Nbr(c->Control_Points); k++) {
1008  Vertex *v;
1009  List_Read(c->Control_Points, k, &v);
1010  vv.insert(v->Num);
1011  }
1012  if(c->beg) vv.insert(c->beg->Num);
1013  if(c->end) vv.insert(c->end->Num);
1014  for(auto it = vv.begin(); it != vv.end(); it++) DeletePoint(*it);
1015  }
1016 }
1017 
1018 void DeleteSurface(int is, bool recursive)
1019 {
1020  Surface *s = FindSurface(is);
1021  if(!s) return;
1022  List_T *Vols = Tree2List(GModel::current()->getGEOInternals()->Volumes);
1023  for(int i = 0; i < List_Nbr(Vols); i++) {
1024  Volume *v;
1025  List_Read(Vols, i, &v);
1026  for(int j = 0; j < List_Nbr(v->Surfaces); j++) {
1027  if(!CompareSurface(List_Pointer(v->Surfaces, j), &s)) {
1028  List_Delete(Vols);
1029  // cannot delete: it's on the boundary of a volume
1030  return;
1031  }
1032  }
1033  }
1034  List_Delete(Vols);
1035 
1036  int tmax = GModel::current()->getGEOInternals()->getMaxTag(2);
1037  if(s->Num == tmax)
1038  GModel::current()->getGEOInternals()->setMaxTag(2, tmax - 1);
1039  Tree_Suppress(GModel::current()->getGEOInternals()->Surfaces, &s);
1040  Tree_Add(GModel::current()->getGEOInternals()->DelSurfaces, &s);
1041 
1042  if(recursive) {
1043  std::set<int> cc, vv;
1044  for(int j = 0; j < List_Nbr(s->Generatrices); j++) {
1045  Curve *c;
1046  List_Read(s->Generatrices, j, &c);
1047  cc.insert(c->Num);
1048  for(int k = 0; k < List_Nbr(c->Control_Points); k++) {
1049  Vertex *v;
1050  List_Read(c->Control_Points, k, &v);
1051  vv.insert(v->Num);
1052  }
1053  if(c->beg) vv.insert(c->beg->Num);
1054  if(c->end) vv.insert(c->end->Num);
1055  }
1056  for(auto it = cc.begin(); it != cc.end(); it++) {
1057  DeleteCurve(*it);
1058  DeleteCurve(-*it);
1059  }
1060  for(auto it = vv.begin(); it != vv.end(); it++) DeletePoint(*it);
1061  }
1062 }
1063 
1064 void DeleteVolume(int iv, bool recursive)
1065 {
1066  Volume *v = FindVolume(iv);
1067  if(!v) return;
1068 
1069  int tmax = GModel::current()->getGEOInternals()->getMaxTag(3);
1070  if(v->Num == tmax)
1071  GModel::current()->getGEOInternals()->setMaxTag(3, tmax - 1);
1072  Tree_Suppress(GModel::current()->getGEOInternals()->Volumes, &v);
1073  Tree_Add(GModel::current()->getGEOInternals()->DelVolumes, &v);
1074 
1075  if(recursive) {
1076  std::set<int> ss, cc, vv;
1077  for(int i = 0; i < List_Nbr(v->Surfaces); i++) {
1078  Surface *s;
1079  List_Read(v->Surfaces, i, &s);
1080  ss.insert(s->Num);
1081  for(int j = 0; j < List_Nbr(s->Generatrices); j++) {
1082  Curve *c;
1083  List_Read(s->Generatrices, j, &c);
1084  cc.insert(c->Num);
1085  for(int k = 0; k < List_Nbr(c->Control_Points); k++) {
1086  Vertex *v;
1087  List_Read(c->Control_Points, k, &v);
1088  vv.insert(v->Num);
1089  }
1090  if(c->beg) vv.insert(c->beg->Num);
1091  if(c->end) vv.insert(c->end->Num);
1092  }
1093  }
1094  for(auto it = ss.begin(); it != ss.end(); it++) DeleteSurface(*it);
1095  for(auto it = cc.begin(); it != cc.end(); it++) {
1096  DeleteCurve(*it);
1097  DeleteCurve(-*it);
1098  }
1099  for(auto it = vv.begin(); it != vv.end(); it++) DeletePoint(*it);
1100  }
1101 }
1102 
1103 void DeletePhysicalPoint(int num)
1104 {
1106  if(p) {
1107  List_Suppress(GModel::current()->getGEOInternals()->PhysicalGroups, &p,
1109  List_Add(GModel::current()->getGEOInternals()->DelPhysicalGroups, &p);
1110  }
1112 }
1113 
1114 void DeletePhysicalLine(int num)
1115 {
1117  if(p) {
1118  List_Suppress(GModel::current()->getGEOInternals()->PhysicalGroups, &p,
1120  List_Add(GModel::current()->getGEOInternals()->DelPhysicalGroups, &p);
1121  }
1123 }
1124 
1126 {
1128  if(p) {
1129  List_Suppress(GModel::current()->getGEOInternals()->PhysicalGroups, &p,
1131  List_Add(GModel::current()->getGEOInternals()->DelPhysicalGroups, &p);
1132  }
1134 }
1135 
1137 {
1139  if(p) {
1140  List_Suppress(GModel::current()->getGEOInternals()->PhysicalGroups, &p,
1142  List_Add(GModel::current()->getGEOInternals()->DelPhysicalGroups, &p);
1143  }
1145 }
1146 
1148 {
1149  bool ok = true;
1150  Curve *newc =
1151  CreateCurve(-c->Num, c->Typ, 1, nullptr, nullptr, -1, -1, 0., 1., ok);
1152 
1153  if(List_Nbr(c->Control_Points)) {
1154  newc->Control_Points =
1155  List_Create(List_Nbr(c->Control_Points), 1, sizeof(Vertex *));
1156  if(c->Typ == MSH_SEGM_ELLI || c->Typ == MSH_SEGM_ELLI_INV) {
1157  Vertex *e1, *e2, *e3, *e4;
1158  List_Read(c->Control_Points, 0, &e1);
1159  List_Read(c->Control_Points, 1, &e2);
1160  List_Read(c->Control_Points, 2, &e3);
1161  List_Read(c->Control_Points, 3, &e4);
1162  List_Add(newc->Control_Points, &e4);
1163  List_Add(newc->Control_Points, &e2);
1164  List_Add(newc->Control_Points, &e3);
1165  List_Add(newc->Control_Points, &e1);
1166  }
1167  else
1168  List_Invert(c->Control_Points, newc->Control_Points);
1169  }
1170 
1171  if(c->Typ == MSH_SEGM_NURBS && c->k) {
1172  newc->k = new float[c->degre + List_Nbr(c->Control_Points) + 1];
1173  for(int i = 0; i < c->degre + List_Nbr(c->Control_Points) + 1; i++)
1174  newc->k[c->degre + List_Nbr(c->Control_Points) - i] = c->k[i];
1175  }
1176 
1177  if(c->Typ == MSH_SEGM_CIRC) newc->Typ = MSH_SEGM_CIRC_INV;
1178  if(c->Typ == MSH_SEGM_CIRC_INV) newc->Typ = MSH_SEGM_CIRC;
1179  if(c->Typ == MSH_SEGM_ELLI) newc->Typ = MSH_SEGM_ELLI_INV;
1180  if(c->Typ == MSH_SEGM_ELLI_INV) newc->Typ = MSH_SEGM_ELLI;
1181 
1182  newc->beg = c->end;
1183  newc->end = c->beg;
1184  newc->begByTag = c->endByTag;
1185  newc->endByTag = c->begByTag;
1186  newc->Method = c->Method;
1187  newc->nbPointsTransfinite = c->nbPointsTransfinite;
1188  newc->typeTransfinite = -c->typeTransfinite;
1189  newc->coeffTransfinite = c->coeffTransfinite;
1190  newc->degre = c->degre;
1191  newc->ubeg = 1. - c->uend;
1192  newc->uend = 1. - c->ubeg;
1193  newc->degenerated = c->degenerated;
1194 
1195  if(c->Extrude) {
1196  newc->Extrude = new ExtrudeParams;
1197  newc->Extrude->geo = c->Extrude->geo;
1198  }
1199 
1200  EndCurve(newc);
1201 
1202  Curve **pc;
1203  if((pc = (Curve **)Tree_PQuery(GModel::current()->getGEOInternals()->Curves,
1204  &newc))) {
1205  FreeCurve(&newc, nullptr);
1206  return *pc;
1207  }
1208  else {
1209  Tree_Add(GModel::current()->getGEOInternals()->Curves, &newc);
1210  return newc;
1211  }
1212 }
1213 
1214 int RecognizeLineLoop(List_T *liste, int *loop)
1215 {
1216  int res = 0;
1217  *loop = 0;
1218  List_T *temp = Tree2List(GModel::current()->getGEOInternals()->EdgeLoops);
1219  for(int i = 0; i < List_Nbr(temp); i++) {
1220  EdgeLoop *pe;
1221  List_Read(temp, i, &pe);
1222  if(!Compare2Lists(pe->Curves, liste, fcmp_absint)) {
1223  res = 1;
1224  *loop = pe->Num;
1225  break;
1226  }
1227  }
1228  List_Delete(temp);
1229  return res;
1230 }
1231 
1232 int RecognizeSurfaceLoop(List_T *liste, int *loop)
1233 {
1234  int res = 0;
1235  *loop = 0;
1236  List_T *temp = Tree2List(GModel::current()->getGEOInternals()->SurfaceLoops);
1237  for(int i = 0; i < List_Nbr(temp); i++) {
1238  EdgeLoop *pe;
1239  List_Read(temp, i, &pe);
1240  if(!Compare2Lists(pe->Curves, liste, fcmp_absint)) {
1241  res = 1;
1242  *loop = pe->Num;
1243  break;
1244  }
1245  }
1246  List_Delete(temp);
1247  return res;
1248 }
1249 
1250 void SetTranslationMatrix(double matrix[4][4], double T[3])
1251 {
1252  for(int i = 0; i < 4; i++) {
1253  for(int j = 0; j < 4; j++) { matrix[i][j] = (i == j) ? 1.0 : 0.0; }
1254  }
1255  for(int i = 0; i < 3; i++) matrix[i][3] = T[i];
1256 }
1257 
1258 void SetSymmetryMatrix(double matrix[4][4], double A, double B, double C,
1259  double D)
1260 {
1261  double p = (A * A + B * B + C * C);
1262  if(!p) p = 1e-12;
1263  double F = -2.0 / p;
1264  matrix[0][0] = 1. + A * A * F;
1265  matrix[0][1] = A * B * F;
1266  matrix[0][2] = A * C * F;
1267  matrix[0][3] = A * D * F;
1268  matrix[1][0] = A * B * F;
1269  matrix[1][1] = 1. + B * B * F;
1270  matrix[1][2] = B * C * F;
1271  matrix[1][3] = B * D * F;
1272  matrix[2][0] = A * C * F;
1273  matrix[2][1] = B * C * F;
1274  matrix[2][2] = 1. + C * C * F;
1275  matrix[2][3] = C * D * F;
1276  matrix[3][0] = B * C * F;
1277  matrix[3][1] = 0.0;
1278  matrix[3][2] = 0.0;
1279  matrix[3][3] = 1.0;
1280 }
1281 
1282 void SetDilatationMatrix(double matrix[4][4], double T[3], double A, double B,
1283  double C)
1284 {
1285  matrix[0][0] = A;
1286  matrix[0][1] = 0.0;
1287  matrix[0][2] = 0.0;
1288  matrix[0][3] = T[0] * (1.0 - A);
1289  matrix[1][0] = 0.0;
1290  matrix[1][1] = B;
1291  matrix[1][2] = 0.0;
1292  matrix[1][3] = T[1] * (1.0 - B);
1293  matrix[2][0] = 0.0;
1294  matrix[2][1] = 0.0;
1295  matrix[2][2] = C;
1296  matrix[2][3] = T[2] * (1.0 - C);
1297  matrix[3][0] = 0.0;
1298  matrix[3][1] = 0.0;
1299  matrix[3][2] = 0.0;
1300  matrix[3][3] = 1.0;
1301 }
1302 
1303 static void GramSchmidt(double v1[3], double v2[3], double v3[3])
1304 {
1305  double tmp[3];
1306  norme(v1);
1307  prodve(v3, v1, tmp);
1308  norme(tmp);
1309  v2[0] = tmp[0];
1310  v2[1] = tmp[1];
1311  v2[2] = tmp[2];
1312  prodve(v1, v2, v3);
1313  norme(v3);
1314 }
1315 
1316 void SetRotationMatrix(double matrix[4][4], double Axe[3], double alpha)
1317 {
1318  double t1[3], t2[3];
1319  if(Axe[0] != 0.0) {
1320  t1[0] = 0.0;
1321  t1[1] = 1.0;
1322  t1[2] = 0.0;
1323  t2[0] = 0.0;
1324  t2[1] = 0.0;
1325  t2[2] = 1.0;
1326  }
1327  else if(Axe[1] != 0.0) {
1328  t1[0] = 1.0;
1329  t1[1] = 0.0;
1330  t1[2] = 0.0;
1331  t2[0] = 0.0;
1332  t2[1] = 0.0;
1333  t2[2] = 1.0;
1334  }
1335  else {
1336  t1[0] = 1.0;
1337  t1[1] = 0.0;
1338  t1[2] = 0.0;
1339  t2[0] = 0.0;
1340  t2[1] = 1.0;
1341  t2[2] = 0.0;
1342  }
1343  GramSchmidt(Axe, t1, t2);
1344  double rot[3][3], plan[3][3], invplan[3][3];
1345  plan[0][0] = Axe[0];
1346  plan[0][1] = Axe[1];
1347  plan[0][2] = Axe[2];
1348  plan[1][0] = t1[0];
1349  plan[1][1] = t1[1];
1350  plan[1][2] = t1[2];
1351  plan[2][0] = t2[0];
1352  plan[2][1] = t2[1];
1353  plan[2][2] = t2[2];
1354  rot[2][2] = cos(alpha);
1355  rot[2][1] = sin(alpha);
1356  rot[2][0] = 0.;
1357  rot[1][2] = -sin(alpha);
1358  rot[1][1] = cos(alpha);
1359  rot[1][0] = 0.;
1360  rot[0][2] = 0.;
1361  rot[0][1] = 0.;
1362  rot[0][0] = 1.;
1363  int i, j, k;
1364  for(i = 0; i < 3; i++)
1365  for(j = 0; j < 3; j++) invplan[i][j] = plan[j][i];
1366  double interm[3][3];
1367  for(i = 0; i < 3; i++)
1368  for(j = 0; j < 3; j++) {
1369  interm[i][j] = 0.0;
1370  for(k = 0; k < 3; k++) interm[i][j] += invplan[i][k] * rot[k][j];
1371  }
1372  for(i = 0; i < 4; i++)
1373  for(j = 0; j < 4; j++) matrix[i][j] = 0.0;
1374  for(i = 0; i < 3; i++)
1375  for(j = 0; j < 3; j++) {
1376  for(k = 0; k < 3; k++) matrix[i][j] += interm[i][k] * plan[k][j];
1377  }
1378  matrix[3][3] = 1.0;
1379 }
1380 
1381 static void vecmat4x4(double mat[4][4], double vec[4], double res[4])
1382 {
1383  for(int i = 0; i < 4; i++) {
1384  res[i] = 0.0;
1385  for(int j = 0; j < 4; j++) { res[i] += mat[i][j] * vec[j]; }
1386  }
1387 }
1388 
1389 static void ApplyTransformationToPointAlways(double matrix[4][4], Vertex *v)
1390 {
1391  double pos[4], vec[4];
1392  vec[0] = v->Pos.X;
1393  vec[1] = v->Pos.Y;
1394  vec[2] = v->Pos.Z;
1395  vec[3] = v->w;
1396  vecmat4x4(matrix, vec, pos);
1397  v->Pos.X = pos[0];
1398  v->Pos.Y = pos[1];
1399  v->Pos.Z = pos[2];
1400  v->w = pos[3];
1401 }
1402 
1403 static void ApplyTransformationToPoint(double matrix[4][4], Vertex *v)
1404 {
1406  ListOfTransformedPoints = List_Create(50, 50, sizeof(int));
1407 
1410  }
1411  else
1412  return;
1414 }
1415 
1416 static void ApplyTransformationToCurve(double matrix[4][4], Curve *c)
1417 {
1418  if(!c->beg || !c->end) {
1419  Msg::Error("Cannot transform curve with no begin/end points");
1420  return;
1421  }
1422 
1423  ApplyTransformationToPoint(matrix, c->beg);
1424  ApplyTransformationToPoint(matrix, c->end);
1425 
1426  for(int i = 0; i < List_Nbr(c->Control_Points); i++) {
1427  Vertex *v;
1428  List_Read(c->Control_Points, i, &v);
1429  ApplyTransformationToPoint(matrix, v);
1430  }
1431  EndCurve(c);
1432 }
1433 
1434 static void ApplyTransformationToSurface(double matrix[4][4], Surface *s)
1435 {
1436  for(int i = 0; i < List_Nbr(s->Generatrices); i++) {
1437  Curve *c;
1438  List_Read(s->Generatrices, i, &c);
1439  Curve *cc = FindCurve(abs(c->Num));
1440  ApplyTransformationToCurve(matrix, cc);
1441  }
1442  EndSurface(s);
1443 }
1444 
1445 static void ApplyTransformationToVolume(double matrix[4][4], Volume *v)
1446 {
1447  for(int i = 0; i < List_Nbr(v->Surfaces); i++) {
1448  Surface *s;
1449  List_Read(v->Surfaces, i, &s);
1450  ApplyTransformationToSurface(matrix, s);
1451  }
1452 }
1453 
1454 static bool ApplicationOnShapes(double matrix[4][4], List_T *shapes)
1455 {
1456  Vertex *v;
1457  Curve *c;
1458  Surface *s;
1459  Volume *vol;
1460  bool ok = true;
1461 
1463 
1464  for(int i = 0; i < List_Nbr(shapes); i++) {
1465  Shape O;
1466  List_Read(shapes, i, &O);
1467  switch(O.Type) {
1468  case MSH_POINT:
1469  v = FindPoint(O.Num);
1470  if(v)
1471  ApplyTransformationToPoint(matrix, v);
1472  else {
1473  Msg::Error("Unknown GEO point with tag %d", O.Num);
1474  ok = false;
1475  }
1476  break;
1477  case MSH_SEGM_LINE:
1478  case MSH_SEGM_SPLN:
1479  case MSH_SEGM_BSPLN:
1480  case MSH_SEGM_BEZIER:
1481  case MSH_SEGM_CIRC:
1482  case MSH_SEGM_CIRC_INV:
1483  case MSH_SEGM_ELLI:
1484  case MSH_SEGM_ELLI_INV:
1485  case MSH_SEGM_NURBS:
1486  c = FindCurve(O.Num);
1487  if(c)
1488  ApplyTransformationToCurve(matrix, c);
1489  else {
1490  Msg::Error("Unknown GEO curve with tag %d", O.Num);
1491  ok = false;
1492  }
1493  break;
1494  case MSH_SURF_REGL:
1495  case MSH_SURF_TRIC:
1496  case MSH_SURF_PLAN:
1497  s = FindSurface(O.Num);
1498  if(s)
1499  ApplyTransformationToSurface(matrix, s);
1500  else {
1501  Msg::Error("Unknown GEO surface with tag %d", O.Num);
1502  ok = false;
1503  }
1504  break;
1505  case MSH_VOLUME:
1506  vol = FindVolume(O.Num);
1507  if(vol)
1508  ApplyTransformationToVolume(matrix, vol);
1509  else {
1510  Msg::Error("Unknown GEO volume with tag %d", O.Num);
1511  ok = false;
1512  }
1513  break;
1514  default:
1515  Msg::Error("Impossible to transform entity %d (of type %d)", O.Num,
1516  O.Type);
1517  ok = false;
1518  break;
1519  }
1520  }
1521 
1522  // recompute curve parameters if control points have been transformed.
1523  // Warning: in theory we should always redo these checks; but in practice this
1524  // is so slow for big models that we need to provide a way to bypass it (which
1525  // is OK if the guy who builds the geometry knowns what he's doing). Instead
1526  // of adding one more option, let's just bypass all the checks if
1527  // auto_coherence==0.
1528  if(CTX::instance()->geom.autoCoherence) {
1529  List_T *All = Tree2List(GModel::current()->getGEOInternals()->Curves);
1530  for(int i = 0; i < List_Nbr(All); i++) {
1531  Curve *c;
1532  List_Read(All, i, &c);
1533  for(int j = 0; j < List_Nbr(c->Control_Points); j++) {
1534  Vertex *pv = *(Vertex **)List_Pointer(c->Control_Points, j);
1536  EndCurve(c);
1537  break;
1538  }
1539  }
1540  }
1541  List_Delete(All);
1542  }
1543 
1545 
1546  return ok;
1547 }
1548 
1549 bool TranslateShapes(double X, double Y, double Z, List_T *shapes)
1550 {
1551  double T[3], matrix[4][4];
1552 
1553  T[0] = X;
1554  T[1] = Y;
1555  T[2] = Z;
1556  SetTranslationMatrix(matrix, T);
1557  bool ok = ApplicationOnShapes(matrix, shapes);
1558 
1559  if(CTX::instance()->geom.autoCoherence) ReplaceAllDuplicates();
1560 
1561  return ok;
1562 }
1563 
1564 bool DilatShapes(double X, double Y, double Z, double A, double B, double C,
1565  List_T *shapes)
1566 {
1567  double T[3], matrix[4][4];
1568 
1569  T[0] = X;
1570  T[1] = Y;
1571  T[2] = Z;
1572  SetDilatationMatrix(matrix, T, A, B, C);
1573  bool ok = ApplicationOnShapes(matrix, shapes);
1574 
1575  if(CTX::instance()->geom.autoCoherence) ReplaceAllDuplicates();
1576 
1577  return ok;
1578 }
1579 
1580 bool RotateShapes(double Ax, double Ay, double Az, double Px, double Py,
1581  double Pz, double alpha, List_T *shapes)
1582 {
1583  double A[3], T[3], matrix[4][4];
1584 
1585  T[0] = -Px;
1586  T[1] = -Py;
1587  T[2] = -Pz;
1588  SetTranslationMatrix(matrix, T);
1589  bool ok = ApplicationOnShapes(matrix, shapes);
1590 
1591  A[0] = Ax;
1592  A[1] = Ay;
1593  A[2] = Az;
1594  SetRotationMatrix(matrix, A, alpha);
1595  ok &= ApplicationOnShapes(matrix, shapes);
1596 
1597  T[0] = Px;
1598  T[1] = Py;
1599  T[2] = Pz;
1600  SetTranslationMatrix(matrix, T);
1601  ok &= ApplicationOnShapes(matrix, shapes);
1602 
1603  if(CTX::instance()->geom.autoCoherence) ReplaceAllDuplicates();
1604 
1605  return ok;
1606 }
1607 
1608 bool SymmetryShapes(double A, double B, double C, double D, List_T *shapes)
1609 {
1610  double matrix[4][4];
1611 
1612  SetSymmetryMatrix(matrix, A, B, C, D);
1613  bool ok = ApplicationOnShapes(matrix, shapes);
1614 
1615  if(CTX::instance()->geom.autoCoherence) ReplaceAllDuplicates();
1616 
1617  return ok;
1618 }
1619 
1621 public:
1622  bool operator()(Shape *v1, Shape *v2) const
1623  {
1624  if(std::abs(v1->Num) < std::abs(v2->Num)) return true;
1625  return false;
1626  }
1627 };
1628 
1629 static int CompareTwoPoints(const void *a, const void *b)
1630 {
1631  Vertex *q = *(Vertex **)a;
1632  Vertex *w = *(Vertex **)b;
1633 
1634  if(q->Typ != w->Typ) return q->Typ - w->Typ;
1635 
1637  return q->boundaryLayerIndex - w->boundaryLayerIndex;
1638 
1639  return ComparePosition(a, b);
1640 }
1641 
1642 static int CompareTwoCurves(const void *a, const void *b)
1643 {
1644  Curve *c1 = *(Curve **)a;
1645  Curve *c2 = *(Curve **)b;
1646  int comp;
1647 
1648  // if two curves are discrete, assume that they are different if their tags
1649  // are different
1650  if(c1->Typ == MSH_SEGM_DISCRETE && c2->Typ == MSH_SEGM_DISCRETE) {
1651  return c1->Num - c2->Num;
1652  }
1653 
1654  if(c1->Typ != c2->Typ) {
1655  if((c1->Typ == MSH_SEGM_CIRC && c2->Typ == MSH_SEGM_CIRC_INV) ||
1656  (c1->Typ == MSH_SEGM_CIRC_INV && c2->Typ == MSH_SEGM_CIRC) ||
1657  (c1->Typ == MSH_SEGM_ELLI && c2->Typ == MSH_SEGM_ELLI_INV) ||
1658  (c1->Typ == MSH_SEGM_ELLI_INV && c2->Typ == MSH_SEGM_ELLI)) {
1659  // this is still ok
1660  }
1661  else
1662  return c1->Typ - c2->Typ;
1663  }
1664 
1665  if(List_Nbr(c1->Control_Points) != List_Nbr(c2->Control_Points))
1666  return List_Nbr(c1->Control_Points) - List_Nbr(c2->Control_Points);
1667 
1668  if(!List_Nbr(c1->Control_Points)) {
1669  if(!c1->beg || !c2->beg) return 1;
1670  comp = CompareVertex(&c1->beg, &c2->beg);
1671  if(comp) return comp;
1672  if(!c1->end || !c2->end) return 1;
1673  comp = CompareVertex(&c1->end, &c2->end);
1674  if(comp) return comp;
1675  }
1676  else {
1677  for(int i = 0; i < List_Nbr(c1->Control_Points); i++) {
1678  Vertex *v1, *v2;
1679  List_Read(c1->Control_Points, i, &v1);
1680  List_Read(c2->Control_Points, i, &v2);
1681  comp = CompareVertex(&v1, &v2);
1682  if(comp) return comp;
1683  }
1684  }
1685 
1686  // compare boundary layer curves using their source extrusion entity, which is
1687  // assumed to be unique; this allows one to have 2 distinct boundary layer
1688  // curves with the same beg/end points
1689  if(c1->Typ == MSH_SEGM_BND_LAYER && c1->Extrude &&
1690  c2->Typ == MSH_SEGM_BND_LAYER && c2->Extrude) {
1691  int comp =
1692  std::abs(c1->Extrude->geo.Source) - std::abs(c2->Extrude->geo.Source);
1693  if(comp) return comp;
1694  }
1695 
1696  return 0;
1697 }
1698 
1699 static int CompareTwoSurfaces(const void *a, const void *b)
1700 {
1701  Surface *s1 = *(Surface **)a;
1702  Surface *s2 = *(Surface **)b;
1703 
1704  // if two surface are discrete, assume that they are different if their tags
1705  // are different
1706  if(s1->Typ == MSH_SURF_DISCRETE && s2->Typ == MSH_SURF_DISCRETE) {
1707  return s1->Num - s2->Num;
1708  }
1709 
1710  // checking types is the "right thing" to do (see e.g. CompareTwoCurves)
1711  // but it would break backward compatibility (see e.g. tutorials/t2.geo),
1712  // so let's just do it for boundary layer surfaces for now:
1713  if(s1->Typ == MSH_SURF_BND_LAYER || s2->Typ == MSH_SURF_BND_LAYER) {
1714  if(s1->Typ != s2->Typ) return s1->Typ - s2->Typ;
1715  }
1716 
1717  // if both surfaces have no generatrices, stay on the safe side and
1718  // assume they are different
1719  if(!List_Nbr(s1->Generatrices) && !List_Nbr(s2->Generatrices) &&
1721  return 1;
1722 
1723  // if generatrices are given bby tag (e.g. for boundary layers on generic
1724  // GModel entities), compare those
1727 
1729 }
1730 
1731 static void MaxNumPoint(void *a, void *b)
1732 {
1733  Vertex *v = *(Vertex **)a;
1735  0, std::max(GModel::current()->getGEOInternals()->getMaxTag(0), v->Num));
1736 }
1737 
1738 static void MaxNumCurve(void *a, void *b)
1739 {
1740  Curve *c = *(Curve **)a;
1742  1, std::max(GModel::current()->getGEOInternals()->getMaxTag(1), c->Num));
1743 }
1744 
1745 static void MaxNumSurface(void *a, void *b)
1746 {
1747  Surface *s = *(Surface **)a;
1749  2, std::max(GModel::current()->getGEOInternals()->getMaxTag(2), s->Num));
1750 }
1751 
1752 static void ReplaceDuplicatePointsNew(double tol = -1.)
1753 {
1754  Msg::Info("New Coherence...");
1755  if(tol < 0) tol = CTX::instance()->geom.tolerance * CTX::instance()->lc;
1756 
1757  // create rtree
1758  MVertexRTree pos(tol);
1759  std::map<MVertex *, Vertex *> v2V;
1760  std::vector<MVertex *> used, unused;
1761  List_T *tmp = Tree2List(GModel::current()->getGEOInternals()->Points);
1762  for(int i = 0; i < List_Nbr(tmp); i++) {
1763  Vertex *V;
1764  List_Read(tmp, i, &V);
1765  MVertex *v = new MVertex(V->Pos.X, V->Pos.Y, V->Pos.Z);
1766  if(!pos.insert(v))
1767  used.push_back(v);
1768  else
1769  unused.push_back(v);
1770  v2V[v] = V;
1771  }
1772  List_Delete(tmp);
1773 
1774  // replace points in curves
1775  tmp = Tree2List(GModel::current()->getGEOInternals()->Curves);
1776  for(int i = 0; i < List_Nbr(tmp); i++) {
1777  Curve *c;
1778  List_Read(tmp, i, &c);
1779  // replace begin/end points
1780  c->beg = v2V[pos.find(c->beg->Pos.X, c->beg->Pos.Y, c->beg->Pos.Z)];
1781  c->end = v2V[pos.find(c->end->Pos.X, c->end->Pos.Y, c->end->Pos.Z)];
1782 
1783  // replace control points
1784  for(int j = 0; j < List_Nbr(c->Control_Points); j++) {
1785  Vertex *V;
1786  List_Read(c->Control_Points, j, &V);
1787  List_Write(c->Control_Points, j,
1788  &v2V[pos.find(V->Pos.X, V->Pos.Y, V->Pos.Z)]);
1789  }
1790  // replace extrusion sources
1791  if(c->Extrude && c->Extrude->geo.Mode == EXTRUDED_ENTITY) {
1792  Vertex *V = FindPoint(std::abs(c->Extrude->geo.Source));
1793  if(V)
1794  c->Extrude->geo.Source =
1795  v2V[pos.find(V->Pos.X, V->Pos.Y, V->Pos.Z)]->Num;
1796  }
1797  }
1798  List_Delete(tmp);
1799 
1800  // replace points in surfaces
1801  tmp = Tree2List(GModel::current()->getGEOInternals()->Surfaces);
1802  for(int i = 0; i < List_Nbr(tmp); i++) {
1803  Surface *s;
1804  List_Read(tmp, i, &s);
1805  // replace transfinite corners
1806  for(int j = 0; j < List_Nbr(s->TrsfPoints); j++) {
1807  Vertex *V;
1808  List_Read(s->TrsfPoints, j, &V);
1809  List_Write(s->TrsfPoints, j,
1810  &v2V[pos.find(V->Pos.X, V->Pos.Y, V->Pos.Z)]);
1811  }
1812  }
1813  List_Delete(tmp);
1814 
1815  // replace points in volumes
1816  tmp = Tree2List(GModel::current()->getGEOInternals()->Volumes);
1817  for(int i = 0; i < List_Nbr(tmp); i++) {
1818  Volume *vol;
1819  List_Read(tmp, i, &vol);
1820  // replace transfinite corners
1821  for(int j = 0; j < List_Nbr(vol->TrsfPoints); j++) {
1822  Vertex *V;
1823  List_Read(vol->TrsfPoints, j, &V);
1824  List_Write(vol->TrsfPoints, j,
1825  &v2V[pos.find(V->Pos.X, V->Pos.Y, V->Pos.Z)]);
1826  }
1827  }
1828  List_Delete(tmp);
1829 
1830  // replace points in physical groups
1831  for(int i = 0;
1832  i < List_Nbr(GModel::current()->getGEOInternals()->PhysicalGroups); i++) {
1833  PhysicalGroup *p;
1834  List_Read(GModel::current()->getGEOInternals()->PhysicalGroups, i, &p);
1835  if(p->Typ == MSH_PHYSICAL_POINT) {
1836  for(int j = 0; j < List_Nbr(p->Entities); j++) {
1837  int num;
1838  List_Read(p->Entities, j, &num);
1839  Vertex *V = FindPoint(std::abs(num));
1840  if(V)
1841  List_Write(p->Entities, j,
1842  &(v2V[pos.find(V->Pos.X, V->Pos.Y, V->Pos.Z)]->Num));
1843  }
1844  }
1845  }
1846 
1847  int start = Tree_Nbr(GModel::current()->getGEOInternals()->Points);
1848  for(std::size_t i = 0; i < unused.size(); i++) {
1849  Vertex *V = v2V[unused[i]];
1850  Tree_Suppress(GModel::current()->getGEOInternals()->Points, &V);
1851  Tree_Add(GModel::current()->getGEOInternals()->DelPoints, &V);
1852  delete unused[i];
1853  }
1854  for(std::size_t i = 0; i < used.size(); i++) { delete used[i]; }
1855  int end = Tree_Nbr(GModel::current()->getGEOInternals()->Points);
1856  Msg::Info("Done new Coherence (removed %d additional points)", start - end);
1857 }
1858 
1859 static void ReplaceDuplicatePoints(std::map<int, int> *v_report = nullptr)
1860 {
1861  // This routine is logically wrong: the CompareTwoPoints() function used in
1862  // the avl tree is not an appropriate comparison function. Fixing the routine
1863  // is easy (we need to a multi-dimensional tree), but it would break backward
1864  // compatibility with old .geo files (the point ids after "Coherence" would
1865  // change, as which point gets removed is implementation-dependent).
1866  //
1867  // Instead, we still use this routine, but call the new one if an error is
1868  // detected.
1869 
1870  Vertex *v, *v2, **pv, **pv2;
1871  Curve *c;
1872  Surface *s;
1873  Volume *vol;
1874  Tree_T *points2delete = Tree_Create(sizeof(Vertex *), CompareVertex);
1875  Tree_T *allNonDuplicatedPoints =
1876  Tree_Create(sizeof(Vertex *), CompareTwoPoints);
1877 
1878  // Create unique points
1879  int start = Tree_Nbr(GModel::current()->getGEOInternals()->Points);
1880 
1881  List_T *All = Tree2List(GModel::current()->getGEOInternals()->Points);
1882  for(int i = 0; i < List_Nbr(All); i++) {
1883  List_Read(All, i, &v);
1884  if(!Tree_Search(allNonDuplicatedPoints, &v)) {
1885  Tree_Insert(allNonDuplicatedPoints, &v);
1886  }
1887  else {
1888  Tree_Suppress(GModel::current()->getGEOInternals()->Points, &v);
1889  Tree_Insert(points2delete, &v);
1890  if(v_report) { // keep track of changes
1891  auto m_it = v_report->find(v->Num);
1892  if(m_it != v_report->end()) {
1893  Vertex **v_rep = (Vertex **)Tree_PQuery(allNonDuplicatedPoints, &v);
1894  if(v_rep) m_it->second = (*v_rep)->Num;
1895  }
1896  }
1897  }
1898  }
1899  List_Delete(All);
1900 
1901  int end = Tree_Nbr(GModel::current()->getGEOInternals()->Points);
1902  if(start == end) {
1903  Tree_Delete(points2delete);
1904  Tree_Delete(allNonDuplicatedPoints);
1905  return;
1906  }
1907 
1908  Msg::Debug("Removed %d duplicate points", start - end);
1909 
1910  if(CTX::instance()->geom.oldNewreg) {
1912  Tree_Action(GModel::current()->getGEOInternals()->Points, MaxNumPoint);
1913  }
1914 
1915  bool success = true;
1916 
1917  // Replace old points in curves
1918  All = Tree2List(GModel::current()->getGEOInternals()->Curves);
1919  for(int i = 0; i < List_Nbr(All); i++) {
1920  List_Read(All, i, &c);
1921  // replace begin/end points
1922  if(c->beg && !Tree_Query(allNonDuplicatedPoints, &c->beg)) {
1923  Msg::Debug("Could not replace point %d in old Coherence", c->beg->Num);
1924  Tree_Insert(GModel::current()->getGEOInternals()->Points, &c->beg);
1925  Tree_Suppress(points2delete, &c->beg);
1926  success = false;
1927  }
1928  if(c->end && !Tree_Query(allNonDuplicatedPoints, &c->end)) {
1929  Msg::Debug("Could not replace point %d in old Coherence", c->end->Num);
1930  Tree_Insert(GModel::current()->getGEOInternals()->Points, &c->end);
1931  Tree_Suppress(points2delete, &c->end);
1932  success = false;
1933  }
1934  // replace control points
1935  for(int j = 0; j < List_Nbr(c->Control_Points); j++) {
1936  pv = (Vertex **)List_Pointer(c->Control_Points, j);
1937  if(!(pv2 = (Vertex **)Tree_PQuery(allNonDuplicatedPoints, pv))) {
1938  Msg::Debug("Could not replace point %d in old Coherence", (*pv)->Num);
1939  Tree_Insert(GModel::current()->getGEOInternals()->Points, pv);
1940  Tree_Suppress(points2delete, pv);
1941  success = false;
1942  }
1943  else
1944  List_Write(c->Control_Points, j, pv2);
1945  }
1946  // replace extrusion sources
1947  if(c->Extrude && c->Extrude->geo.Mode == EXTRUDED_ENTITY) {
1948  v2 = FindPoint(std::abs(c->Extrude->geo.Source), points2delete);
1949  if(v2) {
1950  if(!(pv2 = (Vertex **)Tree_PQuery(allNonDuplicatedPoints, &v2))) {
1951  Msg::Debug("Could not replace point %d in old Coherence", v2->Num);
1952  Tree_Insert(GModel::current()->getGEOInternals()->Points, &v2);
1953  Tree_Suppress(points2delete, &v2);
1954  success = false;
1955  }
1956  else
1957  c->Extrude->geo.Source = (*pv2)->Num;
1958  }
1959  }
1960  }
1961  List_Delete(All);
1962 
1963  // Replace old points in surfaces
1964  All = Tree2List(GModel::current()->getGEOInternals()->Surfaces);
1965  for(int i = 0; i < List_Nbr(All); i++) {
1966  List_Read(All, i, &s);
1967  // replace transfinite corners
1968  for(int j = 0; j < List_Nbr(s->TrsfPoints); j++) {
1969  pv = (Vertex **)List_Pointer(s->TrsfPoints, j);
1970  if(!(pv2 = (Vertex **)Tree_PQuery(allNonDuplicatedPoints, pv))) {
1971  Msg::Debug("Could not replace point %d in old Coherence", (*pv)->Num);
1972  Tree_Insert(GModel::current()->getGEOInternals()->Points, pv);
1973  Tree_Suppress(points2delete, pv);
1974  success = false;
1975  }
1976  else
1977  List_Write(s->TrsfPoints, j, pv2);
1978  }
1979  }
1980  List_Delete(All);
1981 
1982  // Replace old points in volumes
1983  All = Tree2List(GModel::current()->getGEOInternals()->Volumes);
1984  for(int i = 0; i < List_Nbr(All); i++) {
1985  List_Read(All, i, &vol);
1986  // replace transfinite corners
1987  for(int j = 0; j < List_Nbr(vol->TrsfPoints); j++) {
1988  pv = (Vertex **)List_Pointer(vol->TrsfPoints, j);
1989  if(!(pv2 = (Vertex **)Tree_PQuery(allNonDuplicatedPoints, pv))) {
1990  Msg::Debug("Could not replace point %d in old Coherence", (*pv)->Num);
1991  Tree_Insert(GModel::current()->getGEOInternals()->Points, pv);
1992  Tree_Suppress(points2delete, pv);
1993  success = false;
1994  }
1995  else
1996  List_Write(vol->TrsfPoints, j, pv2);
1997  }
1998  }
1999  List_Delete(All);
2000 
2001  // Replace old points in physical groups
2002  for(int i = 0;
2003  i < List_Nbr(GModel::current()->getGEOInternals()->PhysicalGroups); i++) {
2006  if(p->Typ == MSH_PHYSICAL_POINT) {
2007  for(int j = 0; j < List_Nbr(p->Entities); j++) {
2008  int num;
2009  List_Read(p->Entities, j, &num);
2010  v2 = FindPoint(std::abs(num), points2delete);
2011  if(v2) {
2012  if(!(pv2 = (Vertex **)Tree_PQuery(allNonDuplicatedPoints, &v2))) {
2013  Msg::Debug("Could not replace point %d in old Coherence", v2->Num);
2014  Tree_Insert(GModel::current()->getGEOInternals()->Points, &v2);
2015  Tree_Suppress(points2delete, &v2);
2016  success = false;
2017  }
2018  else
2019  List_Write(p->Entities, j, &(*pv2)->Num);
2020  }
2021  }
2022  }
2023  }
2024 
2025  List_T *tmp = Tree2List(points2delete);
2026  for(int i = 0; i < List_Nbr(tmp); i++)
2028  List_Pointer(tmp, i));
2029  List_Delete(tmp);
2030  Tree_Delete(points2delete);
2031  Tree_Delete(allNonDuplicatedPoints);
2032 
2033  if(!success) ReplaceDuplicatePointsNew();
2034 }
2035 
2036 static void ReplaceDuplicateCurves(std::map<int, int> *c_report = nullptr)
2037 {
2038  Curve *c, *c2, **pc, **pc2;
2039  Surface *s;
2040  Tree_T *curves2delete = Tree_Create(sizeof(Curve *), CompareCurve);
2041  Tree_T *allNonDuplicatedCurves =
2042  Tree_Create(sizeof(Curve *), CompareTwoCurves);
2043 
2044  // Create unique curves
2045  int start = Tree_Nbr(GModel::current()->getGEOInternals()->Curves);
2046 
2047  List_T *All = Tree2List(GModel::current()->getGEOInternals()->Curves);
2048  for(int i = 0; i < List_Nbr(All); i++) {
2049  List_Read(All, i, &c);
2050  if(c->Num > 0) {
2051  if(!Tree_Search(allNonDuplicatedCurves, &c)) {
2052  Tree_Insert(allNonDuplicatedCurves, &c);
2053  if(!(c2 = FindCurve(-c->Num))) {
2054  Msg::Error("Unknown GEO curve with tag %d", -c->Num);
2055  List_Delete(All);
2056  List_T *tmp = Tree2List(curves2delete);
2057  for(int i = 0; i < List_Nbr(tmp); i++)
2059  List_Pointer(tmp, i));
2060  List_Delete(tmp);
2061  Tree_Delete(curves2delete);
2062  Tree_Delete(allNonDuplicatedCurves);
2063  return;
2064  }
2065  Tree_Insert(allNonDuplicatedCurves, &c2);
2066  }
2067  else {
2068  Tree_Suppress(GModel::current()->getGEOInternals()->Curves, &c);
2069  if(!(c2 = FindCurve(-c->Num))) {
2070  Msg::Error("Unknown GEO curve with tag %d", -c->Num);
2071  break;
2072  }
2073  Tree_Suppress(GModel::current()->getGEOInternals()->Curves, &c2);
2074  Tree_Insert(curves2delete, &c);
2075  Tree_Insert(curves2delete, &c2);
2076 
2077  if(c_report) { // keep track of changes
2078  auto m_it = c_report->find(c->Num);
2079  if(m_it != c_report->end()) {
2080  Curve **c_rep = (Curve **)Tree_PQuery(allNonDuplicatedCurves, &c);
2081  if(c_rep) m_it->second = (*c_rep)->Num;
2082  }
2083  m_it = c_report->find(c2->Num);
2084  if(m_it != c_report->end()) {
2085  Curve **c_rep_neg =
2086  (Curve **)Tree_PQuery(allNonDuplicatedCurves, &c2);
2087  if(c_rep_neg) m_it->second = (*c_rep_neg)->Num;
2088  }
2089  }
2090  }
2091  }
2092  }
2093  List_Delete(All);
2094 
2095  int end = Tree_Nbr(GModel::current()->getGEOInternals()->Curves);
2096 
2097  if(start == end) {
2098  List_T *tmp = Tree2List(curves2delete);
2099  for(int i = 0; i < List_Nbr(tmp); i++)
2101  List_Pointer(tmp, i));
2102  List_Delete(tmp);
2103  Tree_Delete(curves2delete);
2104  Tree_Delete(allNonDuplicatedCurves);
2105  return;
2106  }
2107 
2108  Msg::Debug("Removed %d duplicate curves", start - end);
2109 
2110  if(CTX::instance()->geom.oldNewreg) {
2112  Tree_Action(GModel::current()->getGEOInternals()->Curves, MaxNumCurve);
2113  }
2114 
2115  // Replace old curves in curves
2116  All = Tree2List(GModel::current()->getGEOInternals()->Curves);
2117  for(int i = 0; i < List_Nbr(All); i++) {
2118  List_Read(All, i, &c);
2119  // replace extrusion sources
2120  if(c->Extrude && c->Extrude->geo.Mode == COPIED_ENTITY) {
2121  c2 = FindCurve(std::abs(c->Extrude->geo.Source), curves2delete);
2122  if(c2) {
2123  if(!(pc2 = (Curve **)Tree_PQuery(allNonDuplicatedCurves, &c2)))
2124  Msg::Error("Could not replace GEO curve with tag %d in Coherence",
2125  c2->Num);
2126  else
2127  c->Extrude->geo.Source = (*pc2)->Num;
2128  }
2129  }
2130  }
2131  List_Delete(All);
2132 
2133  // Replace old curves in surfaces
2134  All = Tree2List(GModel::current()->getGEOInternals()->Surfaces);
2135  for(int i = 0; i < List_Nbr(All); i++) {
2136  List_Read(All, i, &s);
2137  // replace bounding curves
2138  for(int j = 0; j < List_Nbr(s->Generatrices); j++) {
2139  pc = (Curve **)List_Pointer(s->Generatrices, j);
2140  if(!(pc2 = (Curve **)Tree_PQuery(allNonDuplicatedCurves, pc)))
2141  Msg::Error("Could not replace GEO curve with tag %d in Coherence",
2142  (*pc)->Num);
2143  else {
2144  List_Write(s->Generatrices, j, pc2);
2145  // arghhh: check CompareTwoCurves!
2146  EndCurve(*pc2);
2147  }
2148  }
2149  for(int j = 0; j < List_Nbr(s->GeneratricesByTag); j++) {
2150  int num;
2151  List_Read(s->GeneratricesByTag, j, &num);
2152  c2 = FindCurve(std::abs(num), curves2delete);
2153  if(c2) {
2154  if(!(pc2 = (Curve **)Tree_PQuery(allNonDuplicatedCurves, &c2)))
2155  Msg::Error("Could not replace GEO curve with tag %d in Coherence",
2156  c2->Num);
2157  else
2158  List_Write(s->GeneratricesByTag, j, &(*pc2)->Num);
2159  }
2160  }
2161  // replace extrusion sources
2162  if(s->Extrude && s->Extrude->geo.Mode == EXTRUDED_ENTITY) {
2163  c2 = FindCurve(std::abs(s->Extrude->geo.Source), curves2delete);
2164  if(c2) {
2165  if(!(pc2 = (Curve **)Tree_PQuery(allNonDuplicatedCurves, &c2)))
2166  Msg::Error("Could not replace GEO curve with tag %d in Coherence",
2167  c2->Num);
2168  else
2169  s->Extrude->geo.Source = (*pc2)->Num;
2170  }
2171  }
2172  }
2173  List_Delete(All);
2174 
2175  // Replace old curves in physical groups
2176  for(int i = 0;
2177  i < List_Nbr(GModel::current()->getGEOInternals()->PhysicalGroups); i++) {
2180  if(p->Typ == MSH_PHYSICAL_LINE) {
2181  for(int j = 0; j < List_Nbr(p->Entities); j++) {
2182  int num;
2183  List_Read(p->Entities, j, &num);
2184  c2 = FindCurve(std::abs(num), curves2delete);
2185  if(c2) {
2186  if(!(pc2 = (Curve **)Tree_PQuery(allNonDuplicatedCurves, &c2)))
2187  Msg::Error("Could not replace GEO curve with tag %d in Coherence",
2188  c2->Num);
2189  else
2190  List_Write(p->Entities, j, &(*pc2)->Num);
2191  }
2192  }
2193  }
2194  }
2195 
2196  List_T *tmp = Tree2List(curves2delete);
2197  for(int i = 0; i < List_Nbr(tmp); i++)
2199  List_Pointer(tmp, i));
2200  List_Delete(tmp);
2201  Tree_Delete(curves2delete);
2202  Tree_Delete(allNonDuplicatedCurves);
2203 }
2204 
2205 /*
2206  1) Find duplicate points and replace in curves
2207  2) Find duplicate curves and replace in surfaces
2208  3) Find duplicate surfaces and replace in volumes
2209 
2210 --> some curves are degenerate (zero length)
2211 --> some surfaces are degenerate (zero surface)
2212 --> some volumes are degenerate (zero volume)
2213 
2214 */
2215 
2217 {
2218  { // remove degenerate curves from surface generatrices
2219  List_T *All = Tree2List(GModel::current()->getGEOInternals()->Surfaces);
2220  for(int i = 0; i < List_Nbr(All); i++) {
2221  Surface *s;
2222  List_Read(All, i, &s);
2223  List_T *ll = s->Generatrices;
2224  s->Generatrices = List_Create(4, 1, sizeof(Curve *));
2225  // List_Delete(s->GeneratricesByTag);
2226  // s->GeneratricesByTag = List_Create(4, 1, sizeof(int));
2227  for(int j = 0; j < List_Nbr(ll); j++) {
2228  Curve *c;
2229  List_Read(ll, j, &c);
2230  if(!c->degenerate()) {
2231  List_Add(s->Generatrices, &c);
2232  // List_Add(s->GeneratricesByTag, &c->Num);
2233  }
2234  }
2235  if(List_Nbr(ll) != List_Nbr(s->Generatrices))
2236  Msg::Info("Coherence: surface %d goes from %d to %d bounding curves",
2237  s->Num, List_Nbr(ll), List_Nbr(s->Generatrices));
2238  List_Delete(ll);
2239  }
2240  }
2241 
2242  { // actually remove the curves
2243  List_T *All = Tree2List(GModel::current()->getGEOInternals()->Curves);
2244  for(int i = 0; i < List_Nbr(All); i++) {
2245  Curve *c;
2246  List_Read(All, i, &c);
2247  if(c->degenerate()) {
2248  DeleteCurve(c->Num);
2249  DeleteCurve(-c->Num);
2250  }
2251  }
2252  }
2253 }
2254 
2256 {
2257  List_T *Vols = Tree2List(GModel::current()->getGEOInternals()->Volumes);
2258  for(int k = 0; k < List_Nbr(Vols); k++) {
2259  Volume *v;
2260  List_Read(Vols, k, &v);
2261  std::set<int> unique;
2262  int N = List_Nbr(v->Surfaces);
2263  for(int j = 0; j < N; j++) {
2264  Surface *s;
2265  List_Read(v->Surfaces, j, &s);
2266  auto it = unique.find(-s->Num);
2267  if(it == unique.end())
2268  unique.insert(s->Num);
2269  else
2270  unique.erase(it);
2271  }
2272  if(N - unique.size())
2273  Msg::Info("Coherence: removing %d seams on volume %d", N - unique.size(),
2274  v->Num);
2275 
2276  List_T *ll = v->Surfaces;
2277  List_T *ll2 = v->SurfacesOrientations;
2278  v->Surfaces = List_Create(1, 2, sizeof(Surface *));
2279  v->SurfacesOrientations = List_Create(1, 2, sizeof(int));
2280  for(int j = 0; j < List_Nbr(ll); j++) {
2281  Surface *s;
2282  List_Read(ll, j, &s);
2283  if(unique.find(s->Num) != unique.end()) {
2284  List_Add(v->Surfaces, &s);
2286  }
2287  }
2288  List_Delete(ll);
2289  List_Delete(ll2);
2290  if(List_Nbr(v->Surfaces) == 0) {
2291  Msg::Info("Coherence: volume %d is removed (degenerated)", v->Num);
2292  DeleteVolume(v->Num);
2293  }
2294  }
2295 }
2296 
2298 {
2299  List_T *All = Tree2List(GModel::current()->getGEOInternals()->Surfaces);
2300 
2301  for(int i = 0; i < List_Nbr(All); i++) {
2302  Surface *s;
2303  std::set<int> unique;
2304  List_Read(All, i, &s);
2305  int N = List_Nbr(s->Generatrices);
2306  for(int j = 0; j < N; j++) {
2307  Curve *c;
2308  List_Read(s->Generatrices, j, &c);
2309  auto it = unique.find(-c->Num);
2310  if(it == unique.end())
2311  unique.insert(c->Num);
2312  else
2313  unique.erase(it);
2314  }
2315 
2316  if(N - unique.size())
2317  Msg::Info("Coherence: removing %d seams on surface %d", N - unique.size(),
2318  s->Num);
2319 
2320  List_T *ll = s->Generatrices;
2321  s->Generatrices = List_Create(4, 1, sizeof(Curve *));
2322  // List_Delete(s->GeneratricesByTag);
2323  // s->GeneratricesByTag = List_Create(4, 1, sizeof(int));
2324  for(int j = 0; j < List_Nbr(ll); j++) {
2325  Curve *c;
2326  List_Read(ll, j, &c);
2327  if(unique.find(c->Num) != unique.end()) {
2328  List_Add(s->Generatrices, &c);
2329  // List_Add(s->GeneratricesByTag, &c->Num);
2330  }
2331  }
2332  List_Delete(ll);
2333 
2334  if(s->degenerate()) {
2335  Msg::Info("Coherence: surface %d is removed (degenerated)", s->Num);
2336  List_T *Vols = Tree2List(GModel::current()->getGEOInternals()->Volumes);
2337  for(int k = 0; k < List_Nbr(Vols); k++) {
2338  Volume *v;
2339  List_Read(Vols, k, &v);
2340  List_T *ll = v->Surfaces;
2341  List_T *ll2 = v->SurfacesOrientations;
2342  v->Surfaces = List_Create(1, 2, sizeof(Surface *));
2343  v->SurfacesOrientations = List_Create(1, 2, sizeof(int));
2344  for(int j = 0; j < List_Nbr(ll); j++) {
2345  if(CompareSurface(List_Pointer(ll, j), &s)) {
2346  List_Add(v->Surfaces, List_Pointer(ll, j));
2348  }
2349  }
2350  List_Delete(ll);
2351  List_Delete(ll2);
2352  }
2353  DeleteSurface(s->Num);
2354  }
2355  }
2356 }
2357 
2359 {
2360  int N = List_Nbr(Generatrices);
2361  int Nd = 0;
2362  for(int i = 0; i < N; i++) {
2363  Curve *c;
2364  List_Read(Generatrices, i, &c);
2365  if(!c->degenerate()) Nd++;
2366  }
2367  return Nd <= 1;
2368 }
2369 
2370 static void ReplaceDuplicateSurfaces(std::map<int, int> *s_report = nullptr)
2371 {
2372  Surface *s, *s2, **ps, **ps2;
2373  Volume *vol;
2374  Tree_T *surfaces2delete = Tree_Create(sizeof(Surface *), CompareSurface);
2375  Tree_T *allNonDuplicatedSurfaces =
2377 
2378  // Create unique surfaces
2379  int start = Tree_Nbr(GModel::current()->getGEOInternals()->Surfaces);
2380 
2381  List_T *All = Tree2List(GModel::current()->getGEOInternals()->Surfaces);
2382  for(int i = 0; i < List_Nbr(All); i++) {
2383  List_Read(All, i, &s);
2384  if(s->Num > 0) {
2385  if(!Tree_Search(allNonDuplicatedSurfaces, &s)) {
2386  Tree_Insert(allNonDuplicatedSurfaces, &s);
2387  }
2388  else {
2389  Tree_Suppress(GModel::current()->getGEOInternals()->Surfaces, &s);
2390  Tree_Insert(surfaces2delete, &s);
2391 
2392  if(s_report) { // keep track of changes
2393  auto m_it = (*s_report).find(s->Num);
2394  if(m_it != s_report->end()) {
2395  Surface **s_rep =
2396  (Surface **)Tree_PQuery(allNonDuplicatedSurfaces, &s);
2397  if(s_rep) m_it->second = (*s_rep)->Num;
2398  }
2399  }
2400  }
2401  }
2402  }
2403  List_Delete(All);
2404 
2405  int end = Tree_Nbr(GModel::current()->getGEOInternals()->Surfaces);
2406 
2407  if(start == end) {
2408  List_T *tmp = Tree2List(surfaces2delete);
2409  for(int i = 0; i < List_Nbr(tmp); i++)
2411  List_Pointer(tmp, i));
2412  List_Delete(tmp);
2413  Tree_Delete(surfaces2delete);
2414  Tree_Delete(allNonDuplicatedSurfaces);
2415  return;
2416  }
2417 
2418  Msg::Debug("Removed %d duplicate surfaces", start - end);
2419 
2420  if(CTX::instance()->geom.oldNewreg) {
2422  Tree_Action(GModel::current()->getGEOInternals()->Surfaces, MaxNumSurface);
2423  }
2424 
2425  // Replace old surfaces in surfaces
2426  All = Tree2List(GModel::current()->getGEOInternals()->Surfaces);
2427  for(int i = 0; i < List_Nbr(All); i++) {
2428  List_Read(All, i, &s);
2429  // replace extrusion sources
2430  if(s->Extrude && s->Extrude->geo.Mode == COPIED_ENTITY) {
2431  s2 = FindSurface(std::abs(s->Extrude->geo.Source), surfaces2delete);
2432  if(s2) {
2433  if(!(ps2 = (Surface **)Tree_PQuery(allNonDuplicatedSurfaces, &s2)))
2434  Msg::Error("Could not replace surface %d in Coherence", s2->Num);
2435  else
2436  s->Extrude->geo.Source = (*ps2)->Num;
2437  }
2438  }
2439  }
2440  List_Delete(All);
2441 
2442  // Replace old surfaces in volumes
2443  All = Tree2List(GModel::current()->getGEOInternals()->Volumes);
2444  for(int i = 0; i < List_Nbr(All); i++) {
2445  List_Read(All, i, &vol);
2446  // replace bounding surfaces
2447  for(int j = 0; j < List_Nbr(vol->Surfaces); j++) {
2448  ps = (Surface **)List_Pointer(vol->Surfaces, j);
2449  if(!(ps2 = (Surface **)Tree_PQuery(allNonDuplicatedSurfaces, ps)))
2450  Msg::Error("Could not replace surface %d in Coherence", (*ps)->Num);
2451  else
2452  List_Write(vol->Surfaces, j, ps2);
2453  }
2454  for(int j = 0; j < List_Nbr(vol->SurfacesByTag); j++) {
2455  int num;
2456  List_Read(vol->SurfacesByTag, j, &num);
2457  s2 = FindSurface(std::abs(vol->Extrude->geo.Source), surfaces2delete);
2458  if(s2) {
2459  if(!(ps2 = (Surface **)Tree_PQuery(allNonDuplicatedSurfaces, &s2)))
2460  Msg::Error("Could not replace surface %d in Coherence", s2->Num);
2461  else
2462  List_Write(vol->SurfacesByTag, j, &(*ps2)->Num);
2463  }
2464  }
2465  // replace extrusion sources
2466  if(vol->Extrude && vol->Extrude->geo.Mode == EXTRUDED_ENTITY) {
2467  s2 = FindSurface(std::abs(vol->Extrude->geo.Source), surfaces2delete);
2468  if(s2) {
2469  if(!(ps2 = (Surface **)Tree_PQuery(allNonDuplicatedSurfaces, &s2)))
2470  Msg::Error("Could not replace surface %d in Coherence", s2->Num);
2471  else
2472  vol->Extrude->geo.Source = (*ps2)->Num;
2473  }
2474  }
2475  }
2476  List_Delete(All);
2477 
2478  // Replace old surfaces in physical groups
2479  for(int i = 0;
2480  i < List_Nbr(GModel::current()->getGEOInternals()->PhysicalGroups); i++) {
2483  if(p->Typ == MSH_PHYSICAL_SURFACE) {
2484  for(int j = 0; j < List_Nbr(p->Entities); j++) {
2485  int num;
2486  List_Read(p->Entities, j, &num);
2487  s2 = FindSurface(std::abs(num), surfaces2delete);
2488  if(s2) {
2489  if(!(ps2 = (Surface **)Tree_PQuery(allNonDuplicatedSurfaces, &s2)))
2490  Msg::Error("Could not replace surface %d in Coherence", s2->Num);
2491  else
2492  List_Write(p->Entities, j, &(*ps2)->Num);
2493  }
2494  }
2495  }
2496  }
2497 
2498  List_T *tmp = Tree2List(surfaces2delete);
2499  for(int i = 0; i < List_Nbr(tmp); i++)
2501  List_Pointer(tmp, i));
2502  List_Delete(tmp);
2503  Tree_Delete(surfaces2delete);
2504  Tree_Delete(allNonDuplicatedSurfaces);
2505 }
2506 
2507 static void ReplaceAllDuplicates(std::vector<std::map<int, int> > &report)
2508 {
2509  std::map<int, int> *vertex_report = nullptr;
2510  std::map<int, int> *curve_report = nullptr;
2511  std::map<int, int> *surface_report = nullptr;
2512  if(report.size() >= 1 && report[0].size()) vertex_report = &(report[0]);
2513  if(report.size() >= 2 && report[1].size()) curve_report = &(report[1]);
2514  if(report.size() >= 3 && report[2].size()) surface_report = &(report[2]);
2515 
2516  ReplaceDuplicatePoints(vertex_report);
2517  ReplaceDuplicateCurves(curve_report);
2518  ReplaceDuplicateSurfaces(surface_report);
2519 
2520  if(CTX::instance()->geom.autoCoherence == 2) {
2524  }
2525 }
2526 
2528 {
2529  std::vector<std::map<int, int> > report;
2530  report.clear();
2531  ReplaceAllDuplicates(report);
2532 }
2533 
2534 void ReplaceAllDuplicatesNew(double tol)
2535 {
2536  if(tol < 0) tol = CTX::instance()->geom.tolerance * CTX::instance()->lc;
2538  ReplaceDuplicateCurves(nullptr);
2539  ReplaceDuplicateSurfaces(nullptr);
2540 }
2541 
2542 void ProtudeXYZ(double &x, double &y, double &z, ExtrudeParams *e)
2543 {
2544  double matrix[4][4];
2545  double T[3];
2546  Vertex v(x, y, z);
2547 
2548  T[0] = -e->geo.pt[0];
2549  T[1] = -e->geo.pt[1];
2550  T[2] = -e->geo.pt[2];
2551  SetTranslationMatrix(matrix, T);
2553 
2554  SetRotationMatrix(matrix, e->geo.axe, e->geo.angle);
2556 
2557  T[0] = -T[0];
2558  T[1] = -T[1];
2559  T[2] = -T[2];
2560  SetTranslationMatrix(matrix, T);
2562 
2563  x = v.Pos.X;
2564  y = v.Pos.Y;
2565  z = v.Pos.Z;
2566 
2568 }
2569 
2570 int ExtrudePoint(int type, int ip, double T0, double T1, double T2, double A0,
2571  double A1, double A2, double X0, double X1, double X2,
2572  double alpha, Curve **pc, Curve **prc, int final,
2573  ExtrudeParams *e)
2574 {
2575  double matrix[4][4], T[3], Ax[3], d;
2576 
2577  *pc = *prc = nullptr;
2578 
2579  Vertex V;
2580  Vertex *pv = &V;
2581  pv->Num = ip;
2582  int found = Tree_Query(GModel::current()->getGEOInternals()->Points, &pv);
2583 
2584  GVertex *gv = nullptr;
2585  if(!found && type == BOUNDARY_LAYER) {
2586  // we allow boundary layers from generic points
2587  gv = GModel::current()->getVertexByTag(ip);
2588  if(gv)
2589  pv = DuplicateVertex(gv);
2590  }
2591 
2592  if(!found && !gv) return 0;
2593 
2594  Msg::Debug("Extrude Point %d", ip);
2595 
2596  Vertex *chapeau = DuplicateVertex(pv);
2597 
2598  bool ok = true;
2599  Vertex *newp = nullptr;
2600  Curve *c = nullptr;
2601 
2602  switch(type) {
2603  case TRANSLATE:
2604  T[0] = T0;
2605  T[1] = T1;
2606  T[2] = T2;
2607  SetTranslationMatrix(matrix, T);
2609  ApplyTransformationToPoint(matrix, chapeau);
2610  if(!ComparePosition(&pv, &chapeau)) return pv->Num;
2611  c = CreateCurve(NEWCURVE(), MSH_SEGM_LINE, 1, nullptr, nullptr, -1, -1, 0.,
2612  1., ok);
2613  c->Control_Points = List_Create(2, 1, sizeof(Vertex *));
2614  c->Extrude = new ExtrudeParams;
2615  c->Extrude->fill(type, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha);
2616  c->Extrude->geo.Source = pv->Num;
2617  if(e) c->Extrude->mesh = e->mesh;
2618  List_Add(c->Control_Points, &pv);
2619  List_Add(c->Control_Points, &chapeau);
2620  c->beg = pv;
2621  c->end = chapeau;
2622  break;
2623  case BOUNDARY_LAYER:
2624  chapeau->Typ = MSH_POINT_BND_LAYER;
2625  if(e) chapeau->boundaryLayerIndex = e->mesh.BoundaryLayerIndex;
2626  c = CreateCurve(NEWCURVE(), MSH_SEGM_BND_LAYER, 1, nullptr, nullptr, -1, -1,
2627  0., 1., ok);
2628  c->Control_Points = List_Create(2, 1, sizeof(Vertex *));
2629  c->Extrude = new ExtrudeParams;
2630  c->Extrude->fill(type, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha);
2631  c->Extrude->geo.Source = pv->Num;
2632  if(e) c->Extrude->mesh = e->mesh;
2633  List_Add(c->Control_Points, &pv);
2634  List_Add(c->Control_Points, &chapeau);
2635  c->beg = pv;
2636  if(gv) c->begByTag = gv->tag();
2637  c->end = chapeau;
2638  break;
2639  case ROTATE:
2640  T[0] = -X0;
2641  T[1] = -X1;
2642  T[2] = -X2;
2643  SetTranslationMatrix(matrix, T);
2645  ApplyTransformationToPoint(matrix, chapeau);
2646  Ax[0] = A0;
2647  Ax[1] = A1;
2648  Ax[2] = A2;
2649  SetRotationMatrix(matrix, Ax, alpha);
2651  ApplyTransformationToPoint(matrix, chapeau);
2652  T[0] = X0;
2653  T[1] = X1;
2654  T[2] = X2;
2655  SetTranslationMatrix(matrix, T);
2657  ApplyTransformationToPoint(matrix, chapeau);
2658  if(!ComparePosition(&pv, &chapeau)) return pv->Num;
2659  c = CreateCurve(NEWCURVE(), MSH_SEGM_CIRC, 1, nullptr, nullptr, -1, -1, 0.,
2660  1., ok);
2661  c->Control_Points = List_Create(3, 1, sizeof(Vertex *));
2662  c->Extrude = new ExtrudeParams;
2663  c->Extrude->fill(type, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha);
2664  c->Extrude->geo.Source = pv->Num;
2665  if(e) c->Extrude->mesh = e->mesh;
2666  List_Add(c->Control_Points, &pv);
2667  // compute circle center
2668  newp = DuplicateVertex(pv);
2669  Ax[0] = A0;
2670  Ax[1] = A1;
2671  Ax[2] = A2;
2672  norme(Ax);
2673  T[0] = pv->Pos.X - X0;
2674  T[1] = pv->Pos.Y - X1;
2675  T[2] = pv->Pos.Z - X2;
2676  d = prosca(T, Ax);
2677  newp->Pos.X = X0 + d * Ax[0];
2678  newp->Pos.Y = X1 + d * Ax[1];
2679  newp->Pos.Z = X2 + d * Ax[2];
2680  List_Add(c->Control_Points, &newp);
2681  List_Add(c->Control_Points, &chapeau);
2682  c->beg = pv;
2683  c->end = chapeau;
2684  break;
2685  case TRANSLATE_ROTATE:
2687  d = d ? d : 1;
2688  c = CreateCurve(NEWCURVE(), MSH_SEGM_SPLN, 1, nullptr, nullptr, -1, -1, 0.,
2689  1., ok);
2690  c->Control_Points = List_Create(
2691  CTX::instance()->geom.extrudeSplinePoints + 1, 1, sizeof(Vertex *));
2692  c->Extrude = new ExtrudeParams;
2693  c->Extrude->fill(type, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha);
2694  c->Extrude->geo.Source = pv->Num;
2695  if(e) c->Extrude->mesh = e->mesh;
2696  List_Add(c->Control_Points, &pv);
2697  c->beg = pv;
2698  for(int i = 0; i < CTX::instance()->geom.extrudeSplinePoints; i++) {
2699  if(i) chapeau = DuplicateVertex(chapeau);
2700  T[0] = -X0;
2701  T[1] = -X1;
2702  T[2] = -X2;
2703  SetTranslationMatrix(matrix, T);
2705  ApplyTransformationToPoint(matrix, chapeau);
2706  Ax[0] = A0;
2707  Ax[1] = A1;
2708  Ax[2] = A2;
2709  SetRotationMatrix(matrix, Ax, alpha / d);
2711  ApplyTransformationToPoint(matrix, chapeau);
2712  T[0] = X0;
2713  T[1] = X1;
2714  T[2] = X2;
2715  SetTranslationMatrix(matrix, T);
2717  ApplyTransformationToPoint(matrix, chapeau);
2718  T[0] = T0 / d;
2719  T[1] = T1 / d;
2720  T[2] = T2 / d;
2721  SetTranslationMatrix(matrix, T);
2723  ApplyTransformationToPoint(matrix, chapeau);
2724  List_Add(c->Control_Points, &chapeau);
2725  }
2726  c->end = chapeau;
2727  break;
2728  default: Msg::Error("Unknown extrusion type"); return pv->Num;
2729  }
2730 
2731  EndCurve(c);
2732  Tree_Add(GModel::current()->getGEOInternals()->Curves, &c);
2734  *pc = c;
2735  *prc = FindCurve(-c->Num);
2736 
2738 
2739  int chap_num = chapeau->Num;
2740  int body_num = c->Num;
2741 
2742  if(CTX::instance()->geom.autoCoherence && final) {
2743  std::vector<std::map<int, int> > report(3);
2744  report[0][chap_num] = chap_num;
2745  report[1][body_num] = body_num;
2746  ReplaceAllDuplicates(report);
2747  auto m_it = report[0].find(chap_num);
2748  if(m_it != report[0].end())
2749  chap_num = report[0][chap_num];
2750  else
2751  chap_num = 0;
2752  if(report[1][body_num] != body_num) *pc = *prc = nullptr;
2753  }
2754  return chap_num;
2755 }
2756 
2757 int ExtrudeCurve(int type, int ic, double T0, double T1, double T2, double A0,
2758  double A1, double A2, double X0, double X1, double X2,
2759  double alpha, Surface **ps, int final, ExtrudeParams *e)
2760 {
2761  double matrix[4][4], T[3], Ax[3];
2762 
2763  *ps = nullptr;
2764 
2765  Curve *pc = FindCurve(ic);
2766  Curve *revpc = FindCurve(-ic);
2767  GEdge *ge = nullptr;
2768 
2769  if(!pc && !revpc && type == BOUNDARY_LAYER) {
2770  // we allow boundary layers from generic curves
2771  ge = GModel::current()->getEdgeByTag(std::abs(ic));
2772  }
2773 
2774  if((!pc || !revpc) && !ge) { return 0; }
2775 
2776  if(pc) {
2777  if(!pc->beg || !pc->end) {
2778  Msg::Error("Cannot extrude curve with no begin or end point");
2779  return 0;
2780  }
2781  if(pc->beg == pc->end && type != BOUNDARY_LAYER) {
2782  Msg::Warning("Extrusion of periodic curves is not supported with the "
2783  "built-in kernel");
2784  }
2785  }
2786 
2787  if(ge) {
2788  if(ge->degenerate(0)) {
2789  Msg::Info("Skipping boundary layer extrusion of degenerate curve %d",
2790  ge->tag());
2791  return 0;
2792  }
2793 
2794  if(!ge->getBeginVertex() || !ge->getEndVertex()) {
2795  Msg::Error("Cannot extrude curve with no begin or end point");
2796  return 0;
2797  }
2798  }
2799 
2800  Msg::Debug("Extrude Curve %d", ic);
2801 
2802  Curve *chapeau = nullptr;
2803  if(pc)
2804  chapeau = DuplicateCurve(pc);
2805  else
2806  chapeau = DuplicateCurve(ge);
2807 
2808  chapeau->Extrude = new ExtrudeParams(COPIED_ENTITY);
2809  chapeau->Extrude->fill(type, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha);
2810  chapeau->Extrude->geo.Source = ic;
2811  if(e) chapeau->Extrude->mesh = e->mesh;
2812 
2813  switch(type) {
2814  case TRANSLATE:
2815  T[0] = T0;
2816  T[1] = T1;
2817  T[2] = T2;
2818  SetTranslationMatrix(matrix, T);
2820  ApplyTransformationToCurve(matrix, chapeau);
2821  break;
2822  case BOUNDARY_LAYER:
2823  chapeau->Typ = MSH_SEGM_BND_LAYER;
2824  if(chapeau->beg) {
2825  chapeau->beg->Typ = MSH_POINT_BND_LAYER;
2826  if(e) chapeau->beg->boundaryLayerIndex = e->mesh.BoundaryLayerIndex;
2827  }
2828  if(chapeau->end) {
2829  chapeau->end->Typ = MSH_POINT_BND_LAYER;
2830  if(e) chapeau->end->boundaryLayerIndex = e->mesh.BoundaryLayerIndex;
2831  }
2832  for(int i = 0; i < List_Nbr(chapeau->Control_Points); i++) {
2833  Vertex *v;
2834  List_Read(chapeau->Control_Points, i, &v);
2836  }
2837  revpc = FindCurve(-chapeau->Num);
2838  if(revpc) {
2839  revpc->Typ = MSH_SEGM_BND_LAYER;
2840  if(chapeau->Extrude) {
2841  revpc->Extrude = new ExtrudeParams;
2842  revpc->Extrude->geo = chapeau->Extrude->geo;
2843  }
2844  }
2845  break;
2846  case ROTATE:
2847  T[0] = -X0;
2848  T[1] = -X1;
2849  T[2] = -X2;
2850  SetTranslationMatrix(matrix, T);
2852  ApplyTransformationToCurve(matrix, chapeau);
2853  Ax[0] = A0;
2854  Ax[1] = A1;
2855  Ax[2] = A2;
2856  SetRotationMatrix(matrix, Ax, alpha);
2858  ApplyTransformationToCurve(matrix, chapeau);
2859  T[0] = X0;
2860  T[1] = X1;
2861  T[2] = X2;
2862  SetTranslationMatrix(matrix, T);
2864  ApplyTransformationToCurve(matrix, chapeau);
2865  break;
2866  case TRANSLATE_ROTATE:
2867  T[0] = -X0;
2868  T[1] = -X1;
2869  T[2] = -X2;
2870  SetTranslationMatrix(matrix, T);
2872  ApplyTransformationToCurve(matrix, chapeau);
2873  Ax[0] = A0;
2874  Ax[1] = A1;
2875  Ax[2] = A2;
2876  SetRotationMatrix(matrix, Ax, alpha);
2878  ApplyTransformationToCurve(matrix, chapeau);
2879  T[0] = X0;
2880  T[1] = X1;
2881  T[2] = X2;
2882  SetTranslationMatrix(matrix, T);
2884  ApplyTransformationToCurve(matrix, chapeau);
2885  T[0] = T0;
2886  T[1] = T1;
2887  T[2] = T2;
2888  SetTranslationMatrix(matrix, T);
2890  ApplyTransformationToCurve(matrix, chapeau);
2891  break;
2892  default:
2893  Msg::Error("Unknown extrusion type");
2894  return ic;
2895  }
2896 
2897  int ibeg, iend;
2898  if(pc) {
2899  ibeg = pc->beg->Num;
2900  iend = pc->end->Num;
2901  }
2902  else {
2903  ibeg = ge->getBeginVertex()->tag();
2904  iend = ge->getEndVertex()->tag();
2905  }
2906  Curve *CurveBeg, *CurveEnd, *ReverseBeg, *ReverseEnd;
2907  ExtrudePoint(type, ibeg, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha,
2908  &CurveBeg, &ReverseBeg, 0, e);
2909  ExtrudePoint(type, iend, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha,
2910  &CurveEnd, &ReverseEnd, 0, e);
2911 
2912  if(!CurveBeg && !CurveEnd) { return ic; }
2913 
2914  // FIXME: if we extrude by rotation a (non-straight) curve defined by 2 end
2915  // points, with a rotation axis going through the end points, the resulting
2916  // surface would have 2 bounding edges (the axis and the curve). We cannot
2917  // handle this case.
2918 
2919  Surface *s;
2920  if(type == BOUNDARY_LAYER)
2922  else if(!CurveBeg || !CurveEnd)
2924  else
2926 
2927  s->Generatrices = List_Create(4, 1, sizeof(Curve *));
2928  s->GeneratricesByTag = List_Create(4, 1, sizeof(int));
2929  s->Extrude = new ExtrudeParams;
2930  s->Extrude->fill(type, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha);
2931  s->Extrude->geo.Source = ic;
2932  if(e) s->Extrude->mesh = e->mesh;
2933 
2934  Curve *ReverseChapeau = FindCurve(-chapeau->Num);
2935 
2936  if(pc) {
2937  if(!CurveBeg) {
2938  List_Add(s->Generatrices, &pc);
2939  List_Add(s->Generatrices, &CurveEnd);
2940  List_Add(s->Generatrices, &ReverseChapeau);
2941  }
2942  else if(!CurveEnd) {
2943  List_Add(s->Generatrices, &ReverseChapeau);
2944  List_Add(s->Generatrices, &ReverseBeg);
2945  List_Add(s->Generatrices, &pc);
2946  }
2947  else {
2948  List_Add(s->Generatrices, &pc);
2949  List_Add(s->Generatrices, &CurveEnd);
2950  List_Add(s->Generatrices, &ReverseChapeau);
2951  List_Add(s->Generatrices, &ReverseBeg);
2952  }
2953  }
2954  else {
2955  List_Add(s->GeneratricesByTag, ic);
2956  List_Add(s->GeneratricesByTag, &CurveEnd->Num);
2957  List_Add(s->GeneratricesByTag, &ReverseChapeau->Num);
2958  List_Add(s->GeneratricesByTag, &ReverseBeg->Num);
2959  }
2960 
2961  EndSurface(s);
2962  Tree_Add(GModel::current()->getGEOInternals()->Surfaces, &s);
2963 
2965 
2966  *ps = s;
2967 
2968  int chap_num = chapeau->Num;
2969  int body_num = s->Num;
2970 
2971  if(CTX::instance()->geom.autoCoherence && final) {
2972  std::vector<std::map<int, int> > report(3);
2973  report[1][chap_num] = chap_num;
2974  report[2][body_num] = body_num;
2975  ReplaceAllDuplicates(report);
2976  auto m_it = report[1].find(chap_num);
2977  if(m_it != report[1].end())
2978  chap_num = report[1][chap_num];
2979  else
2980  chap_num = 0;
2981  if(report[2][body_num] != body_num) *ps = nullptr;
2982  }
2983 
2984  return chap_num;
2985 }
2986 
2987 int ExtrudeSurface(int type, int is, double T0, double T1, double T2, double A0,
2988  double A1, double A2, double X0, double X1, double X2,
2989  double alpha, Volume **pv, ExtrudeParams *e)
2990 {
2991  *pv = nullptr;
2992 
2993  // 'is' can be negative, to signify that the surface orientation should be
2994  // reversed. This orientation information is only used at the moment when
2995  // creating boundary layers
2996  Surface *ps = FindSurface(std::abs(is));
2997 
2998  GFace *gf = nullptr;
2999  if(!ps && type == BOUNDARY_LAYER) {
3000  // we allow boundary layers from generic surfaces
3001  gf = GModel::current()->getFaceByTag(std::abs(is));
3002  }
3003 
3004  if(!ps && !gf) return 0;
3005 
3006  Msg::Debug("Extrude Surface %d", is);
3007 
3008  Surface *chapeau = nullptr;
3009  std::map<int, int> source;
3010  if(ps)
3011  chapeau = DuplicateSurface(ps);
3012  else
3013  chapeau = DuplicateSurface(gf, source);
3014  chapeau->Extrude = new ExtrudeParams(COPIED_ENTITY);
3015  chapeau->Extrude->fill(type, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha);
3016  chapeau->Extrude->geo.Source = is; // not ps->Num: we need the sign info
3017  if(e) chapeau->Extrude->mesh = e->mesh;
3018 
3019  for(int i = 0; i < List_Nbr(chapeau->Generatrices); i++) {
3020  Curve *c, *c2;
3021  List_Read(chapeau->Generatrices, i, &c);
3022  c->Extrude = new ExtrudeParams(COPIED_ENTITY);
3023  c->Extrude->fill(type, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha);
3024  int c2num = 0;
3025  if(ps) {
3026  List_Read(ps->Generatrices, i, &c2);
3027  // don't take the abs(): the sign of c2->Num is important (used when copying
3028  // the mesh in the extrusion routine)
3029  c2num = c2->Num;
3030  }
3031  else {
3032  c2num = source[c->Num];
3033  }
3034  c->Extrude->geo.Source = c2num;
3035  if(e) c->Extrude->mesh = e->mesh;
3036 
3037  Curve *revc = FindCurve(-c->Num);
3038  if(!revc) {
3039  Msg::Error("Unknown GEO curve with tag %d", -c->Num);
3040  return ps ? ps->Num : gf->tag();
3041  }
3042  revc->Extrude = new ExtrudeParams(COPIED_ENTITY);
3043  revc->Extrude->fill(type, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha);
3044  revc->Extrude->geo.Source = c2num;
3045  if(e) c->Extrude->mesh = e->mesh;
3046  }
3047 
3048  // FIXME: this is a really ugly hack for backward compatibility, so that we
3049  // don't screw up the old .geo files too much. (Before version 1.54, we didn't
3050  // always create new volumes during "Extrude Surface". Now we do, but with
3051  // "CTX::instance()->geom.oldNewreg==1", this bumps the NEWREG() counter, and
3052  // thus changes the whole automatic numbering sequence.) So we locally force
3053  // oldNewreg to 0: in most cases, since we define points, curves, etc., before
3054  // defining volumes, the NEWVOLUME() call below will return a fairly low
3055  // number, that will not interfere with the other numbers...
3056  int tmp = CTX::instance()->geom.oldNewreg;
3057  CTX::instance()->geom.oldNewreg = 0;
3059  CTX::instance()->geom.oldNewreg = tmp;
3060 
3061  v->Extrude = new ExtrudeParams;
3062  v->Extrude->fill(type, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha);
3063  v->Extrude->geo.Source = is;
3064  if(e) v->Extrude->mesh = e->mesh;
3065  int ori = -1;
3066  if(ps) {
3067  List_Add(v->Surfaces, &ps);
3068  }
3069  else {
3070  int tag = gf->tag();
3071  List_Add(v->SurfacesByTag, &tag);
3072  }
3073  List_Add(v->SurfacesOrientations, &ori);
3074  ori = 1;
3075  List_Add(v->Surfaces, &chapeau);
3076  List_Add(v->SurfacesOrientations, &ori);
3077 
3078  int numg = 0;
3079  if(ps) numg = List_Nbr(ps->Generatrices);
3080  else numg = gf->edges().size();
3081 
3082  for(int i = 0; i < numg; i++) {
3083  int cnum = 0;
3084  if(ps) {
3085  Curve *c;
3086  List_Read(ps->Generatrices, i, &c);
3087  cnum = c->Num;
3088  }
3089  else {
3090  cnum = gf->edges()[i]->tag();
3091  std::vector<int> ori = gf->edgeOrientations();
3092  if(i < (int)ori.size() && ori[i] < 0) cnum *= -1;
3093  }
3094  Surface *s;
3095  ExtrudeCurve(type, cnum, T0, T1, T2, A0, A1, A2, X0, X1, X2, alpha, &s, 0,
3096  e);
3097  if(s) {
3098  if(cnum < 0)
3099  ori = -1;
3100  else
3101  ori = 1;
3102  List_Add(v->Surfaces, &s);
3103  List_Add(v->SurfacesOrientations, &ori);
3104  }
3105  }
3106 
3107  double matrix[4][4], T[3], Ax[3];
3108 
3109  switch(type) {
3110  case TRANSLATE:
3111  T[0] = T0;
3112  T[1] = T1;
3113  T[2] = T2;
3114  SetTranslationMatrix(matrix, T);
3116  ApplyTransformationToSurface(matrix, chapeau);
3117  break;
3118  case BOUNDARY_LAYER:
3119  chapeau->Typ = MSH_SURF_BND_LAYER;
3120  for(int i = 0; i < List_Nbr(chapeau->Generatrices); i++) {
3121  Curve *c;
3122  List_Read(chapeau->Generatrices, i, &c);
3123  c->Typ = MSH_SEGM_BND_LAYER;
3124  c = FindCurve(-c->Num);
3125  c->Typ = MSH_SEGM_BND_LAYER;
3126  if(c->beg) {
3127  c->beg->Typ = MSH_POINT_BND_LAYER;
3128  if(e) c->beg->boundaryLayerIndex = e->mesh.BoundaryLayerIndex;
3129  }
3130  if(c->end) {
3131  c->end->Typ = MSH_POINT_BND_LAYER;
3132  if(e) c->end->boundaryLayerIndex = e->mesh.BoundaryLayerIndex;
3133  }
3134  for(int i = 0; i < List_Nbr(c->Control_Points); i++) {
3135  Vertex *v;
3136  List_Read(c->Control_Points, i, &v);
3138  }
3139  }
3140  break;
3141  case ROTATE:
3142  T[0] = -X0;
3143  T[1] = -X1;
3144  T[2] = -X2;
3145  SetTranslationMatrix(matrix, T);
3147  ApplyTransformationToSurface(matrix, chapeau);
3148  Ax[0] = A0;
3149  Ax[1] = A1;
3150  Ax[2] = A2;
3151  SetRotationMatrix(matrix, Ax, alpha);
3153  ApplyTransformationToSurface(matrix, chapeau);
3154  T[0] = X0;
3155  T[1] = X1;
3156  T[2] = X2;
3157  SetTranslationMatrix(matrix, T);
3159  ApplyTransformationToSurface(matrix, chapeau);
3160  break;
3161  case TRANSLATE_ROTATE:
3162  T[0] = -X0;
3163  T[1] = -X1;
3164  T[2] = -X2;
3165  SetTranslationMatrix(matrix, T);
3167  ApplyTransformationToSurface(matrix, chapeau);
3168  Ax[0] = A0;
3169  Ax[1] = A1;
3170  Ax[2] = A2;
3171  SetRotationMatrix(matrix, Ax, alpha);
3173  ApplyTransformationToSurface(matrix, chapeau);
3174  T[0] = X0;
3175  T[1] = X1;
3176  T[2] = X2;
3177  SetTranslationMatrix(matrix, T);
3179  ApplyTransformationToSurface(matrix, chapeau);
3180  T[0] = T0;
3181  T[1] = T1;
3182  T[2] = T2;
3183  SetTranslationMatrix(matrix, T);
3185  ApplyTransformationToSurface(matrix, chapeau);
3186  break;
3187  default: Msg::Error("Unknown extrusion type"); break;
3188  }
3189 
3190  // this is done only for backward compatibility with the old
3191  // numbering scheme
3192  Tree_Suppress(GModel::current()->getGEOInternals()->Surfaces, &chapeau);
3193 
3194  chapeau->Num = NEWSURFACE();
3195 
3196  GModel::current()->getGEOInternals()->setMaxTag(2, chapeau->Num);
3197  Tree_Add(GModel::current()->getGEOInternals()->Surfaces, &chapeau);
3198 
3199  Tree_Add(GModel::current()->getGEOInternals()->Volumes, &v);
3200 
3201  *pv = v;
3202 
3203  int chap_num = chapeau->Num;
3204 
3205  if(CTX::instance()->geom.autoCoherence) {
3206  std::vector<std::map<int, int> > report(3);
3207  report[2][chap_num] = chap_num;
3208  ReplaceAllDuplicates(report);
3209  auto m_it = (report[2]).find(chap_num);
3210  if(m_it != report[2].end())
3211  chap_num = report[2][chap_num];
3212  else
3213  chap_num = 0;
3214  }
3215 
3217 
3218  return chap_num;
3219 }
3220 
3221 void ExtrudeShapes(int type, List_T *list_in, double T0, double T1, double T2,
3222  double A0, double A1, double A2, double X0, double X1,
3223  double X2, double alpha, ExtrudeParams *e, List_T *list_out)
3224 {
3225  for(int i = 0; i < List_Nbr(list_in); i++) {
3226  Shape shape;
3227  List_Read(list_in, i, &shape);
3228  switch(shape.Type) {
3229  case MSH_POINT: {
3230  Curve *pc = nullptr, *prc = nullptr;
3231  Shape top;
3232  top.Num = ExtrudePoint(type, shape.Num, T0, T1, T2, A0, A1, A2, X0, X1,
3233  X2, alpha, &pc, &prc, 1, e);
3234  top.Type = MSH_POINT;
3235  List_Add(list_out, &top);
3236  if(pc) {
3237  Shape body;
3238  body.Num = pc->Num;
3239  body.Type = pc->Typ;
3240  List_Add(list_out, &body);
3241  }
3242  } break;
3243  case MSH_SEGM_LINE:
3244  case MSH_SEGM_SPLN:
3245  case MSH_SEGM_BSPLN:
3246  case MSH_SEGM_BEZIER:
3247  case MSH_SEGM_CIRC:
3248  case MSH_SEGM_CIRC_INV:
3249  case MSH_SEGM_ELLI:
3250  case MSH_SEGM_ELLI_INV:
3251  case MSH_SEGM_NURBS: {
3252  Surface *ps = nullptr;
3253  Shape top;
3254  top.Num = ExtrudeCurve(type, shape.Num, T0, T1, T2, A0, A1, A2, X0, X1,
3255  X2, alpha, &ps, 1, e);
3256  Curve *pc = FindCurve(top.Num);
3257  top.Type = pc ? pc->Typ : 0;
3258  List_Add(list_out, &top);
3259  if(ps) {
3260  Shape body;
3261  body.Num = ps->Num;
3262  body.Type = ps->Typ;
3263  List_Add(list_out, &body);
3264  if(CTX::instance()->geom.extrudeReturnLateral) {
3265  for(int j = 0; j < List_Nbr(ps->Generatrices); j++) {
3266  Curve *c;
3267  List_Read(ps->Generatrices, j, &c);
3268  if(abs(c->Num) != shape.Num && abs(c->Num) != top.Num) {
3269  Shape side;
3270  side.Num = c->Num;
3271  side.Type = c->Typ;
3272  List_Add(list_out, &side);
3273  }
3274  }
3275  }
3276  }
3277  } break;
3278  case MSH_SURF_REGL:
3279  case MSH_SURF_TRIC:
3280  case MSH_SURF_PLAN:
3281  case MSH_SURF_DISCRETE: {
3282  Volume *pv = nullptr;
3283  Shape top;
3284  top.Num = ExtrudeSurface(type, shape.Num, T0, T1, T2, A0, A1, A2, X0, X1,
3285  X2, alpha, &pv, e);
3286  Surface *ps = FindSurface(top.Num);
3287  top.Type = ps ? ps->Typ : 0;
3288 
3289  List_Add(list_out, &top);
3290  if(pv) {
3291  Shape body;
3292  body.Num = pv->Num;
3293  body.Type = pv->Typ;
3294  List_Add(list_out, &body);
3295  if(CTX::instance()->geom.extrudeReturnLateral) {
3296  for(int j = 0; j < List_Nbr(pv->Surfaces); j++) {
3297  Surface *s;
3298  List_Read(pv->Surfaces, j, &s);
3299  if(abs(s->Num) != shape.Num && abs(s->Num) != top.Num) {
3300  Shape side;
3301  side.Num = s->Num;
3302  side.Type = s->Typ;
3303  List_Add(list_out, &side);
3304  }
3305  }
3306  }
3307  }
3308  } break;
3309  default:
3310  Msg::Error("Impossible to extrude entity %d (of type %d)", shape.Num,
3311  shape.Type);
3312  break;
3313  }
3314  }
3315 }
3316 
3317 // Projection of a point on a surface
3318 
3322 };
3323 
3325  void *data)
3326 {
3327  PointSurface *ps = (PointSurface *)data;
3328  Vertex c = InterpolateSurface(ps->s, x(0), x(1), 0, 0);
3329  Vertex du = InterpolateSurface(ps->s, x(0), x(1), 1, 1);
3330  Vertex dv = InterpolateSurface(ps->s, x(0), x(1), 1, 2);
3331  res(0) = (c.Pos.X - ps->p->Pos.X) * du.Pos.X +
3332  (c.Pos.Y - ps->p->Pos.Y) * du.Pos.Y +
3333  (c.Pos.Z - ps->p->Pos.Z) * du.Pos.Z;
3334  res(1) = (c.Pos.X - ps->p->Pos.X) * dv.Pos.X +
3335  (c.Pos.Y - ps->p->Pos.Y) * dv.Pos.Y +
3336  (c.Pos.Z - ps->p->Pos.Z) * dv.Pos.Z;
3337  return true;
3338 }
3339 
3340 bool ProjectPointOnSurface(Surface *s, Vertex &p, double uv[2])
3341 {
3342  fullVector<double> x(2);
3343  x(0) = uv[0];
3344  x(1) = uv[1];
3345  PointSurface ps = {&p, s};
3346 
3347  Vertex pp = InterpolateSurface(s, uv[0], uv[1], 0, 0);
3348  double d2 = (pp.Pos.X - p.Pos.X) * (pp.Pos.X - p.Pos.X) +
3349  (pp.Pos.Y - p.Pos.Y) * (pp.Pos.Y - p.Pos.Y) +
3350  (pp.Pos.Z - p.Pos.Z) * (pp.Pos.Z - p.Pos.Z);
3351  if(d2 < 1.e-12) return true;
3352 
3353  double UMIN = 0.;
3354  double UMAX = 1.;
3355  double VMIN = 0.;
3356  double VMAX = 1.;
3357  int ITER = 0;
3358  while(1) {
3359  bool success = newton_fd(projectPS, x, &ps);
3360  if(success && x(0) >= UMIN && x(0) <= UMAX && x(1) >= VMIN &&
3361  x(1) <= VMAX) {
3362  p = InterpolateSurface(s, x(0), x(1), 0, 0);
3363  uv[0] = x(0);
3364  uv[1] = x(1);
3365  if(ITER >= 0)
3366  Msg::Info(
3367  "ProjectPoint (%g,%g,%g) On Surface %d converged after %d iterations",
3368  p.Pos.X, p.Pos.Y, p.Pos.Z, s->Num, ITER);
3369  return true;
3370  }
3371  x(0) = UMIN + (UMAX - UMIN) * ((rand() % 10000) / 10000.);
3372  x(1) = VMIN + (VMAX - VMIN) * ((rand() % 10000) / 10000.);
3373  if(ITER++ > 100) break;
3374  }
3375  {
3376  int NSAMPLES = 500;
3377  double uok = 0.5, vok = 0.5;
3378  double dmin = 1.e22;
3379  for(int i = 0; i < NSAMPLES; i++) {
3380  const double U = i / (double)(NSAMPLES - 1);
3381  for(int j = 0; j < NSAMPLES; j++) {
3382  const double V = j / (double)(NSAMPLES - 1);
3383  Vertex pp = InterpolateSurface(s, U, V, 0, 0);
3384  double d2 = (pp.Pos.X - p.Pos.X) * (pp.Pos.X - p.Pos.X) +
3385  (pp.Pos.Y - p.Pos.Y) * (pp.Pos.Y - p.Pos.Y) +
3386  (pp.Pos.Z - p.Pos.Z) * (pp.Pos.Z - p.Pos.Z);
3387  if(d2 < dmin) {
3388  dmin = d2;
3389  uok = U;
3390  vok = V;
3391  }
3392  }
3393  }
3394  p = InterpolateSurface(s, uok, vok, 0, 0);
3395  uv[0] = uok;
3396  uv[1] = vok;
3397  if(ITER > 0)
3398  Msg::Info("Brute force method used for projection of point (%g %g %g) on "
3399  "surface %d",
3400  p.Pos.X, p.Pos.Y, p.Pos.Z, s->Num);
3401  return true;
3402  }
3403  return false;
3404 }
3405 
3407 {
3408  int beg, end;
3409  List_Read(nodes, 0, &beg);
3410  List_Read(nodes, List_Nbr(nodes) - 1, &end);
3411  int id = NEWCURVE();
3412  Curve *cnew = nullptr;
3413  bool ok = true;
3414  switch(c->Typ) {
3415  case MSH_SEGM_LINE:
3416  cnew = CreateCurve(id, c->Typ, 1, nodes, nullptr, -1, -1, 0., 1., ok);
3417  break;
3418  case MSH_SEGM_SPLN:
3419  cnew = CreateCurve(id, c->Typ, 3, nodes, nullptr, -1, -1, 0., 1., ok);
3420  break;
3421  case MSH_SEGM_BSPLN:
3422  cnew = CreateCurve(id, c->Typ, 2, nodes, nullptr, -1, -1, 0., 1., ok);
3423  break;
3424  default: // should never reach this point...
3425  Msg::Error("Cannot split a curve with type %i", c->Typ);
3426  return nullptr;
3427  }
3428  Tree_Add(GModel::current()->getGEOInternals()->Curves, &cnew);
3429  CreateReversedCurve(cnew);
3430  return cnew;
3431 }
3432 
3433 bool SplitCurve(int line_id, List_T *vertices_id, List_T *curves)
3434 {
3435  Curve *c = FindCurve(line_id);
3436  if(!c) {
3437  Msg::Error("Unknown curve %i to split", line_id);
3438  return false;
3439  }
3440  switch(c->Typ) {
3441  case MSH_SEGM_LINE:
3442  case MSH_SEGM_SPLN:
3443  case MSH_SEGM_BSPLN: break;
3444  default:
3445  Msg::Error("Cannot split curve %i with type %i", line_id, c->Typ);
3446  return false;
3447  }
3448  std::set<int> v_break;
3449  for(int i = 0; i < List_Nbr(vertices_id); i++) {
3450  int id;
3451  List_Read(vertices_id, i, &id);
3452  v_break.insert(id);
3453  }
3454  bool is_periodic = (c->beg == c->end);
3455  bool first_periodic = true;
3456  bool last_periodic = false;
3457  List_T *new_list =
3458  List_Create(1, List_Nbr(c->Control_Points) / 10, sizeof(int));
3459  List_T *num_shapes = List_Create(2, 1, sizeof(int));
3460  Vertex *pv;
3461  for(int i = 0; i < List_Nbr(c->Control_Points); i++) {
3462  List_Read(c->Control_Points, i, &pv);
3463  List_Add(new_list, &pv->Num);
3464  if(v_break.find(pv->Num) != v_break.end() && List_Nbr(new_list) > 1) {
3465  if(last_periodic) break;
3466  if(!(is_periodic && first_periodic)) {
3467  Curve *cnew = _create_splitted_curve(c, new_list);
3468  List_Add(curves, &cnew);
3469  List_Add(num_shapes, &cnew->Num);
3470  }
3471  first_periodic = false;
3472  List_Reset(new_list);
3473  List_Add(new_list, &pv->Num);
3474  }
3475  if(i == (List_Nbr(c->Control_Points) - 1) && is_periodic &&
3476  !first_periodic) {
3477  i = 0;
3478  last_periodic = true;
3479  }
3480  }
3481  if(List_Nbr(new_list) > 1) {
3482  Curve *cnew = _create_splitted_curve(c, new_list);
3483  List_Add(curves, &cnew);
3484  List_Add(num_shapes, &cnew->Num);
3485  }
3486  // replace original curve by the new curves in all surfaces (and for
3487  // the opposite curve)
3488  List_T *rcurves = List_Create(2, 1, sizeof(Curve *));
3489  int N = List_Nbr(curves);
3490  for(int i = 0; i < List_Nbr(curves); i++) {
3491  Curve *cc, *rcc;
3492  List_Read(curves, N - i - 1, &cc);
3493  rcc = FindCurve(-cc->Num);
3494  List_Add(rcurves, &rcc);
3495  }
3496  List_T *Surfs = Tree2List(GModel::current()->getGEOInternals()->Surfaces);
3497  for(int i = 0; i < List_Nbr(Surfs); i++) {
3498  Surface *s;
3499  List_Read(Surfs, i, &s);
3500  for(int j = 0; j < List_Nbr(s->Generatrices); j++) {
3501  Curve *surface_curve;
3502  List_Read(s->Generatrices, j, &surface_curve);
3503  if(surface_curve->Num == c->Num) {
3504  List_Remove(s->Generatrices, j);
3505  List_Insert_In_List(curves, j, s->Generatrices);
3506  j += List_Nbr(curves) - 1;
3507  }
3508  else if(surface_curve->Num == -c->Num) {
3509  List_Remove(s->Generatrices, j);
3510  List_Insert_In_List(rcurves, j, s->Generatrices);
3511  j += List_Nbr(curves) - 1;
3512  }
3513  }
3514  }
3515  List_Delete(Surfs);
3516 
3517  // replace original curve by the new curves in physical groups
3518  for(int i = 0;
3519  i < List_Nbr(GModel::current()->getGEOInternals()->PhysicalGroups); i++) {
3522  if(p->Typ == MSH_PHYSICAL_LINE) {
3523  for(int j = 0; j < List_Nbr(p->Entities); j++) {
3524  int num;
3525  List_Read(p->Entities, j, &num);
3526  if(num == c->Num) {
3527  List_Remove(p->Entities, j);
3528  List_Insert_In_List(num_shapes, j, p->Entities);
3529  j += List_Nbr(num_shapes) - 1;
3530  }
3531  }
3532  }
3533  }
3534 
3535  DeleteCurve(c->Num);
3536  DeleteCurve(-c->Num);
3537  List_Delete(new_list);
3538  List_Delete(rcurves);
3539  List_Delete(num_shapes);
3540  return true;
3541 }
3542 
3546 };
3547 
3549  void *data)
3550 {
3551  CurveSurface *cs = (CurveSurface *)data;
3552  Vertex vs = InterpolateSurface(cs->s, uvt(0), uvt(1), 0, 0);
3553  Vertex vc = InterpolateCurve(cs->c, uvt(2), 0);
3554  res(0) = vs.Pos.X - vc.Pos.X;
3555  res(1) = vs.Pos.Y - vc.Pos.Y;
3556  res(2) = vs.Pos.Z - vc.Pos.Z;
3557  return true;
3558 }
3559 
3560 bool IntersectCurvesWithSurface(List_T *curve_ids, int surface_id,
3561  List_T *shapes)
3562 {
3563  Surface *s = FindSurface(surface_id);
3564  if(!s) {
3565  Msg::Error("Unknown surface %d", surface_id);
3566  return false;
3567  }
3568  for(int i = 0; i < List_Nbr(curve_ids); i++) {
3569  double curve_id;
3570  List_Read(curve_ids, i, &curve_id);
3571  Curve *c = FindCurve((int)curve_id);
3572  if(c) {
3573  CurveSurface cs = {c, s};
3574  fullVector<double> uvt(3);
3575  uvt(0) = 0.5;
3576  uvt(1) = 0.5;
3577  uvt(2) = 0.5;
3578  if(newton_fd(intersectCS, uvt, &cs)) {
3579  Vertex p = InterpolateCurve(c, uvt(2), 0);
3580  Vertex *v =
3581  CreateVertex(NEWPOINT(), p.Pos.X, p.Pos.Y, p.Pos.Z, p.lc, p.u);
3582  Tree_Insert(GModel::current()->getGEOInternals()->Points, &v);
3583  Shape sh;
3584  sh.Type = MSH_POINT;
3585  sh.Num = v->Num;
3586  List_Add(shapes, &sh);
3587  }
3588  }
3589  else {
3590  Msg::Error("Unknown curve %d", (int)curve_id);
3591  return false;
3592  }
3593  }
3594  return true;
3595 }
3596 
3597 bool SortEdgesInLoop(int num, List_T *edges, bool reorient)
3598 {
3599  // This function sorts the edges in an edge loop; if reorient is set, it
3600  // reorients the edges (and creates reversed edges if necessary). The routine
3601  // also detects subloops if reorient is not set; this is useful for writing
3602  // general scriptable surface generation in complex cases.
3603  Curve *c, *c0, *c1, *c2;
3604  int nbEdges = List_Nbr(edges);
3605  List_T *temp = List_Create(nbEdges, 1, sizeof(Curve *));
3606 
3607  for(int i = 0; i < nbEdges; i++) {
3608  int j;
3609  List_Read(edges, i, &j);
3610  if((c = FindCurve(j))) {
3611  List_Add(temp, &c);
3612  if(c->Typ == MSH_SEGM_DISCRETE) {
3613  Msg::Debug("Aborting curve loop sort for discrete curve: "
3614  "let's hope you know what you're doing ;-)");
3615  List_Delete(temp);
3616  return true;
3617  }
3618  }
3619  else {
3620  Msg::Debug("Unknown curve %d, aborting curve loop sort: "
3621  "let's hope you know what you're doing ;-)",
3622  j);
3623  List_Delete(temp);
3624  return true;
3625  }
3626  }
3627  List_Reset(edges);
3628 
3629  if(!List_Nbr(temp)) return true;
3630 
3631  bool ok = true;
3632  int j = 0, k = 0;
3633  c0 = c1 = *(Curve **)List_Pointer(temp, 0);
3634  List_Add(edges, &c1->Num);
3635  List_PSuppress(temp, 0);
3636  while(List_Nbr(edges) < nbEdges) {
3637  for(int i = 0; i < List_Nbr(temp); i++) {
3638  c2 = *(Curve **)List_Pointer(temp, i);
3639  if(reorient && c1->end == c2->end) {
3640  Curve *c2R = FindCurve(-c2->Num);
3641  if(!c2R) {
3642  Msg::Debug("Creating reversed curve -%d", -c2->Num);
3643  c2R = CreateReversedCurve(c2);
3644  }
3645  c2 = c2R;
3646  }
3647  if(c1->end == c2->beg) {
3648  List_Add(edges, &c2->Num);
3649  List_PSuppress(temp, i);
3650  c1 = c2;
3651  if(c2->end == c0->beg) {
3652  if(List_Nbr(temp)) {
3653  Msg::Info(
3654  "Starting subloop %d in curve loop %d (are you sure about this?)",
3655  ++k, num);
3656  c0 = c1 = *(Curve **)List_Pointer(temp, 0);
3657  List_Add(edges, &c1->Num);
3658  List_PSuppress(temp, 0);
3659  }
3660  }
3661  break;
3662  }
3663  }
3664  if(j++ > nbEdges) {
3665  Msg::Error("Curve loop %d is wrong", num);
3666  ok = false;
3667  break;
3668  }
3669  }
3670  List_Delete(temp);
3671  return ok;
3672 }
3673 
3675 {
3676  int nbLoop = List_Nbr(loops);
3678  s->Generatrices = List_Create(4, 4, sizeof(Curve *));
3680  s->GeneratricesByTag = List_Create(4, 4, sizeof(int));
3681 
3682  for(int i = 0; i < nbLoop; i++) {
3683  int iLoop;
3684  List_Read(loops, i, &iLoop);
3685  EdgeLoop *el;
3686  std::vector<int> fromModel;
3687  if(!(el = FindEdgeLoop(abs(iLoop)))) {
3688  Msg::Error("Unknown curve loop %d in GEO surface %d", iLoop, s->Num);
3690  s->Generatrices = nullptr;
3691  return false;
3692  }
3693  else {
3694  int ic;
3695  Curve *c;
3696  if((i == 0 && iLoop > 0) || // exterior boundary
3697  (i != 0 && iLoop < 0)) { // hole
3698  for(int j = 0; j < List_Nbr(el->Curves); j++) {
3699  List_Read(el->Curves, j, &ic);
3700  ic *= gmsh_sign(iLoop);
3701  if(i != 0) ic *= -1; // hole
3702  if(!(c = FindCurve(ic)))
3703  fromModel.push_back(ic);
3704  else
3705  List_Add(s->Generatrices, &c);
3706  }
3707  }
3708  else {
3709  for(int j = List_Nbr(el->Curves) - 1; j >= 0; j--) {
3710  List_Read(el->Curves, j, &ic);
3711  ic *= gmsh_sign(iLoop);
3712  if(i != 0) ic *= -1; // hole
3713  if(!(c = FindCurve(ic)))
3714  fromModel.push_back(ic);
3715  else
3716  List_Add(s->Generatrices, &c);
3717  }
3718  }
3719  for(std::size_t j = 0; j < fromModel.size(); j++) {
3720  ic = fromModel[j];
3721  GEdge *ge = GModel::current()->getEdgeByTag(abs(ic));
3722  if(ge) { List_Add(s->GeneratricesByTag, &ic); }
3723  else {
3724  Msg::Error("Unknown curve %d", ic);
3725  return false;
3726  }
3727  }
3728  }
3729  }
3730 
3731  return true;
3732 }
3733 
3735 {
3736  List_Reset(v->Surfaces);
3739  for(int i = 0; i < List_Nbr(loops); i++) {
3740  int il;
3741  List_Read(loops, i, &il);
3742  SurfaceLoop *sl;
3743  if(!(sl = FindSurfaceLoop(abs(il)))) {
3744  Msg::Error("Unknown surface loop %d", il);
3745  return false;
3746  }
3747  else {
3748  for(int j = 0; j < List_Nbr(sl->Surfaces); j++) {
3749  int is;
3750  List_Read(sl->Surfaces, j, &is);
3751  Surface *s = FindSurface(abs(is));
3752  if(s) {
3753  // contrary to curves in edge loops, we don't actually create
3754  // "negative" surfaces. So we just store the signs in another list
3755  List_Add(v->Surfaces, &s);
3756  int tmp = gmsh_sign(is) * gmsh_sign(il);
3757  if(i > 0) tmp *= -1; // this is a hole
3758  List_Add(v->SurfacesOrientations, &tmp);
3759  }
3760  else {
3761  GFace *gf = GModel::current()->getFaceByTag(abs(is));
3762  if(gf) { List_Add(v->SurfacesByTag, &is); }
3763  else {
3764  Msg::Error("Unknown surface %d in GEO volume %d", is, v->Num);
3765  return false;
3766  }
3767  }
3768  }
3769  }
3770  }
3771  return true;
3772 }
3773 
3774 // the following routines should be renamed and moved elsewhere
3775 
3777 {
3778  int tag = GModel::current()->getGEOInternals()->getMaxTag(0) + 1;
3779  if(GModel::current()->getOCCInternals())
3780  tag = std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(0) + 1);
3781  return tag;
3782 }
3783 
3785 {
3786  int tag = 0;
3787  if(CTX::instance()->geom.oldNewreg)
3788  tag = NEWREG();
3789  else
3790  tag = GModel::current()->getGEOInternals()->getMaxTag(1) + 1;
3791  if(GModel::current()->getOCCInternals())
3792  tag = std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(1) + 1);
3793  return tag;
3794 }
3795 
3797 {
3798  int tag = 0;
3799  if(CTX::instance()->geom.oldNewreg)
3800  tag = NEWREG();
3801  else
3802  tag = GModel::current()->getGEOInternals()->getMaxTag(-1) + 1;
3803  if(GModel::current()->getOCCInternals())
3804  tag =
3805  std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(-1) + 1);
3806  return tag;
3807 }
3808 
3810 {
3811  int tag = 0;
3812  if(CTX::instance()->geom.oldNewreg)
3813  tag = NEWREG();
3814  else
3815  tag = GModel::current()->getGEOInternals()->getMaxTag(2) + 1;
3816  if(GModel::current()->getOCCInternals())
3817  tag = std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(2) + 1);
3818  return tag;
3819 }
3820 
3822 {
3823  int tag = 0;
3824  if(CTX::instance()->geom.oldNewreg)
3825  tag = NEWREG();
3826  else
3827  tag = GModel::current()->getGEOInternals()->getMaxTag(-2) + 1;
3828  if(GModel::current()->getOCCInternals())
3829  tag =
3830  std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(-2) + 1);
3831  return tag;
3832 }
3833 
3835 {
3836  int tag = 0;
3837  if(CTX::instance()->geom.oldNewreg)
3838  tag = NEWREG();
3839  else
3840  tag = GModel::current()->getGEOInternals()->getMaxTag(3) + 1;
3841  if(GModel::current()->getOCCInternals())
3842  tag = std::max(tag, GModel::current()->getOCCInternals()->getMaxTag(3) + 1);
3843  return tag;
3844 }
3845 
3846 int NEWREG()
3847 {
3848  int tag = 0;
3849  for(int dim = -2; dim <= 3; dim++) {
3850  if(dim)
3851  tag =
3852  std::max(tag, GModel::current()->getGEOInternals()->getMaxTag(dim) + 1);
3853  }
3854  tag = std::max(tag,
3855  GModel::current()->getGEOInternals()->getMaxPhysicalTag() + 1);
3856  if(GModel::current()->getOCCInternals()) {
3857  for(int dim = -2; dim <= 3; dim++) {
3858  if(dim)
3859  tag = std::max(
3860  tag, GModel::current()->getOCCInternals()->getMaxTag(dim) + 1);
3861  }
3862  }
3863  return tag;
3864 }
3865 
3867 {
3868 #if defined(HAVE_MESH)
3869  return (GModel::current()->getFields()->maxId() + 1);
3870 #else
3871  return 0;
3872 #endif
3873 }
3874 
3876 {
3877  if(CTX::instance()->geom.oldNewreg)
3878  return NEWREG();
3879  else
3881 }
contextGeometryOptions::extrudeSplinePoints
int extrudeSplinePoints
Definition: Context.h:95
Volume
Definition: Geo.h:140
MSH_SEGM_DISCRETE
#define MSH_SEGM_DISCRETE
Definition: GeoDefines.h:31
D
#define D
Definition: DefaultOptions.h:24
Surface::TrsfPoints
List_T * TrsfPoints
Definition: Geo.h:122
List_Pointer
void * List_Pointer(List_T *liste, int index)
Definition: ListUtils.cpp:152
Surface::Num
int Num
Definition: Geo.h:113
CurveSurface::c
Curve * c
Definition: Geo.cpp:3544
Geo.h
GeoInterpolation.h
NEWREG
int NEWREG()
Definition: Geo.cpp:3846
GEO_Internals::PhysicalGroups
List_T * PhysicalGroups
Definition: GModelIO_GEO.h:20
MSH_SEGM_BEZIER
#define MSH_SEGM_BEZIER
Definition: GeoDefines.h:29
Compare2Lists
static int Compare2Lists(List_T *List1, List_T *List2, int(*fcmp)(const void *a, const void *b))
Definition: Geo.cpp:649
contextGeometryOptions::tolerance
double tolerance
Definition: Context.h:99
GFace::edges
virtual std::vector< GEdge * > const & edges() const
Definition: GFace.h:121
Vertex::pntOnGeometry
SPoint2 pntOnGeometry
Definition: Geo.h:40
Volume::QuadTri
int QuadTri
Definition: Geo.h:146
Field.h
CreateVolume
Volume * CreateVolume(int Num, int Typ)
Definition: Geo.cpp:617
GEO_Internals::DelCurves
Tree_T * DelCurves
Definition: GModelIO_GEO.h:19
gmsh_sign
int gmsh_sign(T const &value)
Definition: Numeric.h:28
GEO_Internals::getMaxTag
int getMaxTag(int dim) const
Definition: GModelIO_GEO.cpp:99
PhysicalGroup::Num
int Num
Definition: Geo.h:156
CompareTwoPoints
static int CompareTwoPoints(const void *a, const void *b)
Definition: Geo.cpp:1629
SymmetryShapes
bool SymmetryShapes(double A, double B, double C, double D, List_T *shapes)
Definition: Geo.cpp:1608
pc2
const double pc2
Definition: GaussQuadratureQuad.cpp:60
SetDilatationMatrix
void SetDilatationMatrix(double matrix[4][4], double T[3], double A, double B, double C)
Definition: Geo.cpp:1282
GVertex::z
virtual double z() const =0
CurveSurface::s
Surface * s
Definition: Geo.cpp:3545
List_Copy
void List_Copy(List_T *a, List_T *b)
Definition: ListUtils.cpp:283
GFace::edgeOrientations
virtual std::vector< int > const & edgeOrientations() const
Definition: GFace.h:139
CreateReversedCurve
Curve * CreateReversedCurve(Curve *c)
Definition: Geo.cpp:1147
DeleteVolume
void DeleteVolume(int iv, bool recursive)
Definition: Geo.cpp:1064
MSH_PHYSICAL_SURFACE
#define MSH_PHYSICAL_SURFACE
Definition: GeoDefines.h:45
NO_QUADTRI
#define NO_QUADTRI
Definition: GmshDefines.h:263
Curve::nbPointsTransfinite
int nbPointsTransfinite
Definition: Geo.h:80
Curve
Definition: Geo.h:74
fullVector< double >
FindSurfaceLoop
SurfaceLoop * FindSurfaceLoop(int inum)
Definition: Geo.cpp:744
List_Write
void List_Write(List_T *liste, int index, void *data)
Definition: ListUtils.cpp:120
Surface::Typ
int Typ
Definition: Geo.h:114
GFace
Definition: GFace.h:33
MaxNumPoint
static void MaxNumPoint(void *a, void *b)
Definition: Geo.cpp:1731
newton_fd
bool newton_fd(bool(*func)(fullVector< double > &, fullVector< double > &, void *), fullVector< double > &x, void *data, double relax, double tolx)
Definition: Numeric.cpp:685
Msg::Info
static void Info(const char *fmt,...)
Definition: GmshMessage.cpp:587
GEntity::degenerate
virtual bool degenerate(int dim) const
Definition: GEntity.h:248
F
#define F
Definition: DefaultOptions.h:23
GEO_Internals::setMaxTag
void setMaxTag(int dim, int val)
Definition: GModelIO_GEO.cpp:87
MSH_SURF_BND_LAYER
#define MSH_SURF_BND_LAYER
Definition: GeoDefines.h:36
SPoint2
Definition: SPoint2.h:12
MSH_SURF_PLAN
#define MSH_SURF_PLAN
Definition: GeoDefines.h:33
ProtudeXYZ
void ProtudeXYZ(double &x, double &y, double &z, ExtrudeParams *e)
Definition: Geo.cpp:2542
List_T::size
int size
Definition: ListUtils.h:12
MSH_PHYSICAL_LINE
#define MSH_PHYSICAL_LINE
Definition: GeoDefines.h:44
Msg::Debug
static void Debug(const char *fmt,...)
Definition: GmshMessage.cpp:752
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
EdgeLoop::Num
int Num
Definition: Geo.h:107
CompareEdgeLoop
int CompareEdgeLoop(const void *a, const void *b)
Definition: Geo.cpp:67
ExtrudeParams::BoundaryLayerIndex
int BoundaryLayerIndex
Definition: ExtrudeParams.h:46
ExtrudePoint
int ExtrudePoint(int type, int ip, double T0, double T1, double T2, double A0, double A1, double A2, double X0, double X1, double X2, double alpha, Curve **pc, Curve **prc, int final, ExtrudeParams *e)
Definition: Geo.cpp:2570
MVertex
Definition: MVertex.h:24
FreePhysicalGroup
void FreePhysicalGroup(void *a, void *b)
Definition: Geo.cpp:158
Vertex::u
double u
Definition: Geo.h:33
DuplicateCurve
Curve * DuplicateCurve(Curve *c)
Definition: Geo.cpp:830
Curve::end
Vertex * end
Definition: Geo.h:85
Tree_Search
int Tree_Search(Tree_T *tree, void *data)
Definition: TreeUtils.cpp:61
SplitCurve
bool SplitCurve(int line_id, List_T *vertices_id, List_T *curves)
Definition: Geo.cpp:3433
List_T
Definition: ListUtils.h:9
Msg::Warning
static void Warning(const char *fmt,...)
Definition: GmshMessage.cpp:543
List_Suppress
int List_Suppress(List_T *liste, void *data, int(*fcmp)(const void *a, const void *b))
Definition: ListUtils.cpp:236
Msg::Error
static void Error(const char *fmt,...)
Definition: GmshMessage.cpp:482
Tree_T
Definition: TreeUtils.h:12
NEWPOINT
int NEWPOINT()
Definition: Geo.cpp:3776
List_Reset
void List_Reset(List_T *liste)
Definition: ListUtils.cpp:269
SPoint3
Definition: SPoint3.h:14
gmshSurface::point
virtual SPoint3 point(double par1, double par2) const =0
FreeVolume
void FreeVolume(void *a, void *b)
Definition: Geo.cpp:635
COPIED_ENTITY
#define COPIED_ENTITY
Definition: ExtrudeParams.h:18
List_Nbr
int List_Nbr(List_T *liste)
Definition: ListUtils.cpp:106
GModel::getFaceByTag
GFace * getFaceByTag(int n) const
Definition: GModel.cpp:326
Vertex
Definition: Geo.h:29
PhysicalGroup::Entities
List_T * Entities
Definition: Geo.h:158
ExtrudeParams::pt
double pt[3]
Definition: ExtrudeParams.h:53
MSH_POINT
#define MSH_POINT
Definition: GeoDefines.h:16
CompareVertex
int CompareVertex(const void *a, const void *b)
Definition: Geo.cpp:30
Tree2List
List_T * Tree2List(Tree_T *pTree)
Definition: TreeUtils.cpp:110
FreeVertex
void FreeVertex(void *a, void *b)
Definition: Geo.cpp:133
List_Create
List_T * List_Create(int n, int incr, int size)
Definition: ListUtils.cpp:46
GModelIO_OCC.h
SortEdgesInLoop
bool SortEdgesInLoop(int num, List_T *edges, bool reorient)
Definition: Geo.cpp:3597
GEO_Internals::setMaxPhysicalTag
void setMaxPhysicalTag(int val)
Definition: GModelIO_GEO.h:133
GModelIO_GEO.h
CopySurface
static void CopySurface(Surface *s, Surface *ss)
Definition: Geo.cpp:869
Surface::MeshSizeFromBoundary
int MeshSizeFromBoundary
Definition: Geo.h:130
RemoveDegenerateVolumes
static void RemoveDegenerateVolumes()
Definition: Geo.cpp:2255
GEO_Internals::DelSurfaces
Tree_T * DelSurfaces
Definition: GModelIO_GEO.h:19
CreateVertex
Vertex * CreateVertex(int Num, double X, double Y, double Z, double lc, double u)
Definition: Geo.cpp:106
List_Search
int List_Search(List_T *liste, void *data, int(*fcmp)(const void *a, const void *b))
Definition: ListUtils.cpp:199
NEWSURFACE
int NEWSURFACE()
Definition: Geo.cpp:3809
PointSurface::s
Surface * s
Definition: Geo.cpp:3321
SetTranslationMatrix
void SetTranslationMatrix(double matrix[4][4], double T[3])
Definition: Geo.cpp:1250
List_Invert
void List_Invert(List_T *a, List_T *b)
Definition: ListUtils.cpp:259
GModel::getEdgeByTag
GEdge * getEdgeByTag(int n) const
Definition: GModel.cpp:336
CompareAbsCurve
static int CompareAbsCurve(const void *a, const void *b)
Definition: Geo.cpp:797
CreatePhysicalGroup
PhysicalGroup * CreatePhysicalGroup(int Num, int typ, List_T *intlist)
Definition: Geo.cpp:142
GmshMessage.h
edges
static int edges[6][2]
Definition: meshGRegionLocalMeshMod.cpp:23
ApplyTransformationToSurface
static void ApplyTransformationToSurface(double matrix[4][4], Surface *s)
Definition: Geo.cpp:1434
GramSchmidt
static void GramSchmidt(double v1[3], double v2[3], double v3[3])
Definition: Geo.cpp:1303
ExtrudeParams::geo
struct ExtrudeParams::@15 geo
FindVolume
Volume * FindVolume(int inum)
Definition: Geo.cpp:722
gmshSurface::vertex_defined_on_surface
bool vertex_defined_on_surface
Definition: gmshSurface.h:28
CopyVertex
static void CopyVertex(Vertex *v, Vertex *vv)
Definition: Geo.cpp:769
ApplyTransformationToPoint
static void ApplyTransformationToPoint(double matrix[4][4], Vertex *v)
Definition: Geo.cpp:1403
MSH_SEGM_SPLN
#define MSH_SEGM_SPLN
Definition: GeoDefines.h:21
List_Remove
void List_Remove(List_T *a, int i)
Definition: ListUtils.cpp:293
ReplaceAllDuplicates
static void ReplaceAllDuplicates(std::vector< std::map< int, int > > &report)
Definition: Geo.cpp:2507
TRANSLATE_ROTATE
#define TRANSLATE_ROTATE
Definition: ExtrudeParams.h:23
Vertex::boundaryLayerIndex
int boundaryLayerIndex
Definition: Geo.h:41
NEWCURVELOOP
int NEWCURVELOOP()
Definition: Geo.cpp:3796
CopyCurve
static void CopyCurve(Curve *c, Curve *cc)
Definition: Geo.cpp:804
InterpolateCurve
Vertex InterpolateCurve(Curve *c, double u, int const derivee)
Definition: GeoInterpolation.cpp:441
CreateSurface
Surface * CreateSurface(int Num, int Typ)
Definition: Geo.cpp:579
Curve::endByTag
int endByTag
Definition: Geo.h:86
Volume::Surfaces
List_T * Surfaces
Definition: Geo.h:149
norm3
double norm3(double a[3])
Definition: Numeric.h:119
Vertex::Num
int Num
Definition: Geo.h:31
Volume::Extrude
ExtrudeParams * Extrude
Definition: Geo.h:147
intersectCS
static bool intersectCS(fullVector< double > &uvt, fullVector< double > &res, void *data)
Definition: Geo.cpp:3548
Shape::Type
int Type
Definition: GeoDefines.h:11
ApplyTransformationToCurve
static void ApplyTransformationToCurve(double matrix[4][4], Curve *c)
Definition: Geo.cpp:1416
List_Add
void List_Add(List_T *liste, void *data)
Definition: ListUtils.cpp:90
NEWFIELD
int NEWFIELD()
Definition: Geo.cpp:3866
ProjectPointOnSurface
bool ProjectPointOnSurface(Surface *s, Vertex &p, double uv[2])
Definition: Geo.cpp:3340
CTX::instance
static CTX * instance()
Definition: Context.cpp:122
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
Curve::Control_Points
List_T * Control_Points
Definition: Geo.h:88
PointSurface
Definition: Geo.cpp:3319
CopyVolume
static void CopyVolume(Volume *v, Volume *vv)
Definition: Geo.cpp:926
Curve::begByTag
int begByTag
Definition: Geo.h:86
CurveSurface
Definition: Geo.cpp:3543
Curve::uend
double uend
Definition: Geo.h:87
Volume::Typ
int Typ
Definition: Geo.h:143
ExtrudeParams::mesh
struct ExtrudeParams::@14 mesh
myatan2
double myatan2(double a, double b)
Definition: Numeric.cpp:12
MaxNumCurve
static void MaxNumCurve(void *a, void *b)
Definition: Geo.cpp:1738
DeleteSurface
void DeleteSurface(int is, bool recursive)
Definition: Geo.cpp:1018
Volume::Method
int Method
Definition: Geo.h:144
gmshSurface
Definition: gmshSurface.h:22
Curve::ubeg
double ubeg
Definition: Geo.h:87
DeletePhysicalSurface
void DeletePhysicalSurface(int num)
Definition: Geo.cpp:1125
Surface::Extrude
ExtrudeParams * Extrude
Definition: Geo.h:124
ShapeLessThan::operator()
bool operator()(Shape *v1, Shape *v2) const
Definition: Geo.cpp:1622
FindCurve
static Curve * FindCurve(int inum, Tree_T *t)
Definition: Geo.cpp:694
Curve::Method
int Method
Definition: Geo.h:79
CompareSurfaceLoop
int CompareSurfaceLoop(const void *a, const void *b)
Definition: Geo.cpp:60
FindPhysicalGroup
PhysicalGroup * FindPhysicalGroup(int num, int type)
Definition: Geo.cpp:755
EXTRUDED_ENTITY
#define EXTRUDED_ENTITY
Definition: ExtrudeParams.h:17
GVertex
Definition: GVertex.h:23
GVertex::prescribedMeshSizeAtVertex
virtual double prescribedMeshSizeAtVertex() const
Definition: GVertex.h:75
Tree_Action
void Tree_Action(Tree_T *tree, void(*action)(void *data, void *dummy))
Definition: TreeUtils.cpp:100
MVertexRTree::insert
MVertex * insert(MVertex *v, bool warnIfExists=false, std::set< MVertex *, MVertexPtrLessThan > *duplicates=nullptr)
Definition: MVertexRTree.h:38
CompareSurface
int CompareSurface(const void *a, const void *b)
Definition: Geo.cpp:81
CTX::lc
double lc
Definition: Context.h:234
MESH_UNSTRUCTURED
#define MESH_UNSTRUCTURED
Definition: GmshDefines.h:260
NEWPHYSICAL
int NEWPHYSICAL()
Definition: Geo.cpp:3875
MSH_SEGM_CIRC_INV
#define MSH_SEGM_CIRC_INV
Definition: GeoDefines.h:23
MSH_SEGM_BND_LAYER
#define MSH_SEGM_BND_LAYER
Definition: GeoDefines.h:30
Curve::typeTransfinite
int typeTransfinite
Definition: Geo.h:81
TranslateShapes
bool TranslateShapes(double X, double Y, double Z, List_T *shapes)
Definition: Geo.cpp:1549
Tree_Add
void * Tree_Add(Tree_T *tree, void *data)
Definition: TreeUtils.cpp:37
Curve::k
float * k
Definition: Geo.h:90
ExtrudeParams::fill
void fill(int type, double T0, double T1, double T2, double A0, double A1, double A2, double X0, double X1, double X2, double angle)
Definition: ExtrudeParams.cpp:34
Numeric.h
Tree_PQuery
void * Tree_PQuery(Tree_T *tree, void *data)
Definition: TreeUtils.cpp:77
GEO_Internals::DelPoints
Tree_T * DelPoints
Definition: GModelIO_GEO.h:19
DeleteCurve
void DeleteCurve(int ip, bool recursive)
Definition: Geo.cpp:981
FindEdgeLoop
EdgeLoop * FindEdgeLoop(int inum)
Definition: Geo.cpp:733
MSH_PHYSICAL_VOLUME
#define MSH_PHYSICAL_VOLUME
Definition: GeoDefines.h:46
Curve::beg
Vertex * beg
Definition: Geo.h:85
MSH_SEGM_NURBS
#define MSH_SEGM_NURBS
Definition: GeoDefines.h:28
Vertex::Typ
int Typ
Definition: Geo.h:32
Projette
void Projette(Vertex *v, double mat[3][3])
Definition: Geo.h:177
GEdge::getBeginVertex
virtual GVertex * getBeginVertex() const
Definition: GEdge.h:63
InterpolateSurface
Vertex InterpolateSurface(Surface *s, double u, double v, int derivee, int u_v)
Definition: GeoInterpolation.cpp:958
ShapeLessThan
Definition: Geo.cpp:1620
Surface
Definition: Geo.h:111
MSH_SURF_DISCRETE
#define MSH_SURF_DISCRETE
Definition: GeoDefines.h:38
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
GEO_Internals::getMaxPhysicalTag
int getMaxPhysicalTag() const
Definition: GModelIO_GEO.h:132
List_Insert_In_List
void List_Insert_In_List(List_T *a, int i, List_T *b)
Definition: ListUtils.cpp:302
List_Delete
void List_Delete(List_T *liste)
Definition: ListUtils.cpp:66
prosca
double prosca(double const a[3], double const b[3])
Definition: Numeric.h:112
FreeCurve
void FreeCurve(void *a, void *b)
Definition: Geo.cpp:567
Shape
Definition: GeoDefines.h:9
RemoveDegenerateSurfaces
static void RemoveDegenerateSurfaces()
Definition: Geo.cpp:2297
ExtrudeParams::Mode
int Mode
Definition: ExtrudeParams.h:49
Parser.h
Vertex::lc
double lc
Definition: Geo.h:33
MSH_SURF_REGL
#define MSH_SURF_REGL
Definition: GeoDefines.h:34
Volume::SurfacesOrientations
List_T * SurfacesOrientations
Definition: Geo.h:150
PhysicalGroup
Definition: Geo.h:154
ROTATE
#define ROTATE
Definition: ExtrudeParams.h:22
contextGeometryOptions::oldNewreg
int oldNewreg
Definition: Context.h:94
Curve::mat
double mat[4][4]
Definition: Geo.h:84
GEntity::tag
int tag() const
Definition: GEntity.h:280
EndCurve
bool EndCurve(Curve *c)
Definition: Geo.cpp:225
EdgeLoop
Definition: Geo.h:105
Curve::l
double l
Definition: Geo.h:83
SurfaceLoop::Num
int Num
Definition: Geo.h:136
MVertexRTree.h
MSH_SEGM_ELLI_INV
#define MSH_SEGM_ELLI_INV
Definition: GeoDefines.h:25
prodve
void prodve(double a[3], double b[3], double c[3])
Definition: Numeric.h:105
RotateShapes
bool RotateShapes(double Ax, double Ay, double Az, double Px, double Py, double Pz, double alpha, List_T *shapes)
Definition: Geo.cpp:1580
CTX::geom
contextGeometryOptions geom
Definition: Context.h:311
DeletePhysicalPoint
void DeletePhysicalPoint(int num)
Definition: Geo.cpp:1103
Tree_Delete
void Tree_Delete(Tree_T *tree)
Definition: TreeUtils.cpp:23
PhysicalGroup::Typ
int Typ
Definition: Geo.h:157
ReplaceDuplicateSurfaces
static void ReplaceDuplicateSurfaces(std::map< int, int > *s_report=nullptr)
Definition: Geo.cpp:2370
S
#define S
Definition: DefaultOptions.h:21
Curve::degenerated
bool degenerated
Definition: Geo.h:78
SetSymmetryMatrix
void SetSymmetryMatrix(double matrix[4][4], double A, double B, double C, double D)
Definition: Geo.cpp:1258
Curve::geometry
gmshSurface * geometry
Definition: Geo.h:93
RemoveDegenerateCurves
static void RemoveDegenerateCurves()
Definition: Geo.cpp:2216
CompareTwoSurfaces
static int CompareTwoSurfaces(const void *a, const void *b)
Definition: Geo.cpp:1699
ExtrudeParams::Source
int Source
Definition: ExtrudeParams.h:51
MSH_SEGM_CIRC
#define MSH_SEGM_CIRC
Definition: GeoDefines.h:22
Surface::GeneratricesByTag
List_T * GeneratricesByTag
Definition: Geo.h:121
ApplyTransformationToVolume
static void ApplyTransformationToVolume(double matrix[4][4], Volume *v)
Definition: Geo.cpp:1445
GVertex::x
virtual double x() const =0
MSH_SURF_TRIC
#define MSH_SURF_TRIC
Definition: GeoDefines.h:35
IntersectCurvesWithSurface
bool IntersectCurvesWithSurface(List_T *curve_ids, int surface_id, List_T *shapes)
Definition: Geo.cpp:3560
Curve::Extrude
ExtrudeParams * Extrude
Definition: Geo.h:89
MSH_PHYSICAL_POINT
#define MSH_PHYSICAL_POINT
Definition: GeoDefines.h:43
ApplyTransformationToPointAlways
static void ApplyTransformationToPointAlways(double matrix[4][4], Vertex *v)
Definition: Geo.cpp:1389
EndSurface
void EndSurface(Surface *s)
Definition: Geo.cpp:426
Surface::MeshAlgorithm
int MeshAlgorithm
Definition: Geo.h:130
_create_splitted_curve
static Curve * _create_splitted_curve(Curve *c, List_T *nodes)
Definition: Geo.cpp:3406
Shape::Num
int Num
Definition: GeoDefines.h:12
GVertex::y
virtual double y() const =0
Surface::TransfiniteSmoothing
int TransfiniteSmoothing
Definition: Geo.h:119
CreateEdgeLoop
EdgeLoop * CreateEdgeLoop(int Num, List_T *intlist)
Definition: Geo.cpp:168
ListOfTransformedPoints
static List_T * ListOfTransformedPoints
Definition: Geo.cpp:28
CreateSurfaceLoop
SurfaceLoop * CreateSurfaceLoop(int Num, List_T *intlist)
Definition: Geo.cpp:193
Tree_Insert
int Tree_Insert(Tree_T *tree, void *data)
Definition: TreeUtils.cpp:52
List_Sort
void List_Sort(List_T *liste, int(*fcmp)(const void *a, const void *b))
Definition: ListUtils.cpp:176
Coord::X
double X
Definition: Geo.h:26
RecognizeLineLoop
int RecognizeLineLoop(List_T *liste, int *loop)
Definition: Geo.cpp:1214
EdgeLoop::Curves
List_T * Curves
Definition: Geo.h:108
Surface::RecombineAngle
double RecombineAngle
Definition: Geo.h:118
Surface::Recombine
int Recombine
Definition: Geo.h:116
Context.h
sys2x2
int sys2x2(double mat[2][2], double b[2], double res[2])
Definition: Numeric.cpp:101
SetRotationMatrix
void SetRotationMatrix(double matrix[4][4], double Axe[3], double alpha)
Definition: Geo.cpp:1316
Volume::SurfacesByTag
List_T * SurfacesByTag
Definition: Geo.h:151
DilatShapes
bool DilatShapes(double X, double Y, double Z, double A, double B, double C, List_T *shapes)
Definition: Geo.cpp:1564
RecognizeSurfaceLoop
int RecognizeSurfaceLoop(List_T *liste, int *loop)
Definition: Geo.cpp:1232
MVertexRTree::find
MVertex * find(double x, double y, double z)
Definition: MVertexRTree.h:70
DeletePhysicalVolume
void DeletePhysicalVolume(int num)
Definition: Geo.cpp:1136
z
const double z
Definition: GaussQuadratureQuad.cpp:56
Curve::Num
int Num
Definition: Geo.h:76
MSH_POINT_BND_LAYER
#define MSH_POINT_BND_LAYER
Definition: GeoDefines.h:17
ExtrudeSurface
int ExtrudeSurface(int type, int is, double T0, double T1, double T2, double A0, double A1, double A2, double X0, double X1, double X2, double alpha, Volume **pv, ExtrudeParams *e)
Definition: Geo.cpp:2987
Tree_Nbr
int Tree_Nbr(Tree_T *tree)
Definition: TreeUtils.cpp:46
O
#define O
Definition: DefaultOptions.h:22
NEWVOLUME
int NEWVOLUME()
Definition: Geo.cpp:3834
FreeEdgeLoop
void FreeEdgeLoop(void *a, void *b)
Definition: Geo.cpp:183
Vertex::geometry
gmshSurface * geometry
Definition: Geo.h:39
GModel::removePhysicalGroup
void removePhysicalGroup(int dim, int num)
Definition: GModel.cpp:901
Coord::Z
double Z
Definition: Geo.h:26
GEdge
Definition: GEdge.h:26
MSH_SEGM_BSPLN
#define MSH_SEGM_BSPLN
Definition: GeoDefines.h:27
ComparePhysicalGroup
int ComparePhysicalGroup(const void *a, const void *b)
Definition: Geo.cpp:95
Tree_Suppress
int Tree_Suppress(Tree_T *tree, void *data)
Definition: TreeUtils.cpp:85
Curve::ReverseMesh
int ReverseMesh
Definition: Geo.h:94
direction
static void direction(Vertex *v1, Vertex *v2, double d[3])
Definition: Geo.cpp:218
PointSurface::p
Vertex * p
Definition: Geo.cpp:3320
BOUNDARY_LAYER
#define BOUNDARY_LAYER
Definition: ExtrudeParams.h:24
ApplicationOnShapes
static bool ApplicationOnShapes(double matrix[4][4], List_T *shapes)
Definition: Geo.cpp:1454
DeletePhysicalLine
void DeletePhysicalLine(int num)
Definition: Geo.cpp:1114
FreeSurface
void FreeSurface(void *a, void *b)
Definition: Geo.cpp:604
DuplicateVertex
Vertex * DuplicateVertex(Vertex *v)
Definition: Geo.cpp:778
Coord::Y
double Y
Definition: Geo.h:26
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
NEWCURVE
int NEWCURVE()
Definition: Geo.cpp:3784
MSH_VOLUME
#define MSH_VOLUME
Definition: GeoDefines.h:40
Vertex::Pos
Coord Pos
Definition: Geo.h:34
ExtrudeShapes
void ExtrudeShapes(int type, List_T *list_in, double T0, double T1, double T2, double A0, double A1, double A2, double X0, double X1, double X2, double alpha, ExtrudeParams *e, List_T *list_out)
Definition: Geo.cpp:3221
SurfaceLoop
Definition: Geo.h:134
Volume::TrsfPoints
List_T * TrsfPoints
Definition: Geo.h:148
CreateCurve
Curve * CreateCurve(int Num, int Typ, int Order, List_T *Liste, List_T *Knots, int p1, int p2, double u1, double u2, bool &ok)
Definition: Geo.cpp:445
MVertexRTree
Definition: MVertexRTree.h:16
Surface::Generatrices
List_T * Generatrices
Definition: Geo.h:120
GModel.h
DuplicateSurface
Surface * DuplicateSurface(Surface *s)
Definition: Geo.cpp:895
Volume::Recombine3D
int Recombine3D
Definition: Geo.h:145
ExtrudeCurve
int ExtrudeCurve(int type, int ic, double T0, double T1, double T2, double A0, double A1, double A2, double X0, double X1, double X2, double alpha, Surface **ps, int final, ExtrudeParams *e)
Definition: Geo.cpp:2757
SetVolumeSurfaces
bool SetVolumeSurfaces(Volume *v, List_T *loops)
Definition: Geo.cpp:3734
DeletePoint
void DeletePoint(int ip, bool recursive)
Definition: Geo.cpp:956
FreeSurfaceLoop
void FreeSurfaceLoop(void *a, void *b)
Definition: Geo.cpp:208
NEWSURFACELOOP
int NEWSURFACELOOP()
Definition: Geo.cpp:3821
Surface::geometry
gmshSurface * geometry
Definition: Geo.h:129
MSH_SEGM_ELLI
#define MSH_SEGM_ELLI
Definition: GeoDefines.h:24
Surface::Recombine_Dir
int Recombine_Dir
Definition: Geo.h:117
GEdge::getEndVertex
virtual GVertex * getEndVertex() const
Definition: GEdge.h:64
FindPoint
static Vertex * FindPoint(int inum, Tree_T *t)
Definition: Geo.cpp:680
ExtrudeParams::angle
double angle
Definition: ExtrudeParams.h:53
CompareTwoCurves
static int CompareTwoCurves(const void *a, const void *b)
Definition: Geo.cpp:1642
Surface::ReverseMesh
int ReverseMesh
Definition: Geo.h:130
List_PSuppress
int List_PSuppress(List_T *liste, int index)
Definition: ListUtils.cpp:248
myasin
double myasin(double a)
Definition: Numeric.cpp:18
Tree_Create
Tree_T * Tree_Create(int size, int(*fcmp)(const void *a, const void *b))
Definition: TreeUtils.cpp:15
angle_02pi
double angle_02pi(double A3)
Definition: Numeric.cpp:255
ReplaceAllDuplicatesNew
void ReplaceAllDuplicatesNew(double tol)
Definition: Geo.cpp:2534
TRANSLATE
#define TRANSLATE
Definition: ExtrudeParams.h:21
CircParam::n
double n[3]
Definition: Geo.h:71
norme
double norme(double a[3])
Definition: Numeric.h:123
Curve::degre
int degre
Definition: Geo.h:91
Curve::Typ
int Typ
Definition: Geo.h:77
CompareVolume
int CompareVolume(const void *a, const void *b)
Definition: Geo.cpp:88
Surface::InSphereCenter
Vertex * InSphereCenter
Definition: Geo.h:123
projectPS
static bool projectPS(fullVector< double > &x, fullVector< double > &res, void *data)
Definition: Geo.cpp:3324
GModel::getVertexByTag
GVertex * getVertexByTag(int n) const
Definition: GModel.cpp:346
Volume::Num
int Num
Definition: Geo.h:142
ExtrudeParams
Definition: ExtrudeParams.h:26
GModel::getGEOInternals
GEO_Internals * getGEOInternals()
Definition: GModel.h:315
Curve::coeffTransfinite
double coeffTransfinite
Definition: Geo.h:82
c1
const double c1
Definition: GaussQuadratureHex.cpp:16
MaxNumSurface
static void MaxNumSurface(void *a, void *b)
Definition: Geo.cpp:1745
SurfaceLoop::Surfaces
List_T * Surfaces
Definition: Geo.h:137
Vertex::w
double w
Definition: Geo.h:33
vecmat4x4
static void vecmat4x4(double mat[4][4], double vec[4], double res[4])
Definition: Geo.cpp:1381
ReplaceDuplicateCurves
static void ReplaceDuplicateCurves(std::map< int, int > *c_report=nullptr)
Definition: Geo.cpp:2036
List_Read
void List_Read(List_T *liste, int index, void *data)
Definition: ListUtils.cpp:111
Surface::degenerate
bool degenerate() const
Definition: Geo.cpp:2358
fullMatrix.h
fcmp_absint
int fcmp_absint(const void *a, const void *b)
Definition: ListUtils.cpp:28
FindSurface
static Surface * FindSurface(int inum, Tree_T *t)
Definition: Geo.cpp:708
CompareCurve
int CompareCurve(const void *a, const void *b)
Definition: Geo.cpp:74
Tree_Query
int Tree_Query(Tree_T *tree, void *data)
Definition: TreeUtils.cpp:68
GModel::current
static GModel * current(int index=-1)
Definition: GModel.cpp:136
MSH_SEGM_LINE
#define MSH_SEGM_LINE
Definition: GeoDefines.h:20
List_PQuery
void * List_PQuery(List_T *liste, void *data, int(*fcmp)(const void *a, const void *b))
Definition: ListUtils.cpp:225
Surface::Method
int Method
Definition: Geo.h:115
DuplicateVolume
Volume * DuplicateVolume(Volume *v)
Definition: Geo.cpp:942
ComparePosition
static int ComparePosition(const void *a, const void *b)
Definition: Geo.cpp:37
Curve::Circle
CircParam Circle
Definition: Geo.h:92
ExtrudeParams::axe
double axe[3]
Definition: ExtrudeParams.h:53
ReplaceDuplicatePointsNew
static void ReplaceDuplicatePointsNew(double tol=-1.)
Definition: Geo.cpp:1752
ReplaceDuplicatePoints
static void ReplaceDuplicatePoints(std::map< int, int > *v_report=nullptr)
Definition: Geo.cpp:1859
SetSurfaceGeneratrices
bool SetSurfaceGeneratrices(Surface *s, List_T *loops)
Definition: Geo.cpp:3674