30
32
#include <algorithm>
32
// computes the center of the circum circle in the tangent plane
33
// the metric given by a b d is supposed to be constant
34
void MTri3::Center_Circum_Aniso(double a, double b, double d, double &x, double &y, double &r) const
36
double sys[2][2], X[2];
37
const double LIMIT_ = 0.5 * sqrt(2.0);
39
/* This function controls the frontal algorithm */
40
static bool isActive ( MTri3 *t , double limit_, int &active){
41
if (t->isDeleted()) return false;
42
for (active=0;active<3;active++){
43
MTri3 *neigh = t->getNeigh(active);
44
if (!neigh || neigh->getRadius() < limit_)return true;
45
//if (!neigh || neigh->done)return true;
51
void circumCenterXY(double *p1, double *p2, double *p3, double *res)
55
const double x1 = p1[0];
56
const double x2 = p2[0];
57
const double x3 = p3[0];
58
const double y1 = p1[1];
59
const double y2 = p2[1];
60
const double y3 = p3[1];
62
d = 2. * (double)(y1 * (x2 - x3) + y2 * (x3 - x1) + y3 * (x1 - x2));
64
Msg(WARNING, "Colinear points in circum circle computation");
65
res[0] = res[1] = -99999.;
69
a1 = x1 * x1 + y1 * y1;
70
a2 = x2 * x2 + y2 * y2;
71
a3 = x3 * x3 + y3 * y3;
72
res[0] = (double)((a1 * (y3 - y2) + a2 * (y1 - y3) + a3 * (y2 - y1)) / d);
73
res[1] = (double)((a1 * (x2 - x3) + a2 * (x3 - x1) + a3 * (x1 - x2)) / d);
76
void circumCenterXYZ(double *p1, double *p2, double *p3, double *res, double *uv)
78
double v1[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
79
double v2[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
80
double vx[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
81
double vy[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
82
double vz[3]; prodve(vx, vy, vz); prodve(vz, vx, vy);
83
norme(vx); norme(vy); norme(vz);
84
double p1P[2] = {0.0, 0.0};
85
double p2P[2]; prosca(v1, vx, &p2P[0]); prosca(v1, vy, &p2P[1]);
86
double p3P[2]; prosca(v2, vx, &p3P[0]); prosca(v2, vy, &p3P[1]);
89
circumCenterXY(p1P, p2P, p3P,resP);
92
double mat[2][2] = {{p2P[0] - p1P[0], p3P[0] - p1P[0]},
93
{p2P[1] - p1P[1], p3P[1] - p1P[1]}};
94
double rhs[2] = {resP[0] - p1P[0], resP[1] - p1P[1]};
98
res[0] = p1[0] + resP[0] * vx[0] + resP[1] * vy[0];
99
res[1] = p1[1] + resP[0] * vx[1] + resP[1] * vy[1];
100
res[2] = p1[2] + resP[0] * vx[2] + resP[1] * vy[2];
103
bool circumCenterMetricInTriangle(MTriangle *base,
104
const double *metric,
105
const std::vector<double> &Us,
106
const std::vector<double> &Vs)
108
double R, x[2], uv[2];
109
circumCenterMetric(base, metric, Us, Vs, x, R);
110
return invMapUV(base, x, Us, Vs, uv, 1.e-8);
113
void circumCenterMetric(double *pa, double *pb, double *pc,
114
const double *metric,
115
double *x, double &Radius2)
117
// d = (u2-u1) M (u2-u1) = u2 M u2 + u1 M u1 - 2 u2 M u1
38
double x1, y1, x2, y2, x3, y3;
40
x1 = base->getVertex(0)->x();
41
y1 = base->getVertex(0)->y();
42
x2 = base->getVertex(1)->x();
43
y2 = base->getVertex(1)->y();
44
x3 = base->getVertex(2)->x();
45
y3 = base->getVertex(2)->y();
47
sys[0][0] = 2. * a * (x1 - x2) + 2. * b * (y1 - y2);
48
sys[0][1] = 2. * d * (y1 - y2) + 2. * b * (x1 - x2);
49
sys[1][0] = 2. * a * (x1 - x3) + 2. * b * (y1 - y3);
50
sys[1][1] = 2. * d * (y1 - y3) + 2. * b * (x1 - x3);
121
const double a = metric[0];
122
const double b = metric[1];
123
const double d = metric[2];
125
sys[0][0] = 2. * a * (pa[0] - pb[0]) + 2. * b * (pa[1] - pb[1]);
126
sys[0][1] = 2. * d * (pa[1] - pb[1]) + 2. * b * (pa[0] - pb[0]);
127
sys[1][0] = 2. * a * (pa[0] - pc[0]) + 2. * b * (pa[1] - pc[1]);
128
sys[1][1] = 2. * d * (pa[1] - pc[1]) + 2. * b * (pa[0] - pc[0]);
53
a * (x1 * x1 - x2 * x2) + d * (y1 * y1 - y2 * y2) + 2. * b * (x1 * y1 -
131
a * (pa[0] * pa[0] - pb[0] * pb[0]) +
132
d * (pa[1] * pa[1] - pb[1] * pb[1]) +
133
2. * b * (pa[0] * pa[1] - pb[0] * pb[1]);
56
a * (x1 * x1 - x3 * x3) + d * (y1 * y1 - y3 * y3) + 2. * b * (x1 * y1 -
63
r = sqrt((X[0] - x1) * (X[0] - x1) * a
64
+ (X[1] - y1) * (X[1] - y1) * d
65
+ 2. * (X[0] - x1) * (X[1] - y1) * b);
69
// find a common basis for 2 metrics in 2D
70
void simultaneousMetricReduction( const gmsh2dMetric &M1, const gmsh2dMetric &M2,
71
double & l1,double & l2, double V[2][2])
73
double a11=M1.a11,a21=M1.a21,a22=M1.a22;
74
double b11=M2.a11,b21=M2.a21,b22=M2.a22;
75
const double /*c11 = a11*a11,*/ c21= a21*a21;
76
const double /*d11 = b11*b11,*/ d21= b21*b21;
77
const double a=b11*b22 - d21;
78
const double b=-a11*b22-a22*b11+2*a21*b21;
79
const double c=-c21+a11*a22;
80
const double bb = b*b,ac= a*c;
81
const double delta = bb - 4 * ac;
82
if (bb + fabs(ac) < 1.0e-20 || (delta< 1.0E-4 * bb ) )
84
if (fabs(a) < 1.e-30 )
94
const double delta2 = sqrt(delta);
95
l1= (-b - delta2)/(2*a);
96
l2= (-b + delta2)/(2*a);
97
double v0 = a11-l1*b11, v1 = a21-l1*b21,v2 = a22 - l1*b22;
98
double s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2;
99
double vp1x,vp1y,vp2x,vp2y;
101
s0=sqrt(s0),vp1x=v1/s0,vp1y=-v0/s0;
103
s1=sqrt(s1),vp1x=v2/s1,vp1y=-v1/s1;
105
v0 = a11-l2*b11, v1 = a21-l2*b21,v2 = a22 - l2*b22;
106
s0 = v0*v0 + v1*v1, s1 = v1*v1 +v2*v2;
108
s0=sqrt(s0),vp2x=v1/s0,vp2y=-v0/s0;
110
s1=sqrt(s1),vp2x=v2/s1,vp2y=-v1/s1;
118
gmsh2dMetric metricIntersection(const gmsh2dMetric &Ma,const gmsh2dMetric &Mb)
120
double M[2][2],M1[2][2];
122
simultaneousMetricReduction(Ma,Mb,l1,l2,M);
124
const double M1ev1 = Ma.eval(M[0][0],M[0][1]);
125
const double M1ev2 = Ma.eval(M[0][0],M[0][1]);
126
const double M2ev1 = Mb.eval(M[1][0],M[1][1]);
127
const double M2ev2 = Mb.eval(M[1][0],M[1][1]);
129
const double D0 = std::max( M1ev1,M1ev2);
130
const double D1 = std::max( M2ev1,M2ev2);
132
return gmsh2dMetric(M1[0][0] * D0 * M1[0][0] + M1[0][1] * D1 * M1[0][1] ,
133
0.5 * ( M1[0][0] * D0 * M1[1][0] + M1[0][1] * D1 * M1[1][1] +
134
M1[1][0] * D0 * M1[0][0] + M1[1][1] * D1 * M1[0][1] ),
135
M1[1][0] * D0 * M1[1][0] + M1[1][1] * D1 * M1[1][1] );
138
gmsh2dMetric metricInterpolationTriangle(const gmsh2dMetric &M1,
139
const gmsh2dMetric &M2,
140
const gmsh2dMetric &M3,
144
double m1[2][2] = {{M1.a11,0.5*M1.a21},{0.5*M1.a21,M1.a22}};
145
double m2[2][2] = {{M2.a11,0.5*M2.a21},{0.5*M2.a21,M2.a22}};
146
double m3[2][2] = {{M3.a11,0.5*M3.a21},{0.5*M3.a21,M3.a22}};
147
double invm1 [2][2]; inv2x2 ( m1, invm1 );
148
double invm2 [2][2]; inv2x2 ( m2, invm2 );
149
double invm3 [2][2]; inv2x2 ( m3, invm3 );
151
for (int i=0;i<2;i++)
152
for (int j=0;j<2;j++)
153
invm[i][j] = (1.-u-v) * invm1[i][j] + u * invm2[i][j] + v * invm3[i][j];
154
double m [2][2]; inv2x2 ( invm, m );
155
return gmsh2dMetric ( m[0][0] , m[0][1] , m[1][1] );
158
gmsh2dMetric :: gmsh2dMetric ( double lc )
159
: a11 ( 1./(lc*lc) ) ,a21 ( 0.0 ) ,a22 ( 1./(lc*lc) )
164
MTri3::MTri3 ( MTriangle * t, std::vector<gmsh2dMetric> & sizes) : deleted(false), base (t)
135
a * (pa[0] * pa[0] - pc[0] * pc[0]) +
136
d * (pa[1] * pa[1] - pc[1] * pc[1]) +
137
2. * b * (pa[0] * pa[1] - pc[0] * pc[1]);
142
(x[0] - pa[0]) * (x[0] - pa[0]) * a +
143
(x[1] - pa[1]) * (x[1] - pa[1]) * d +
144
2. * (x[0] - pa[0]) * (x[1] - pa[1]) * b;
147
void circumCenterMetric(MTriangle *base,
148
const double *metric,
149
const std::vector<double> &Us,
150
const std::vector<double> &Vs,
151
double *x, double &Radius2)
153
// d = (u2-u1) M (u2-u1) = u2 M u2 + u1 M u1 - 2 u2 M u1
154
double pa[2] = {Us[base->getVertex(0)->getNum()],
155
Vs[base->getVertex(0)->getNum()]};
156
double pb[2] = {Us[base->getVertex(1)->getNum()],
157
Vs[base->getVertex(1)->getNum()]};
158
double pc[2] = {Us[base->getVertex(2)->getNum()],
159
Vs[base->getVertex(2)->getNum()]};
160
circumCenterMetric(pa, pb, pc, metric, x, Radius2);
163
void buildMetric(GFace *gf, double *uv, double *metric)
165
Pair<SVector3, SVector3> der = gf->firstDer(SPoint2(uv[0], uv[1]));
166
metric[0] = dot(der.first(), der.first());
167
metric[1] = dot(der.second(), der.first());
168
metric[2] = dot(der.second(), der.second());
171
int inCircumCircleAniso(GFace *gf, double *p1, double *p2, double *p3,
172
double *uv, double *metric)
174
double x[2], Radius2;
175
circumCenterMetric(p1, p2, p3, metric, x, Radius2);
176
const double a = metric[0];
177
const double b = metric[1];
178
const double d = metric[2];
179
double d2 = (x[0] - uv[0]) * (x[0] - uv[0]) * a
180
+ (x[1] - uv[1]) * (x[1] - uv[1]) * d
181
+ 2. * (x[0] - uv[0]) * (x[1] - uv[1]) * b;
185
int inCircumCircleAniso(GFace *gf, MTriangle *base,
186
const double *uv, const double *metricb,
187
const std::vector<double> &Us,
188
const std::vector<double> &Vs)
190
double x[2], Radius2, metric[3];
191
double pa[2] = {(Us[base->getVertex(0)->getNum()] + Us[base->getVertex(1)->getNum()] +
192
Us[base->getVertex(2)->getNum()]) / 3.,
193
(Vs[base->getVertex(0)->getNum()] + Vs[base->getVertex(1)->getNum()] +
194
Vs[base->getVertex(2)->getNum()]) / 3.};
196
buildMetric(gf, pa, metric);
197
circumCenterMetric(base, metric, Us, Vs, x, Radius2);
199
const double a = metric[0];
200
const double b = metric[1];
201
const double d = metric[2];
203
double d2 = (x[0] - uv[0]) * (x[0] - uv[0]) * a
204
+ (x[1] - uv[1]) * (x[1] - uv[1]) * d
205
+ 2. * (x[0] - uv[0]) * (x[1] - uv[1]) * b;
210
MTri3::MTri3(MTriangle *t, double lc) : deleted(false), base(t)//,done(0)
166
212
neigh[0] = neigh[1] = neigh[2] = 0;
167
// compute the metric at the centroid
168
metric = metricInterpolationTriangle(sizes [base->getVertex(0)->getNum()] ,
169
sizes [base->getVertex(1)->getNum()] ,
170
sizes [base->getVertex(2)->getNum()] ,
172
Center_Circum_Aniso(metric.a11,metric.a21,metric.a22, xc, yc, circum_radius);
173
// printf("metric %g %g %g circum_radius = %g\n",metric.a11,metric.a21,metric.a22,circum_radius);
176
int inCircumCircle ( MTri3 *t , const double *p , const gmsh2dMetric &metric )
179
double eps, d1, d2, x[2];
180
t->Center_Circum_Aniso(metric.a11,metric.a21,metric.a22,xc, yc, d1);
185
d2 = sqrt(fabs(metric.eval(x[0],x[1])));
187
eps = fabs(d1 - d2) / (d1 + d2);
197
int MTri3::inCircumCircle ( const double *p ) const
200
double pa[2] = {base->getVertex(0)->x(),base->getVertex(0)->y()};
201
double pb[2] = {base->getVertex(1)->x(),base->getVertex(1)->y()};
202
double pc[2] = {base->getVertex(2)->x(),base->getVertex(2)->y()};
203
double result = gmsh::incircle(pa, pb, pc, (double*)p) * gmsh::orient2d(pa, pb, pc);
204
return (result > 0) ? 1 : 0;
207
double eps, d1, d2, x[2];
213
d2 = sqrt(fabs(metric.eval(x[0],x[1])));
215
eps = fabs(d1 - d2) / (d1 + d2);
229
edgeXface ( MTri3 *_t, int iFac)
232
v[0] = t1->tri()->getVertex ( iFac == 0 ? 2 : iFac-1 );
233
v[1] = t1->tri()->getVertex ( iFac );
234
std::sort ( v, v+2 );
236
inline bool operator < ( const edgeXface & other) const
238
if (v[0] < other.v[0])return true;
239
if (v[0] > other.v[0])return false;
240
if (v[1] < other.v[1])return true;
214
// compute the circumradius of the triangle
215
double pa[3] = {base->getVertex(0)->x(), base->getVertex(0)->y(), base->getVertex(0)->z()};
216
double pb[3] = {base->getVertex(1)->x(), base->getVertex(1)->y(), base->getVertex(1)->z()};
217
double pc[3] = {base->getVertex(2)->x(), base->getVertex(2)->y(), base->getVertex(2)->z()};
219
circumCenterXYZ(pa, pb, pc, center);
220
const double dx = base->getVertex(0)->x() - center[0];
221
const double dy = base->getVertex(0)->y() - center[1];
222
const double dz = base->getVertex(0)->z() - center[2];
224
circum_radius = sqrt(dx * dx + dy * dy + dz * dz);
228
int MTri3::inCircumCircle(const double *p) const
230
double pa[3] = {base->getVertex(0)->x(), base->getVertex(0)->y(), base->getVertex(0)->z()};
231
double pb[3] = {base->getVertex(1)->x(), base->getVertex(1)->y(), base->getVertex(1)->z()};
232
double pc[3] = {base->getVertex(2)->x(), base->getVertex(2)->y(), base->getVertex(2)->z()};
234
fourthPoint(pa, pb, pc, fourth);
236
double result = gmsh::insphere(pa, pb, pc, fourth, (double*)p) *
237
gmsh::orient3d(pa, pb, pc,fourth);
238
return (result > 0) ? 1 : 0;
241
int inCircumCircle(MTriangle *base,
242
const double *p, const double *param ,
243
std::vector<double> &Us, std::vector<double> &Vs)
245
double pa[2] = {Us[base->getVertex(0)->getNum()],
246
Vs[base->getVertex(0)->getNum()]};
247
double pb[2] = {Us[base->getVertex(1)->getNum()],
248
Vs[base->getVertex(1)->getNum()]};
249
double pc[2] = {Us[base->getVertex(2)->getNum()],
250
Vs[base->getVertex(2)->getNum()]};
252
double result = gmsh::incircle(pa, pb, pc, (double*)param) * gmsh::orient2d(pa, pb, pc);
253
return (result > 0) ? 1 : 0;
245
256
template <class ITER>
246
void connectTris ( ITER beg, ITER end)
257
void connectTris(ITER beg, ITER end)
248
259
std::set<edgeXface> conn;
252
if (!(*beg)->isDeleted())
254
for (int i=0;i<3;i++)
256
edgeXface fxt ( *beg , i );
257
std::set<edgeXface>::iterator found = conn.find (fxt);
258
if (found == conn.end())
260
else if (found->t1 != *beg)
262
found->t1->setNeigh(found->i1,*beg);
263
(*beg)->setNeigh ( i, found->t1);
261
if (!(*beg)->isDeleted()){
262
for (int i = 0; i < 3; i++){
263
edgeXface fxt(*beg, i);
264
std::set<edgeXface>::iterator found = conn.find(fxt);
265
if (found == conn.end())
267
else if (found->t1 != *beg){
268
found->t1->setNeigh(found->i1, *beg);
269
(*beg)->setNeigh(i, found->t1);
273
void recurFindCavity (const gmsh2dMetric &metric,
274
std::list<edgeXface> & shell,
275
std::list<MTri3*> & cavity,
280
// the cavity that has to be removed
281
// because it violates delaunay criterion
284
for (int i=0;i<3;i++)
286
MTri3 *neigh = t->getNeigh(i) ;
288
shell.push_back ( edgeXface ( t, i ) );
289
else if (!neigh->isDeleted())
291
int circ = inCircumCircle ( neigh, v, metric );
293
recurFindCavity ( metric,shell, cavity,v , neigh);
295
shell.push_back ( edgeXface ( t, i ) );
300
bool insertVertex (MVertex *v ,
302
std::set<MTri3*,compareTri3Ptr> &allTets,
303
std::vector<gmsh2dMetric> & vSizes,
304
const gmsh2dMetric &metric)
306
std::list<edgeXface> shell;
307
std::list<MTri3*> cavity;
308
std::list<MTri3*> new_cavity;
310
double p[2] = {v->x(),v->y()};
312
recurFindCavity ( metric,shell, cavity, p , t);
277
void connectTriangles(std::list<MTri3*> &l)
279
connectTris(l.begin(), l.end());
282
void connectTriangles(std::vector<MTri3*> &l)
284
connectTris(l.begin(), l.end());
287
void connectTriangles(std::set<MTri3*, compareTri3Ptr> &l)
289
connectTris(l.begin(), l.end());
292
void recurFindCavity(std::list<edgeXface> &shell, std::list<MTri3*> &cavity,
293
double *v, double *param, MTri3 *t,
294
std::vector<double> &Us, std::vector<double> &Vs)
297
// the cavity that has to be removed
298
// because it violates delaunay criterion
301
for (int i = 0; i < 3; i++){
302
MTri3 *neigh = t->getNeigh(i) ;
304
shell.push_back(edgeXface(t, i));
305
else if (!neigh->isDeleted()){
306
int circ = inCircumCircle(neigh->tri(), v , param, Us, Vs);
308
recurFindCavity(shell, cavity, v, param, neigh, Us, Vs);
310
shell.push_back(edgeXface(t, i));
315
void recurFindCavityAniso (GFace *gf,
316
std::list<edgeXface> &shell, std::list<MTri3*> &cavity,
317
double *metric, double *param, MTri3 *t,
318
std::vector<double> &Us, std::vector<double> &Vs)
321
// the cavity that has to be removed
322
// because it violates delaunay criterion
325
for (int i = 0; i < 3; i++){
326
MTri3 *neigh = t->getNeigh(i) ;
328
shell.push_back(edgeXface(t, i));
329
else if (!neigh->isDeleted()){
330
int circ = inCircumCircleAniso(gf, neigh->tri(), param, metric, Us, Vs);
332
recurFindCavityAniso(gf, shell, cavity,metric, param, neigh, Us, Vs);
334
shell.push_back(edgeXface(t, i));
339
bool circUV(MTriangle *t, std::vector<double> & Us, std::vector<double> &Vs,
340
double *res, GFace *gf)
342
double u1 [3] = {Us[t->getVertex(0)->getNum()], Vs[t->getVertex(0)->getNum()], 0};
343
double u2 [3] = {Us[t->getVertex(1)->getNum()], Vs[t->getVertex(1)->getNum()], 0};
344
double u3 [3] = {Us[t->getVertex(2)->getNum()], Vs[t->getVertex(2)->getNum()], 0};
345
circumCenterXY(u1, u2, u3, res);
347
double p1 [3] = {t->getVertex(0)->x(), t->getVertex(0)->y(), t->getVertex(0)->z()};
348
double p2 [3] = {t->getVertex(1)->x(), t->getVertex(1)->y(), t->getVertex(1)->z()};
349
double p3 [3] = {t->getVertex(2)->x(), t->getVertex(2)->y(), t->getVertex(2)->z()};
350
double resxy[3], uv[2];
351
circumCenterXYZ(p1, p2, p3, resxy,uv);
355
bool invMapUV(MTriangle *t, double *p,
356
const std::vector<double> &Us, const std::vector<double> &Vs,
357
double *uv, double tol)
362
double u0 = Us[t->getVertex(0)->getNum()];
363
double v0 = Vs[t->getVertex(0)->getNum()];
364
double u1 = Us[t->getVertex(1)->getNum()];
365
double v1 = Vs[t->getVertex(1)->getNum()];
366
double u2 = Us[t->getVertex(2)->getNum()];
367
double v2 = Vs[t->getVertex(2)->getNum()];
382
1. - uv[0] - uv[1] > -tol) {
388
double getSurfUV(MTriangle *t, std::vector<double> &Us, std::vector<double> &Vs)
390
double u1 = Us[t->getVertex(0)->getNum()];
391
double v1 = Vs[t->getVertex(0)->getNum()];
392
double u2 = Us[t->getVertex(1)->getNum()];
393
double v2 = Vs[t->getVertex(1)->getNum()];
394
double u3 = Us[t->getVertex(2)->getNum()];
395
double v3 = Vs[t->getVertex(2)->getNum()];
396
const double vv1 [2] = {u2 - u1, v2 - v1};
397
const double vv2 [2] = {u3 - u1, v3 - v1};
398
double s = vv1[0] * vv2[1] - vv1[1] * vv2[0];
402
bool insertVertex(GFace *gf, MVertex *v, double *param , MTri3 *t,
403
std::set<MTri3*, compareTri3Ptr> &allTets,
404
std::set<MTri3*, compareTri3Ptr> *activeTets,
405
std::vector<double> &vSizes, std::vector<double> &vSizesBGM,
406
std::vector<double> &Us, std::vector<double> &Vs,
409
std::list<edgeXface> shell;
410
std::list<MTri3*> cavity;
411
std::list<MTri3*> new_cavity;
414
double p[3] = {v->x(), v->y(), v->z()};
415
recurFindCavity(shell, cavity, p, param, t, Us, Vs);
418
recurFindCavityAniso(gf, shell, cavity, metric, param, t, Us, Vs);
314
421
// check that volume is conserved
315
422
double newVolume = 0;
316
423
double oldVolume = 0;
318
425
std::list<MTri3*>::iterator ittet = cavity.begin();
319
426
std::list<MTri3*>::iterator ittete = cavity.end();
320
while ( ittet != ittete )
322
oldVolume += fabs((*ittet)->getSurfaceXY());
328
// sprintf(name,"test%d.pos",III);
329
// FILE *ff = fopen (name,"w");
330
// fprintf(ff,"View\"test\"{\n");
333
MTri3** newTris = new MTri3*[shell.size()];;
427
while(ittet != ittete){
428
oldVolume += fabs(getSurfUV((*ittet)->tri(),Us,Vs));
432
MTri3 **newTris = new MTri3*[shell.size()];
335
std::list<edgeXface>::iterator it = shell.begin();
337
while (it != shell.end())
339
MTriangle *t = new MTriangle ( it->v[0],
342
MTri3 *t4 = new MTri3 ( t , vSizes);
343
// fprintf(ff,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {0,0,0};\n",
354
// all new triangles are pushed front in order to
355
// ba able to destroy them if the cavity is not
356
// star shaped around the new vertex.
357
new_cavity.push_back (t4);
358
MTri3 *otherSide = it->t1->getNeigh(it->i1);
361
new_cavity.push_back (otherSide);
362
// if (!it->t1->isDeleted())throw;
363
double ss = fabs(t4->getSurfaceXY());
364
if (ss < 1.e-12)ss = 1256172121;
368
// fprintf(ff,"};\n");
370
// printf("%d %d newVolume %g oldVolume %g\n",cavity.size(),new_cavity.size(),newVolume,oldVolume);
374
if (fabs(oldVolume - newVolume) < 1.e-10 * oldVolume )
376
connectTris ( new_cavity.begin(),new_cavity.end() );
377
allTets.insert(newTris,newTris+shell.size());
434
std::list<edgeXface>::iterator it = shell.begin();
437
bool onePointIsTooClose = false;
438
while (it != shell.end()){
439
MTriangle *t = new MTriangle(it->v[0], it->v[1], v);
440
double lc = 0.3333333333 * (vSizes[t->getVertex(0)->getNum()] +
441
vSizes[t->getVertex(1)->getNum()] +
442
vSizes[t->getVertex(2)->getNum()]);
443
double lcBGM = 0.3333333333 * (vSizesBGM[t->getVertex(0)->getNum()] +
444
vSizesBGM[t->getVertex(1)->getNum()] +
445
vSizesBGM[t->getVertex(2)->getNum()]);
446
double LL = Extend1dMeshIn2dSurfaces() ? std::min(lc, lcBGM) : lcBGM;
447
MTri3 *t4 = new MTri3(t, LL);
449
double d1 = sqrt((it->v[0]->x()-v->x())*(it->v[0]->x()-v->x())+
450
(it->v[0]->y()-v->y())*(it->v[0]->y()-v->y())+
451
(it->v[0]->z()-v->z())*(it->v[0]->z()-v->z()));
452
double d2 = sqrt((it->v[1]->x()-v->x())*(it->v[1]->x()-v->x())+
453
(it->v[1]->y()-v->y())*(it->v[1]->y()-v->y())+
454
(it->v[1]->z()-v->z())*(it->v[1]->z()-v->z()));
455
if (d1 < LL*.25 ||d2 < LL*.25)onePointIsTooClose = true;
457
// if (t4->getRadius () < LIMIT_ / 2)onePointIsTooClose = true;
460
// all new triangles are pushed front in order to
461
// ba able to destroy them if the cavity is not
462
// star shaped around the new vertex.
463
new_cavity.push_back (t4);
464
MTri3 *otherSide = it->t1->getNeigh(it->i1);
466
new_cavity.push_back (otherSide);
467
double ss = fabs(getSurfUV(t4->tri(),Us,Vs));
468
if (ss < 1.e-25)ss = 1256172121;
472
if (fabs(oldVolume - newVolume) < 1.e-12 * oldVolume && shell.size() > 3 && !onePointIsTooClose){
473
connectTris(new_cavity.begin(),new_cavity.end());
474
allTets.insert(newTris,newTris+shell.size());
476
for (std::list<MTri3*>::iterator i = new_cavity.begin();i!=new_cavity.end();++i){
478
if(isActive(*i,LIMIT_,active_edge) && (*i)->getRadius() > LIMIT_){
479
if ((*activeTets).find(*i) == (*activeTets).end())
480
(*activeTets).insert(*i);
381
487
// The cavity is NOT star shaped
384
for (unsigned int i=0;i<shell.size();i++)delete newTris[i];
386
ittet = cavity.begin();
387
ittete = cavity.end();
388
while ( ittet != ittete )
390
(*ittet)->setDeleted(false);
397
static gmsh2dMetric evalMetricTensor ( GFace *gf , MVertex *mv , double lc )
399
Pair<SVector3,SVector3> der = gf->firstDer(SPoint2(mv->x(),mv->y())) ;
400
const double oneoverlc2 = 1./(lc*lc);
401
const double a11 = dot(der.first() ,der.first() ) * oneoverlc2;
402
const double a21 = dot(der.second(),der.first() ) * oneoverlc2;
403
const double a22 = dot(der.second(),der.second()) * oneoverlc2;
405
// printf("metric : %g %g %g - %g %g\n",a11,a21,a22,oneoverlc2,lc);
407
return gmsh2dMetric ( a11, a21 , a22);
410
static void setLcs ( MTriangle *t, std::map<MVertex*,double> &vSizes)
412
for (int i=0;i<3;i++)
414
for (int j=i+1;j<3;j++)
416
MVertex *vi = t->getVertex(i);
417
MVertex *vj = t->getVertex(j);
418
double dx = vi->x()-vj->x();
419
double dy = vi->y()-vj->y();
420
double dz = vi->z()-vj->z();
421
double l = sqrt(dx*dx+dy*dy+dz*dz);
422
std::map<MVertex*,double>::iterator iti = vSizes.find(vi);
423
std::map<MVertex*,double>::iterator itj = vSizes.find(vj);
424
if (iti==vSizes.end() || iti->second > l)vSizes[vi] = l;
425
if (itj==vSizes.end() || itj->second > l)vSizes[vj] = l;
430
void insertVerticesInFace (GFace *gf, BDS_Mesh *bds)
489
for (unsigned int i = 0; i < shell.size(); i++) delete newTris[i];
491
ittet = cavity.begin();
492
ittete = cavity.end();
493
while(ittet != ittete){
494
(*ittet)->setDeleted(false);
501
void _printTris(char *name, std::set<MTri3*, compareTri3Ptr> &AllTris,
502
std::vector<double> &Us, std::vector<double> &Vs, bool param=true)
504
FILE *ff = fopen (name,"w");
505
fprintf(ff,"View\"test\"{\n");
506
std::set<MTri3*,compareTri3Ptr>::iterator it = AllTris.begin();
507
while (it != AllTris.end() ){
509
if (!worst->isDeleted()){
511
fprintf(ff,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {0,0,0};\n",
512
Us [(worst)->tri()->getVertex(0)->getNum()],
513
Vs [(worst)->tri()->getVertex(0)->getNum()],
515
Us [(worst)->tri()->getVertex(1)->getNum()],
516
Vs [(worst)->tri()->getVertex(1)->getNum()],
518
Us [(worst)->tri()->getVertex(2)->getNum()],
519
Vs [(worst)->tri()->getVertex(2)->getNum()],
522
fprintf(ff,"ST(%g,%g,%g,%g,%g,%g,%g,%g,%g) {%g,%g,%g};\n",
523
(worst)->tri()->getVertex(0)->x(),
524
(worst)->tri()->getVertex(0)->y(),
525
(worst)->tri()->getVertex(0)->z(),
526
(worst)->tri()->getVertex(1)->x(),
527
(worst)->tri()->getVertex(1)->y(),
528
(worst)->tri()->getVertex(1)->z(),
529
(worst)->tri()->getVertex(2)->x(),
530
(worst)->tri()->getVertex(2)->y(),
531
(worst)->tri()->getVertex(2)->z(),
532
(worst)->getRadius(),
533
(worst)->getRadius(),
544
static void insertAPoint(GFace *gf,
545
std::set<MTri3*,compareTri3Ptr>::iterator it,
548
std::vector<double> &Us,
549
std::vector<double> &Vs,
550
std::vector<double> &vSizes,
551
std::vector<double> &vSizesBGM,
552
std::set<MTri3*,compareTri3Ptr> &AllTris,
553
std::set<MTri3*,compareTri3Ptr> * ActiveTris = 0,
556
it = AllTris.find(worst);
557
if (worst != *it)throw;
563
MTriangle *base = worst->tri();
564
bool inside = invMapUV(worst->tri(), center, Us, Vs, uv, 1.e-8);
565
if (inside)ptin = worst;
566
if (!inside && worst->getNeigh(0)){
567
inside |= invMapUV(worst->getNeigh(0)->tri(), center, Us, Vs, uv, 1.e-8);
568
if (inside)ptin = worst->getNeigh(0);
570
if (!inside && worst->getNeigh(1)){
571
inside |= invMapUV(worst->getNeigh(1)->tri(), center, Us, Vs, uv, 1.e-8);
572
if (inside)ptin = worst->getNeigh(1);
574
if (!inside && worst->getNeigh(2)){
575
inside |= invMapUV(worst->getNeigh(2)->tri(), center, Us, Vs, uv, 1.e-8);
576
if (inside)ptin = worst->getNeigh(2);
579
// we use here local coordinates as real coordinates
580
// x,y and z will be computed hereafter
581
// Msg(INFO,"Point is inside");
582
GPoint p = gf->point(center[0], center[1]);
583
// printf("the new point is %g %g\n",p.x(),p.y());
584
MVertex *v = new MFaceVertex(p.x(), p.y(), p.z(), gf, center[0], center[1]);
585
v->setNum(Us.size());
586
double lc1 = ((1. - uv[0] - uv[1]) * vSizes[ptin->tri()->getVertex(0)->getNum()] +
587
uv[0] * vSizes [ptin->tri()->getVertex(1)->getNum()] +
588
uv[1] * vSizes [ptin->tri()->getVertex(2)->getNum()]);
589
// double eigMetricSurface = gf->getMetricEigenvalue(SPoint2(center[0],center[1]));
590
double lc = BGM_MeshSize(gf,center[0],center[1],p.x(),p.y(),p.z());
591
vSizesBGM.push_back(lc);
592
vSizes.push_back(lc1);
593
Us.push_back(center[0]);
594
Vs.push_back(center[1]);
596
if (!insertVertex(gf, v, center, worst, AllTris,ActiveTris, vSizes, vSizesBGM,
598
Msg(DEBUG2,"2D Delaunay : a cavity is not star shaped");
600
worst->forceRadius(-1);
601
AllTris.insert(worst);
605
gf->mesh_vertices.push_back(v);
608
Msg(DEBUG2,"Point %g %g is outside (%g %g , %g %g , %g %g) (metric %g %g %g)",
609
center[0], center[1],
610
Us[base->getVertex(0)->getNum()],
611
Vs[base->getVertex(0)->getNum()],
612
Us[base->getVertex(1)->getNum()],
613
Vs[base->getVertex(1)->getNum()],
614
Us[base->getVertex(2)->getNum()],
615
Vs[base->getVertex(2)->getNum()],
616
metric[0], metric[1], metric[2]);
618
worst->forceRadius(0);
619
AllTris.insert(worst);
623
void gmshBowyerWatson(GFace *gf)
625
if (CTX.mesh.algo2d == ALGO_2D_FRONTAL){
626
gmshBowyerWatsonFrontal(gf);
433
629
std::set<MTri3*,compareTri3Ptr> AllTris;
434
std::map<MVertex*,double> vSizesMap;
435
std::map<const BDS_Point*,MVertex*> recoverMap;
436
std::vector<gmsh2dMetric> vMetrics;
437
std::vector<double> vSizes;
440
// compute edge sizes on the contour and propagate thos sizes inside the surface
441
for (unsigned int i=0;i<gf->triangles.size();i++)setLcs ( gf->triangles[i] , vSizesMap);
443
// set vertex positions to local coordinates of the face
444
// compute metric tensors of the surface
446
for (std::map<MVertex*,double>::iterator it = vSizesMap.begin();it!=vSizesMap.end();++it)
449
p = bds->find_point(it->first->getNum());
450
it->first->x() = p->u;
451
it->first->y() = p->v;
453
it->first->setNum(NUM++);
454
vSizes.push_back(it->second);
455
recoverMap[p]= (it->first);
456
vMetrics.push_back(evalMetricTensor ( gf , it->first, it->second));
459
for (unsigned int i=0;i<gf->triangles.size();i++)
460
AllTris.insert ( new MTri3 ( gf->triangles[i] ,vMetrics ) );
462
gf->triangles.clear();
463
connectTris ( AllTris.begin(), AllTris.end() );
465
Msg(DEBUG,"All %d tris were connected",AllTris.size());
467
// here the classification should be done
630
std::vector<double> vSizes, vSizesBGM, Us, Vs;
632
buidMeshGenerationDataStructures(gf, AllTris, vSizes, vSizesBGM, Us, Vs);
634
// _printTris ("before.pos", AllTris, Us,Vs);
635
int nbSwaps = edgeSwapPass(gf, AllTris, SWCR_DEL, Us, Vs, vSizes, vSizesBGM);
636
// _printTris ("after2.pos", AllTris, Us,Vs);
637
Msg(DEBUG2,"Delaunization of the initial mesh done (%d swaps)", nbSwaps);
473
MTri3 *worst = *AllTris.begin();
475
if (worst->isDeleted())
479
AllTris.erase(AllTris.begin());
480
// Msg(INFO,"Worst tet is deleted");
485
Msg(DEBUG,"%7d points created -- Worst tri radius is %8.3f",vSizes.size(),worst->getRadius());
486
if (worst->getRadius() < 0.5 * sqrt(2.0)) break;
487
double center[2],uv[2];
488
worst->getCenter(center);
489
// worst->tri()->circumcenterXY(center);
490
bool inside = worst->tri()->invertmappingXY(center,uv);
493
// we use here local coordinates as real coordinates
494
// x,y and z will be computed hereafter
495
// Msg(INFO,"Point is inside");
496
MVertex *v = new MFaceVertex (center[0],center[1],0.0,gf,center[0],center[1]);
498
double lc1 = (1.-uv[0]-uv[1]) * vSizes [worst->tri()->getVertex(0)->getNum()] +
499
uv[0] * vSizes [worst->tri()->getVertex(1)->getNum()] +
500
uv[1] * vSizes [worst->tri()->getVertex(2)->getNum()] ;
501
GPoint p = gf->point (center[0],center[1]);
502
double lc = std::min(lc1,BGM_MeshSize(gf,center[0],center[1],p.x(),p.y(),p.z()));
503
vSizes.push_back(lc);
504
gmsh2dMetric metr = evalMetricTensor ( gf , v, lc);
505
vMetrics.push_back(metr);
507
// compute mesh spacing there
508
if (!insertVertex ( v , worst, AllTris,vMetrics,metr))
510
AllTris.erase(AllTris.begin());
511
worst->forceRadius(0);
512
AllTris.insert(worst);
517
gf->mesh_vertices.push_back(v);
522
// Msg(INFO,"Point is outside");
523
AllTris.erase(AllTris.begin());
524
worst->forceRadius(0);
525
AllTris.insert(worst);
530
// restore real coordinates of vertices
532
std::map<const BDS_Point*,MVertex*>::const_iterator itx = recoverMap.begin();
533
while (itx != recoverMap.end())
535
MVertex *v = (itx->second);
536
const BDS_Point *p = (itx->first);
542
for (unsigned int i=0;i<gf->mesh_vertices.size();i++)
544
double u = gf->mesh_vertices[i]->x();
545
double v = gf->mesh_vertices[i]->y();
546
GPoint p = gf->point(u,v);
547
gf->mesh_vertices[i]->x() = p.x();
548
gf->mesh_vertices[i]->y() = p.y();
549
gf->mesh_vertices[i]->z() = p.z();
553
// fill new gmsh structures with triangles
556
if (AllTris.begin() == AllTris.end() ) break;
557
MTri3 *worst = *AllTris.begin();
558
if (worst->isDeleted())
564
gf->triangles.push_back(worst->tri());
641
MTri3 *worst = *AllTris.begin();
642
if (worst->isDeleted()){
567
AllTris.erase(AllTris.begin());
645
AllTris.erase(AllTris.begin());
648
if(ITER++ % 5000 == 0)
649
Msg(DEBUG1,"%7d points created -- Worst tri radius is %8.3f",
650
vSizes.size(), worst->getRadius());
651
double center[2],metric[3],r2;
652
if (worst->getRadius() < 0.5 * sqrt(2.0)) break;
653
circUV(worst->tri(), Us, Vs, center, gf);
654
MTriangle *base = worst->tri();
655
double pa[2] = {(Us[base->getVertex(0)->getNum()] +
656
Us[base->getVertex(1)->getNum()] +
657
Us[base->getVertex(2)->getNum()]) / 3.,
658
(Vs[base->getVertex(0)->getNum()] +
659
Vs[base->getVertex(1)->getNum()] +
660
Vs[base->getVertex(2)->getNum()]) / 3.};
661
buildMetric(gf, pa, metric);
662
circumCenterMetric(worst->tri(), metric, Us, Vs, center, r2);
663
insertAPoint(gf,AllTris.begin(),center,metric,Us,Vs,vSizes,vSizesBGM,AllTris);
666
transferDataStructure(gf, AllTris);
670
Let's try a frontal delaunay approach now that the delaunay mesher is stable
672
We use the approach of Rebay (JCP 1993) that we extend to anisotropic metrics
674
The point isertion is done on the Voronoi Edges
678
static double length_metric ( const double p[2], const double q[2], const double metric[3])
680
return sqrt ( (p[0]-q[0]) * metric [0] * (p[0]-q[0]) +
681
2*(p[0]-q[0]) * metric [1] * (p[1]-q[1]) +
682
(p[1]-q[1]) * metric [2] * (p[1]-q[1]) );
700
(3 r/2)^2 = lc^2 - lc^2/4
704
r^2 /4 + lc^2/4 = r^2
710
void gmshBowyerWatsonFrontal(GFace *gf){
711
std::set<MTri3*,compareTri3Ptr> AllTris;
712
std::set<MTri3*,compareTri3Ptr> ActiveTris;
713
std::vector<double> vSizes, vSizesBGM, Us, Vs;
714
buidMeshGenerationDataStructures(gf, AllTris, vSizes, vSizesBGM, Us, Vs);
716
// delaunise the initial mesh
717
int nbSwaps = edgeSwapPass(gf, AllTris, SWCR_DEL, Us, Vs, vSizes, vSizesBGM);
718
Msg(DEBUG2,"Delaunization of the initial mesh done (%d swaps)", nbSwaps);
720
int ITER = 0, active_edge;
721
// compute active triangle
722
std::set<MTri3*,compareTri3Ptr>::iterator it = AllTris.begin();
723
for ( ; it!=AllTris.end();++it){
724
if(isActive(*it,LIMIT_,active_edge))
725
ActiveTris.insert(*it);
726
else if ((*it)->getRadius() < LIMIT_)break;
731
if (!ActiveTris.size())break;
732
MTri3 *worst = (*ActiveTris.begin());
733
ActiveTris.erase(ActiveTris.begin());
734
// printf("active_tris.size = %d\n",ActiveTris.size());
736
if (!worst->isDeleted() && isActive(worst,LIMIT_,active_edge) && worst->getRadius() > LIMIT_){
737
if(ITER++ % 5000 == 0)
738
Msg(DEBUG1,"%7d points created -- Worst tri radius is %8.3f",
739
vSizes.size(), worst->getRadius());
740
// compute circum center of that guy
741
double center[2],metric[3],r2;
742
MTriangle *base = worst->tri();
743
circUV(base, Us, Vs, center, gf);
744
double pa[2] = {(Us[base->getVertex(0)->getNum()] +
745
Us[base->getVertex(1)->getNum()] +
746
Us[base->getVertex(2)->getNum()]) / 3.,
747
(Vs[base->getVertex(0)->getNum()] +
748
Vs[base->getVertex(1)->getNum()] +
749
Vs[base->getVertex(2)->getNum()]) / 3.};
750
buildMetric(gf, pa, metric);
751
circumCenterMetric(worst->tri(), metric, Us, Vs, center, r2);
752
// compute the middle point of the edge
753
int ip1 = active_edge - 1 < 0 ? 2 : active_edge - 1;
754
int ip2 = active_edge;
755
// printf("the active edge is %d : %g %g -> %g %g\n",active_edge,base->getVertex(ip1)->x(),base->getVertex(ip1)->y(),
756
// base->getVertex(ip2)->x(),base->getVertex(ip2)->y());
757
double P[2] = {Us[base->getVertex(ip1)->getNum()],
758
Vs[base->getVertex(ip1)->getNum()]};
759
double Q[2] = {Us[base->getVertex(ip2)->getNum()],
760
Vs[base->getVertex(ip2)->getNum()]};
761
double midpoint[2] = {0.5*(P[0]+Q[0]),0.5*(P[1]+Q[1])};
763
// now we have the edge center and the center of the circumcircle,
764
// we try to find a point that would produce a perfect triangle while
765
// connecting the 2 points of the active edge
767
double dir[2] = {center[0]-midpoint[0],center[1]-midpoint[1]};
768
double norm = sqrt(dir[0]*dir[0]+dir[1]*dir[1]);
771
const double RATIO = sqrt( dir[0]*dir[0]*metric[0]+
772
2*dir[1]*dir[0]*metric[1]+
773
dir[1]*dir[1]*metric[2]);
776
const double p = 0.5*length_metric (P,Q,metric);// / RATIO;
777
const double q = length_metric (center,midpoint,metric);
778
const double rhoM1 = 0.5 * (vSizes[base->getVertex(ip1)->getNum()] + vSizes[base->getVertex(ip2)->getNum()] ) / sqrt(3.);// * RATIO;
779
const double rhoM2 = 0.5 * (vSizesBGM[base->getVertex(ip1)->getNum()] + vSizesBGM[base->getVertex(ip2)->getNum()] ) / sqrt(3.);// * RATIO;
780
const double rhoM = Extend1dMeshIn2dSurfaces() ? std::min(rhoM1, rhoM2) : rhoM2;
781
// const double rhoM = 0.5 * (vSizes[base->getVertex(ip1)->getNum()] + vSizes[base->getVertex(ip2)->getNum()] ) / sqrt(3.);// * RATIO;
783
const double rhoM_hat = std::min(std::max(rhoM,p),(p*p+q*q)/(2*q));
784
const double d = (rhoM_hat + sqrt (rhoM_hat*rhoM_hat - p*p))/RATIO;
788
midpoint[0] + d * dir[0],
789
midpoint[1] + d * dir[1]
791
insertAPoint(gf,AllTris.end(),newPoint,metric,Us,Vs,vSizes,vSizesBGM,AllTris,&ActiveTris,worst);
796
sprintf(name,"frontal%d.pos",gf->tag());
797
// _printTris (name, AllTris, Us,Vs);
798
transferDataStructure(gf, AllTris);
803
void gmshBowyerWatsonFrontal(GFace *gf){
805
std::set<MTri3*,compareTri3Ptr> AllTris;
806
std::vector<double> vSizes, vSizesBGM, Us, Vs;
807
buidMeshGenerationDataStructures(gf, AllTris, vSizes, vSizesBGM, Us, Vs);
809
// delaunise the initial mesh
810
int nbSwaps = edgeSwapPass(gf, AllTris, SWCR_DEL, Us, Vs, vSizes, vSizesBGM);
811
Msg(DEBUG2,"Delaunization of the initial mesh done (%d swaps)", nbSwaps);
814
int ITER = 0, active_edge;
816
// compute active triangle
817
std::set<MTri3*,compareTri3Ptr> ActiveTris;
818
std::set<MTri3*,compareTri3Ptr>::reverse_iterator it = AllTris.rbegin();
819
for ( ; it!=AllTris.rend();++it){
820
if ((*it)->getRadius() < LIMIT_)
822
else if(isActive(*it,LIMIT_,active_edge))
823
ActiveTris.insert(*it);
825
if (ActiveTris.size() == 0)break;
829
if (!ActiveTris.size())break;
830
MTri3 *worst = (*ActiveTris.begin());
831
ActiveTris.erase(ActiveTris.begin());
832
// printf("active_tris.size = %d\n",ActiveTris.size());
834
if (!worst->isDeleted() && isActive(worst,LIMIT_,active_edge) && worst->getRadius() > LIMIT_){
835
if(ITER++ % 5000 == 0)
836
Msg(DEBUG1,"%7d points created -- Worst tri radius is %8.3f",
837
vSizes.size(), worst->getRadius());
838
// compute circum center of that guy
839
double center[2],uv[2],metric[3],r2;
840
MTriangle *base = worst->tri();
841
circUV(base, Us, Vs, center, gf);
842
double pa[2] = {(Us[base->getVertex(0)->getNum()] +
843
Us[base->getVertex(1)->getNum()] +
844
Us[base->getVertex(2)->getNum()]) / 3.,
845
(Vs[base->getVertex(0)->getNum()] +
846
Vs[base->getVertex(1)->getNum()] +
847
Vs[base->getVertex(2)->getNum()]) / 3.};
848
buildMetric(gf, pa, metric);
849
circumCenterMetric(worst->tri(), metric, Us, Vs, center, r2);
850
// compute the middle point of the edge
851
int ip1 = active_edge - 1 < 0 ? 2 : active_edge - 1;
852
int ip2 = active_edge;
853
// printf("the active edge is %d : %g %g -> %g %g\n",active_edge,base->getVertex(ip1)->x(),base->getVertex(ip1)->y(),
854
// base->getVertex(ip2)->x(),base->getVertex(ip2)->y());
855
double P[2] = {Us[base->getVertex(ip1)->getNum()],
856
Vs[base->getVertex(ip1)->getNum()]};
857
double Q[2] = {Us[base->getVertex(ip2)->getNum()],
858
Vs[base->getVertex(ip2)->getNum()]};
859
double midpoint[2] = {0.5*(P[0]+Q[0]),0.5*(P[1]+Q[1])};
861
// now we have the edge center and the center of the circumcircle,
862
// we try to find a point that would produce a perfect triangle while
863
// connecting the 2 points of the active edge
865
double dir[2] = {center[0]-midpoint[0],center[1]-midpoint[1]};
866
double norm = sqrt(dir[0]*dir[0]+dir[1]*dir[1]);
869
const double RATIO = sqrt( dir[0]*dir[0]*metric[0]+
870
2*dir[1]*dir[0]*metric[1]+
871
dir[1]*dir[1]*metric[2]);
874
const double p = 0.5*length_metric (P,Q,metric);// / RATIO;
875
const double q = length_metric (center,midpoint,metric);
876
const double rhoM1 = 0.5 * (vSizes[base->getVertex(ip1)->getNum()] + vSizes[base->getVertex(ip2)->getNum()] ) / sqrt(3.);// * RATIO;
877
const double rhoM2 = 0.5 * (vSizesBGM[base->getVertex(ip1)->getNum()] + vSizesBGM[base->getVertex(ip2)->getNum()] ) / sqrt(3.);// * RATIO;
878
const double rhoM = Extend1dMeshIn2dSurfaces() ? std::min(rhoM1, rhoM2) : rhoM2;
879
// const double rhoM = 0.5 * (vSizes[base->getVertex(ip1)->getNum()] + vSizes[base->getVertex(ip2)->getNum()] ) / sqrt(3.);// * RATIO;
881
const double rhoM_hat = std::min(std::max(rhoM,p),(p*p+q*q)/(2*q));
882
const double d = (rhoM_hat + sqrt (rhoM_hat*rhoM_hat - p*p))/RATIO;
886
midpoint[0] + d * dir[0],
887
midpoint[1] + d * dir[1]
889
insertAPoint(gf,AllTris.end(),newPoint,metric,Us,Vs,vSizes,vSizesBGM,AllTris,&ActiveTris,worst);
893
_printTris ("frontal.pos", AllTris, Us,Vs);
894
transferDataStructure(gf, AllTris);