Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
isosiz_3d.c
Go to the documentation of this file.
1/* =============================================================================
2** This file is part of the mmg software package for the tetrahedral
3** mesh modification.
4** Copyright (c) Bx INP/CNRS/Inria/UBordeaux/UPMC, 2004-
5**
6** mmg is free software: you can redistribute it and/or modify it
7** under the terms of the GNU Lesser General Public License as published
8** by the Free Software Foundation, either version 3 of the License, or
9** (at your option) any later version.
10**
11** mmg is distributed in the hope that it will be useful, but WITHOUT
12** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13** FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14** License for more details.
15**
16** You should have received a copy of the GNU Lesser General Public
17** License and of the GNU General Public License along with mmg (in
18** files COPYING.LESSER and COPYING). If not, see
19** <http://www.gnu.org/licenses/>. Please read their terms carefully and
20** use this copy of the mmg distribution only if you accept them.
21** =============================================================================
22*/
23
35#include "libmmg3d.h"
36#include "libmmg3d_private.h"
38#include "mmgexterns_private.h"
39
40extern int8_t ddb;
41
42#define MAXLEN 1.0e9
43#define A64TH 0.015625
44#define A16TH 0.0625
45#define A32TH 0.03125
46
47
61inline double MMG5_lenedgCoor_iso(double *ca,double *cb,double *ma,double *mb) {
62 double h1,h2,l,r,len;
63
64 h1 = *ma;
65 h2 = *mb;
66 l = (cb[0]-ca[0])*(cb[0]-ca[0]) + (cb[1]-ca[1])*(cb[1]-ca[1]) \
67 + (cb[2]-ca[2])*(cb[2]-ca[2]);
68 l = sqrt(l);
69 r = h2 / h1 - 1.0;
70 len = fabs(r) < MMG5_EPS ? l / h1 : l / (h2-h1) * log1p(r);
71
72 return len;
73}
74
91static double
92MMG5_defsizreg(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int nump,MMG5_int *lists,
93 int ilists, double hmin,double hmax,double hausd) {
94 MMG5_pTetra pt;
95 MMG5_pxTetra pxt;
96 MMG5_pPoint p0,p1;
97 MMG5_Tria tt;
99 double ux,uy,uz,det2d,h,isqhmin,isqhmax,ll,lmin,lmax,hnm,s;
100 double *n,*t,r[3][3],lispoi[3*MMG3D_LMAX+1],intm[3],b0[3],b1[3],c[3],tAA[6],tAb[3],d[3];
101 double kappa[2],vp[2][2];
102 MMG5_int k,na,nb,ntempa,ntempb,iel,ip0;
103 int8_t iface,i,j,i0;
104 static int8_t mmgWarn0=0,mmgWarn1=0,mmgWarn2=0,mmgWarn3=0;
105
106 p0 = &mesh->point[nump];
107
108 if ( (!p0->xp) || MG_EDG_OR_NOM(p0->tag) || (p0->tag & MG_REQ)) {
109 if ( !mmgWarn0 ) {
110 mmgWarn0 = 1;
111 fprintf(stderr,"\n ## Error: %s: at least 1 wrong point"
112 " qualification : xp ? %" MMG5_PRId ".\n",__func__,p0->xp);
113 }
114 return FLT_MAX;
115 }
116
117 /* Check that we don't pass here for a corner (not directly tested previously
118 * because corners doesn't have xpoints) */
119 assert ( (!(MG_CRN & p0->tag)) && "We should not pass here with corner points" );
120
121 isqhmin = 1.0 / (hmin*hmin);
122 isqhmax = 1.0 / (hmax*hmax);
123
124 n = &mesh->xpoint[p0->xp].n1[0];
125
126 /* Step 1 : rotation matrix that sends normal n to the third coordinate vector
127 * of R^3 */
128 if ( !MMG5_rotmatrix(n,r) ) {
129 if ( !mmgWarn1 ) {
130 mmgWarn1 = 1;
131 fprintf(stderr,"\n ## Warning: %s: function MMG5_rotmatrix return 0.\n",
132 __func__);
133 }
134 return FLT_MAX;
135 }
136
137 /* Step 2 : rotation of the oriented surfacic ball with r : lispoi[k] is the
138 common edge between faces lists[k-1] and lists[k] */
139 iel = lists[0] / 4;
140 iface = lists[0] % 4;
141 pt = &mesh->tetra[iel];
142 lmin = MAXLEN;
143 lmax = 0.0;
144
145 na = nb = 0;
146 for (i=0; i<3; i++) {
147 if ( pt->v[MMG5_idir[iface][i]] != nump ) {
148 if ( !na )
149 na = pt->v[MMG5_idir[iface][i]];
150 else
151 nb = pt->v[MMG5_idir[iface][i]];
152 }
153 }
154
155 for (k=1; k<ilists; k++) {
156 iel = lists[k] / 4;
157 iface = lists[k] % 4;
158 pt = &mesh->tetra[iel];
159 ntempa = ntempb = 0;
160 for (i=0; i<3; i++) {
161 if ( pt->v[MMG5_idir[iface][i]] != nump ) {
162 if ( !ntempa )
163 ntempa = pt->v[MMG5_idir[iface][i]];
164 else
165 ntempb = pt->v[MMG5_idir[iface][i]];
166 }
167 }
168 if ( ntempa == na )
169 p1 = &mesh->point[na];
170 else if ( ntempa == nb )
171 p1 = &mesh->point[nb];
172 else if ( ntempb == na )
173 p1 = &mesh->point[na];
174 else {
175 assert(ntempb == nb);
176 p1 = &mesh->point[nb];
177 }
178 ux = p1->c[0] - p0->c[0];
179 uy = p1->c[1] - p0->c[1];
180 uz = p1->c[2] - p0->c[2];
181
182 lispoi[3*k+1] = r[0][0]*ux + r[0][1]*uy + r[0][2]*uz;
183 lispoi[3*k+2] = r[1][0]*ux + r[1][1]*uy + r[1][2]*uz;
184 lispoi[3*k+3] = r[2][0]*ux + r[2][1]*uy + r[2][2]*uz;
185
186 ll = lispoi[3*k+1]*lispoi[3*k+1] + lispoi[3*k+2]*lispoi[3*k+2] + lispoi[3*k+3]*lispoi[3*k+3];
187 lmin = MG_MIN(lmin,ll);
188 lmax = MG_MAX(lmax,ll);
189
190 na = ntempa;
191 nb = ntempb;
192 }
193
194 /* Finish with point 0 */
195 iel = lists[0] / 4;
196 iface = lists[0] % 4;
197 pt = &mesh->tetra[iel];
198 ntempa = ntempb = 0;
199 for (i=0; i<3; i++) {
200 if ( pt->v[MMG5_idir[iface][i]] != nump ) {
201 if ( !ntempa )
202 ntempa = pt->v[MMG5_idir[iface][i]];
203 else
204 ntempb = pt->v[MMG5_idir[iface][i]];
205 }
206 }
207 if ( ntempa == na )
208 p1 = &mesh->point[na];
209 else if ( ntempa == nb )
210 p1 = &mesh->point[nb];
211 else if ( ntempb == na )
212 p1 = &mesh->point[na];
213 else {
214 assert(ntempb == nb);
215 p1 = &mesh->point[nb];
216 }
217
218 ux = p1->c[0] - p0->c[0];
219 uy = p1->c[1] - p0->c[1];
220 uz = p1->c[2] - p0->c[2];
221
222 lispoi[1] = r[0][0]*ux + r[0][1]*uy + r[0][2]*uz;
223 lispoi[2] = r[1][0]*ux + r[1][1]*uy + r[1][2]*uz;
224 lispoi[3] = r[2][0]*ux + r[2][1]*uy + r[2][2]*uz;
225
226 ll = lispoi[1]*lispoi[1] + lispoi[2]*lispoi[2] + lispoi[3]*lispoi[3];
227 lmin = MG_MIN(lmin,ll);
228 lmax = MG_MAX(lmax,ll);
229
230 /* list goes modulo ilist */
231 lispoi[3*ilists+1] = lispoi[1];
232 lispoi[3*ilists+2] = lispoi[2];
233 lispoi[3*ilists+3] = lispoi[3];
234
235 /* At this point, lispoi contains the oriented surface ball of point p0, that has been rotated
236 through r, with the convention that triangle l has edges lispoi[l]; lispoi[l+1] */
237 if ( lmax/lmin > 4.0*hmax*hmax/(hmin*hmin) ) return hmax;
238
239 /* Check all projections over tangent plane. */
240 for (k=0; k<ilists-1; k++) {
241 det2d = lispoi[3*k+1]*lispoi[3*(k+1)+2] - lispoi[3*k+2]*lispoi[3*(k+1)+1];
242 if ( det2d < 0.0 ) return hmax;
243 }
244 det2d = lispoi[3*(ilists-1)+1]*lispoi[3*0+2] - lispoi[3*(ilists-1)+2]*lispoi[3*0+1];
245 if ( det2d < 0.0 ) return hmax;
246
247 /* Reconstitution of the curvature tensor at p0 in the tangent plane,
248 with a quadric fitting approach */
249 memset(intm,0x00,3*sizeof(double));
250 memset(tAA,0x00,6*sizeof(double));
251 memset(tAb,0x00,3*sizeof(double));
252
253 for (k=0; k<ilists; k++) {
254 iel = lists[k] / 4;
255 iface = lists[k] % 4;
256
257 assert( 0<=iface && iface<4 && "unexpected local face idx");
258 MMG5_tet2tri(mesh,iel,iface,&tt);
259
260 pxt = &mesh->xtetra[mesh->tetra[iel].xt];
261 if ( !MMG5_bezierCP(mesh,&tt,&b,MG_GET(pxt->ori,iface)) ) {
262 if ( !mmgWarn2 ) {
263 mmgWarn2 = 1;
264 fprintf(stderr,"\n ## Warning: %s: function MMG5_bezierCP return 0.\n",
265 __func__);
266 }
267 return FLT_MAX;
268 }
269
270 for (i0=0; i0<3; i0++) {
271 if ( tt.v[i0] == nump ) break;
272 }
273 assert(i0 < 3);
274
275 for (j=0; j<10; j++) {
276 c[0] = b.b[j][0] - p0->c[0];
277 c[1] = b.b[j][1] - p0->c[1];
278 c[2] = b.b[j][2] - p0->c[2];
279
280 b.b[j][0] = r[0][0]*c[0] + r[0][1]*c[1] + r[0][2]*c[2];
281 b.b[j][1] = r[1][0]*c[0] + r[1][1]*c[1] + r[1][2]*c[2];
282 b.b[j][2] = r[2][0]*c[0] + r[2][1]*c[1] + r[2][2]*c[2];
283 }
284
285 /* Mid-point along left edge and endpoint in the rotated frame */
286 if ( i0 == 0 ) {
287 memcpy(b0,&(b.b[7][0]),3*sizeof(double));
288 memcpy(b1,&(b.b[8][0]),3*sizeof(double));
289 }
290 else if ( i0 == 1 ) {
291 memcpy(b0,&(b.b[3][0]),3*sizeof(double));
292 memcpy(b1,&(b.b[4][0]),3*sizeof(double));
293 }
294 else {
295 memcpy(b0,&(b.b[5][0]),3*sizeof(double));
296 memcpy(b1,&(b.b[6][0]),3*sizeof(double));
297 }
298 s = 0.5;
299
300 /* At this point, the two control points are expressed in the rotated frame */
301 c[0] = 3.0*s*(1.0-s)*(1.0-s)*b0[0] + 3.0*s*s*(1.0-s)*b1[0] + s*s*s*lispoi[3*k+1];
302 c[1] = 3.0*s*(1.0-s)*(1.0-s)*b0[1] + 3.0*s*s*(1.0-s)*b1[1] + s*s*s*lispoi[3*k+2];
303 c[2] = 3.0*s*(1.0-s)*(1.0-s)*b0[2] + 3.0*s*s*(1.0-s)*b1[2] + s*s*s*lispoi[3*k+3];
304
305 /* Fill matric tAA and second member tAb*/
306 tAA[0] += c[0]*c[0]*c[0]*c[0];
307 tAA[1] += c[0]*c[0]*c[1]*c[1];
308 tAA[2] += c[0]*c[0]*c[0]*c[1];
309 tAA[3] += c[1]*c[1]*c[1]*c[1];
310 tAA[4] += c[0]*c[1]*c[1]*c[1];
311 tAA[5] += c[0]*c[0]*c[1]*c[1];
312
313 tAb[0] += c[0]*c[0]*c[2];
314 tAb[1] += c[1]*c[1]*c[2];
315 tAb[2] += c[0]*c[1]*c[2];
316
317 s = 1.0;
318 /* At this point, the two control points are expressed in the rotated frame */
319 c[0] = 3.0*s*(1.0-s)*(1.0-s)*b0[0] + 3.0*s*s*(1.0-s)*b1[0] + s*s*s*lispoi[3*k+1];
320 c[1] = 3.0*s*(1.0-s)*(1.0-s)*b0[1] + 3.0*s*s*(1.0-s)*b1[1] + s*s*s*lispoi[3*k+2];
321 c[2] = 3.0*s*(1.0-s)*(1.0-s)*b0[2] + 3.0*s*s*(1.0-s)*b1[2] + s*s*s*lispoi[3*k+3];
322
323 /* Fill matric tAA and second member tAb*/
324 tAA[0] += c[0]*c[0]*c[0]*c[0];
325 tAA[1] += c[0]*c[0]*c[1]*c[1];
326 tAA[2] += c[0]*c[0]*c[0]*c[1];
327 tAA[3] += c[1]*c[1]*c[1]*c[1];
328 tAA[4] += c[0]*c[1]*c[1]*c[1];
329 tAA[5] += c[0]*c[0]*c[1]*c[1];
330
331 tAb[0] += c[0]*c[0]*c[2];
332 tAb[1] += c[1]*c[1]*c[2];
333 tAb[2] += c[0]*c[1]*c[2];
334
335 /* Mid-point along median edge and endpoint in the rotated frame */
336 if ( i0 == 0 ) {
337 c[0] = A64TH*(b.b[1][0] + b.b[2][0] + 3.0*(b.b[3][0] + b.b[4][0])) \
338 + 3.0*A16TH*(b.b[6][0] + b.b[7][0] + b.b[9][0]) + A32TH*(b.b[5][0] + b.b[8][0]);
339 c[1] = A64TH*(b.b[1][1] + b.b[2][1] + 3.0*(b.b[3][1] + b.b[4][1])) \
340 + 3.0*A16TH*(b.b[6][1] + b.b[7][1] + b.b[9][1]) + A32TH*(b.b[5][1] + b.b[8][1]);
341 c[2] = A64TH*(b.b[1][2] + b.b[2][2] + 3.0*(b.b[3][2] + b.b[4][2])) \
342 + 3.0*A16TH*(b.b[6][2] + b.b[7][2] + b.b[9][2]) + A32TH*(b.b[5][2] + b.b[8][2]);
343
344 d[0] = 0.125*b.b[1][0] + 0.375*(b.b[3][0] + b.b[4][0]) + 0.125*b.b[2][0];
345 d[1] = 0.125*b.b[1][1] + 0.375*(b.b[3][1] + b.b[4][1]) + 0.125*b.b[2][1];
346 d[2] = 0.125*b.b[1][2] + 0.375*(b.b[3][2] + b.b[4][2]) + 0.125*b.b[2][2];
347 }
348 else if (i0 == 1) {
349 c[0] = A64TH*(b.b[0][0] + b.b[2][0] + 3.0*(b.b[5][0] + b.b[6][0])) \
350 + 3.0*A16TH*(b.b[3][0] + b.b[8][0] + b.b[9][0]) + A32TH*(b.b[4][0] + b.b[7][0]);
351 c[1] = A64TH*(b.b[0][1] + b.b[2][1] + 3.0*(b.b[5][1] + b.b[6][1])) \
352 + 3.0*A16TH*(b.b[3][1] + b.b[8][1] + b.b[9][1]) + A32TH*(b.b[4][1] + b.b[7][1]);
353 c[2] = A64TH*(b.b[0][2] + b.b[2][2] + 3.0*(b.b[5][2] + b.b[6][2])) \
354 + 3.0*A16TH*(b.b[3][2] + b.b[8][2] + b.b[9][2]) + A32TH*(b.b[4][2] + b.b[7][2]);
355
356 d[0] = 0.125*b.b[2][0] + 0.375*(b.b[5][0] + b.b[6][0]) + 0.125*b.b[0][0];
357 d[1] = 0.125*b.b[2][1] + 0.375*(b.b[5][1] + b.b[6][1]) + 0.125*b.b[0][1];
358 d[2] = 0.125*b.b[2][2] + 0.375*(b.b[5][2] + b.b[6][2]) + 0.125*b.b[0][2];
359 }
360 else {
361 c[0] = A64TH*(b.b[0][0] + b.b[1][0] + 3.0*(b.b[7][0] + b.b[8][0])) \
362 + 3.0*A16TH*(b.b[4][0] + b.b[5][0] + b.b[9][0]) + A32TH*(b.b[3][0] + b.b[6][0]);
363 c[1] = A64TH*(b.b[0][1] + b.b[1][1] + 3.0*(b.b[7][1] + b.b[8][1])) \
364 + 3.0*A16TH*(b.b[4][1] + b.b[5][1] + b.b[9][1]) + A32TH*(b.b[3][1] + b.b[6][1]);
365 c[2] = A64TH*(b.b[0][2] + b.b[1][2] + 3.0*(b.b[7][2] + b.b[8][2])) \
366 + 3.0*A16TH*(b.b[4][2] + b.b[5][2] + b.b[9][2]) + A32TH*(b.b[3][2] + b.b[6][2]);
367
368 d[0] = 0.125*b.b[0][0] + 0.375*(b.b[7][0] + b.b[8][0]) + 0.125*b.b[1][0];
369 d[1] = 0.125*b.b[0][1] + 0.375*(b.b[7][1] + b.b[8][1]) + 0.125*b.b[1][1];
370 d[2] = 0.125*b.b[0][2] + 0.375*(b.b[7][2] + b.b[8][2]) + 0.125*b.b[1][2];
371 }
372
373 /* Fill matric tAA and second member tAb*/
374 tAA[0] += c[0]*c[0]*c[0]*c[0];
375 tAA[1] += c[0]*c[0]*c[1]*c[1];
376 tAA[2] += c[0]*c[0]*c[0]*c[1];
377 tAA[3] += c[1]*c[1]*c[1]*c[1];
378 tAA[4] += c[0]*c[1]*c[1]*c[1];
379 tAA[5] += c[0]*c[0]*c[1]*c[1];
380
381 tAb[0] += c[0]*c[0]*c[2];
382 tAb[1] += c[1]*c[1]*c[2];
383 tAb[2] += c[0]*c[1]*c[2];
384
385 tAA[0] += d[0]*d[0]*d[0]*d[0];
386 tAA[1] += d[0]*d[0]*d[1]*d[1];
387 tAA[2] += d[0]*d[0]*d[0]*d[1];
388 tAA[3] += d[1]*d[1]*d[1]*d[1];
389 tAA[4] += d[0]*d[1]*d[1]*d[1];
390 tAA[5] += d[0]*d[0]*d[1]*d[1];
391
392 tAb[0] += d[0]*d[0]*d[2];
393 tAb[1] += d[1]*d[1]*d[2];
394 tAb[2] += d[0]*d[1]*d[2];
395 }
396
397 /* solve now (a b c) = tAA^{-1} * tAb */
398 if ( !MMG5_sys33sym(tAA,tAb,c) ) return hmax;
399
400 intm[0] = 2.0*c[0];
401 intm[1] = c[2];
402 intm[2] = 2.0*c[1];
403
404 /* At this point, intm stands for the integral matrix of Taubin's approach : vp[0] and vp[1]
405 are the two pr. directions of curvature, and the two curvatures can be inferred from lambdas*/
406 if( !MMG5_eigensym(intm,kappa,vp) ){
407 if ( !mmgWarn3 ) {
408 mmgWarn3 = 1;
409 fprintf(stderr,"\n # Warning: %s: function MMG5_eigensym return 0.\n",
410 __func__);
411 }
412 return FLT_MAX;
413 }
414
415 /* h computation : h(x) = sqrt( 9*hausd / (2 * max(kappa1(x),kappa2(x)) ) */
416 kappa[0] = 2.0/9.0 * fabs(kappa[0]) / hausd;
417 kappa[0] = MG_MIN(kappa[0],isqhmin);
418 kappa[0] = MG_MAX(kappa[0],isqhmax);
419
420 kappa[1] = 2.0/9.0 * fabs(kappa[1]) / hausd;
421 kappa[1] = MG_MIN(kappa[1],isqhmin);
422 kappa[1] = MG_MAX(kappa[1],isqhmax);
423
424 kappa[0] = 1.0 / sqrt(kappa[0]);
425 kappa[1] = 1.0 / sqrt(kappa[1]);
426
427 h = MG_MIN(kappa[0],kappa[1]);
428
429 /* Travel surfacic ball one last time and update metric of non manifold
430 * regular points of ball */
431 for (k=0; k<ilists; k++) {
432 iface = lists[k] % 4;
433
434 for (j=0; j<3; j++) {
435 i0 = MMG5_idir[iface][j];
436 ip0 = pt->v[i0];
437 p1 = &mesh->point[ip0];
438
439 if ( MG_SIN(p1->tag) ) {
440 /* Do not treat singular points */
441 continue;
442 }
443
444 if ( !(p1->tag & MG_NOM) ) {
445 /* Do not treat manifold points */
446 continue;
447 }
448
449 assert(p1->xp);
450 t = &p1->n[0];
451 memcpy(c,t,3*sizeof(double));
452
453 d[0] = r[0][0]*c[0] + r[0][1]*c[1] + r[0][2]*c[2];
454 d[1] = r[1][0]*c[0] + r[1][1]*c[1] + r[1][2]*c[2];
455
456 hnm = intm[0]*d[0]*d[0] + 2.0*intm[1]*d[0]*d[1] + intm[2]*d[1]*d[1];
457 hnm = 2.0/9.0 * fabs(hnm) / hausd;
458 hnm = MG_MIN(hnm,isqhmin);
459 hnm = MG_MAX(hnm,isqhmax);
460 hnm = 1.0 / sqrt(hnm);
461 met->m[ip0] = MG_MIN(met->m[ip0],hnm);
462 }
463 }
464 return h;
465}
466
482double MMG5_meansizreg_iso(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int nump,MMG5_int *lists,
483 int ilists, double hmin,double hmax) {
484 MMG5_pTetra pt;
485 MMG5_pPoint p0,p1;
486 double len,ux,uy,uz;
487 MMG5_int k,iel,ip1;
488 int8_t i,iface;
489
490 p0 = &mesh->point[nump];
491
492 len = 0;
493 for (k=0; k<ilists; k++) {
494 iel = lists[k] / 4;
495 iface = lists[k] % 4;
496 pt = &mesh->tetra[iel];
497
498 for (i=0; i<3; i++) {
499 if ( pt->v[MMG5_idir[iface][i]] == nump ) {
500 break;
501 }
502 }
503 assert(i!=3);
504
505 ip1 = pt->v[MMG5_idir[iface][MMG5_inxt2[i]]];
506 p1 = &mesh->point[ip1];
507
508 ux = p1->c[0] - p0->c[0];
509 uy = p1->c[1] - p0->c[1];
510 uz = p1->c[2] - p0->c[2];
511 len += sqrt(ux*ux + uy*uy + uz*uz);
512 }
513 len /=ilists;
514
515 return MG_MIN(hmax,MG_MAX(hmin,len));
516}
517
532static inline
534 MMG5_pTetra pt,int8_t i) {
535 MMG5_int ip0,ip1;
536
537 ip0 = pt->v[MMG5_iare[i][0]];
538 ip1 = pt->v[MMG5_iare[i][1]];
539
540 /* Check if the edge is already treated */
541 if ( MMG5_hashGet(hash,ip0,ip1) ) return 1;
542
543 /* Mark the edge as treated */
544 if ( !MMG5_hashEdge(mesh,hash,ip0,ip1,1) ) return 0;
545
546 if ( !MMG5_sum_reqEdgeLengthsAtPoint(mesh,met,ip0,ip1) )
547 return 0;
548
549 return 1;
550}
551
565 MMG5_pTetra pt;
566 MMG5_pxTetra pxt;
567 MMG5_Hash hash;
568 MMG5_int k,j,ip0,ip1,iad0,iad1;
569 int i;
570
571 /* Reset the input metric at required edges extremities */
572 if ( ismet ) {
573 for ( k=1; k<=mesh->ne; k++ ) {
574 pt = &mesh->tetra[k];
575 if ( !MG_EOK(pt) ) continue;
576
577 if ( pt->tag & MG_REQ ) {
578 for ( i=0; i<6; i++ ) {
579 ip0 = pt->v[MMG5_iare[i][0]];
580 ip1 = pt->v[MMG5_iare[i][1]];
581 iad0 = met->size*ip0;
582 iad1 = met->size*ip1;
583 for ( j=0; j<met->size; ++j ) {
584 met->m[iad0+j] = 0.;
585 met->m[iad1+j] = 0.;
586 }
587 }
588 }
589 else {
590 if ( !pt->xt ) continue;
591 pxt = &mesh->xtetra[pt->xt];
592
593 for ( i=0; i<6; i++ ) {
594 if ( (pxt->tag[i] & MG_REQ) || (pxt->tag[i] & MG_NOSURF) ||
595 (pxt->tag[i] & MG_PARBDY) ) {
596 ip0 = pt->v[MMG5_iare[i][0]];
597 ip1 = pt->v[MMG5_iare[i][1]];
598 iad0 = met->size*ip0;
599 iad1 = met->size*ip1;
600 for ( j=0; j<met->size; ++j ) {
601 met->m[iad0+j] = 0.;
602 met->m[iad1+j] = 0.;
603 }
604 }
605 }
606 }
607 }
608 }
609
610 /* Process the required edges and add the edge length to the metric of the
611 * edge extremities */
612 if ( !MMG5_hashNew(mesh,&hash,mesh->np,7*mesh->np) ) return 0;
613
614 for ( k=1; k<=mesh->ne; k++ ) {
615 pt = &mesh->tetra[k];
616 if ( !MG_EOK(pt) ) continue;
617
618 if ( pt->tag & MG_REQ ) {
619 for ( i=0; i<6; i++ ) {
620 if ( !MMG3D_sum_reqEdgeLengthsAtPoint(mesh,met,&hash,pt,i) ) {
621 MMG5_DEL_MEM(mesh,hash.item);
622 return 0;
623 }
624 }
625 }
626 else {
627 if ( !pt->xt ) continue;
628 pxt = &mesh->xtetra[pt->xt];
629
630 for ( i=0; i<6; i++ ) {
631 if ( (pxt->tag[i] & MG_REQ) || (pxt->tag[i] & MG_NOSURF) ||
632 (pxt->tag[i] & MG_PARBDY) ) {
633 if ( !MMG3D_sum_reqEdgeLengthsAtPoint(mesh,met,&hash,pt,i) ) {
634 MMG5_DEL_MEM(mesh,hash.item);
635 return 0;
636 }
637 }
638 }
639 }
640 }
641 MMG5_DEL_MEM(mesh,hash.item);
642
643 /* Travel the points and compute the metric of the points belonging to
644 * required edges as the mean of the required edges length */
645 if ( !MMG5_compute_meanMetricAtMarkedPoints ( mesh,met ) ) {
646 return 0;
647 }
648
649 return 1;
650}
651
663 MMG5_pTetra pt,ptloc;
664 MMG5_pPrism pp;
665 MMG5_pxTetra pxt;
666 MMG5_pPoint p0,p1;
667 double hp,v[3],b0[3],b1[3],b0p0[3],b1b0[3],p1b1[3],hausd,hmin,hmax;
668 double secder0[3],secder1[3],kappa,tau[3],gammasec[3],ntau2,intau,ps,lm;
669 MMG5_int lists[MMG3D_LMAX+2],k,ip0,ip1;
670 int64_t listv[MMG3D_LMAX+2];
671 int ilists,ilistv,l;
672 int kk,isloc;
673 int8_t ismet;
674 int8_t i,j,ia,ised,i0,i1;
675 MMG5_pPar par;
676
677 if ( !MMG5_defsiz_startingMessage (mesh,met,__func__) ) {
678 return 0;
679 }
680
681 for (k=1; k<=mesh->np; k++) {
682 p0 = &mesh->point[k];
683 p0->flag = 0;
684 p0->s = 0;
685 }
686
688 hmax = DBL_MAX;
689 hmin = 0.;
690
691 /* alloc structure */
692 if ( !met->m ) {
693 ismet = 0;
694
695 /* Allocate and store the header informations for each solution */
697 return 0;
698 }
699 }
700 else {
701 ismet = 1;
702 assert ( met->np );
703 }
704
708 if ( !mesh->info.nosizreq ) {
709 if ( !MMG3D_set_metricAtPointsOnReqEdges ( mesh,met,ismet ) ) {
710 return 0;
711 }
712 }
713
715 if ( !ismet ) {
716 /* init constant size */
717 for (k=1; k<=mesh->ne; k++) {
718 pt = &mesh->tetra[k];
719 if ( !MG_EOK(pt) ) continue;
720
721 for (i=0; i<4; i++) {
722 ip0 = pt->v[i];
723 p0 = &mesh->point[ip0];
724
725 if ( p0->flag ) continue;
726
728 isloc = 0;
729 hmax = mesh->info.hmax;
730
731 /* Local param at vertex */
732 if ( mesh->info.parTyp & MG_Vert ) {
733 for (l=0; l<mesh->info.npar; l++) {
734
735 par = &mesh->info.par[l];
736 if ( (par->elt == MMG5_Vertex) && (p0->ref == par->ref ) ) {
737 hmax = par->hmax;
738 isloc = 1;
739 break;
740 }
741 }
742 }
743
744 /* Local param at tetrahedra */
745 if ( mesh->info.parTyp & MG_Tetra ) {
746 ilistv = MMG5_boulevolp(mesh,k,i,listv);
747 l = 0;
748 do
749 {
750 if ( isloc ) break;
751
752 par = &mesh->info.par[l];
753 if ( par->elt != MMG5_Tetrahedron ) continue;
754
755 for ( kk=0; kk<ilistv; ++kk ) {
756 ptloc = &mesh->tetra[listv[kk]/4];
757 if ( par->ref == ptloc->ref ) {
758 hmax = par->hmax;
759 isloc = 1;
760 break;
761 }
762 }
763 } while ( ++l<mesh->info.npar );
764
765 for ( ; l<mesh->info.npar; ++l ) {
766 par = &mesh->info.par[l];
767 if ( par->elt != MMG5_Tetrahedron ) continue;
768
769 for ( kk=0; kk<ilistv; ++kk ) {
770 ptloc = &mesh->tetra[listv[kk]/4];
771 if ( par->ref == ptloc->ref ) {
772 hmax = MG_MIN(hmax,par->hmax);
773 break;
774 }
775 }
776 }
777 }
779 met->m[ip0] = hmax;
780 p0->flag = 1;
781 }
782 }
783
785 for (k=1; k<=mesh->nprism; k++) {
786 pp = &mesh->prism[k];
787 if ( !MG_EOK(pp) ) continue;
788
789 for (i=0; i<6; i++) {
790 ip0 = pp->v[i];
791 p0 = &mesh->point[ip0];
792
793 if ( p0->flag ) continue;
794
795 met->m[ip0] = hmax;
796 p0->flag = 1;
797 }
798 }
799 }
800 else {
801
802 /* size truncation */
803 for (k=1; k<=mesh->ne; k++) {
804 pt = &mesh->tetra[k];
805 if ( !MG_EOK(pt) ) continue;
806
807 for (i=0; i<4; i++) {
808 ip0 = pt->v[i];
809 p0 = &mesh->point[ip0];
810
811 if ( p0->flag ) continue;
812
814 isloc = 0;
815 hmin = mesh->info.hmin;
816 hmax = mesh->info.hmax;
817
818 /* Local param at vertex */
819 if ( mesh->info.parTyp & MG_Vert ) {
820 for (l=0; l<mesh->info.npar; l++) {
821 par = &mesh->info.par[l];
822 if ( (par->elt == MMG5_Vertex) && (p0->ref == par->ref ) ) {
823 hmin = par->hmin;
824 hmax = par->hmax;
825 isloc = 1;
826 break;
827 }
828 }
829 }
830
831 /* Local param ar tetrahedra */
832 if ( mesh->info.parTyp & MG_Tetra ) {
833 ilistv = MMG5_boulevolp(mesh,k,i,listv);
834 l = 0;
835 do
836 {
837 if ( isloc ) break;
838
839 par = &mesh->info.par[l];
840 if ( par->elt != MMG5_Tetrahedron ) continue;
841
842 for ( kk=0; kk<ilistv; ++kk ) {
843 ptloc = &mesh->tetra[listv[kk]/4];
844 if ( par->ref == ptloc->ref ) {
845 hmin = par->hmin;
846 hmax = par->hmax;
847 isloc = 1;
848 break;
849 }
850 }
851 } while ( ++l<mesh->info.npar );
852
853 for ( ; l<mesh->info.npar; ++l ) {
854 par = &mesh->info.par[l];
855 if ( par->elt != MMG5_Tetrahedron ) continue;
856
857 for ( kk=0; kk<ilistv; ++kk ) {
858 ptloc = &mesh->tetra[listv[kk]/4];
859 if ( par->ref == ptloc->ref ) {
860 hmin = MG_MAX(hmin,par->hmin);
861 hmax = MG_MIN(hmax,par->hmax);
862 break;
863 }
864 }
865 }
866 }
868 met->m[ip0] = MG_MIN(hmax,MG_MAX(hmin,met->m[ip0]));
869 p0->flag = 1;
870 }
871 }
872
874 for (k=1; k<=mesh->nprism; k++) {
875 pp = &mesh->prism[k];
876 if ( !MG_EOK(pp) ) continue;
877
878 for (i=0; i<6; i++) {
879 ip0 = pp->v[i];
880 p0 = &mesh->point[ip0];
881
882 if ( p0->flag ) continue;
883
884 met->m[ip0] = MG_MIN(hmax,MG_MAX(hmin,met->m[ip0]));
885 p0->flag = 1;
886 }
887 }
888 }
889
891 for (k=1; k<=mesh->ne; k++) {
892 pt = &mesh->tetra[k];
893 // Warning: why are we skipped the tetra with negative refs ?
894 if ( !MG_EOK(pt) || pt->ref < 0 || (pt->tag & MG_REQ) ) continue;
895 else if ( !pt->xt ) continue;
896
897 pxt = &mesh->xtetra[pt->xt];
898 for (i=0; i<4; i++) {
899 if ( !(pxt->ftag[i] & MG_BDY) ) continue;
900 if ( !MG_GET(mesh->xtetra[mesh->tetra[k].xt].ori,i) ) continue;
901
902 for (j=0; j<3; j++) {
903 i0 = MMG5_idir[i][j];
904 ip0 = pt->v[i0];
905 p0 = &mesh->point[ip0];
906
907 if ( p0->flag>1 ) continue;
908
909 if ( MG_SIN_OR_NOM(p0->tag) || MG_EDG(p0->tag) )
910 continue;
911
913 if ( MMG5_boulesurfvolp(mesh,k,i0,i,listv,&ilistv,lists,&ilists,0) != 1 )
914 continue;
915
916 if ( !MMG3D_localParamReg(mesh,ip0,listv,ilistv,lists,ilists,
917 &hausd,&hmin,&hmax) ) {
918 hmin = mesh->info.hmin;
919 hmax = mesh->info.hmax;
920 hausd = mesh->info.hausd;
921 }
922
924 /* Define size coming from the hausdorff approximation at regular
925 * surface point and update metric at non-singular non-manifold points
926 * of surfacic ball*/
927 hp = MMG5_defsizreg(mesh,met,ip0,lists,ilists,hmin,hmax,hausd);
928
929 met->m[ip0] = MG_MIN(met->m[ip0],hp);
930 p0->flag = 2;
931 }
932 }
933 }
934
937 /* Warning: here we pass more than once per each point because we see it from
938 all the edges to which it belongs */
939 for (k=1; k<=mesh->ne; k++) {
940
941 pt = &mesh->tetra[k];
942 if ( !MG_EOK(pt) || (pt->tag & MG_REQ) ) continue;
943 else if ( !pt->xt ) continue;
944 pxt = &mesh->xtetra[pt->xt];
945
946 for (i=0; i<4; i++) {
947 if ( !(pxt->ftag[i] & MG_BDY) ) continue;
948 else if ( !MMG5_norface(mesh,k,i,v) ) continue;
949
950 for (j=0; j<3; j++) {
951 ia = MMG5_iarf[i][j];
952 i0 = MMG5_iare[ia][0];
953 i1 = MMG5_iare[ia][1];
954 ip0 = pt->v[i0];
955 ip1 = pt->v[i1];
956 p0 = &mesh->point[ip0];
957 p1 = &mesh->point[ip1];
958
959 /* Skip this step if both points are on a required edge */
960 if ( p0->flag == 3 && p1->flag == 3 ) continue;
961
962 /* Skip regular edges */
963 if ( !MG_EDG(p0->tag) && !MG_EDG(p1->tag) ) continue;
964
966 if ( !MMG3D_localParamNm(mesh,k,i,ia,&hausd,&hmin,&hmax) ) {
967 hausd = mesh->info.hausd;
968 hmin = mesh->info.hmin;
969 hmax = mesh->info.hmax;
970 }
971
973 ised = MG_EDG_OR_NOM(pxt->tag[ia]);
974
975 MMG5_BezierEdge(mesh,ip0,ip1,b0,b1,ised,v);
976
977 b0p0[0] = b0[0] - p0->c[0];
978 b0p0[1] = b0[1] - p0->c[1];
979 b0p0[2] = b0[2] - p0->c[2];
980
981 b1b0[0] = b1[0] - b0[0];
982 b1b0[1] = b1[1] - b0[1];
983 b1b0[2] = b1[2] - b0[2];
984
985 p1b1[0] = p1->c[0] - b1[0];
986 p1b1[1] = p1->c[1] - b1[1];
987 p1b1[2] = p1->c[2] - b1[2];
988
989 secder0[0] = p0->c[0] + b1[0] - 2.0*b0[0];
990 secder0[1] = p0->c[1] + b1[1] - 2.0*b0[1];
991 secder0[2] = p0->c[2] + b1[2] - 2.0*b0[2];
992
993 secder1[0] = p1->c[0] + b0[0] - 2.0*b1[0];
994 secder1[1] = p1->c[1] + b0[1] - 2.0*b1[1];
995 secder1[2] = p1->c[2] + b0[2] - 2.0*b1[2];
996
997 kappa = 0.0;
998 for (l=0; l<4; l++) {
999 tau[0] = 3.0*(1.0-MMG5_ATHIRD*l)*(1.0-MMG5_ATHIRD*l)*b0p0[0] + 6.0*MMG5_ATHIRD*l*(1.0-MMG5_ATHIRD*l)*b1b0[0] \
1000 + 3.0*MMG5_ATHIRD*l*MMG5_ATHIRD*l*p1b1[0];
1001 tau[1] = 3.0*(1.0-MMG5_ATHIRD*l)*(1.0-MMG5_ATHIRD*l)*b0p0[1] + 6.0*MMG5_ATHIRD*l*(1.0-MMG5_ATHIRD*l)*b1b0[1] \
1002 + 3.0*MMG5_ATHIRD*l*MMG5_ATHIRD*l*p1b1[1];
1003 tau[2] = 3.0*(1.0-MMG5_ATHIRD*l)*(1.0-MMG5_ATHIRD*l)*b0p0[2] + 6.0*MMG5_ATHIRD*l*(1.0-MMG5_ATHIRD*l)*b1b0[2] \
1004 + 3.0*MMG5_ATHIRD*l*MMG5_ATHIRD*l*p1b1[2];
1005
1006 gammasec[0] = 6.0*((1.0-MMG5_ATHIRD*l)*secder0[0] + MMG5_ATHIRD*l*secder1[0]);
1007 gammasec[1] = 6.0*((1.0-MMG5_ATHIRD*l)*secder0[1] + MMG5_ATHIRD*l*secder1[1]);
1008 gammasec[2] = 6.0*((1.0-MMG5_ATHIRD*l)*secder0[2] + MMG5_ATHIRD*l*secder1[2]);
1009
1010 ntau2 = tau[0]*tau[0] + tau[1]*tau[1] + tau[2]*tau[2];
1011 if ( ntau2 < MMG5_EPSD ) continue;
1012 intau = 1.0/sqrt(ntau2);
1013 ntau2 = 1.0/ntau2;
1014 tau[0] *= intau;
1015 tau[1] *= intau;
1016 tau[2] *= intau;
1017
1018 ps = gammasec[0]*tau[0] + gammasec[1]*tau[1] + gammasec[2]*tau[2];
1019 gammasec[0] = gammasec[0]*ntau2 - ps*ntau2*tau[0];
1020 gammasec[1] = gammasec[1]*ntau2 - ps*ntau2*tau[1];
1021 gammasec[2] = gammasec[2]*ntau2 - ps*ntau2*tau[2];
1022 kappa = MG_MAX(kappa,gammasec[0]*gammasec[0] + gammasec[1]*gammasec[1] + gammasec[2]*gammasec[2] );
1023 }
1024 kappa = sqrt(kappa);
1025 if ( kappa < MMG5_EPSD )
1026 lm = MAXLEN;
1027 else
1028 lm = sqrt(8.0*hausd / kappa);
1029
1030 if ( MG_EDG(p0->tag) && !MG_SIN_OR_NOM(p0->tag) && p0->flag != 3 )
1031 met->m[ip0] = MG_MAX(hmin,MG_MIN(met->m[ip0],lm));
1032 if ( MG_EDG(p1->tag) && !MG_SIN_OR_NOM(p1->tag) && p1->flag != 3 )
1033 met->m[ip1] = MG_MAX(hmin,MG_MIN(met->m[ip1],lm));
1034 }
1035 }
1036 }
1037
1038 return 1;
1039}
1040
1049 MMG5_pTetra pt;
1050 MMG5_pxTetra pxt;
1051 MMG5_pPoint ppt;
1052 MMG5_int k;
1053 int8_t i;
1054
1055 for ( k=1; k<=mesh->np; k++ ) {
1056 ppt = &mesh->point[k];
1057 ppt->s = 0;
1058 }
1059
1060 /* Mark the points that belongs to a required edge */
1061 for ( k=1; k<=mesh->ne; k++ ) {
1062 pt = &mesh->tetra[k];
1063 if ( (!MG_EOK(pt)) || !pt->xt ) { continue; }
1064
1065 pxt = &mesh->xtetra[pt->xt];
1066 for (i=0; i<6; i++) {
1067 if ( pxt->tag[i] & MG_REQ ) {
1068 mesh->point[pt->v[MMG5_iare[i][0]]].s = 4*mesh->ne+3;
1069 mesh->point[pt->v[MMG5_iare[i][1]]].s = 4*mesh->ne+3;
1070 }
1071 }
1072 }
1073}
1074
1084 MMG5_pTetra pt;
1085 MMG5_pPoint p0,p1;
1086 double l,hn,ux,uy,uz;
1087 int it,maxit;
1088 MMG5_int ip0,ip1,k,nu,nup;
1089 int8_t i,j,ia,i0,i1;
1090
1091 if ( abs(mesh->info.imprim) > 5 || mesh->info.ddebug )
1092 fprintf(stdout," ** Grading mesh\n");
1093
1095
1096 for (k=1; k<=mesh->np; k++) {
1097 mesh->point[k].flag = mesh->base;
1098 }
1099
1100 it = nup = 0;
1101 maxit = 100;
1102 do {
1103 mesh->base++;
1104 nu = 0;
1105 for (k=1; k<=mesh->ne; k++) {
1106 pt = &mesh->tetra[k];
1107 if ( !MG_EOK(pt) || (pt->tag & MG_REQ) ) continue;
1108
1109 for (i=0; i<4; i++) {
1110 for (j=0; j<3; j++) {
1111 ia = MMG5_iarf[i][j];
1112 i0 = MMG5_iare[ia][0];
1113 i1 = MMG5_iare[ia][1];
1114 ip0 = pt->v[i0];
1115 ip1 = pt->v[i1];
1116 p0 = &mesh->point[ip0];
1117 p1 = &mesh->point[ip1];
1118 if ( p0->flag < mesh->base-1 && p1->flag < mesh->base-1 ) continue;
1119
1120 /* Skip points belonging to a required edge */
1121 if ( p0->s || p1->s ) continue;
1122
1123 ux = p1->c[0]-p0->c[0];
1124 uy = p1->c[1]-p0->c[1];
1125 uz = p1->c[2]-p0->c[2];
1126
1127 l = ux*ux + uy*uy + uz*uz;
1128 l = sqrt(l);
1129
1130 if ( met->m[ip0] < met->m[ip1] ) {
1131 if ( met->m[ip0] < MMG5_EPSD ) continue;
1132 hn = met->m[ip0] + mesh->info.hgrad*l;
1133 if ( met->m[ip1] > hn ) {
1134 met->m[ip1] = hn;
1135 p1->flag = mesh->base;
1136 nu++;
1137 }
1138 }
1139 else {
1140 if ( met->m[ip1] < MMG5_EPSD ) continue;
1141 hn = met->m[ip1] + mesh->info.hgrad*l;
1142 if ( met->m[ip0] > hn ) {
1143 met->m[ip0] = hn;
1144 p0->flag = mesh->base;
1145 nu++;
1146 }
1147 }
1148 }
1149 }
1150 }
1151 nup += nu;
1152 }
1153 while( ++it < maxit && nu > 0 );
1154
1155 if ( abs(mesh->info.imprim) > 4 )
1156 fprintf(stdout," gradation: %7" MMG5_PRId " updated, %d iter.\n",nup,it);
1157 return 1;
1158}
1159
1169 MMG5_pTetra pt;
1170 MMG5_pPoint p0,p1;
1171 double hgrad,ll,h0,h1,hn,ux,uy,uz;
1172 int it,maxit;
1173 MMG5_int ip0,ip1,ipslave,ipmaster,k,nu,nup;
1174 int8_t i,j,ia,i0,i1;
1175
1176 if ( abs(mesh->info.imprim) > 5 || mesh->info.ddebug ) {
1177 fprintf(stdout," ** Grading required points.\n");
1178 }
1179
1180 if ( mesh->info.hgrad < 0. ) {
1183 }
1184
1186 hgrad = mesh->info.hgradreq;
1187 it = nup = 0;
1188 maxit = 100;
1189
1190 do {
1191 nu = 0;
1192 for (k=1; k<=mesh->ne; k++) {
1193 pt = &mesh->tetra[k];
1194 if ( !MG_EOK(pt) ) {
1195 continue;
1196 }
1197
1198 for (i=0; i<4; i++) {
1199 for (j=0; j<3; j++) {
1200 ia = MMG5_iarf[i][j];
1201 i0 = MMG5_iare[ia][0];
1202 i1 = MMG5_iare[ia][1];
1203 ip0 = pt->v[i0];
1204 ip1 = pt->v[i1];
1205 p0 = &mesh->point[ip0];
1206 p1 = &mesh->point[ip1];
1207
1208 if ( MMG5_abs ( p0->s - p1->s ) < 2 ) {
1209 /* No size to propagate */
1210 continue;
1211 }
1212 else if ( p0->s > p1->s ) {
1213 ipmaster = ip0;
1214 ipslave = ip1;
1215 }
1216 else {
1217 assert ( p1->s > p0->s );
1218 ipmaster = ip1;
1219 ipslave = ip0;
1220 }
1221
1222 ux = p1->c[0]-p0->c[0];
1223 uy = p1->c[1]-p0->c[1];
1224 uz = p1->c[2]-p0->c[2];
1225
1226 ll = ux*ux + uy*uy + uz*uz;
1227 ll = sqrt(ll);
1228
1229 h0 = met->m[ipmaster];
1230 h1 = met->m[ipslave];
1231 if ( h0 < h1 ) {
1232 if ( h0 < MMG5_EPSD ) {
1233 continue;
1234 }
1235 hn = h0 + hgrad*ll;
1236 if ( h1 <= hn ) {
1237 continue;
1238 }
1239 }
1240 else {
1241 hn = h0 - hgrad*ll;
1242 if ( h1 >= hn ) {
1243 continue;
1244 }
1245 }
1246 met->m[ipslave] = hn;
1247 mesh->point[ipslave].s = mesh->point[ipmaster].s - 1;
1248 nu++;
1249 }
1250 }
1251 }
1252 nup += nu;
1253 }
1254 while ( ++it < maxit && nu > 0 );
1255
1256 if ( abs(mesh->info.imprim) > 4 && nup ) {
1257 fprintf(stdout," gradation (required): %7" MMG5_PRId " updated, %d iter.\n",nup,it);
1258 }
1259
1260 return nup;
1261}
int MMG3D_Set_solSize(MMG5_pMesh mesh, MMG5_pSol sol, int typEntity, MMG5_int np, int typSol)
MMG5_pMesh * mesh
int MMG5_BezierEdge(MMG5_pMesh mesh, MMG5_int ip0, MMG5_int ip1, double b0[3], double b1[3], int8_t ised, double v[3])
Definition: bezier_3d.c:152
MMG5_Info info
int MMG5_boulevolp(MMG5_pMesh mesh, MMG5_int start, int ip, int64_t *list)
Definition: boulep_3d.c:54
int MMG5_boulesurfvolp(MMG5_pMesh mesh, MMG5_int start, int ip, int iface, int64_t *listv, int *ilistv, MMG5_int *lists, int *ilists, int isnm)
Definition: boulep_3d.c:607
int MMG5_eigensym(double m[3], double lambda[2], double vp[2][2])
Definition: eigenv.c:973
#define MMG5_EPSD
#define MMG5_EPS
int MMG5_hashNew(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int hsiz, MMG5_int hmax)
Definition: hash.c:526
MMG5_int MMG5_hashGet(MMG5_Hash *hash, MMG5_int a, MMG5_int b)
Definition: hash.c:495
int MMG5_hashEdge(MMG5_pMesh mesh, MMG5_Hash *hash, MMG5_int a, MMG5_int b, MMG5_int k)
Definition: hash.c:345
int MMG5_sum_reqEdgeLengthsAtPoint(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int ip0, MMG5_int ip1)
Definition: isosiz.c:129
int MMG5_defsiz_startingMessage(MMG5_pMesh mesh, MMG5_pSol met, const char *funcname)
Definition: isosiz.c:77
#define A64TH
Definition: isosiz_3d.c:43
double MMG5_lenedgCoor_iso(double *ca, double *cb, double *ma, double *mb)
Compute edge length from edge's coordinates.
Definition: isosiz_3d.c:61
#define A16TH
Definition: isosiz_3d.c:44
double MMG5_meansizreg_iso(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int nump, MMG5_int *lists, int ilists, double hmin, double hmax)
Definition: isosiz_3d.c:482
int MMG3D_set_metricAtPointsOnReqEdges(MMG5_pMesh mesh, MMG5_pSol met, int8_t ismet)
Definition: isosiz_3d.c:564
void MMG3D_mark_pointsOnReqEdge_fromTetra(MMG5_pMesh mesh)
Definition: isosiz_3d.c:1048
static int MMG3D_sum_reqEdgeLengthsAtPoint(MMG5_pMesh mesh, MMG5_pSol met, MMG5_Hash *hash, MMG5_pTetra pt, int8_t i)
Definition: isosiz_3d.c:533
int MMG3D_gradsizreq_iso(MMG5_pMesh mesh, MMG5_pSol met)
Definition: isosiz_3d.c:1168
int8_t ddb
Definition: mmg3d1_delone.c:42
int MMG3D_gradsiz_iso(MMG5_pMesh mesh, MMG5_pSol met)
Definition: isosiz_3d.c:1083
int MMG3D_defsiz_iso(MMG5_pMesh mesh, MMG5_pSol met)
Definition: isosiz_3d.c:662
#define MAXLEN
Definition: isosiz_3d.c:42
static double MMG5_defsizreg(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int nump, MMG5_int *lists, int ilists, double hmin, double hmax, double hausd)
Definition: isosiz_3d.c:92
#define A32TH
Definition: isosiz_3d.c:45
API headers for the mmg3d library.
#define MMG3D_LMAX
Definition: libmmg3d.h:58
int MMG3D_localParamReg(MMG5_pMesh, MMG5_int, int64_t *, int, MMG5_int *, int, double *, double *, double *)
Definition: tools_3d.c:1023
int MMG3D_localParamNm(MMG5_pMesh, MMG5_int, int, int, double *, double *, double *)
Definition: tools_3d.c:1143
static const int8_t MMG5_iarf[4][3]
iarf[i]: edges of face opposite to vertex i
static const uint8_t MMG5_iare[6][2]
vertices of extremities of the edges of the tetra
void MMG5_tet2tri(MMG5_pMesh mesh, MMG5_int k, int8_t ie, MMG5_Tria *ptt)
Definition: mmg3d1.c:102
int MMG5_norface(MMG5_pMesh mesh, MMG5_int k, int iface, double v[3])
Definition: tools_3d.c:52
static const uint8_t MMG5_idir[4][3]
idir[i]: vertices of face opposite to vertex i
@ MMG5_Scalar
Definition: libmmgtypes.h:213
@ MMG5_Vertex
Definition: libmmgtypes.h:224
@ MMG5_Tetrahedron
Definition: libmmgtypes.h:227
#define MG_Vert
#define MG_REQ
#define MG_EOK(pt)
#define MG_PARBDY
#define MG_MIN(a, b)
#define MG_MAX(a, b)
#define MG_EDG(tag)
#define MMG5_ATHIRD
#define MG_EDG_OR_NOM(tag)
#define MG_SIN(tag)
#define MG_Tetra
#define MG_GET(flag, bit)
static const uint8_t MMG5_inxt2[6]
#define MG_CRN
int MMG5_rotmatrix(double n[3], double r[3][3])
Definition: tools.c:467
int MMG5_sys33sym(double a[6], double b[3], double r[3])
Definition: tools.c:769
#define MG_BDY
#define MG_NOSURF
#define MG_NOM
#define MG_SIN_OR_NOM(tag)
#define MMG5_DEL_MEM(mesh, ptr)
double b[10][3]
Identic as MMG5_HGeom but use MMG5_hedge to store edges instead of MMG5_hgeom (memory economy).
Definition: libmmgtypes.h:595
MMG5_hedge * item
Definition: libmmgtypes.h:597
int8_t parTyp
Definition: libmmgtypes.h:541
int8_t ddebug
Definition: libmmgtypes.h:532
double hmin
Definition: libmmgtypes.h:518
double hgrad
Definition: libmmgtypes.h:518
double hmax
Definition: libmmgtypes.h:518
uint8_t nosizreq
Definition: libmmgtypes.h:546
MMG5_pPar par
Definition: libmmgtypes.h:517
double hgradreq
Definition: libmmgtypes.h:518
double hausd
Definition: libmmgtypes.h:518
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_int ne
Definition: libmmgtypes.h:612
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_pPrism prism
Definition: libmmgtypes.h:645
MMG5_pxPoint xpoint
Definition: libmmgtypes.h:642
MMG5_int base
Definition: libmmgtypes.h:616
MMG5_pTetra tetra
Definition: libmmgtypes.h:643
MMG5_int np
Definition: libmmgtypes.h:612
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:644
MMG5_int nprism
Definition: libmmgtypes.h:613
double hmin
Definition: libmmgtypes.h:258
double hmax
Definition: libmmgtypes.h:259
MMG5_int ref
Definition: libmmgtypes.h:261
int8_t elt
Definition: libmmgtypes.h:262
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
double n[3]
Definition: libmmgtypes.h:272
int16_t tag
Definition: libmmgtypes.h:284
double c[3]
Definition: libmmgtypes.h:271
MMG5_int xp
Definition: libmmgtypes.h:279
MMG5_int s
Definition: libmmgtypes.h:283
MMG5_int ref
Definition: libmmgtypes.h:278
MMG5_int flag
Definition: libmmgtypes.h:282
MMG5_int v[6]
Definition: libmmgtypes.h:463
double * m
Definition: libmmgtypes.h:671
MMG5_int np
Definition: libmmgtypes.h:665
MMG5_int v[4]
Definition: libmmgtypes.h:403
MMG5_int xt
Definition: libmmgtypes.h:407
MMG5_int ref
Definition: libmmgtypes.h:404
int16_t tag
Definition: libmmgtypes.h:410
MMG5_int v[3]
Definition: libmmgtypes.h:334
double n1[3]
Definition: libmmgtypes.h:295
Structure to store the surface tetrahedra of a MMG mesh.
Definition: libmmgtypes.h:418
int16_t ftag[4]
Definition: libmmgtypes.h:423
int16_t tag[6]
Definition: libmmgtypes.h:425
int8_t ori
Definition: libmmgtypes.h:427