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