Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
swap_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"
38
39extern int8_t ddb;
40
57int MMG5_chkswpbdy(MMG5_pMesh mesh, MMG5_pSol met, int64_t *list,int ilist,
58 MMG5_int it1,MMG5_int it2,int8_t typchk) {
59 MMG5_pTetra pt,pt0;
60 MMG5_pxTetra pxt;
61 MMG5_pPoint p0,p1,ppt0;
62 MMG5_Tria tt1,tt2;
63 MMG5_pPar par;
64 double b0[3],b1[3],n[3],v[3],c[3],ux,uy,uz,ps,disnat,dischg;
65 double cal1,cal2,calnat,calchg,calold,calnew,caltmp,hausd;
66 MMG5_int iel,iel1,iel2,np,nq,na1,na2,k,nminus,nplus,info,refm;
67 int isloc,l;
68 int8_t ifa1,ifa2,ia,ip,iq,ia1,ia2,j,isshell,ier;
69
70 iel = list[0] / 6;
71 ia = list[0] % 6;
72 pt = &mesh->tetra[iel];
73 pt0 = &mesh->tetra[0];
74 ppt0= &mesh->point[0];
75 memset(ppt0,0,sizeof(MMG5_Point));
76
77 np = pt->v[MMG5_iare[ia][0]];
78 nq = pt->v[MMG5_iare[ia][1]];
79
80 // Algiane 05/04/24: I think that the assumption that was previously made that
81 // we can arrive from a tetrahedra without a boundary face (i.e. without an
82 // xtetra) never happens
83 assert ( pt->xt && "Boundary edges have to be swapped from a boundary face" );
84
85 /* No swap of geometric edge */
86 pxt = &mesh->xtetra[pt->xt];
87 if ( (pxt->edg[ia]>0) || MG_EDG_OR_NOM(pxt->tag[ia]) || (pxt->tag[ia] & MG_REQ) ) {
88 return 0;
89 }
90
91 /* No swap when either internal or external component has only 1 element (as
92 * we can't swap geometric edges here we know that the edge shares at most 2
93 * domains).*/
94 nminus = nplus = 0;
95 refm = pt->ref;
96 for (k=0; k<ilist; k++) {
97 iel = list[k] / 6;
98 pt = &mesh->tetra[iel];
99 if ( pt->ref == refm ) {
100 nminus++;
101 }
102 else {
103 nplus++;
104 }
105 }
106 if ( nplus == 1 || nminus == 1 ) return 0;
107
108 iel1 = it1 / 4;
109 ifa1 = it1 % 4;
110
111 assert(it2);
112 iel2 = it2 / 4;
113 ifa2 = it2 % 4;
114 assert( 0<=ifa1 && ifa1<4 && "unexpected local face idx");
115 assert( 0<=ifa2 && ifa2<4 && "unexpected local face idx");
116 MMG5_tet2tri(mesh,iel1,ifa1,&tt1);
117 MMG5_tet2tri(mesh,iel2,ifa2,&tt2);
118
119 for (ia1=0; ia1<3; ia1++) {
120 if ( (tt1.v[ia1] != np) && (tt1.v[ia1] != nq) ) break;
121 }
122 assert( ia1 < 3 );
123 if ( ia1==3 ) return 0;
124
125 assert( (tt1.v[MMG5_inxt2[ia1]] == np && tt1.v[MMG5_iprv2[ia1]] == nq) ||
126 (tt1.v[MMG5_inxt2[ia1]] == nq && tt1.v[MMG5_iprv2[ia1]] == np) );
127 na1 = tt1.v[ia1];
128
129 for (ia2=0; ia2<3; ia2++) {
130 if ( (tt2.v[ia2] != np) && (tt2.v[ia2] != nq) ) break;
131 }
132
133 assert ( ia2 < 3 );
134 if ( ia2 ==3 ) return 0;
135
136 assert ( (tt2.v[MMG5_inxt2[ia2]] == np && tt2.v[MMG5_iprv2[ia2]] == nq) ||
137 (tt2.v[MMG5_inxt2[ia2]] == nq && tt2.v[MMG5_iprv2[ia2]] == np) );
138 na2 = tt2.v[ia2];
139
140 /* Check non convexity (temporarily use b0,b1)*/
141 MMG5_norpts(mesh,tt1.v[ia1],tt1.v[MMG5_inxt2[ia1]],tt2.v[ia2],b0);
142 MMG5_norpts(mesh,tt2.v[ia2],tt2.v[MMG5_inxt2[ia2]],tt1.v[ia1],b1);
143 ps = b0[0]*b1[0] + b0[1]*b1[1] + b0[2]*b1[2];
144
145 /* Here we put ANGEDG because in nr mode the test over dhd may create inverted
146 * tetra */
147 if ( ps < MMG5_ANGEDG ) {
148 return 0;
149 }
150
151 /* Check normal deviation with neighbours */
152 if ( !MG_GEO_OR_NOM( tt1.tag[MMG5_iprv2[ia1]] ) ) {
153 ier = MMG3D_normalAdjaTri(mesh,iel1,ifa1,MMG5_iprv2[ia1],n);
154 if ( ier < 0 ) return -1;
155 else if ( !ier ) return 0;
156 ps = b0[0]*n[0] + b0[1]*n[1] + b0[2]*n[2];
157
158 if ( ps < mesh->info.dhd ) return 0;
159 }
160
161 if ( !MG_GEO_OR_NOM( tt2.tag[MMG5_inxt2[ia2]]) ) {
162 ier = MMG3D_normalAdjaTri(mesh,iel2,ifa2,MMG5_inxt2[ia2],n);
163 if ( ier<0 ) return -1;
164 else if ( !ier ) return 0;
165 ps = b0[0]*n[0] + b0[1]*n[1] + b0[2]*n[2];
166
167 if ( ps < mesh->info.dhd ) return 0;
168 }
169
170 if ( !MG_GEO_OR_NOM( tt1.tag[MMG5_inxt2[ia1]] ) ) {
171 ier = MMG3D_normalAdjaTri(mesh,iel1,ifa1,MMG5_inxt2[ia1],n);
172 if ( ier<0 ) return -1;
173 else if ( !ier ) return 0;
174 ps = b1[0]*n[0] + b1[1]*n[1] + b1[2]*n[2];
175
176 if ( ps < mesh->info.dhd ) return 0;
177 }
178
179 if ( !MG_GEO_OR_NOM(tt2.tag[MMG5_iprv2[ia2]]) ) {
180 ier = MMG3D_normalAdjaTri(mesh,iel2,ifa2,MMG5_iprv2[ia2],n);
181 if ( ier<0 ) return -1;
182 else if ( !ier ) return 0;
183 ps = b1[0]*n[0] + b1[1]*n[1] + b1[2]*n[2];
184
185 if ( ps < mesh->info.dhd ) return 0;
186 }
187
188 /* Compare contributions to Hausdorff distance in both configurations */
189 MMG5_norface(mesh,iel1,ifa1,v);
190
191 p0 = &mesh->point[np];
192 p1 = &mesh->point[nq];
193
194 /* local parameters */
195 hausd = mesh->info.hausd;
196 isloc = 0;
197
198 /* Local params at triangles containing the edge */
199 if ( mesh->info.parTyp & MG_Tria ) {
200 if ( tt1.ref == tt2.ref ) {
201 for ( l=0; l<mesh->info.npar; ++l ) {
202 par = &mesh->info.par[l];
203 if ( par->elt != MMG5_Triangle ) continue;
204
205 hausd = par->hausd;
206 isloc = 1;
207 break;
208 }
209 }
210 else {
211 l = 0;
212 info = -1000;
213 do {
214 if ( isloc ) break;
215 par = &mesh->info.par[l];
216 if ( par->elt != MMG5_Triangle ) continue;
217
218 if ( tt1.ref!=par->ref && tt2.ref !=par->ref ) continue;
219
220 hausd = par->hausd;
221 isloc = 1;
222 info = par->ref;
223 } while ( ++l < mesh->info.npar );
224
225 for ( ; l<mesh->info.npar; ++l ) {
226 par = &mesh->info.par[l];
227 if ( par->elt != MMG5_Triangle || par->ref==info ) continue;
228
229 if ( tt1.ref!=par->ref && tt2.ref !=par->ref ) continue;
230
231 hausd = MG_MIN(hausd,par->hausd);
232 break;
233 }
234 }
235 }
236
237 /* Local params at tetra of the edge shell */
238 if ( mesh->info.parTyp & MG_Tetra ) {
239 l = 0;
240 do
241 {
242 if ( isloc ) break;
243
244 par = &mesh->info.par[l];
245 if ( par->elt != MMG5_Tetrahedron ) continue;
246
247 for ( k=0; k<ilist; ++k ) {
248 pt = &mesh->tetra[list[k]/6];
249 if ( par->ref != pt->ref ) continue;
250
251 hausd = par->hausd;
252 isloc = 1;
253 }
254 } while ( ++l<mesh->info.npar );
255
256 for ( ; l<mesh->info.npar; ++l ) {
257 par = &mesh->info.par[l];
258 if ( par->elt != MMG5_Tetrahedron ) continue;
259
260 for ( k=0; k<ilist; ++k ) {
261 pt = &mesh->tetra[list[k]/6];
262 if ( par->ref != pt->ref ) continue;
263
264 hausd = MG_MIN(hausd,par->hausd);
265 break;
266 }
267 }
268 }
269
270 ux = p1->c[0] - p0->c[0];
271 uy = p1->c[1] - p0->c[1];
272 uz = p1->c[2] - p0->c[2];
273
274 MMG5_BezierEdge(mesh,np,nq,b0,b1,0,v);
275 c[0] = b0[0] - (p0->c[0] + MMG5_ATHIRD*ux);
276 c[1] = b0[1] - (p0->c[1] + MMG5_ATHIRD*uy);
277 c[2] = b0[2] - (p0->c[2] + MMG5_ATHIRD*uz);
278
279 disnat = c[0]*c[0] + c[1]*c[1] + c[2]*c[2];
280
281 c[0] = b1[0] - (p1->c[0] - MMG5_ATHIRD*ux);
282 c[1] = b1[1] - (p1->c[1] - MMG5_ATHIRD*uy);
283 c[2] = b1[2] - (p1->c[2] - MMG5_ATHIRD*uz);
284
285 disnat = MG_MAX(disnat, c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
286
287 /* local param at vertices */
288 // hausd = min (hausd_ref, hausd_np,hausd_nq)
289 disnat = MG_MAX(disnat,hausd * hausd);
290
291 p0 = &mesh->point[na1];
292 p1 = &mesh->point[na2];
293 ux = p1->c[0] - p0->c[0];
294 uy = p1->c[1] - p0->c[1];
295 uz = p1->c[2] - p0->c[2];
296
297 /* local param at vertices */
298 // hausd = min (hausd_ref, hausd_na1,hausd_na2)
299 MMG5_BezierEdge(mesh,na1,na2,b0,b1,0,v);
300 c[0] = b0[0] - (p0->c[0] + MMG5_ATHIRD*ux);
301 c[1] = b0[1] - (p0->c[1] + MMG5_ATHIRD*uy);
302 c[2] = b0[2] - (p0->c[2] + MMG5_ATHIRD*uz);
303
304 dischg = c[0]*c[0] + c[1]*c[1] + c[2]*c[2];
305
306 c[0] = b1[0] - (p1->c[0] - MMG5_ATHIRD*ux);
307 c[1] = b1[1] - (p1->c[1] - MMG5_ATHIRD*uy);
308 c[2] = b1[2] - (p1->c[2] - MMG5_ATHIRD*uz);
309
310 dischg = MG_MAX(dischg,c[0]*c[0] + c[1]*c[1] + c[2]*c[2]);
311 dischg = MG_MAX(dischg,hausd * hausd);
312
313 if ( dischg > disnat ) return 0;
314
315 if ( typchk==1 && met->size > 1 && met->m ) {
316 cal1 = MMG5_caltri33_ani(mesh,met,&tt1);
317 cal2 = MMG5_caltri33_ani(mesh,met,&tt2);
318 }
319 else {
320 cal1 = MMG5_caltri(mesh,met,&tt1);
321 cal2 = MMG5_caltri(mesh,met,&tt2);
322 }
323
324 calnat = MG_MIN(cal1,cal2);
325 for (j=0; j<3; j++) {
326 if ( tt1.v[j] == nq ) tt1.v[j] = na2;
327 if ( tt2.v[j] == np ) tt2.v[j] = na1;
328 }
329
330 if ( typchk==1 && met->size > 1 && met->m ) {
331 cal1 = MMG5_caltri33_ani(mesh,met,&tt1);
332 cal2 = MMG5_caltri33_ani(mesh,met,&tt2);
333 }
334 else {
335 cal1 = MMG5_caltri(mesh,met,&tt1);
336 cal2 = MMG5_caltri(mesh,met,&tt2);
337 }
338
339 calchg = MG_MIN(cal1,cal2);
340 if ( calchg < 1.01 * calnat ) return 0;
341
342 /* Check mechanical validity of forthcoming operations */
343 p0 = &mesh->point[np];
344 p1 = &mesh->point[nq];
345 ppt0->c[0] = 0.5*(p0->c[0] + p1->c[0]);
346 ppt0->c[1] = 0.5*(p0->c[1] + p1->c[1]);
347 ppt0->c[2] = 0.5*(p0->c[2] + p1->c[2]);
348
349#ifndef NDEBUG
350 /* Security check: ensure that the edge is boundary */
351 uint16_t tag = 0;
352 MMG5_int ref = 0;
353 if ( !MMG3D_get_shellEdgeTag(mesh,list[0]/6,list[0]%6,&tag,&ref) ) {
354 fprintf(stderr,"\n ## Warning: %s: 0. unable to get edge info"
355 " (tetra %d).\n",__func__,MMG3D_indElt(mesh,list[0]/6));
356 return 0;
357 }
358 assert ( (tag & MG_BDY) && "Edge should be boundary but is not");
359#endif
360
361 if ( met->m ) {
362 pt = &mesh->tetra[list[0]/6];
363 assert ( pt->xt && "Boundary edge interpolated from non-boundary face");
364
365 /* Mark edge as boundary to ensure suitable detection of bdy edge during
366 * interpolation */
367 mesh->xtetra[pt->xt].tag[list[0]%6] |= MG_BDY;
368
369 if ( typchk == 1 && (met->size>1) ) {
370 if ( MMG3D_intmet33_ani(mesh,met,list[0]/6,list[0]%6,0,0.5) <= 0 )
371 return 0;
372 }
373 else {
374 if ( MMG5_intmet(mesh,met,list[0]/6,list[0]%6,0,0.5) <= 0 )
375 return 0;
376 }
377 }
378
379 /* Check validity of insertion of midpoint on edge (pq), then collapse of m on a1 */
380 calold = calnew = DBL_MAX;
381 for (k=0; k<ilist; k++) {
382 iel = list[k] / 6;
383 pt = &mesh->tetra[iel];
384 memcpy(pt0,pt,sizeof(MMG5_Tetra));
385 calold = MG_MIN(calold, pt->qual);
386 assert ( isfinite(calold) );
387
388 ia1 = ia2 = ip = iq = -1;
389 for (j=0; j< 4; j++) {
390 if (pt->v[j] == np) ip = j;
391 else if (pt->v[j] == nq) iq = j;
392 else if ( ia1 < 0 ) ia1 = j;
393 else ia2 = j;
394 }
395 assert((ip >= 0) && (iq >= 0) && (ia1 >= 0) && (ia2 >= 0));
396 isshell = (pt->v[ia1] == na1 || pt->v[ia2] == na1);
397
398 /* 2 elts resulting from split and collapse */
399 pt0->v[ip] = 0;
400
401 if ( typchk==1 && met->size > 1 && met->m )
402 caltmp = MMG5_caltet33_ani(mesh,met,pt0);
403 else
404 caltmp = MMG5_orcal(mesh,met,0);
405
406
407 if ( caltmp < MMG5_NULKAL ) return 0;
408
409 if ( !isshell ) {
410 /* Test that we don't recreate an existing elt */
411 MMG5_int adj = mesh->adja[4*(iel-1)+1+ip];
412 if ( adj ) {
413 int8_t voy = adj%4;
414 adj /= 4;
415
416 if ( mesh->tetra[adj].v[voy] == na1 ) {
417 return 0;
418 }
419 }
420
421 /* Test future quality */
422 pt0->v[ip] = na1;
423
424 if ( typchk==1 && met->size > 1 && met->m )
425 caltmp = MMG5_caltet33_ani(mesh,met,pt0);
426 else
427 caltmp = MMG5_orcal(mesh,met,0);
428
429 calnew = MG_MIN(calnew,caltmp);
430 }
431 memcpy(pt0,pt,sizeof(MMG5_Tetra));
432 pt0->v[iq] = 0;
433
434 if ( typchk==1 && met->size > 1 && met->m )
435 caltmp = MMG5_caltet33_ani(mesh,met,pt0);
436 else
437 caltmp = MMG5_orcal(mesh,met,0);
438
439 if ( caltmp < MMG5_NULKAL ) return 0;
440
441 if ( !isshell ) {
442 /* Test that we don't recreate an existing elt */
443 MMG5_int adj = mesh->adja[4*(iel-1)+1+iq];
444 if ( adj ) {
445 int8_t voy = adj%4;
446 adj /= 4;
447
448 if ( mesh->tetra[adj].v[voy] == na1 ) {
449 return 0;
450 }
451 }
452
453 /* Test future quality */
454 pt0->v[iq] = na1;
455
456 if ( typchk==1 && met->size > 1 && met->m )
457 caltmp = MMG5_caltet33_ani(mesh,met,pt0);
458 else
459 caltmp = MMG5_orcal(mesh,met,0);
460
461 if ( caltmp < MMG5_NULKAL ) return 0;
462
463 calnew = MG_MIN(calnew,caltmp);
464 }
465 }
466 if ( calold < MMG5_EPSOK && calnew <= calold ) return 0;
467
468 else if ( calnew < 0.3 * calold ) return 0;
469
470 return 1;
471}
472
489int MMG5_swpbdy(MMG5_pMesh mesh,MMG5_pSol met,int64_t *list,int ret,MMG5_int it1,
490 MMG3D_pPROctree PROctree, int8_t typchk) {
491 MMG5_pTetra pt,pt1;
492 MMG5_pPoint p0,p1;
493 int ilist;
494 MMG5_int iel,np,nq,nm,src,iel1;
495 double c[3];
496 int8_t ia,iface1,j,ipa,im;
497 int ier;
498#ifndef NDEBUG
499 MMG5_int na;
500#endif
501
502 iel = list[0] / 6;
503 ia = list[0] % 6;
504 pt = &mesh->tetra[iel];
505
506 np = pt->v[MMG5_iare[ia][0]];
507 nq = pt->v[MMG5_iare[ia][1]];
508#ifndef NDEBUG
509 na = 0;
510#endif
511
512 p0 = &mesh->point[np];
513 p1 = &mesh->point[nq];
514
515 /* search for na = the point on quadrangle surfacic configuration on which collapse
516 validity has been checked in MMG5_chkswpbdy */
517 iel1 = it1 / 4;
518 iface1 = it1 % 4;
519 pt1 = &mesh->tetra[iel1];
520
521 for (j=0; j<3;j++) {
522 ipa = MMG5_idir[iface1][j];
523 if ( (pt1->v[ipa] != np)&&(pt1->v[ipa] != nq) ) {
524#ifndef NDEBUG
525 na = pt1->v[ipa];
526#endif
527 break;
528 }
529 }
530 assert(na);
531
532 /* Create midpoint m on edge (pq), then split edge */
533 c[0] = 0.5*( p0->c[0] + p1->c[0]);
534 c[1] = 0.5*( p0->c[1] + p1->c[1]);
535 c[2] = 0.5*( p0->c[2] + p1->c[2]);
536#ifdef USE_POINTMAP
537 src = mesh->point[np].src;
538#else
539 src = 1;
540#endif
541 nm = MMG3D_newPt(mesh,c,MG_BDY,src);
542 if ( !nm ) {
544 fprintf(stderr,"\n ## Error: %s: unable to allocate a"
545 " new point\n",__func__);
547 return -1
548 ,c,MG_BDY,src);
549 }
550 assert ( met );
551 if ( met->m ) {
552 if ( typchk == 1 && (met->size>1) ) {
553 if ( MMG3D_intmet33_ani(mesh,met,iel,ia,nm,0.5)<=0 ) return 0;
554 }
555 else {
556 if ( MMG5_intmet(mesh,met,iel,ia,nm,0.5)<=0 ) return 0;
557 }
558 }
559
560 ier = MMG5_split1b(mesh,met,list,ret,nm,0,typchk-1,0);
561 /* pointer adress may change if we need to realloc memory during split */
562 pt1 = &mesh->tetra[iel1];
563
564 if ( ier < 0 ) {
565 fprintf(stderr,"\n ## Warning: %s: unable to swap boundary edge.\n",
566 __func__);
567 return -1;
568 }
569 else if ( !ier ) {
570 MMG3D_delPt(mesh,nm);
571 return 0;
572 }
573
574 /* Collapse m on na after taking (new) ball of m */
575 memset(list,0,(MMG3D_LMAX+2)*sizeof(MMG5_int));
576 for (j=0; j<3; j++) {
577 im = MMG5_idir[iface1][j];
578 if ( pt1->v[im] == nm ) break;
579 }
580 if ( pt1->v[im] != nm ){
581 MMG3D_delPt(mesh,nm);
582 fprintf(stderr,"\n # Warning: %s: pt1->v[im] != nm.\n",__func__);
583 return 0;
584 }
585 ilist = MMG5_boulevolp(mesh,iel1,im,list);
586
587 assert(list[0]/4 == iel1);
588 assert(pt1->v[ipa] == na);
589
590 ier = MMG5_colver(mesh,met,list,ilist,ipa,typchk);
591 if ( ier < 0 ) {
592 fprintf(stderr,"\n ## Warning: %s: unable to swap boundary edge.\n",
593 __func__);
594 return -1;
595 }
596 else if ( ier ) {
598 ier = 1;
599 }
600
601 /* Check for non convex situation */
602 assert ( ier && "Unable to collapse the point created during the boundary swap");
603
604 return ier;
605}
606
625int MMG3D_swap23(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,int8_t metRidTyp,
626 int ifac,int conf0,MMG5_int adj,int conf1) {
627 MMG5_pTetra pt0,pt1,ptnew;
628 MMG5_xTetra xt[3];
629 MMG5_pxTetra pxt0,pxt1;
630 MMG5_int xt1,k1,*adja,iel,np;
631 MMG5_int adj0_2,adj0_3,adj1_1,adj1_2,adj1_3;
632 int8_t i,isxt[3];
633 uint8_t tau0[4],tau1[4];
634 const uint8_t *taued0,*taued1;
635
636 pt0 = &mesh->tetra[k];
637
638 assert ( pt0->xt );
639 assert ( ifac>=0 && adj>0 );
640
642 k1 = adj/4;
643
644 assert(k1);
645
646 /* Search in which configurations are the tetrahedra (default is case 0-0)
647 *
648 * 3 2------------- 0
649 * ,/|`\ |`\ /|
650 * ,/ | `\ | `\ /.|
651 * ,/ '. `\ '. `\ / |
652 * ,/ | `\ | `\ / .|
653 * ,/ | `\ | /\.|
654 * 0-----------'.--------2 ' / 3
655 * `\. | ,/ | / ,/
656 * `\. | ,/ | /,/
657 * `\. '. ,/ '. ,/
658 * `\. |/ |/
659 * `1 1
660 */
661
662 /* k may be in configuration 0, 3, 6 or 9. Default is case 0 */
663 switch(conf0) {
664 case 3:
665 tau0[0] = 1; tau0[1] = 0; tau0[2] = 3; tau0[3] = 2;
666 taued0 = &MMG5_permedge[3][0];
667 break;
668 case 6:
669 tau0[0] = 2; tau0[1] = 0; tau0[2] = 1; tau0[3] = 3;
670 taued0 = &MMG5_permedge[6][0];
671 break;
672 case 9:
673 tau0[0] = 3; tau0[1] = 0; tau0[2] = 2; tau0[3] = 1;
674 taued0 = &MMG5_permedge[9][0];
675 break;
676 default:
677 assert ( !conf0 );
678
679 tau0[0] = 0; tau0[1] = 1; tau0[2] = 2; tau0[3] = 3;
680 taued0 = &MMG5_permedge[0][0];
681 break;
682 }
683
684 /* k1 may be in configuration adj%4, adj%4+1, adj%4+2. Default case is case 0 */
685 pt1 = &mesh->tetra[k1];
686
687 assert(pt0->ref == pt1->ref);
688
689 switch(conf1) {
690 case 1:
691 tau1[0] = 0; tau1[1] = 2; tau1[2] = 3; tau1[3] = 1;
692 taued1 = &MMG5_permedge[1][0];
693 break;
694 case 2:
695 tau1[0] = 0; tau1[1] = 3; tau1[2] = 1; tau1[3] = 2;
696 taued1 = &MMG5_permedge[2][0];
697 break;
698 case 3:
699 tau1[0] = 1; tau1[1] = 0; tau1[2] = 3; tau1[3] = 2;
700 taued1 = &MMG5_permedge[3][0];
701 break;
702 case 4:
703 tau1[0] = 1; tau1[1] = 3; tau1[2] = 2; tau1[3] = 0;
704 taued1 = &MMG5_permedge[5][0];
705 break;
706 case 5:
707 tau1[0] = 1; tau1[1] = 2; tau1[2] = 0; tau1[3] = 3;
708 taued1 = &MMG5_permedge[4][0];
709 break;
710 case 6:
711 tau1[0] = 2; tau1[1] = 0; tau1[2] = 1; tau1[3] = 3;
712 taued1 = &MMG5_permedge[6][0];
713 break;
714 case 7:
715 tau1[0] = 2; tau1[1] = 1; tau1[2] = 3; tau1[3] = 0;
716 taued1 = &MMG5_permedge[7][0];
717 break;
718 case 8:
719 tau1[0] = 2; tau1[1] = 3; tau1[2] = 0; tau1[3] = 1;
720 taued1 = &MMG5_permedge[8][0];
721 break;
722 case 9:
723 tau1[0] = 3; tau1[1] = 0; tau1[2] = 2; tau1[3] = 1;
724 taued1 = &MMG5_permedge[9][0];
725 break;
726 case 10:
727 tau1[0] = 3; tau1[1] = 2; tau1[2] = 1; tau1[3] = 0;
728 taued1 = &MMG5_permedge[11][0];
729 break;
730 case 11:
731 tau1[0] = 3; tau1[1] = 1; tau1[2] = 0; tau1[3] = 2;
732 taued1 = &MMG5_permedge[10][0];
733 break;
734 default:
735 assert(!conf1);
736 tau1[0] = 0; tau1[1] = 1; tau1[2] = 2; tau1[3] = 3;
737 taued1 = &MMG5_permedge[0][0];
738 break;
739 }
740
742 /* Store useful information from pt1 before overwrite by memcpy*/
743 xt1 = pt1->xt;
744
745 np = pt1->v[tau1[0]];
746
747 MMG5_int ref[6] = {0};
748 uint16_t tag[6] = {0};
749 for (i=0;i<6;i++) {
750 if ( !MMG3D_get_shellEdgeTag(mesh,k1,taued1[i],&tag[i],&ref[i]) ) {
751 fprintf(stderr,"\n ## Error: %s: %d. unable to get edge info.\n",__func__,i);
752 return 0;
753 }
754 }
755
756 memcpy(pt1,pt0,sizeof(MMG5_Tetra));
757
758 iel = MMG3D_newElt(mesh);
759 if ( !iel ) {
761 fprintf(stderr,"\n ## Error: %s: unable to allocate"
762 " a new element.\n",__func__);
764 fprintf(stderr," Exit program.\n");
765 return -1);
766 pt0 = &mesh->tetra[k];
767 pt1 = &mesh->tetra[k1];
768 }
769 ptnew = &mesh->tetra[iel];
770 memcpy(ptnew,pt0,sizeof(MMG5_Tetra));
771
772 /* First tetra: k */
773 pt0->v[tau0[1]] = np;
774
775 /* Second tetra: k1 */
776 pt1->v[tau0[2]] = np;
777
778 /* Third tetra: iel */
779 ptnew->v[tau0[3]] = np;
780
781 /* xtetra and adjacency update */
782 pxt0 = &mesh->xtetra[pt0->xt];
783 memcpy(&xt[0],pxt0,sizeof(MMG5_xTetra));
784 memcpy(&xt[1],pxt0,sizeof(MMG5_xTetra));
785 memcpy(&xt[2],pxt0,sizeof(MMG5_xTetra));
786
787 /* Store the old adja */
788 adja = &mesh->adja[4*(k-1) +1];
789 adj0_2 = adja[tau0[2]];
790 adj0_3 = adja[tau0[3]];
791
792 adja = &mesh->adja[4*(k1-1) +1];
793 adj1_1 = adja[tau1[1]];
794 adj1_2 = adja[tau1[2]];
795 adj1_3 = adja[tau1[3]];
796
797 /* New adja for the new tets */
798 adja = &mesh->adja[4*(k-1) +1];
799 adja[tau0[0]] = adj1_1;
800 adja[tau0[2]] = 4*k1 + tau0[1] ;
801 adja[tau0[3]] = 4*iel + tau0[1] ;
802 if ( adj1_1 )
803 mesh->adja[4*(adj1_1/4-1) + 1 + adj1_1%4] = 4*k + tau0[0];
804
805 adja = &mesh->adja[4*(k1-1) +1];
806 adja[tau0[0]] = adj1_3;
807 adja[tau0[1]] = 4*k + tau0[2] ;
808 adja[tau0[2]] = adj0_2;
809 adja[tau0[3]] = 4*iel + tau0[2] ;
810 if ( adj1_3 )
811 mesh->adja[4*(adj1_3/4-1) + 1 + adj1_3%4] = 4*k1 + tau0[0];
812 if ( adj0_2 )
813 mesh->adja[4*(adj0_2/4-1) + 1 + adj0_2%4] = 4*k1 + tau0[2];
814
815 adja = &mesh->adja[4*(iel-1) +1];
816 adja[tau0[0]] = adj1_2;
817 adja[tau0[1]] = 4*k + tau0[3] ;
818 adja[tau0[2]] = 4*k1 + tau0[3] ;
819 adja[tau0[3]] = adj0_3;
820 if ( adj1_2 )
821 mesh->adja[4*(adj1_2/4-1) + 1 + adj1_2%4] = 4*iel + tau0[0];
822 if ( adj0_3 )
823 mesh->adja[4*(adj0_3/4-1) + 1 + adj0_3%4] = 4*iel + tau0[3];
824
825 pxt1 = NULL;
826 if ( !pt1->xt ) {
827 /* Assignation of the xt fields to the appropriate tets */
828 /* xt[0] */
829 xt[0].tag[taued0[0]] = 0;
830 xt[0].tag[taued0[3]] = 0;
831 xt[0].tag[taued0[4]] = 0;
832
833 xt[0].edg[taued0[0]] = 0;
834 xt[0].edg[taued0[3]] = 0;
835 xt[0].edg[taued0[4]] = 0;
836
837 xt[0].ref[ tau0[0]] = 0;
838 xt[0].ref[ tau0[2]] = 0;
839 xt[0].ref[ tau0[3]] = 0;
840 xt[0].ftag[tau0[0]] = 0;
841 xt[0].ftag[tau0[2]] = 0;
842 xt[0].ftag[tau0[3]] = 0;
843
844 MG_SET(xt[0].ori, tau0[0]);
845 MG_SET(xt[0].ori, tau0[2]);
846 MG_SET(xt[0].ori, tau0[3]);
847
848 /* xt[1] */
849 xt[1].tag[taued0[1]] = 0;
850 xt[1].tag[taued0[3]] = 0;
851 xt[1].tag[taued0[5]] = 0;
852
853 xt[1].edg[taued0[1]] = 0;
854 xt[1].edg[taued0[3]] = 0;
855 xt[1].edg[taued0[5]] = 0;
856
857 xt[1].ref[ tau0[0]] = 0;
858 xt[1].ref[ tau0[1]] = 0;
859 xt[1].ref[ tau0[3]] = 0;
860 xt[1].ftag[tau0[0]] = 0;
861 xt[1].ftag[tau0[1]] = 0;
862 xt[1].ftag[tau0[3]] = 0;
863
864 MG_SET(xt[1].ori, tau0[0]);
865 MG_SET(xt[1].ori, tau0[1]);
866 MG_SET(xt[1].ori, tau0[3]);
867
868 /* xt[2] */
869 xt[1].tag[taued0[2]] = 0;
870 xt[1].tag[taued0[4]] = 0;
871 xt[1].tag[taued0[5]] = 0;
872
873 xt[1].edg[taued0[2]] = 0;
874 xt[1].edg[taued0[4]] = 0;
875 xt[1].edg[taued0[5]] = 0;
876
877 xt[1].ref[ tau0[0]] = 0;
878 xt[1].ref[ tau0[1]] = 0;
879 xt[1].ref[ tau0[2]] = 0;
880 xt[1].ftag[tau0[0]] = 0;
881 xt[1].ftag[tau0[1]] = 0;
882 xt[1].ftag[tau0[2]] = 0;
883
884 MG_SET(xt[1].ori, tau0[0]);
885 MG_SET(xt[1].ori, tau0[1]);
886 MG_SET(xt[1].ori, tau0[2]);
887
888 }
889 else {
890 pxt1 = &mesh->xtetra[xt1];
891
892 /* Assignation of the xt fields to the appropriate tets */
893 /* Warning: after collapses, some boundary edges not connected to boundary
894 * faces may have a 0 tag inside a xtetra (see \ref MMG5_colver when a
895 * xtetra is assigned to one of the neighbours of the tetra of the edge
896 * shell). In consequence, we cannot simply use the stored tags. */
897
898 /* xt[0] */
899 xt[0].tag[taued0[0]] = 0;
900
901 xt[0].tag[taued0[3]] = tag[2];
902 xt[0].tag[taued0[4]] = tag[1];
903 /* As the edge tag of tetra 0 may be erroneous if the edge doesn't belong to
904 * a boundary face */
905 xt[0].tag[taued0[5]] = tag[5];
906
907
908 xt[0].edg[taued0[0]] = 0;
909 xt[0].edg[taued0[3]] = ref[2];
910 xt[0].edg[taued0[4]] = ref[1];
911 xt[0].edg[taued0[5]] = ref[5];
912
913 xt[0].ref[ tau0[0]] = pxt1->ref[tau1[1]];
914 xt[0].ref[ tau0[2]] = 0;
915 xt[0].ref[ tau0[3]] = 0;
916 xt[0].ftag[tau0[0]] = pxt1->ftag[tau1[1]];
917 xt[0].ftag[tau0[2]] = 0;
918 xt[0].ftag[tau0[3]] = 0;
919
920 if ( MG_GET(pxt1->ori,tau1[1]) ) MG_SET(xt[0].ori, tau0[0]);
921 MG_SET(xt[0].ori, tau0[2]);
922 MG_SET(xt[0].ori, tau0[3]);
923
924 /* xt[1] */
925 xt[1].tag[taued0[1]] = 0;
926
927 xt[1].tag[taued0[3]] = tag[0];
928 xt[1].tag[taued0[5]] = tag[1];
929
930 /* As the edge tag of tetra 0 may be erroneous if the edge doesn't belong to
931 * a boundary face */
932 xt[1].tag[taued0[4]] = tag[3];
933
934 xt[1].edg[taued0[1]] = 0;
935 xt[1].edg[taued0[3]] = ref[0];
936 xt[1].edg[taued0[5]] = ref[1];
937 xt[1].edg[taued0[4]] = ref[3];
938
939 xt[1].ref[ tau0[0]] = pxt1->ref[tau1[3]];
940 xt[1].ref[ tau0[1]] = 0;
941 xt[1].ref[ tau0[3]] = 0;
942 xt[1].ftag[tau0[0]] = pxt1->ftag[tau1[3]];
943 xt[1].ftag[tau0[1]] = 0;
944 xt[1].ftag[tau0[3]] = 0;
945
946 if ( MG_GET(pxt1->ori,tau1[3]) ) MG_SET(xt[1].ori, tau0[0]);
947 MG_SET(xt[1].ori, tau0[1]);
948 MG_SET(xt[1].ori, tau0[3]);
949
950 /* xt[2] */
951 xt[2].tag[taued0[2]] = 0;
952
953 xt[2].tag[taued0[4]] = tag[0];
954 xt[2].tag[taued0[5]] = tag[2];
955
956 /* As the edge tag of tetra 0 may be erroneous if the edge doesn't belong to
957 * a boundary face */
958 xt[2].tag[taued0[3]] = tag[4];
959
960 xt[2].edg[taued0[2]] = 0;
961 xt[2].edg[taued0[4]] = ref[0];
962 xt[2].edg[taued0[5]] = ref[2];
963 xt[2].edg[taued0[3]] = ref[4];
964
965 xt[2].ref[ tau0[0]] = pxt1->ref[tau1[2]];
966 xt[2].ref[ tau0[1]] = 0;
967 xt[2].ref[ tau0[2]] = 0;
968 xt[2].ftag[tau0[0]] = pxt1->ftag[tau1[2]];
969 xt[2].ftag[tau0[1]] = 0;
970 xt[2].ftag[tau0[2]] = 0;
971
972 if ( MG_GET(pxt1->ori,tau1[2]) ) MG_SET(xt[2].ori, tau0[0]);
973 MG_SET(xt[2].ori, tau0[1]);
974 MG_SET(xt[2].ori, tau0[2]);
975 }
976
977 /* Assignation of the xt fields to the appropriate tets */
978 isxt[0] = isxt[1] = isxt[2] = 0;
979 for (i=0; i<4; i++) {
980 if ( xt[0].ref[i] || xt[0].ftag[i] ) isxt[0] = 1;
981 if ( xt[1].ref[i] || xt[1].ftag[i] ) isxt[1] = 1;
982 if ( xt[2].ref[i] || xt[2].ftag[i] ) isxt[2] = 1;
983 }
984
985 assert ( (isxt[0] && isxt[1]) || (isxt[1] && isxt[2]) || (isxt[2] && isxt[0]) );
986
987 if ( isxt[0] ) {
988 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
989
990 if ( xt1 ) {
991 if ( isxt[1] ) {
992 pt1->xt = xt1;
993 memcpy(pxt1,&xt[1],sizeof(MMG5_xTetra));
994 if ( isxt[2] ) {
995 mesh->xt++;
996 if ( mesh->xt > mesh->xtmax ) {
997 /* realloc of xtetras table */
999 "larger xtetra table",
1000 mesh->xt--;
1001 fprintf(stderr," Exit program.\n");
1002 return -1);
1003 }
1004 ptnew->xt = mesh->xt;
1005 pxt0 = &mesh->xtetra[mesh->xt];
1006 memcpy(pxt0,&xt[2],sizeof(MMG5_xTetra));
1007 }
1008 else ptnew->xt = 0;
1009 }
1010 else {
1011 pt1->xt = 0;
1012 ptnew->xt = xt1;
1013 memcpy(pxt1,&xt[2],sizeof(MMG5_xTetra));
1014 }
1015 }
1016 else {
1017 if ( isxt[1] ) {
1018 mesh->xt++;
1019 if ( mesh->xt > mesh->xtmax ) {
1020 /* realloc of xtetras table */
1022 "larger xtetra table",
1023 mesh->xt--;
1024 fprintf(stderr," Exit program.\n");
1025 return -1);
1026 }
1027 pt1->xt = mesh->xt;
1028 pxt0 = &mesh->xtetra[mesh->xt];
1029 memcpy(pxt0,&xt[1],sizeof(MMG5_xTetra));
1030 }
1031 else pt1->xt = 0;
1032
1033 if ( isxt[2] ) {
1034 mesh->xt++;
1035 if ( mesh->xt > mesh->xtmax ) {
1036 /* realloc of xtetras table */
1038 "larger xtetra table",
1039 mesh->xt--;
1040 fprintf(stderr," Exit program.\n");
1041 return -1);
1042 }
1043 ptnew->xt = mesh->xt;
1044 pxt0 = &mesh->xtetra[mesh->xt];
1045 memcpy(pxt0,&xt[2],sizeof(MMG5_xTetra));
1046 }
1047 else ptnew->xt = 0;
1048 }
1049 }
1050 else {
1051 pt0->xt = 0;
1052 memcpy(pxt0 ,&xt[2],sizeof(MMG5_xTetra));
1053
1054 if ( xt1 ) {
1055 pt1->xt = xt1;
1056 memcpy(pxt1,&xt[1],sizeof(MMG5_xTetra));
1057 }
1058 else {
1059 mesh->xt++;
1060 if ( mesh->xt > mesh->xtmax ) {
1061 /* realloc of xtetras table */
1063 "larger xtetra table",
1064 mesh->xt--;
1065 fprintf(stderr," Exit program.\n");
1066 return -1);
1067 }
1068 pt1->xt = mesh->xt;
1069 pxt0 = &mesh->xtetra[mesh->xt];
1070 memcpy(pxt0,&xt[1],sizeof(MMG5_xTetra));
1071 }
1072 }
1073
1075 if ( (!metRidTyp) && met->m && met->size>1 )
1076 pt0->qual = MMG5_caltet33_ani(mesh,met,pt0);
1077 else
1078 pt0->qual = MMG5_orcal(mesh,met,k);
1079
1080 if ( (!metRidTyp) && met->m && met->size>1 )
1081 pt1->qual = MMG5_caltet33_ani(mesh,met,pt1);
1082 else
1083 pt1->qual = MMG5_orcal(mesh,met,k1);
1084
1085 if ( (!metRidTyp) && met->m && met->size>1 )
1086 ptnew->qual = MMG5_caltet33_ani(mesh,met,ptnew);
1087 else
1088 ptnew->qual = MMG5_orcal(mesh,met,iel);
1089
1090 pt0->mark = mesh->mark;
1091 pt1->mark = mesh->mark;
1092 ptnew->mark = mesh->mark;
1093
1094 return 1;
1095}
int ier
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)
Given a vertex and a tetrahedron, find all tetrahedra in the ball of this vertex.
Definition: boulep_3d.c:57
int MMG3D_get_shellEdgeTag(MMG5_pMesh mesh, MMG5_int start, int8_t ia, uint16_t *tag, MMG5_int *ref)
Definition: colver_3d.c:439
MMG5_int MMG5_colver(MMG5_pMesh mesh, MMG5_pSol met, int64_t *list, int ilist, int8_t indq, int8_t typchk)
Definition: colver_3d.c:1154
static double MMG5_orcal(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int iel)
int MMG3D_intmet33_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t i, MMG5_int ip, double s)
Definition: intmet_3d.c:126
API headers and documentation for the mmg3d library, for volumetric meshes in 3D.
#define MMG3D_LMAX
Definition: libmmg3d.h:130
int MMG5_split1b(MMG5_pMesh, MMG5_pSol, int64_t *, int, MMG5_int, int, int8_t, int8_t)
Definition: split_3d.c:629
MMG5_int MMG3D_newElt(MMG5_pMesh mesh)
Definition: zaldy_3d.c:99
int MMG3D_normalAdjaTri(MMG5_pMesh, MMG5_int, int8_t, int, double n[3])
Definition: split_3d.c:472
void MMG3D_delPt(MMG5_pMesh mesh, MMG5_int ip)
Definition: zaldy_3d.c:80
static const uint8_t MMG5_permedge[12][6]
MMG5_int MMG3D_newPt(MMG5_pMesh mesh, double c[3], uint16_t tag, MMG5_int src)
Definition: zaldy_3d.c:39
double MMG5_caltet33_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pTetra pt)
Definition: quality_3d.c:109
static const uint8_t MMG5_iare[6][2]
vertices of extremities of the edges of the tetra
#define MMG3D_POINT_REALLOC(mesh, sol, ip, wantedGap, law, o, tag, src)
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
#define MMG3D_TETRA_REALLOC(mesh, jel, wantedGap, law)
static const uint8_t MMG5_idir[4][3]
idir[i]: vertices of face opposite to vertex i
MMG5_int MMG3D_indElt(MMG5_pMesh mesh, MMG5_int kel)
Definition: tools_3d.c:862
@ MMG5_Tetrahedron
Definition: libmmgtypes.h:233
@ MMG5_Triangle
Definition: libmmgtypes.h:232
#define MG_Tria
#define MG_REQ
#define MMG5_EPSOK
#define MMG5_INCREASE_MEM_MESSAGE()
#define MG_MIN(a, b)
#define MG_MAX(a, b)
#define MMG5_GAP
static const uint8_t MMG5_iprv2[3]
#define MMG5_ATHIRD
#define MG_EDG_OR_NOM(tag)
#define MMG5_TAB_RECALLOC(mesh, ptr, initSize, wantedGap, type, message, law)
#define MMG5_NULKAL
#define MG_GEO_OR_NOM(tag)
#define MG_Tetra
#define MG_GET(flag, bit)
static const uint8_t MMG5_inxt2[6]
#define MG_BDY
#define MMG5_ANGEDG
int MMG5_norpts(MMG5_pMesh, MMG5_int, MMG5_int, MMG5_int, double *)
Definition: tools.c:183
double MMG5_caltri33_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pTria pt)
Definition: quality.c:47
#define MG_SET(flag, bit)
int8_t parTyp
Definition: libmmgtypes.h:548
MMG5_pPar par
Definition: libmmgtypes.h:524
double dhd
Definition: libmmgtypes.h:525
double hausd
Definition: libmmgtypes.h:525
MMG mesh structure.
Definition: libmmgtypes.h:613
MMG5_Info info
Definition: libmmgtypes.h:659
MMG5_int xt
Definition: libmmgtypes.h:628
MMG5_pPoint point
Definition: libmmgtypes.h:649
MMG5_int mark
Definition: libmmgtypes.h:626
MMG5_int * adja
Definition: libmmgtypes.h:632
MMG5_int xtmax
Definition: libmmgtypes.h:620
double gap
Definition: libmmgtypes.h:616
MMG5_pTetra tetra
Definition: libmmgtypes.h:651
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:652
Local parameters for a specific entity and reference.
Definition: libmmgtypes.h:263
double hausd
Definition: libmmgtypes.h:266
MMG5_int ref
Definition: libmmgtypes.h:267
int8_t elt
Definition: libmmgtypes.h:268
Structure to store vertices of an MMG mesh.
Definition: libmmgtypes.h:276
double c[3]
Definition: libmmgtypes.h:277
double * m
Definition: libmmgtypes.h:680
Structure to store tetrahedra of an MMG mesh.
Definition: libmmgtypes.h:407
MMG5_int v[4]
Definition: libmmgtypes.h:409
MMG5_int xt
Definition: libmmgtypes.h:413
MMG5_int ref
Definition: libmmgtypes.h:410
MMG5_int mark
Definition: libmmgtypes.h:412
double qual
Definition: libmmgtypes.h:408
Structure to store triangles of a MMG mesh.
Definition: libmmgtypes.h:338
MMG5_int ref
Definition: libmmgtypes.h:341
uint16_t tag[3]
Definition: libmmgtypes.h:348
MMG5_int v[3]
Definition: libmmgtypes.h:340
Structure to store additional information for the surface tetrahedra of an MMG mesh.
Definition: libmmgtypes.h:425
uint16_t tag[6]
Definition: libmmgtypes.h:432
int8_t ori
Definition: libmmgtypes.h:434
MMG5_int edg[6]
Definition: libmmgtypes.h:428
MMG5_int ref[4]
Definition: libmmgtypes.h:426
uint16_t ftag[4]
Definition: libmmgtypes.h:430
int MMG3D_swap23(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t metRidTyp, int ifac, int conf0, MMG5_int adj, int conf1)
Definition: swap_3d.c:625
int MMG5_swpbdy(MMG5_pMesh mesh, MMG5_pSol met, int64_t *list, int ret, MMG5_int it1, MMG3D_pPROctree PROctree, int8_t typchk)
Definition: swap_3d.c:489
int8_t ddb
Definition: mmg3d1_delone.c:42
int MMG5_chkswpbdy(MMG5_pMesh mesh, MMG5_pSol met, int64_t *list, int ilist, MMG5_int it1, MMG5_int it2, int8_t typchk)
Definition: swap_3d.c:57