11 #include "GmshConfig.h"
29 #if defined(HAVE_DOMHEX)
30 #include "pointInsertion.h"
31 #include "surfaceFiller.h"
34 static double LIMIT_ = 0.5 * std::sqrt(2.0) * 1;
40 const std::vector<GEdge *> &ed = gf->
edges();
41 for(
size_t i = 0; i < ed.size(); i++) {
56 if(a * b > 0)
return 0;
59 if(a * b > 0)
return 0;
63 template <
class ITERATOR>
67 FILE *ff =
Fopen(name,
"w");
72 fprintf(ff,
"View\"test\"{\n");
79 for(
int i = 0; i < 3; i++) {
81 (
degenerated->find((worst)->tri()->getVertex(i)->onWhat()) !=
84 (worst)->tri()->getVertex((i + 1) % 3)->onWhat()) !=
87 double u1 = data->
Us[data->
getIndex((worst)->tri()->getVertex(i))];
89 data->
Us[data->
getIndex((worst)->tri()->getVertex((i + 1) % 3))];
90 double v1 = data->
Vs[data->
getIndex((worst)->tri()->getVertex(i))];
92 data->
Vs[data->
getIndex((worst)->tri()->getVertex((i + 1) % 3))];
94 for(
int j = 0; j < N; j++) {
95 double t = (double)j / (N - 1);
96 double u = u1 + t * (u2 - u1);
97 double v = v1 + t * (v2 - v1);
100 fprintf(ff,
"SL(%g,%g,%g,%g,%g,%g){1,1};\n", p_prec.
x(),
101 p_prec.
y(), p_prec.
z(), p.x(), p.y(), p.z());
116 double u1 = data->
Us[data->
getIndex((worst)->tri()->getVertex(0))];
117 double v1 = data->
Vs[data->
getIndex((worst)->tri()->getVertex(0))];
118 double u2 = data->
Us[data->
getIndex((worst)->tri()->getVertex(1))];
119 double v2 = data->
Vs[data->
getIndex((worst)->tri()->getVertex(1))];
120 double u3 = data->
Us[data->
getIndex((worst)->tri()->getVertex(2))];
121 double v3 = data->
Vs[data->
getIndex((worst)->tri()->getVertex(2))];
126 degenerated->find((worst)->tri()->getVertex(0)->onWhat()) !=
129 degenerated->find((worst)->tri()->getVertex(1)->onWhat()) !=
132 degenerated->find((worst)->tri()->getVertex(2)->onWhat()) !=
134 if(deg[0] && !deg[1] && !deg[2]) {
136 ff,
"SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d,%d};\n",
137 u3, v1, 0., u2, v1, 0., u2, v2, 0., u3, v3, 0.,
138 (worst)->tri()->getVertex(0)->getNum(),
139 (worst)->tri()->getVertex(0)->getNum(),
140 (worst)->tri()->getVertex(1)->getNum(),
141 (worst)->tri()->getVertex(2)->getNum());
143 else if(!deg[0] && deg[1] && !deg[2]) {
145 ff,
"SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d,%d};\n",
146 u1, v2, 0., u3, v2, 0., u3, v3, 0., u1, v1, 0.,
147 (worst)->tri()->getVertex(1)->getNum(),
148 (worst)->tri()->getVertex(1)->getNum(),
149 (worst)->tri()->getVertex(2)->getNum(),
150 (worst)->tri()->getVertex(0)->getNum());
152 else if(!deg[0] && !deg[1] && deg[2]) {
154 ff,
"SQ(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d,%d};\n",
155 u2, v3, 0., u1, v3, 0., u1, v1, 0., u2, v2, 0.,
156 (worst)->tri()->getVertex(2)->getNum(),
157 (worst)->tri()->getVertex(2)->getNum(),
158 (worst)->tri()->getVertex(0)->getNum(),
159 (worst)->tri()->getVertex(1)->getNum());
161 else if(!deg[0] && !deg[1] && !deg[2]) {
162 fprintf(ff,
"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d};\n", u1,
163 v1, 0., u2, v2, 0., u3, v3, 0.,
164 (worst)->tri()->getVertex(0)->getNum(),
165 (worst)->tri()->getVertex(1)->getNum(),
166 (worst)->tri()->getVertex(2)->getNum());
170 fprintf(ff,
"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d};\n", u1, v1,
171 0., u2, v2, 0., u3, v3, 0.,
172 (worst)->tri()->getVertex(0)->getNum(),
173 (worst)->tri()->getVertex(1)->getNum(),
174 (worst)->tri()->getVertex(2)->getNum());
178 fprintf(ff,
"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%d,%d,%d};\n",
179 (worst)->tri()->getVertex(0)->x(),
180 (worst)->tri()->getVertex(0)->y(),
181 (worst)->tri()->getVertex(0)->
z(),
182 (worst)->tri()->getVertex(1)->x(),
183 (worst)->tri()->getVertex(1)->y(),
184 (worst)->tri()->getVertex(1)->
z(),
185 (worst)->tri()->getVertex(2)->x(),
186 (worst)->tri()->getVertex(2)->y(),
187 (worst)->tri()->getVertex(2)->
z(),
188 (worst)->tri()->getVertex(0)->getNum(),
189 (worst)->tri()->getVertex(1)->getNum(),
190 (worst)->tri()->getVertex(2)->getNum());
202 for(active = 0; active < 3; active++) {
216 std::set<MEdge, MEdgeLessThan> *front)
219 for(i = 0; i < 3; i++) {
222 int ip1 = i - 1 < 0 ? 2 : i - 1;
225 if(front->find(me) != front->end()) {
return true; }
232 std::set<MEdge, MEdgeLessThan> &front)
235 for(
int active = 0; active < 3; active++) {
238 int ip1 = active - 1 < 0 ? 2 : active - 1;
247 const double *metric,
double *x,
double &Radius2)
253 const double a = metric[0];
254 const double b = metric[1];
255 const double d = metric[2];
257 sys[0][0] = 2. * a * (pa[0] - pb[0]) + 2. * b * (pa[1] - pb[1]);
258 sys[0][1] = 2. * d * (pa[1] - pb[1]) + 2. * b * (pa[0] - pb[0]);
259 sys[1][0] = 2. * a * (pa[0] - pc[0]) + 2. * b * (pa[1] - pc[1]);
260 sys[1][1] = 2. * d * (pa[1] - pc[1]) + 2. * b * (pa[0] - pc[0]);
262 rhs[0] = a * (pa[0] * pa[0] - pb[0] * pb[0]) +
263 d * (pa[1] * pa[1] - pb[1] * pb[1]) +
264 2. * b * (pa[0] * pa[1] - pb[0] * pb[1]);
265 rhs[1] = a * (pa[0] * pa[0] - pc[0] * pc[0]) +
266 d * (pa[1] * pa[1] - pc[1] * pc[1]) +
267 2. * b * (pa[0] * pa[1] - pc[0] * pc[1]);
269 if(!
sys2x2(sys, rhs, x)) {
273 Radius2 = (x[0] - pa[0]) * (x[0] - pa[0]) * a +
274 (x[1] - pa[1]) * (x[1] - pa[1]) * d +
275 2. * (x[0] - pa[0]) * (x[1] - pa[1]) * b;
279 SMetric3 &metric,
double *res,
double *uv,
282 double v1[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
283 double v2[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
284 double vx[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
285 double vy[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
292 double p1P[2] = {0.0, 0.0};
299 for(
int i = 0; i < 3; i++) T(0, i) = vx[i];
300 for(
int i = 0; i < 3; i++) T(1, i) = vy[i];
301 for(
int i = 0; i < 3; i++) T(2, i) = vz[i];
303 double mm[3] = {tra(0, 0), tra(0, 1), tra(1, 1)};
308 double mat[2][2] = {{p2P[0] - p1P[0], p3P[0] - p1P[0]},
309 {p2P[1] - p1P[1], p3P[1] - p1P[1]}};
310 double rhs[2] = {resP[0] - p1P[0], resP[1] - p1P[1]};
314 res[0] = p1[0] + resP[0] * vx[0] + resP[1] * vy[0];
315 res[1] = p1[1] + resP[0] * vx[1] + resP[1] * vy[1];
316 res[2] = p1[2] + resP[0] * vx[2] + resP[1] * vy[2];
326 double pa[2] = {data.
Us[index0], data.
Vs[index0]};
327 double pb[2] = {data.
Us[index1], data.
Vs[index1]};
328 double pc[2] = {data.
Us[index2], data.
Vs[index2]};
343 if(radius <= 1e3)
return 1e-12;
344 if(radius <= 1e5)
return 1e-11;
349 double *uv,
double *metric)
351 double x[2], Radius2;
353 const double a = metric[0];
354 const double b = metric[1];
355 const double d = metric[2];
356 const double d0 = (x[0] - uv[0]);
357 const double d1 = (x[1] - uv[1]);
358 const double d3 = d0 * d0 * a + d1 * d1 * d + 2.0 * d0 * d1 * b;
367 double x[2], Radius2;
373 double pa[2] = {(data.
Us[index0] + data.
Us[index1] + data.
Us[index2]) / 3.,
374 (data.
Vs[index0] + data.
Vs[index1] + data.
Vs[index2]) / 3.};
378 metric[0] = metricb[0];
379 metric[1] = metricb[1];
380 metric[2] = metricb[2];
384 const double a = metric[0];
385 const double b = metric[1];
386 const double d = metric[2];
388 const double d0 = (x[0] - uv[0]);
389 const double d1 = (x[1] - uv[1]);
390 const double d3 = d0 * d0 * a + d1 * d1 * d + 2.0 * d0 * d1 * b;
394 static void fourthPoint(
double *p1,
double *p2,
double *p3,
double *p4)
398 double vx[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
399 double vy[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
404 sqrt((p1[0] -
c[0]) * (p1[0] -
c[0]) + (p1[1] -
c[1]) * (p1[1] -
c[1]) +
405 (p1[2] -
c[2]) * (p1[2] -
c[2]));
406 p4[0] =
c[0] + R * vz[0];
407 p4[1] =
c[1] + R * vz[1];
408 p4[2] =
c[2] + R * vz[2];
413 : deleted(false), base(t)
437 double const p1[2] = {data->
Us[index0], data->
Vs[index0]};
438 double const p2[2] = {data->
Us[index1], data->
Vs[index1]};
439 double const p3[2] = {data->
Us[index2], data->
Vs[index2]};
441 double midpoint[2] = {(p1[0] + p2[0] + p3[0]) / 3.0,
442 (p1[1] + p2[1] + p3[1]) / 3.0};
449 double x0 = p1[0] * std::cos(quadAngle) + p1[1] * std::sin(quadAngle);
450 double y0 = -p1[0] * std::sin(quadAngle) + p1[1] * std::cos(quadAngle);
451 double x1 = p2[0] * std::cos(quadAngle) + p2[1] * std::sin(quadAngle);
452 double y1 = -p2[0] * std::sin(quadAngle) + p2[1] * std::cos(quadAngle);
453 double x2 = p3[0] * std::cos(quadAngle) + p3[1] * std::sin(quadAngle);
454 double y2 = -p3[0] * std::sin(quadAngle) + p3[1] * std::cos(quadAngle);
455 double xmax = std::max(std::max(x0, x1), x2);
456 double ymax = std::max(std::max(y0, y1), y2);
457 double xmin = std::min(std::min(x0, x1), x2);
458 double ymin = std::min(std::min(y0, y1), y2);
463 std::pow(metric[0] * metric[2] - metric[1] * metric[1], -0.25);
496 return (result > 0) ? 1 : 0;
505 double pa[2] = {data.
Us[index0], data.
Vs[index0]};
506 double pb[2] = {data.
Us[index1], data.
Vs[index1]};
507 double pc[2] = {data.
Us[index2], data.
Vs[index2]};
511 return (result > 0) ? 1 : 0;
514 template <
class Iterator>
516 std::vector<edgeXface> &
conn)
521 if(!(*beg)->isDeleted()) {
522 for(
int j = 0; j < 3; j++) {
conn.push_back(
edgeXface(*beg, j)); }
527 if(
conn.empty())
return;
529 std::sort(
conn.begin(),
conn.end());
531 for(std::size_t i = 0; i <
conn.size() - 1; i++) {
535 if(f1 == f2 && f1.
t1 != f2.
t1) {
545 std::vector<edgeXface>
conn;
551 std::vector<edgeXface>
conn;
557 std::vector<edgeXface>
conn;
566 double p1[2] = {v1->
x(), v1->
y()};
567 double p2[2] = {v2->
x(), v2->
y()};
568 double p3[2] = {v3->
x(), v3->
y()};
569 double pp[2] = {
v->x(),
v->y()};
572 return (result > 0) ? 1 : 0;
583 for(
int i = 0; i < 3; i++) {
598 std::list<MTri3 *> &cavity,
double *metric,
606 for(
int i = 0; i < 3; i++) {
612 shell.push_back(exf);
618 shell.push_back(exf);
628 double u1[3] = {data.
Us[index0], data.
Vs[index0], 0};
629 double u2[3] = {data.
Us[index1], data.
Vs[index1], 0};
630 double u3[3] = {data.
Us[index2], data.
Vs[index2], 0};
645 double u0 = data.
Us[index0];
646 double v0 = data.
Vs[index0];
647 double u1 = data.
Us[index1];
648 double v1 = data.
Vs[index1];
649 double u2 = data.
Us[index2];
650 double v2 = data.
Vs[index2];
661 return uv[0] >= -tol && uv[1] >= -tol && uv[0] <= 1. + tol &&
662 uv[1] <= 1. + tol && 1. - uv[0] - uv[1] > -tol;
671 double u1 = data.
Us[index0];
672 double v1 = data.
Vs[index0];
673 double u2 = data.
Us[index1];
674 double v2 = data.
Vs[index1];
675 double u3 = data.
Us[index2];
676 double v3 = data.
Vs[index2];
678 const double vv1[2] = {u2 - u1, v2 - v1};
679 const double vv2[2] = {u3 - u1, v3 - v1};
681 return 0.5 * (vv1[0] * vv2[1] - vv1[1] * vv2[0]);
685 std::list<MTri3 *> &cavity,
bool force,
GFace *gf,
687 std::set<MTri3 *, compareTri3Ptr> &allTets,
688 std::set<MTri3 *, compareTri3Ptr> *activeTets,
690 MTri3 **oneNewTriangle,
691 bool verifyStarShapeness =
true)
693 if(cavity.size() == 1)
return -1;
695 if(shell.size() != cavity.size() + 2)
return -2;
697 double EPS = verifyStarShapeness ? 1.e-12 : 1.e12;
700 double newVolume = 0.0;
701 double newMinQuality = 2.0;
703 double oldVolume = std::accumulate(
704 begin(cavity), end(cavity), 0.0, [&](
double volume,
MTri3 *
const triangle) {
710 std::vector<MTri3 *> new_cavity;
714 auto it = shell.begin();
716 bool onePointIsTooClose =
false;
718 while(it != shell.end()) {
732 constexpr
double ONE_THIRD = 1. / 3.;
733 double lc = ONE_THIRD * (data.
vSizes[index0] + data.
vSizes[index1] +
738 double LL = std::min(
lc,
lcBGM);
745 *oneNewTriangle = t4;
753 double cosv = ((d1 * d1 + d2 * d2 - d3 * d3) / (2. * d1 * d2));
756 SVector3 v0v1(v1->
x() - v0->
x(), v1->
y() - v0->
y(), v1->
z() - v0->
z());
757 SVector3 v0v(
v->x() - v0->
x(),
v->y() - v0->
y(),
v->z() - v0->
z());
762 if((d1 < LL * .5 || d2 < LL * .5 || d4 < LL * .4 || cosv < -.9999) &&
764 onePointIsTooClose =
true;
770 new_cavity.push_back(t4);
773 if(otherSide) new_cavity.push_back(otherSide);
776 if(ss < 1.e-25) ss = 1.e22;
784 std::vector<edgeXface>
conn;
788 if(std::abs(oldVolume - newVolume) < EPS * oldVolume && !onePointIsTooClose) {
791 allTets.insert(newTris, newTris + shell.size());
793 for(
auto i = new_cavity.begin(); i != new_cavity.end(); ++i) {
796 if((*activeTets).find(*i) == (*activeTets).end())
797 (*activeTets).insert(*i);
806 std::for_each(begin(cavity), end(cavity),
813 for(std::size_t i = 0; i < shell.size(); i++) {
814 delete newTris[i]->tri();
819 if(std::abs(oldVolume - newVolume) > EPS * oldVolume)
return -3;
820 if(onePointIsTooClose)
return -4;
830 double mat[2][2], b[2], uv[2], tol = 1.e-6;
831 mat[0][0] = v1->
x() - v0->
x();
832 mat[0][1] = v2->
x() - v0->
x();
833 mat[1][0] = v1->
y() - v0->
y();
834 mat[1][1] = v2->
y() - v0->
y();
836 b[0] =
v->x() - v0->
x();
837 b[1] =
v->y() - v0->
y();
840 if(uv[0] >= -tol && uv[1] >= -tol && uv[0] <= 1. + tol && uv[1] <= 1. + tol &&
841 1. - uv[0] - uv[1] > -tol) {
855 for(i = 0; i < 3; i++) {
856 int i1 = i == 0 ? 2 : i - 1;
869 if(ITER++ > .5 * maxx)
break;
875 std::set<MTri3 *, compareTri3Ptr> &AllTris,
876 double uv[2],
bool force =
false)
879 bool inside =
invMapUV(t->
tri(), pt, data, uv, 1.e-8);
888 SPoint3 q2((data.
Us[index0] + data.
Us[index1] + data.
Us[index2]) / 3.0,
889 (data.
Vs[index0] + data.
Vs[index1] + data.
Vs[index2]) / 3.0, 0);
891 for(i = 0; i < 3; i++) {
899 printf(
"impossible\n");
904 bool inside =
invMapUV(t->
tri(), pt, data, uv, 1.e-8);
906 if(ITER++ > (
int)AllTris.size())
break;
912 for(
auto itx = AllTris.begin(); itx != AllTris.end(); ++itx) {
913 if(!(*itx)->isDeleted()) {
914 inside =
invMapUV((*itx)->tri(), pt, data, uv, 1.e-8);
915 if(inside) {
return *itx; }
925 std::set<MTri3 *, compareTri3Ptr> &AllTris,
926 std::set<MTri3 *, compareTri3Ptr> *ActiveTris =
nullptr,
927 MTri3 *worst =
nullptr,
MTri3 **oneNewTriangle =
nullptr,
928 bool testStarShapeness =
false)
931 it = AllTris.find(worst);
940 MTri3 *ptin =
nullptr;
941 std::list<edgeXface> shell;
942 std::list<MTri3 *> cavity;
948 for(
auto itc = cavity.begin(); itc != cavity.end(); ++itc) {
949 if(
invMapUV((*itc)->tri(), center, data, uv, 1.e-8)) {
957 oneNewTriangle ?
true :
false);
974 lc1 = (1. - uv[0] - uv[1]) * data.
vSizes[index0] +
975 uv[0] * data.
vSizes[index1] + uv[1] * data.
vSizes[index2];
985 result =
insertVertexB(shell, cavity,
false, gf,
v, center, ptin, AllTris,
986 ActiveTris, data, metric, oneNewTriangle,
991 Msg::Debug(
"Point %g %g cannot be inserted because cavity if of size 1",
992 center[0], center[1]);
994 Msg::Debug(
"Point %g %g cannot be inserted because euler formula is "
996 center[0], center[1]);
999 "Point %g %g cannot be inserted because cavity is not star shaped",
1000 center[0], center[1]);
1002 Msg::Debug(
"Point %g %g cannot be inserted because it is too close to "
1004 center[0], center[1]);
1006 Msg::Debug(
"Point %g %g cannot be inserted because it is out of the "
1007 "parametric domain)",
1008 center[0], center[1]);
1011 worst->forceRadius(-1);
1012 AllTris.insert(worst);
1014 for(
auto itc = cavity.begin(); itc != cavity.end(); ++itc)
1015 (*itc)->setDeleted(
false);
1024 for(
auto itc = cavity.begin(); itc != cavity.end(); ++itc)
1025 (*itc)->setDeleted(
false);
1027 worst->forceRadius(0);
1028 AllTris.insert(worst);
1034 std::map<MVertex *, MVertex *> *equivalence,
1037 std::set<MTri3 *, compareTri3Ptr> AllTris;
1041 Msg::Error(
"Invalid meshing data structure");
1045 if(AllTris.empty()) {
1053 MTri3 *worst = *AllTris.begin();
1055 delete worst->
tri();
1057 AllTris.erase(AllTris.begin());
1061 if(ITER++ % 5000 == 0) {
1062 Msg::Debug(
"%7d points created -- Worst tri radius is %8.3f",
1066 if(worst->
getRadius() < 0.5 * std::sqrt(2.0) ||
1067 (
int)DATA.
vSizes.size() > MAXPNT) {
1071 double center[2], metric[3], r2;
1078 (DATA.
Us[index0] + DATA.
Us[index1] + DATA.
Us[index2]) / 3.,
1079 (DATA.
Vs[index0] + DATA.
Vs[index1] + DATA.
Vs[index2]) / 3.};
1083 insertAPoint(gf, AllTris.begin(), center, metric, DATA, AllTris);
1095 const double quadAngle)
1097 double const xp = p[0] * std::cos(quadAngle) + p[1] * std::sin(quadAngle);
1098 double const yp = -p[0] * std::sin(quadAngle) + p[1] * std::cos(quadAngle);
1099 double const xq = q[0] * std::cos(quadAngle) + q[1] * std::sin(quadAngle);
1100 double const yq = -q[0] * std::sin(quadAngle) + q[1] * std::cos(quadAngle);
1101 double const xmax = std::max(xp, xq);
1102 double const xmin = std::min(xp, xq);
1103 double const ymax = std::max(yp, yq);
1104 double const ymin = std::min(yp, yq);
1105 return std::max(xmax - xmin, ymax - ymin);
1114 double const pa[2] = {data.
Us[index0], data.
Vs[index0]};
1115 double const pb[2] = {data.
Us[index1], data.
Vs[index1]};
1116 double const pc[2] = {data.
Us[index2], data.
Vs[index2]};
1117 double const xa = pa[0] * std::cos(quadAngle) - pa[1] * std::sin(quadAngle);
1118 double const ya = pa[0] * std::sin(quadAngle) + pa[1] * std::cos(quadAngle);
1119 double const xb = pb[0] * std::cos(quadAngle) - pb[1] * std::sin(quadAngle);
1120 double const yb = pb[0] * std::sin(quadAngle) + pb[1] * std::cos(quadAngle);
1121 double const xc = pc[0] * std::cos(quadAngle) - pc[1] * std::sin(quadAngle);
1122 double const yc = pc[0] * std::sin(quadAngle) + pc[1] * std::cos(quadAngle);
1123 double const xmax = std::max(std::max(xa, xb), xc);
1124 double const ymax = std::max(std::max(ya, yb), yc);
1125 double const xmin = std::min(std::min(xa, xb), xc);
1126 double const ymin = std::min(std::min(ya, yb), yc);
1127 x[0] = 0.5 * (xmax - xmin);
1128 x[1] = 0.5 * (ymax - ymin);
1132 const double metric[3])
1134 return std::sqrt((p[0] - q[0]) * metric[0] * (p[0] - q[0]) +
1135 2 * (p[0] - q[0]) * metric[1] * (p[1] - q[1]) +
1136 (p[1] - q[1]) * metric[2] * (p[1] - q[1]));
1167 double center[2], r2;
1169 circUV(base, data, center, gf);
1173 double pa[2] = {(data.
Us[index0] + data.
Us[index1] + data.
Us[index2]) / 3.,
1174 (data.
Vs[index0] + data.
Vs[index1] + data.
Vs[index2]) / 3.};
1178 int ip1 = active_edge - 1 < 0 ? 2 : active_edge - 1;
1179 int ip2 = active_edge;
1183 double P[2] = {data.
Us[index0], data.
Vs[index0]};
1184 double Q[2] = {data.
Us[index1], data.
Vs[index1]};
1185 double midpoint[2] = {0.5 * (P[0] + Q[0]), 0.5 * (P[1] + Q[1])};
1190 double dir[2] = {center[0] - midpoint[0], center[1] - midpoint[1]};
1191 double norm = std::sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
1194 const double RATIO =
1195 std::sqrt(dir[0] * dir[0] * metric[0] + 2 * dir[1] * dir[0] * metric[1] +
1196 dir[1] * dir[1] * metric[2]);
1198 const double rhoM1 =
1200 const double rhoM2 =
1204 const double rhoM_hat = rhoM;
1206 const double q =
lengthMetric(center, midpoint, metric);
1207 const double d = rhoM_hat * std::sqrt(3.0) * 0.5;
1211 const double L = std::min(d, q);
1213 newPoint[0] = midpoint[0] + L * dir[0] / RATIO;
1214 newPoint[1] = midpoint[1] + L * dir[1] / RATIO;
1242 int ip1 = (active_edge + 2) % 3;
1243 int ip2 = active_edge;
1244 int ip3 = (active_edge + 1) % 3;
1248 SVector3 middle((v1->
x() + v2->
x()) * .5, (v1->
y() + v2->
y()) * .5,
1249 (v1->
z() + v2->
z()) * .5);
1250 SVector3 v1v2(v2->
x() - v1->
x(), v2->
y() - v1->
y(), v2->
z() - v1->
z());
1251 SVector3 tmp(v3->
x() - middle.
x(), v3->
y() - middle.
y(),
1252 v3->
z() - middle.
z());
1254 if(n1.
norm() < 1.e-12)
return true;
1263 #if defined(HAVE_HXT)
1274 double uvt[3] = {newPoint[0], newPoint[1], 0.0};
1280 newPoint[0] = uvt[0];
1281 newPoint[1] = uvt[1];
1291 std::vector<SPoint2> *true_boundary)
1293 std::set<MTri3 *, compareTri3Ptr> AllTris;
1294 std::set<MTri3 *, compareTri3Ptr> ActiveTris;
1296 bool testStarShapeness =
true;
1302 Msg::Error(
"Invalid meshing data structure");
1306 int ITER = 0, active_edge;
1308 auto it = AllTris.begin();
1309 for(; it != AllTris.end(); ++it) {
1311 ActiveTris.insert(*it);
1312 else if((*it)->getRadius() <
LIMIT_)
1336 if(!ActiveTris.size())
break;
1337 MTri3 *worst = (*ActiveTris.begin());
1338 ActiveTris.erase(ActiveTris.begin());
1342 if(ITER++ % 5000 == 0)
1343 Msg::Debug(
"%7d points created -- Worst tri radius is %8.3f",
1345 double newPoint[2], metric[3];
1347 SPoint2 NP(newPoint[0], newPoint[1]);
1349 if(!true_boundary ||
1351 insertAPoint(gf, AllTris.end(), newPoint, metric, DATA, AllTris,
1352 &ActiveTris, worst,
nullptr, testStarShapeness);
1371 int ip1 = active_edge - 1 < 0 ? 2 : active_edge - 1;
1372 int ip2 = active_edge;
1373 int ip3 = (active_edge + 1) % 3;
1379 double P[2] = {data.
Us[index1], data.
Vs[index1]};
1380 double Q[2] = {data.
Us[index2], data.
Vs[index2]};
1381 double O[2] = {data.
Us[index3], data.
Vs[index3]};
1382 double midpoint[2] = {0.5 * (P[0] + Q[0]), 0.5 * (P[1] + Q[1])};
1391 double XP1 = 0.5 * (Q[0] - P[0]);
1392 double YP1 = 0.5 * (Q[1] - P[1]);
1393 double xp = XP1 * std::cos(quadAngle) + YP1 * std::sin(quadAngle);
1394 double yp = -XP1 * std::sin(quadAngle) + YP1 * std::cos(quadAngle);
1396 bool exchange =
false;
1397 if(std::abs(xp) < std::abs(yp)) {
1405 double RATIO = std::pow(metric[0] * metric[2] - metric[1] * metric[1], -0.25);
1410 const double rhoM1 =
1411 0.5 * RATIO * (data.
vSizes[index1] + data.
vSizes[index2]) / std::sqrt(3.0);
1412 const double rhoM2 = 0.5 * RATIO *
1418 const double rhoM_hat =
1419 std::min(std::max(rhoM, p), (p * p + q * q) / (2 * q));
1420 const double factor =
1421 (rhoM_hat + std::sqrt(rhoM_hat * rhoM_hat - p * p)) / (std::sqrt(3.) * p);
1425 npx = -std::abs(xp) * factor;
1426 npy = std::abs(xp) * (1. + factor) - std::abs(yp);
1429 npx = std::abs(xp) * factor;
1430 npy = (1. + factor) * std::abs(xp) - std::abs(yp);
1439 midpoint[0] + std::cos(quadAngle) * npx - std::sin(quadAngle) * npy;
1441 midpoint[1] + std::sin(quadAngle) * npx + std::cos(quadAngle) * npy;
1443 if((midpoint[0] - newPoint[0]) * (midpoint[0] -
O[0]) +
1444 (midpoint[1] - newPoint[1]) * (midpoint[1] -
O[1]) <
1447 midpoint[0] - std::cos(quadAngle) * npx + std::sin(quadAngle) * npy;
1449 midpoint[1] - std::sin(quadAngle) * npx - std::cos(quadAngle) * npy;
1454 std::map<MVertex *, MVertex *> *equivalence,
1457 #if defined(HAVE_DOMHEX)
1458 if(!old_algo_hexa())
return;
1460 Msg::Debug(
"build background mesh (Bowyer Watson, fixed size) ...");
1465 std::vector<MTriangle *> TR;
1466 for(std::size_t i = 0; i < gf->
triangles.size(); i++) {
1482 if(crossFieldClosestPoint)
1488 sprintf(name,
"bgm-%d.pos", gf->
tag());
1490 sprintf(name,
"cross-%d.pos", gf->
tag());
1498 GFace *gf,
bool quad, std::map<MVertex *, MVertex *> *equivalence,
1501 std::set<MTri3 *, compareTri3Ptr> AllTris;
1502 std::set<MTri3 *, compareTri3Ptr> ActiveTris;
1506 LIMIT_ = std::sqrt(2.0) * 0.99;
1512 Msg::Error(
"Invalid meshing data structure");
1516 int ITER = 0, active_edge;
1518 auto it = AllTris.begin();
1519 std::set<MEdge, MEdgeLessThan> _front;
1520 for(; it != AllTris.end(); ++it) {
1522 ActiveTris.insert(*it);
1525 else if((*it)->getRadius() <
LIMIT_)
1531 int max_layers = quad ? 10000 : 4;
1542 std::set<MTri3 *, compareTri3Ptr> ActiveTrisNotInFront;
1547 if(!ActiveTris.size())
break;
1555 auto WORST_ITER = ActiveTris.begin();
1557 MTri3 *worst = (*WORST_ITER);
1558 ActiveTris.erase(WORST_ITER);
1560 (ITERATION > max_layers ?
1567 if(ITER++ % 5000 == 0)
1569 "%7d points created -- Worst tri infinite radius is %8.3f -- "
1574 double newPoint[2], metric[3] = {1, 0, 1};
1581 insertAPoint(gf, AllTris.end(), newPoint,
nullptr, DATA, AllTris,
1582 &ActiveTris, worst);
1596 ActiveTrisNotInFront.insert(worst);
1600 it = ActiveTrisNotInFront.begin();
1601 for(; it != ActiveTrisNotInFront.end(); ++it) {
1603 ActiveTris.insert(*it);
1609 if(!ActiveTris.size())
break;
1614 LIMIT_ = 0.5 * std::sqrt(2.0) * 1;
1622 GFace *gf, std::map<MVertex *, MVertex *> *equivalence,
1625 std::set<MTri3 *, compareTri3Ptr> AllTris;
1627 std::vector<MVertex *> packed;
1628 std::vector<SMetric3> metrics;
1630 Msg::Debug(
"- Face %i: bowyerWatsonParallelograms ...", gf->
tag());
1633 "- Face %i: no CAD parametrization available, cannot mesh with algo PACK",
1638 #if defined(HAVE_DOMHEX)
1639 if(old_algo_hexa()) {
1640 Msg::Debug(
"bowyerWatsonParallelograms: call packingOfParallelograms()");
1641 packingOfParallelograms(gf, packed, metrics);
1644 Msg::Debug(
"bowyerWatsonParallelograms: call Filler2D::pointInsertion2D()");
1646 f.pointInsertion2D(gf, packed, metrics);
1649 Msg::Error(
"Packing of parallelograms algorithm requires DOMHEX");
1652 Msg::Info(
"%lu Nodes created --> now staring insertion", packed.size());
1655 Msg::Error(
"Invalid meshing data structure");
1661 Msg::Debug(
"bowyerWatsonParallelograms: %li candidate points to insert in "
1662 "the triangulation",
1665 MTri3 *oneNewTriangle =
nullptr;
1666 for(std::size_t i = 0; i < packed.size();) {
1667 MTri3 *worst = *AllTris.begin();
1669 delete worst->
tri();
1671 AllTris.erase(AllTris.begin());
1675 packed[i]->getParameter(0, newPoint[0]);
1676 packed[i]->getParameter(1, newPoint[1]);
1682 insertAPoint(gf, AllTris.begin(), newPoint, metric, DATA, AllTris,
1683 nullptr, oneNewTriangle, &oneNewTriangle);
1684 if(!success) oneNewTriangle =
nullptr;
1688 if(1.0 * AllTris.size() > 2.5 * DATA.
vSizes.size()) {
1689 auto itd = AllTris.begin();
1690 while(itd != AllTris.end()) {
1691 if((*itd)->isDeleted()) {
1693 AllTris.erase(itd++);
1705 "bowyerWatsonParallelograms: %li candidate points -> %li inserted vertices",
1712 GFace *gf,
const std::set<MVertex *> &constr_vertices,
1713 std::map<MVertex *, MVertex *> *equivalence,
1716 Msg::Error(
"bowyerWatsonParallelogramsConstrained deprecated");
1719 std::set<MTri3 *, compareTri3Ptr> AllTris;
1721 std::vector<MVertex *> packed;
1722 std::vector<SMetric3> metrics;
1724 #if defined(HAVE_DOMHEX)
1728 Msg::Error(
"Packing of parallelograms algorithm requires DOMHEX");
1732 Msg::Error(
"Invalid meshing data structure");
1738 MTri3 *oneNewTriangle =
nullptr;
1739 for(std::size_t i = 0; i < packed.size();) {
1740 MTri3 *worst = *AllTris.begin();
1742 delete worst->
tri();
1744 AllTris.erase(AllTris.begin());
1748 packed[i]->getParameter(0, newPoint[0]);
1749 packed[i]->getParameter(1, newPoint[1]);
1755 insertAPoint(gf, AllTris.begin(), newPoint, metric, DATA, AllTris,
1756 nullptr, oneNewTriangle, &oneNewTriangle);
1757 if(!success) oneNewTriangle =
nullptr;
1761 if(1.0 * AllTris.size() > 2.5 * DATA.
vSizes.size()) {
1762 auto itd = AllTris.begin();
1763 while(itd != AllTris.end()) {
1764 if((*itd)->isDeleted()) {
1766 AllTris.erase(itd++);
1777 double para0, para1;
1787 std::vector<MTri3 *> &t)
1790 for(std::size_t i = 0; i <
v.size(); i++) {
1801 t.push_back(
new MTri3(t0, 0.0));
1802 t.push_back(
new MTri3(t1, 0.0));
1809 std::size_t k = t.size() - 1;
1810 while(t[k]->isDeleted()) { k--; }
1811 MTri3 *start = t[k];
1813 if(start)
return start;
1814 for(
size_t i = 0; i < t.size(); i++) {
1822 for(
size_t i = 0; i < 3; i++) {
1823 for(
size_t j = 0; j < 4; j++) {
1835 std::vector<MTriangle *> &result,
bool removeBox,
1836 std::vector<MEdge> *edgesToRecover,
bool hilbertSort)
1838 std::vector<MTri3 *> t;
1839 t.reserve(
v.size() * 2);
1840 std::vector<edgeXface>
conn;
1841 std::vector<edgeXface> shell;
1842 std::vector<MTri3 *> cavity;
1848 for(
size_t i = 0; i <
v.size(); i++) {
1854 Msg::Error(
"Cannot insert a point in 2D Delaunay");
1862 std::vector<MTri3 *> extended_cavity;
1863 for(std::size_t count = 0; count < shell.size(); count++) {
1870 if(count < cavity.size()) {
1879 t3 =
new MTri3(tr, 0.0);
1882 extended_cavity.push_back(t3);
1883 if(otherSide) extended_cavity.push_back(otherSide);
1886 for(std::size_t k = 0; k < std::min(cavity.size(), shell.size()); k++) {
1887 cavity[k]->setDeleted(
false);
1888 for(std::size_t l = 0; l < 3; l++) { cavity[k]->setNeigh(l,
nullptr); }
1895 for(
size_t i = 0; i < t.size(); i++) {
1896 if(t[i]->isDeleted() || (removeBox &&
triOnBox(t[i]->tri(),
box)))
1899 result.push_back(t[i]->tri());
1905 for(
int i = 0; i < 4; i++)
delete box[i];
1908 for(
int i = 0; i < 4; i++)
v.push_back(
box[i]);
1916 if(!t2)
return false;
1924 if(std::abs(BEFORE - AFTER) / BEFORE > 1.e-8) {
1935 std::set<MTri3 *> cavity;
1938 for(
int i = 0; i < 3; i++) {
1942 std::vector<edgeXface>
conn;
1949 if(v1 == p1 || v2 == p1 || v1 == p2 || v2 == p2)
return false;
1959 for(std::size_t i = 0; i < t.size(); i++) {
1960 for(std::size_t j = 0; j < 3; j++) {
1961 MVertex *v1 = t[i]->tri()->getVertex((j + 2) % 3);
1962 MVertex *v2 = t[i]->tri()->getVertex(j);
1963 MVertex *v3 = t[i]->tri()->getVertex((j + 1) % 3);
1964 MVertex *o = t[i]->otherSide(j);
1970 if(
diffend(v1, v2, mv1, mv2)) {
1977 (v3 == mv1 || o == mv1 || v3 == mv2 || o == mv2)) {
1978 if(
swapedge(v1, v2, v3, o, t[i], j))
return true;
1995 std::set<MEdge, MEdgeLessThan> setOfMeshEdges;
1996 for(
size_t i = 0; i < t.size(); i++) {
1997 for(
int j = 0; j < 3; j++) {
1998 setOfMeshEdges.insert(t[i]->tri()->getEdge(j));
2002 std::vector<MEdge> edgesToRecover;
2003 for(std::size_t i = 0; i <
edges.size(); i++) {
2004 if(setOfMeshEdges.find(
edges[i]) == setOfMeshEdges.end())
2005 edgesToRecover.push_back(
edges[i]);
2008 Msg::Info(
"%d edges to recover among %d edges", edgesToRecover.size(),
2014 for(std::size_t i = 0; i < edgesToRecover.size(); i++) {
2015 MVertex *mstart = edgesToRecover[i].getVertex(0);
2016 MVertex *mend = edgesToRecover[i].getVertex(1);