Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
opttyp_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
33#include "libmmg3d.h"
35
65static int MMG3D_typelt(MMG5_pMesh mesh,MMG5_int iel,int *item) {
66 MMG5_pTetra pt;
67 MMG5_pPoint pa,pb,pc,pd;
68 double abx,aby,abz,acx,acy,acz,adx,ady,adz,v1,v2,v3,vol;
69 double bcx,bcy,bcz,bdx,bdy,bdz,cdx,cdy,cdz,h[6],volchk,ssmall;
70 double s[4],dd,rapmin,rapmax,surmin,surmax;
71 int i,k,isur,isurmax,isurmin,iarmax,iarmin;
72 MMG5_int ia,ib,ic,id;
73 int nobtus,naigu;
74 short i0,i1,i2;
75 double EPSVOL = 0.001;
76 double RAPMAX = 0.25;
77
78 pt = &mesh->tetra[iel];
79 if ( !pt->v[0] ) return -1;
80
81 ia = pt->v[0];
82 ib = pt->v[1];
83 ic = pt->v[2];
84 id = pt->v[3];
85 pa = &mesh->point[ia];
86 pb = &mesh->point[ib];
87 pc = &mesh->point[ic];
88 pd = &mesh->point[id];
89
90 /* volume */
91 abx = pb->c[0] - pa->c[0];
92 aby = pb->c[1] - pa->c[1];
93 abz = pb->c[2] - pa->c[2];
94
95 acx = pc->c[0] - pa->c[0];
96 acy = pc->c[1] - pa->c[1];
97 acz = pc->c[2] - pa->c[2];
98
99 adx = pd->c[0] - pa->c[0];
100 ady = pd->c[1] - pa->c[1];
101 adz = pd->c[2] - pa->c[2];
102
103 v1 = acy*adz - acz*ady;
104 v2 = acz*adx - acx*adz;
105 v3 = acx*ady - acy*adx;
106 vol = abx * v1 + aby * v2 + abz * v3;
107
108 /* max edge */
109 h[0] = abx*abx + aby*aby + abz*abz;
110 h[1] = acx*acx + acy*acy + acz*acz;
111 h[2] = adx*adx + ady*ady + adz*adz;
112
113 bcx = pc->c[0] - pb->c[0];
114 bcy = pc->c[1] - pb->c[1];
115 bcz = pc->c[2] - pb->c[2];
116
117 bdx = pd->c[0] - pb->c[0];
118 bdy = pd->c[1] - pb->c[1];
119 bdz = pd->c[2] - pb->c[2];
120
121 cdx = pd->c[0] - pc->c[0];
122 cdy = pd->c[1] - pc->c[1];
123 cdz = pd->c[2] - pc->c[2];
124
125 h[3] = bcx*bcx + bcy*bcy + bcz*bcz;
126 h[4] = bdx*bdx + bdy*bdy + bdz*bdz;
127 h[5] = cdx*cdx + cdy*cdy + cdz*cdz;
128
129 /* face areas */
130 dd = cdy*bdz - cdz*bdy;
131 s[0] = dd * dd;
132 dd = cdz*bdx - cdx*bdz;
133 s[0] = s[0] + dd * dd;
134 dd = cdx*bdy - cdy*bdx;
135 s[0] = s[0] + dd * dd;
136 s[0] = sqrt(s[0]);
137
138 s[1] = sqrt(v1*v1 + v2*v2 + v3*v3);
139
140 dd = bdy*adz - bdz*ady;
141 s[2] = dd * dd;
142 dd = bdz*adx - bdx*adz;
143 s[2] = s[2] + dd * dd;
144 dd = bdx*ady - bdy*adx;
145 s[2] = s[2] + dd * dd;
146 s[2] = sqrt(s[2]);
147
148 dd = aby*acz - abz*acy;
149 s[3] = dd * dd;
150 dd = abz*acx - abx*acz;
151 s[3] = s[3] + dd * dd;
152 dd = abx*acy - aby*acx;
153 s[3] = s[3] + dd * dd;
154 s[3] = sqrt(s[3]);
155
156 /* classification */
157 rapmin = h[0];
158 rapmax = h[0];
159 iarmin = 0;
160 iarmax = 0;
161 for (i=1; i<6; i++) {
162 if ( h[i] < rapmin ) {
163 rapmin = h[i];
164 iarmin = i;
165 }
166 else if ( h[i] > rapmax ) {
167 rapmax = h[i];
168 iarmax = i;
169 }
170 }
171 rapmin = sqrt(rapmin);
172 rapmax = sqrt(rapmax);
173 volchk = EPSVOL * rapmin*rapmin*rapmin;
174
175 /* small volume: types 1,2,3,4 */
176 item[0] = item[1] = -1;
177 if ( vol < volchk ) {
178 // puts("volume nul : type 1,2,3,4");
179 ssmall = 0.4 * (s[0]+s[1]+s[2]+s[3]);
180 isur = 0;
181 for (i=0; i<4; i++)
182 isur += s[i] > ssmall;
183
184 /* types 2,3 */
185 item[0] = iarmax;
186 item[1] = MMG5_isar[iarmax][0];
187 if ( isur == 1 ) {
188 surmin = s[0];
189 isurmin = 0;
190 surmax = s[0];
191 isurmax = 0;
192 for (i=1; i<4; i++) {
193 if ( s[i] < surmin ) {
194 surmin = s[i];
195 isurmin = i;
196 }
197 else if ( s[i] > surmax ) {
198 surmax = s[i];
199 isurmax = i;
200 }
201 }
202 dd = surmin / surmax;
203 if ( dd < RAPMAX ) {
204 item[1] = MMG5_isar[iarmax][0];
205 return 3;
206 }
207 else {
208 item[0] = isurmax;
209 item[1] = isurmin;
210 return 2;
211 }
212 }
213
214 /* type 1 */
215 isur = 0;
216 if ( s[0]+s[1] > ssmall ) isur = 1;
217 if ( s[0]+s[2] > ssmall ) isur++;
218 if ( s[0]+s[3] > ssmall ) isur++;
219
220 if ( isur > 2 ) {
221 dd = rapmin / rapmax;
222 item[0] = 0; //iarmin;
223 // Changed by 0 because we overflow idir
224 item[1] = 0; //MMG5_idir[iarmin][0];
225 if ( dd < 0.01 ) return 4;
226 if ( s[0]+s[1] > ssmall ) {
227 item[0] = 0;
228 return 1;
229 }
230 if ( s[0]+s[2] > ssmall ) {
231 item[0] = 1;
232 return 1;
233 }
234 if ( s[0]+s[3] > ssmall ) {
235 item[0] = 2;
236 return 1;
237 }
238 }
239
240 //puts("default");
241 item[0] = 0;
242 return 1;
243 }/* end chkvol */
244
245 dd = rapmin / rapmax;
246 /* types 3,6,7 */
247 if ( dd < RAPMAX ) {
248 /* One edge is 4 time smaller than another one */
249
250 for (i=0; i<6; i++) h[i] = sqrt(h[i]);
251
252 nobtus = 0;
253 for (k=0; k<4; k++) {
254 for (i=0; i<3; i++) {
255 i0 = MMG5_idir[k][i];
256 i1 = MMG5_idir[k][MMG5_inxt2[i]];
257 i2 = MMG5_idir[k][MMG5_inxt2[i+1]];
258 if ( h[i0]+h[i1] < 1.2*h[i2] ) {
259 /* Obtuse face */
260 nobtus++;
261 item[0] = i2;
262 item[1] = MMG5_idir[k][MMG5_inxt2[i+1]];
263 }
264 }
265 }
266
267 switch(nobtus){
268 case 0 :
269 break;
270 case 1:
271 item[0] = iarmax;
272 item[1] = MMG5_isar[iarmax][0];
273 return 3;
274 case 2:
275 item[0] = iarmin;
276 item[1] = iarmax;
277 return 6;
278 default:
279 item[0] = iarmin;
280 item[1] = iarmax;
281 return 7;
282 }
283 }
284
285 /* type 4,5,7 */
286 else if ( dd < 0.7*RAPMAX ) {
287 naigu = 0;
288 for (k=0; k<4; k++) {
289 for (i=0; i<3; i++) {
290 i0 = MMG5_idir[k][i];
291 i1 = MMG5_idir[k][MMG5_inxt2[i]];
292 i2 = MMG5_idir[k][MMG5_inxt2[i+1]];
293 if ( h[i0]+h[i1] > 1.5*h[i2] ) naigu++;
294 }
295 }
296 switch(naigu){
297 case 0 :
298 break;
299 case 1:
300 break;
301 case 2:
302 item[0] = iarmin;
303 return 4;
304 case 3:
305 /* Item to define */
306 return 5;
307 default:
308 item[0] = iarmin;
309 item[1] = iarmax;
310 return 7;
311 }
312 }
313 item[0] = 0;
314 return 1;
315}
316
328int MMG3D_swpItem(MMG5_pMesh mesh, MMG5_pSol met,MMG3D_pPROctree PROctree,MMG5_int k,int iar) {
329 MMG5_pTetra pt;
330 MMG5_pxTetra pxt;
331 int64_t list[MMG3D_LMAX+2];
332 MMG5_int nconf;
333 int lon,ier;
334 double OCRIT = 1.01;
335
336 ier = 0;
337 pt = &mesh->tetra[k];
338 /* Prevent swap of a ref or tagged edge */
339 if ( pt->xt ) {
340 pxt = &mesh->xtetra[pt->xt];
341 if ( pxt->edg[iar] || pxt->tag[iar] ) return 0;
342 }
343
344 nconf = MMG5_chkswpgen(mesh,met,k,iar,&lon,list,OCRIT,2);
345 if ( nconf ) {
346 ier = MMG5_swpgen(mesh,met,nconf,lon,list,PROctree,2);
347 if ( ier < 0 ) return -1;
348 else
349 return ier;
350 }
351
352 return ier;
353}
354
366static inline
368 MMG5_int k,int iar) {
369 int i,ier;
370
371 ier = 0;
372 for(i=0 ; i<6 ; i++) {
373 if(i==iar) continue;
374 ier = MMG3D_swpItem(mesh,met,PROctree,k,i);
375 if ( ier < 0 ) return -1;
376 else if(ier)
377 return ier;
378 }
379 return ier;
380}
381
395 MMG5_int k,int iar,double OCRIT) {
396 MMG5_pTetra pt;
397 double len;
398 double LLONG2 = 0.1;
399 int j;
400 MMG5_int ier;
401
402 ier = 0;
403 pt = &mesh->tetra[k];
404
405 if ( mesh->info.noinsert ) return 0;
406
407 len = MMG5_lenedg(mesh,met,iar,pt);
408 if(len > LLONG2) {
409 ier = MMG5_splitedg(mesh,met,k,iar,OCRIT);
410 }
411
412 if ( ier && !mesh->info.nomove ) {
413 /*if there is a reallocation inside splitedg, the pointer is unvalid*/
414 pt = &mesh->tetra[k];
415 for(j=0 ; j<4 ; j++) {
416 if(pt->v[j] == ier) break;
417 }
418 assert(j<4);
419 if(met->size!=1)
420 ier = MMG3D_movv_ani(mesh,met,k,j);
421 else
422 ier = MMG3D_movv_iso(mesh,met,k,j);
423
424 }
425 return ier;
426}
427
439static inline
441 MMG5_int k,int iar) {
442 int i,ier;
443 double OCRIT=1.01;
444
445 ier = 0;
446
447 /* if(MMG5_orvolnorm(mesh,k) < 5.e-9) { */
448 /* OCRIT *= 0.5; */
449 /* } else */
450 /* OCRIT *= 0.75; */
451
452 for(i=0 ; i<6 ; i++) {
453 if(i==iar) continue;
454 ier = MMG3D_splitItem(mesh,met,PROctree,k,i,OCRIT);
455 if(ier) return ier;
456 }
457
458 return ier;
459}
460
472MMG5_int MMG3D_opttyp(MMG5_pMesh mesh, MMG5_pSol met,MMG3D_pPROctree PROctree,MMG5_int testmark) {
473 MMG5_pTetra pt;
474 MMG5_pxTetra pxt;
475 double crit;
476 int ityp,item[2];
477 MMG5_int k,ntot,ne,nd,cs[10],ds[10];
478 int ier,i,npeau;
479 int it,maxit;
480// double OCRIT = 1.01;
481 MMG5_int nbdy,nbdy2,base ;
482
483 ntot = 0;
484 crit = 0.2 / MMG3D_ALPHAD;
485 base = testmark;
486
487 it = 0;
488 maxit = 10;
489 do {
490 ne = mesh->ne;
491 nd = 0;
492 nbdy = nbdy2 = 0;
493 memset(cs,0,10*sizeof(MMG5_int));
494 memset(ds,0,10*sizeof(MMG5_int));
495
496 for (k=1 ; k<=ne ; k++) {
497 pt = &mesh->tetra[k];
498 if(!MG_EOK(pt) || (pt->tag & MG_REQ) ) continue;
499 else if ( pt->mark < base ) continue;
500
501 if(pt->qual > crit) continue;
502
503 ityp = MMG3D_typelt(mesh,k,item);
504 cs[ityp]++;
505
506 /*tet with bdry faces*/
507 pxt = pt->xt ? &mesh->xtetra[pt->xt] : 0;
508
509 /*optim bdry tetra*/
510 npeau = 0;
511 if ( pxt ) {
512 for(i=0 ; i<4 ; i++) {
513 if ( pxt->ftag[i] & MG_BDY ) npeau++;
514 }
515
516 if(npeau>1) {
517 nbdy++;
518 continue;
519 } else if ( npeau ) {
520 nbdy2++;
521
522 ier = MMG3D_optbdry(mesh,met,PROctree,k);
523 if(ier) {
524 nd++;
525 ds[ityp]++;
526 continue;
527 }
528 }
529 }
530
531 switch(ityp) {
532
533 case 1: /* sliver */
534 case 3: /* fin */
535 case 6: /* no good face: move away closest vertices */
536 case 7:
537 default:
538
539 if(mesh->info.noswap) break;
540
541 ier = MMG3D_swpItem(mesh,met,PROctree,k,item[0]);
542
543 if(ier > 0) {
544 nd++;
545 ds[ityp]++;
546 break;
547 } else if(!ier) {
548 /* second try to split the biggest edge */
549 if(!mesh->info.noinsert) {
550 /* if(MMG5_orvolnorm(mesh,k) < 5.e-9) { */
551 /* OCRIT *= 0.5; */
552 /* } else */
553 /* OCRIT *= 0.75; */
554 ier = MMG3D_splitItem(mesh,met,PROctree,k,item[0],1.01);
555
556 if(ier) {
557 nd++;
558 ds[ityp]++;
559 break;
560 }
561 } /* end noinsert */
562
563 ier = MMG3D_swpalmostall(mesh,met,PROctree,k,item[0]);
564
565 if(ier > 0) {
566 nd++;
567 ds[ityp]++;
568 break;
569 }
570
571 if ( !mesh->info.noinsert ) {
572 ier = MMG3D_splitalmostall(mesh,met,PROctree,k,item[0]);
573
574 if(ier > 0) {
575 nd++;
576 ds[ityp]++;
577 break;
578 }
579 }
580 }
581 if ( !mesh->info.nomove ) {
582 for(i=0 ; i<4 ; i++) {
583 if ( ((met->size!=1) && MMG3D_movv_ani(mesh,met,k,i)) ||
584 ((met->size==1) && MMG3D_movv_iso(mesh,met,k,i)) ) {
585 nd++;
586 ds[ityp]++;
587 break;
588 }
589 }
590 }
591 break;
592 case 2: /*chapeau*/
593 if ( !mesh->info.nomove ) {
594 if ( ( (met->size!=1) && MMG3D_movv_ani(mesh,met,k,item[0])) ||
595 ((met->size==1) && MMG3D_movv_iso(mesh,met,k,item[0])) ) {
596 nd++;
597 ds[ityp]++;
598 } else {
599 for(i=0 ; i<4 ; i++) {
600 if(item[0]==i) continue;
601 if( ((met->size!=1) && MMG3D_movv_ani(mesh,met,k,i)) ||
602 ((met->size==1) && MMG3D_movv_iso(mesh,met,k,i)) ) {
603 nd++;
604 ds[ityp]++;
605 break;
606 }
607 }
608 }
609 }
610 break;
611 } /* end switch */
612 } /* end for k */
613
614 /* printf("bdry : %" MMG5_PRId " %" MMG5_PRId "\n",nbdy,nbdy2); */
615 /* for (k=0; k<=7; k++) */
616 /* if ( cs[k] ) */
617 /* printf(" optim [%" MMG5_PRId "] = %5d %5d %6.2f %%\n",k,cs[k],ds[k],100.0*ds[k]/cs[k]); */
618
619 ntot += nd;
620 if(base==-1) base = mesh->mark-1;
621 } while (nd && it++<maxit);
622
623 return ntot;
624}
int ier
MMG5_pMesh * mesh
API headers for the mmg3d library.
#define MMG3D_LMAX
Definition: libmmg3d.h:58
#define MMG3D_ALPHAD
int MMG3D_movv_ani(MMG5_pMesh, MMG5_pSol, MMG5_int, int)
Definition: movpt_3d.c:1626
MMG5_int MMG5_chkswpgen(MMG5_pMesh, MMG5_pSol, MMG5_int, int, int *, int64_t *, double, int8_t)
Definition: swapgen_3d.c:57
MMG5_int MMG5_splitedg(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int iel, int iar, double crit)
Definition: split_3d.c:4753
static const uint8_t MMG5_isar[6][2]
isar[i][]: vertices of extremities of the edge opposite to the ith edge
int MMG3D_movv_iso(MMG5_pMesh, MMG5_pSol, MMG5_int, int)
Definition: movpt_3d.c:1875
int MMG3D_optbdry(MMG5_pMesh, MMG5_pSol, MMG3D_pPROctree, MMG5_int)
Definition: optbdry_3d.c:259
int MMG5_swpgen(MMG5_pMesh, MMG5_pSol, MMG5_int, int, int64_t *, MMG3D_pPROctree, int8_t)
Definition: swapgen_3d.c:271
static const uint8_t MMG5_idir[4][3]
idir[i]: vertices of face opposite to vertex i
#define MG_REQ
#define MG_EOK(pt)
static const uint8_t MMG5_inxt2[6]
#define MG_BDY
MMG5_int MMG3D_opttyp(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree PROctree, MMG5_int testmark)
Definition: opttyp_3d.c:472
static int MMG3D_swpalmostall(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree PROctree, MMG5_int k, int iar)
Definition: opttyp_3d.c:367
static int MMG3D_typelt(MMG5_pMesh mesh, MMG5_int iel, int *item)
Definition: opttyp_3d.c:65
int MMG3D_swpItem(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree PROctree, MMG5_int k, int iar)
Definition: opttyp_3d.c:328
static int MMG3D_splitalmostall(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree PROctree, MMG5_int k, int iar)
Definition: opttyp_3d.c:440
int MMG3D_splitItem(MMG5_pMesh mesh, MMG5_pSol met, MMG3D_pPROctree PROctree, MMG5_int k, int iar, double OCRIT)
Definition: opttyp_3d.c:394
uint8_t noswap
Definition: libmmgtypes.h:546
uint8_t noinsert
Definition: libmmgtypes.h:546
uint8_t nomove
Definition: libmmgtypes.h:546
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_int mark
Definition: libmmgtypes.h:618
MMG5_pTetra tetra
Definition: libmmgtypes.h:643
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:644
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
double c[3]
Definition: libmmgtypes.h:271
MMG5_int v[4]
Definition: libmmgtypes.h:403
MMG5_int xt
Definition: libmmgtypes.h:407
MMG5_int mark
Definition: libmmgtypes.h:406
double qual
Definition: libmmgtypes.h:402
int16_t tag
Definition: libmmgtypes.h:410
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
MMG5_int edg[6]
Definition: libmmgtypes.h:421