Mmg
Simplicial remeshers (mesh adaptation, isovalue discretization, lagrangian movement)
split_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
36#include "libmmg3d.h"
39
40extern int8_t ddb;
41
52inline
53void MMG3D_split1_cfg(MMG5_int flag,uint8_t *tau,const uint8_t **taued) {
54
55 /* default is case 1 */
56 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
57 *taued = &MMG5_permedge[0][0];
58 switch(flag) {
59 case 2:
60 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
61 *taued = &MMG5_permedge[6][0];
62 break;
63 case 4:
64 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
65 *taued = &MMG5_permedge[2][0];
66 break;
67 case 8:
68 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
69 *taued = &MMG5_permedge[4][0];
70 break;
71 case 16:
72 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
73 *taued = &MMG5_permedge[10][0];
74 break;
75 case 32:
76 tau[0] = 3 ; tau[1] = 2 ; tau[2] = 1 ; tau[3] = 0;
77 *taued = &MMG5_permedge[11][0];
78 break;
79 }
80
81 return;
82}
83
94int MMG3D_split1_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
95 MMG5_pTetra pt,pt0;
96 double vold,vnew;
97 uint8_t tau[4];
98 const uint8_t *taued;
99
100 /* tau = sigma^-1 = permutation that sends the reference config (edge 01 split) to the current */
101 pt = &mesh->tetra[k];
102 vold = MMG5_orvol(mesh->point,pt->v);
103
104 if ( vold < MMG5_EPSOK ) return 0;
105
106 pt0 = &mesh->tetra[0];
107
108 MMG3D_split1_cfg(pt->flag,tau,&taued);
109
110 /* Test volume of the two created tets */
111 memcpy(pt0,pt,sizeof(MMG5_Tetra));
112 pt0->v[tau[1]] = vx[taued[0]];
113 vnew = MMG5_orvol(mesh->point,pt0->v);
114 if ( vnew < MMG5_EPSOK ) return 0;
115
116 memcpy(pt0,pt,sizeof(MMG5_Tetra));
117 pt0->v[tau[0]] = vx[taued[0]];
118 vnew = MMG5_orvol(mesh->point,pt0->v);
119 if ( vnew < MMG5_EPSOK ) return 0;
120
121 return 1;
122}
123
134int MMG5_split1(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
135 MMG5_pTetra pt,pt1;
136 MMG5_xTetra xt,xt1;
137 MMG5_pxTetra pxt0;
138 MMG5_int iel;
139 int8_t i,isxt,isxt1;
140 uint8_t tau[4];
141 int16_t ftag[4];
142 const uint8_t *taued;
143
144 /* create a new tetra */
145 pt = &mesh->tetra[k];
146 iel = MMG3D_newElt(mesh);
147 if ( !iel ) {
149 fprintf(stderr,"\n ## Error: %s: unable to allocate"
150 " a new element.\n",__func__);
152 fprintf(stderr," Exit program.\n");
153 return 0);
154 pt = &mesh->tetra[k];
155 }
156
157 pt1 = &mesh->tetra[iel];
158 pt1 = memcpy(pt1,pt,sizeof(MMG5_Tetra));
159 pxt0 = NULL;
160 if ( pt->xt ) {
161 pxt0 = &mesh->xtetra[pt->xt];
162 memcpy(&xt,pxt0,sizeof(MMG5_xTetra));
163 memcpy(&xt1,pxt0,sizeof(MMG5_xTetra));
164 }
165 else {
166 memset(&xt,0,sizeof(MMG5_xTetra));
167 memset(&xt1,0,sizeof(MMG5_xTetra));
168 }
169
170 MMG3D_split1_cfg(pt->flag,tau,&taued);
171
172 /* Store face tags from split tetra*/
173 for (i=0; i<4; i++) {
174 ftag[i] = (xt.ftag[i] & ~MG_REF);
175 }
176
177 /* Generic formulation of split of 1 edge */
178 pt->v[tau[1]] = pt1->v[tau[0]] = vx[taued[0]];
179
180 if ( pt->xt ) {
181 /* Reset edge tag */
182 xt.tag [taued[3]] = ftag[tau[3]]; xt.tag [taued[4]] = ftag[tau[2]];
183 xt1.tag[taued[1]] = ftag[tau[3]]; xt1.tag[taued[2]] = ftag[tau[2]];
184 xt.edg [taued[3]] = 0; xt.edg [taued[4]] = 0;
185 xt1.edg[taued[1]] = 0; xt1.edg[taued[2]] = 0;
186 xt.ref [ tau[0]] = 0; xt.ftag [ tau[0]] = 0; MG_SET( xt.ori, tau[0]);
187 xt1.ref[ tau[1]] = 0; xt1.ftag[ tau[1]] = 0; MG_SET(xt1.ori, tau[1]);
188 }
189
190 pt->flag = pt1->flag = 0;
191 isxt = 0 ;
192 isxt1 = 0;
193 for (i=0; i<4; i++) {
194 if ( xt.ref[i] || xt.ftag[i] ) isxt = 1;
195 if ( xt1.ref[i] || xt1.ftag[i] ) isxt1 = 1;
196 if ( isxt && isxt1 ) goto nextstep1;
197 }
198
199nextstep1:
200 if ( pt->xt ) {
201 if ( isxt && !isxt1 ) {
202 pt1->xt = 0;
203 memcpy(pxt0,&xt,sizeof(MMG5_xTetra));
204 }
205 else if ( !isxt && isxt1 ) {
206 pt1->xt = pt->xt;
207 pt->xt = 0;
208 pxt0 = &mesh->xtetra[pt1->xt];
209 memcpy(pxt0,&xt1,sizeof(MMG5_xTetra));
210 }
211 else if ( isxt && isxt1 ) {
212 mesh->xt++;
213 if ( mesh->xt > mesh->xtmax ) {
214 /* realloc of xtetras table */
216 "larger xtetra table",
217 mesh->xt--;
218 fprintf(stderr," Exit program.\n");
219 return 0);
220 pxt0 = &mesh->xtetra[pt->xt];
221 }
222 pt1->xt = mesh->xt;
223
224 assert ( pxt0 );
225 memcpy(pxt0,&xt,sizeof(MMG5_xTetra));
226 pxt0 = &mesh->xtetra[mesh->xt];
227 assert ( pxt0 );
228 memcpy(pxt0,&xt1,sizeof(MMG5_xTetra));
229 }
230 else {
231 pt->xt = 0;
232 pt1->xt = 0;
233 }
234 }
235 /* Quality update */
236 if ( (!metRidTyp) && met->m && met->size>1 ) {
237 pt->qual=MMG5_caltet33_ani(mesh,met,pt);
238 pt1->qual=MMG5_caltet33_ani(mesh,met,pt1);
239 }
240 else if ( (!met) || (!met->m) ) {
241 /* in ls mode + -A option, orcal calls caltet_ani that fails */
242 pt->qual=MMG5_caltet_iso(mesh,met,pt);
243 pt1->qual=MMG5_caltet_iso(mesh,met,pt1);
244 }
245 else {
246 pt->qual=MMG5_orcal(mesh,met,k);
247 pt1->qual=MMG5_orcal(mesh,met,iel);
248 }
249 return 1;
250}
251
271static inline
272int MMG3D_normalDeviation(MMG5_pMesh mesh , MMG5_int start, int8_t iface, int8_t ia,
273 MMG5_int idx , MMG5_int ip , double n0[3])
274{
275 MMG5_Tria tt0;
276 double n1[3];
277 int iedge,iploc,ier;
278
281 assert(iface >=0 && iface < 4 && "local face idx");
282
283 MMG5_tet2tri(mesh,start,iface,&tt0);
284
285 iedge = MMG5_iarfinv[iface][ia];
286
287 switch (idx)
288 {
289 case 0:
290 iploc = MMG5_iprv2[iedge];
291 break;
292 case 1:
293 iploc = MMG5_inxt2[iedge];
294 break;
295 }
296
297 tt0.v[iploc] = ip;
298
300 if ( !MMG5_nortri(mesh, &tt0, n0) ) return -1;
301
302 if ( MG_GEO_OR_NOM(tt0.tag[iploc]) ) return 1;
303
306 ier = MMG3D_normalAdjaTri(mesh,start,iface,iploc,n1);
307 if ( ier<0 ) return -1;
308 else if ( !ier ) return 0;
309
310 ier = MMG5_devangle( n0, n1, mesh->info.dhd );
311
312 return ier;
313}
314
330int MMG3D_simbulgept(MMG5_pMesh mesh,MMG5_pSol met,int64_t *list,int ret,MMG5_int ip) {
331 MMG5_pTetra pt,pt0;
332 MMG5_pxTetra pxt;
333 MMG5_pPoint ppt0;
334 double calold,calnew,caltmp;
335 double n0[6],n1[6];
336 int j,k,ilist,idx,iface,ier;
337 MMG5_int iel,sum1,sum2,mins1,mins2,maxs1,maxs2;
338 MMG5_int is0,is1,is2;
339 int8_t ie,ia,ib,complete,wrongOri;
340
341 ilist = ret / 2;
342 pt0 = &mesh->tetra[0];
343 ppt0 = &mesh->point[0];
344 memcpy(ppt0->c ,&mesh->point[ip].c , 3*sizeof(double));
345 ppt0->tag = mesh->point[ip].tag;
346
347 memcpy(&met->m[0],&met->m[met->size*ip], met->size*sizeof(double));
348
349 calold = calnew = DBL_MAX;
350 for (k=0; k<ilist; k++) {
351 iel = list[k] / 6;
352 ie = list[k] % 6;
353 ia = MMG5_iare[ie][0];
354 ib = MMG5_iare[ie][1];
355
356 pt = &mesh->tetra[iel];
357 memcpy(pt0,pt,sizeof(MMG5_Tetra));
358 pt0->v[ia] = 0;
359 calold = MG_MIN(calold,pt->qual);
360 caltmp = MMG5_orcal(mesh,met,0);
361 if ( caltmp < MMG5_EPSOK ) return 0;
362 calnew = MG_MIN(calnew,caltmp);
363
364 memcpy(pt0,pt,sizeof(MMG5_Tetra));
365 pt0->v[ib] = 0;
366 caltmp = MMG5_orcal(mesh,met,0);
367 if ( caltmp < MMG5_EPSOK ) return 0;
368 calnew = MG_MIN(calnew,caltmp);
369 }
370 if ( calnew <= MMG5_EPSOK ) {
371 return 0;
372 }
373
374 /* if ( calnew < 0.3*calold ) return 0;*/
375
377 /* analyze surfacic ball of p */
378 wrongOri = complete = idx = 0;
379 maxs1 = mins1 = sum1 = 0;
380 for (k=0; k<ilist; k++) {
381 iel = list[k] / 6;
382 ie = list[k] % 6;
383
384 pt = &mesh->tetra[iel];
385 if(!pt->xt) continue;
386
387 pxt = &mesh->xtetra[pt->xt];
388
389 for ( j=0; j<2; ++j ) {
390 iface = MMG5_ifar[ie][j];
391 if ( !(pxt->ftag[iface] & MG_BDY) ) continue;
392
393 is0 = pt->v[MMG5_idir[iface][0]];
394 is1 = pt->v[MMG5_idir[iface][1]];
395 is2 = pt->v[MMG5_idir[iface][2]];
396
397 /* Normal deviation between the two new triangles and their neighbors */
398 ier = MMG3D_normalDeviation(mesh,iel,iface,ie,0,ip,&n0[idx]);
399 if ( ier < 0 ) return -1;
400 else if ( ier == 0 ) return 2;
401
402 ier = MMG3D_normalDeviation(mesh,iel,iface,ie,1,ip,&n1[idx]);
403 if ( ier < 0 ) return -1;
404 else if ( ier == 0 ) return 2;
405
406 /* Test sharp angle creation along the new edge */
407 if ( !MMG5_devangle(&n0[idx],&n1[idx],mesh->info.dhd) ) {
408 return 2;
409 }
410
411 if ( !idx ) {
412 sum1 = is0 + is1 + is2;
413 mins1 = MG_MIN(is0, MG_MIN(is1,is2));
414 maxs1 = MG_MAX(is0, MG_MAX(is1,is2));
415 idx = 3;
416 }
417 else {
418 /* don't check if it is a ridge edge or if we have already cross 2
419 * boundaries */
420 if ( complete || MG_GEO_OR_NOM(pxt->tag[ie]) )
421 continue;
422
423 /* We are manifold thus we have exactly two faces in our shell: check
424 * that we don't see twice a boundary face (multidomain case) */
425 sum2 = is0 + is1 + is2;
426 mins2 = MG_MIN(is0, MG_MIN(is1,is2));
427 maxs2 = MG_MAX(is0, MG_MAX(is1,is2));
428
429 if ( (sum2 == sum1 && mins2 == mins1 && maxs2 == maxs1) ) {
430 /* Multidomain: we see the tria for the second time (and from another
431 * side), this means that the next seen tria will be seen from the
432 * wrong side. */
433 wrongOri = 1;
434 continue;
435 }
436 else if ( wrongOri ) {
437 /* We skeep this tria because it is seen from a wrong side. The next
438 * will be ok */
439 wrongOri = 0;
440 continue;
441 }
442 complete = 1;
443
444 /* Test sharp angle creation along the splitted edge */
445 if ( !MMG5_devangle(&n0[0],&n1[idx],mesh->info.dhd) ) {
446 return 2;
447 }
448 if ( !MMG5_devangle(&n1[0],&n0[idx],mesh->info.dhd) ) {
449 return 2;
450 }
451 }
452 }
453 }
454
455 return 1;
456}
457
472int MMG3D_normalAdjaTri(MMG5_pMesh mesh , MMG5_int start, int8_t iface, int ia,
473 double n[3] )
474{
475 MMG5_Tria tt;
476 int iedgeOpp;
477 int64_t list[MMG3D_LMAX+2];
478 MMG5_int it1,it2,it;
479
480 iedgeOpp = MMG5_iarf[iface][ia];
481
484 if ( MMG5_coquilface( mesh,start,iface,iedgeOpp,list,&it1,&it2,0) <= 0 )
485 return -1;
486
487 if ( it1/4 != start || it1%4 != iface ) {
488 //assert ( it2/4==start && it2%4==iface );
489 if ( it2/4!=start || it2%4!=iface ) return 0;
490
491 it = it1;
492 }
493 else {
494 it = it2;
495 }
496 assert ( it/4>0 && 0<=it%4 && it%4<4 && "unexpected idx for tetra or local face idx" );
497 MMG5_tet2tri(mesh,it/4,it%4,&tt);
498
500 if ( !MMG5_nortri(mesh, &tt, n) ) return 0;
501
502 return 1;
503}
504
518static inline
519int MMG5_split1b_eltspl(MMG5_pMesh mesh,MMG5_int ip,MMG5_int k,int64_t *list,MMG5_int *newtet,uint8_t tau[4]) {
520 MMG5_pTetra pt,pt1;
521 MMG5_xTetra xt,xt1;
522 MMG5_pxTetra pxt0;
523 MMG5_int iel;
524 MMG5_int jel;
525 int16_t ftag[4];
526 int8_t ie,isxt,isxt1,i;
527 const uint8_t *taued;
528
529 iel = list[k] / 6;
530 ie = list[k] % 6;
531 pt = &mesh->tetra[iel];
532 jel = MMG5_abs(newtet[k]);
533 pt1 = &mesh->tetra[jel];
534
535 pxt0 = 0;
536 if ( pt->xt ) {
537 pxt0 = &mesh->xtetra[pt->xt];
538 memcpy(&xt,pxt0,sizeof(MMG5_xTetra));
539 memcpy(&xt1,pxt0,sizeof(MMG5_xTetra));
540 }
541 else {
542 memset(&xt,0, sizeof(MMG5_xTetra));
543 memset(&xt1,0, sizeof(MMG5_xTetra));
544 }
545
546 MMG5_int flag = 0;
547 MG_SET(flag,ie);
548 MMG3D_split1_cfg(flag,tau,&taued);
549
550 /* Store face tags and refs from split tetra*/
551 for (i=0; i<4; i++) {
552 ftag[i] = (xt.ftag[i] & ~MG_REF);
553 }
554
555 /* Generic formulation of split of 1 edge */
556 pt->v[tau[1]] = pt1->v[tau[0]] = ip;
557 if ( pt->xt ) {
558 /* Reset edge tag */
559 xt.tag [taued[3]] = ftag[tau[3]]; xt.tag [taued[4]] = ftag[tau[2]];
560 xt1.tag[taued[1]] = ftag[tau[3]]; xt1.tag[taued[2]] = ftag[tau[2]];
561 xt.edg [taued[3]] = 0; xt.edg [taued[4]] = 0;
562 xt1.edg[taued[1]] = 0; xt1.edg[taued[2]] = 0;
563 xt.ref [ tau[0]] = 0; xt.ftag [ tau[0]] = 0; MG_SET( xt.ori, tau[0]);
564 xt1.ref[ tau[1]] = 0; xt1.ftag[ tau[1]] = 0; MG_SET(xt1.ori, tau[1]);
565 }
566
567 pt->flag = pt1->flag = 0;
568
569 isxt = 0 ;
570 isxt1 = 0;
571
572 for (i=0; i<4; i++) {
573 if ( xt.ref[i] || xt.ftag[i] ) isxt = 1;
574 if ( xt1.ref[i] || xt1.ftag[i] ) isxt1 = 1;
575 }
576
577 if ( pt->xt ) {
578 if ( (isxt)&&(!isxt1) ) {
579 pt1->xt = 0;
580 pxt0 = &mesh->xtetra[pt->xt];
581 memcpy(pxt0,&xt,sizeof(MMG5_xTetra));
582 }
583 else if ((!isxt)&&(isxt1) ) {
584 pt1->xt = pt->xt;
585 pt->xt = 0;
586 pxt0 = &mesh->xtetra[pt1->xt];
587 memcpy(pxt0,&xt1,sizeof(MMG5_xTetra));
588 }
589 else if (isxt && isxt1 ) {
590 mesh->xt++;
591 if ( mesh->xt > mesh->xtmax ) {
592 /* realloc of xtetras table */
594 "larger xtetra table",
595 mesh->xt--;
596 return 0);
597 }
598 pt1->xt = mesh->xt;
599 pxt0 = &mesh->xtetra[pt->xt];
600 memcpy(pxt0,&xt,sizeof(MMG5_xTetra));
601 pxt0 = &mesh->xtetra[pt1->xt];
602 memcpy(pxt0,&xt1,sizeof(MMG5_xTetra));
603 }
604 else {
605 pt->xt = 0;
606 pt1->xt = 0;
607 }
608 }
609 return 1;
610}
611
629int MMG5_split1b(MMG5_pMesh mesh, MMG5_pSol met,int64_t *list, int ret, MMG5_int ip,
630 int cas,int8_t metRidTyp,int8_t chkRidTet){
631 MMG5_pTetra pt,pt1,pt0;
632 double lmin,lmax,len;
633 int ilist,k,open,j;
634 MMG5_int iel,jel,newtet[MMG3D_LMAX+2],nump,*adja;
635 MMG5_int *adjan,nei2,nei3,mel;
636 int8_t ie,i,voy;
637 uint8_t tau[4];
638 const uint8_t *taued;
639
640 ilist = ret / 2;
641 open = ret % 2;
642
643
644 if ( cas && met->m ) {
645 lmin = 0.6;
646 lmax = 1.3;
647 for (j=0; j<ilist; j++) {
648 for (i=0; i<6; i++) {
649 pt = &mesh->tetra[list[j]/6];
650 if ( (!metRidTyp) && met->m && met->size>1 )
651 // Warning: we may erroneously approximate the length of a curve
652 // boundary edge by the length of the straight edge if the "MG_BDY"
653 // tag is missing along the edge.
654 len = MMG5_lenedg33_ani(mesh,met,i,pt);
655 else
656 // Warning: for aniso metrics we may erroneously approximate the
657 // length of a curve boundary edge by the length of the straight edge
658 // if the "MG_BDY" tag is missing along the edge.
659 len = MMG5_lenedg(mesh,met,i,pt);
660 if ( len < lmin) {
661 lmin = len;
662 }
663 else if ( len > lmax) {
664 lmax = len;
665 }
666 }
667 }
668 assert( lmin!=0 );
669
675 for (j=0; j<ilist; j++) {
676 iel = list[j] / 6;
677 pt = &mesh->tetra[iel];
678 ie = list[j] % 6;
679 pt0 = &mesh->tetra[0];
680 memcpy(pt0,pt,sizeof(MMG5_Tetra));
681
682 MMG5_int flag = 0;
683 MG_SET(flag,ie);
684 MMG3D_split1_cfg(flag,tau,&taued);
685
686 pt0->v[MMG5_isar[ie][1]] = ip;
687 if ( chkRidTet ) {
688 if ( !MMG3D_chk4ridVertices(mesh,pt0) ) {
689 break;
690 }
691 }
692 if ( (!metRidTyp) && met->m && met->size>1 )
693 /* Computation of straight edge length */
694 len = MMG5_lenedgspl33_ani(mesh,met,taued[5],pt0);
695 else
696 /* if edge is marked MG_BDY, curve length is computed, if edge is not
697 * MG_BDY, straight length is computed (even if the edge is indeed along
698 * the boundary but misses the tag). // Algiane 06/24: to check and fix
699 * or comment (I don't know if it is useful to compute the accurate
700 * curve length here)
701 */
702 len = MMG5_lenedgspl(mesh,met,taued[5],pt0);
703
704 if ( len < lmin ) break;
705 memcpy(pt0,pt,sizeof(MMG5_Tetra));
706
707 pt0->v[MMG5_isar[ie][0]] = ip;
708 if ( chkRidTet ) {
709 if ( !MMG3D_chk4ridVertices(mesh,pt0) ) {
710 break;
711 }
712 }
713
714 if ( (!metRidTyp) && met->m && met->size>1 )
715 /* Computation of straight edge length */
716 len = MMG5_lenedgspl33_ani(mesh,met,taued[5],pt0);
717 else
718 /* if edge is marked MG_BDY, curve length is computed, if edge is not
719 * MG_BDY, straight length is computed (even if the edge is indeed along
720 * the boundary but misses the tag). // Algiane 06/24: to check and fix
721 * or comment (I don't know if it is useful to compute the accurate
722 * curve length here)
723 */
724 len = MMG5_lenedgspl(mesh,met,taued[5],pt0);
725 if ( len < lmin ) break;
726 }
727 if ( j < ilist ) return 0;
728 }
729
730 iel = list[0] / 6;
731 ie = list[0] % 6;
732 pt = &mesh->tetra[iel];
733
734 nump = pt->v[MMG5_iare[ie][0]];
735
736 /* Fill list newtet[k] = +_created tetra for list[k]/6 : + if kept tetra (= one associated to
737 pt->v[tau[0]]) is associated with nump, - if with numq */
738 for (k=0; k<ilist; k++) {
739 iel = list[k] / 6;
740 ie = list[k] % 6;
741 pt = &mesh->tetra[iel];
742
743 MMG5_int flag = 0;
744 MG_SET(flag,ie);
745 MMG3D_split1_cfg(flag,tau,&taued);
746
747 jel = MMG3D_newElt(mesh);
748 if ( !jel ) {
750 fprintf(stderr,"\n ## Error: %s: unable to allocate"
751 " a new element.\n",__func__);
753 k--;
754 for ( ; k>=0 ; --k ) {
755 if ( !MMG3D_delElt(mesh,MMG5_abs(newtet[k])) ) return -1;
756 }
757 return -1);
758 pt = &mesh->tetra[iel];
759 }
760 pt1 = &mesh->tetra[jel];
761 memcpy(pt1,pt,sizeof(MMG5_Tetra));
762
763 if ( pt->v[tau[0]] == nump )
764 newtet[k] = jel;
765 else
766 newtet[k] = -jel;
767 }
768
769 /* Special case : only one element in the shell */
770 if ( ilist == 1 ) {
771 assert(open);
772
773 if ( !MMG5_split1b_eltspl(mesh,ip,0,list,newtet,tau) ) {
774 return -1;
775 }
776
777 /* Update of adjacency relations */
778 iel = list[0] / 6;
779 pt = &mesh->tetra[iel];
780 jel = MMG5_abs(newtet[0]);
781 pt1 = &mesh->tetra[jel];
782
783 adja = &mesh->adja[4*(iel-1)+1];
784 adjan = &mesh->adja[4*(jel-1)+1];
785
786 adja[tau[2]] = 0;
787 adja[tau[3]] = 0;
788 adjan[tau[2]] = 0;
789 adjan[tau[3]] = 0;
790
791 mel = adja[tau[0]] / 4;
792 voy = adja[tau[0]] % 4;
793 adja[tau[0]] = 4*jel + tau[1];
794 adjan[tau[0]] = 4*mel + voy;
795 adjan[tau[1]] = 4*iel + tau[0];
796
797 if ( mel ) {
798 adjan = &mesh->adja[4*(mel -1) +1];
799 adjan[voy] = 4*jel + tau[0];
800 }
801 /* Quality update */
802 if ( (!metRidTyp) && met->m && met->size>1 ) {
803 pt->qual=MMG5_caltet33_ani(mesh,met,pt);
804 pt1->qual=MMG5_caltet33_ani(mesh,met,pt1);
805 }
806 else {
807 pt->qual=MMG5_orcal(mesh,met,iel);
808 pt1->qual=MMG5_orcal(mesh,met,jel);
809 }
810 pt->mark = mesh->mark;
811 pt1->mark = mesh->mark;
812
813 return 1;
814 }
815
816 /* General case : update each element of the shell */
817 for (k=0; k<ilist; k++) {
818 if ( !MMG5_split1b_eltspl(mesh,ip,k,list,newtet,tau) ) {
819 return -1;
820 }
821
822 /* Update of adjacency relations */
823 iel = list[k] / 6;
824 pt = &mesh->tetra[iel];
825 jel = MMG5_abs(newtet[k]);
826 pt1 = &mesh->tetra[jel];
827
828 adja = &mesh->adja[4*(iel-1)+1];
829 adjan = &mesh->adja[4*(jel-1)+1];
830
831 nei2 = adja[tau[2]];
832 nei3 = adja[tau[3]];
833
834 /* Adjacency relations through both splitted faces */
835 if ( k == 0 ) {
836 if ( (list[1] / 6) == (nei2 / 4) ) {
837 if ( MG_SMSGN(newtet[0],newtet[1]) ) { //new elt of list[0] goes with new elt of list[1]
838 adja[tau[2]] = nei2;
839 adjan[tau[2]] = 4*MMG5_abs(newtet[1])+(nei2 %4);
840 }
841 else {
842 adja[tau[2]] = 4*MMG5_abs(newtet[1])+(nei2 %4);
843 adjan[tau[2]] = nei2;
844 }
845
846 if ( open ) {
847 adja[tau[3]] = 0;
848 adjan[tau[3]] = 0;
849 }
850
851 else {
852 assert((list[ilist-1] / 6) == (nei3 / 4));
853 if ( MG_SMSGN(newtet[0],newtet[ilist-1]) ) {
854 adja[tau[3]] = nei3;
855 adjan[tau[3]] = 4*MMG5_abs(newtet[ilist-1])+(nei3 %4);
856 }
857 else {
858 adja[tau[3]] = 4*MMG5_abs(newtet[ilist-1])+(nei3 %4);
859 adjan[tau[3]] = nei3;
860 }
861 }
862 }
863
864 else {
865 assert((list[1] / 6) == (nei3 / 4));
866 if ( MG_SMSGN(newtet[0],newtet[1]) ) {
867 adja[tau[3]] = nei3;
868 adjan[tau[3]] = 4*MMG5_abs(newtet[1])+(nei3 %4);
869 }
870 else {
871 adja[tau[3]] = 4*MMG5_abs(newtet[1])+(nei3 %4);
872 adjan[tau[3]] = nei3;
873 }
874
875 if ( open ) {
876 adja[tau[2]] = 0;
877 adjan[tau[2]] = 0;
878 }
879
880 else {
881 assert((list[ilist-1]) / 6 == (nei2 / 4));
882 if ( MG_SMSGN(newtet[0],newtet[ilist-1]) ) {
883 adja[tau[2]] = nei2;
884 adjan[tau[2]] = 4*MMG5_abs(newtet[ilist-1])+(nei2 %4);
885 }
886 else {
887 adja[tau[2]] = 4*MMG5_abs(newtet[ilist-1])+(nei2 %4);
888 adjan[tau[2]] = nei2;
889 }
890 }
891 }
892 }
893
894 else if ( k==ilist-1 ) {
895 if ( (list[ilist-2] / 6) == (nei2 / 4) ) {
896 if ( MG_SMSGN(newtet[ilist-1],newtet[ilist-2]) ) {
897 adja[tau[2]] = nei2;
898 adjan[tau[2]] = 4*MMG5_abs(newtet[ilist-2])+(nei2 %4);
899 }
900 else {
901 adja[tau[2]] = 4*MMG5_abs(newtet[ilist-2])+(nei2 %4);
902 adjan[tau[2]] = nei2;
903 }
904
905 if ( open ) {
906 adja[tau[3]] = 0;
907 adjan[tau[3]] = 0;
908 }
909
910 else {
911 assert((list[0]) / 6 == (nei3 / 4));
912 if ( MG_SMSGN(newtet[ilist-1],newtet[0]) ) {
913 adja[tau[3]] = nei3;
914 adjan[tau[3]] = 4*MMG5_abs(newtet[0])+(nei3 %4);
915 }
916 else {
917 adja[tau[3]] = 4*MMG5_abs(newtet[0])+(nei3 %4);
918 adjan[tau[3]] = nei3;
919 }
920 }
921 }
922
923 else {
924 assert((list[ilist-2] / 6) == (nei3 / 4));
925 if ( MG_SMSGN(newtet[ilist-1],newtet[ilist-2]) ) {
926 adja[tau[3]] = nei3;
927 adjan[tau[3]] = 4*MMG5_abs(newtet[ilist-2])+(nei3 %4);
928 }
929 else {
930 adja[tau[3]] = 4*MMG5_abs(newtet[ilist-2])+(nei3 %4);
931 adjan[tau[3]] = nei3;
932 }
933
934 if ( open ) {
935 adja[tau[2]] = 0;
936 adjan[tau[2]] = 0;
937 }
938
939 else {
940 assert((list[0]) / 6 == (nei2 / 4));
941 if ( MG_SMSGN(newtet[ilist-1],newtet[0]) ) {
942 adja[tau[2]] = nei2;
943 adjan[tau[2]] = 4*MMG5_abs(newtet[0])+(nei2 %4);
944 }
945 else {
946 adja[tau[2]] = 4*MMG5_abs(newtet[0])+(nei2 %4);
947 adjan[tau[2]] = nei2;
948 }
949 }
950 }
951 }
952
953 else {
954 if ( (list[k-1] / 6) == (nei2 / 4) ) {
955 if ( MG_SMSGN(newtet[k],newtet[k-1]) ) {
956 adja[tau[2]] = nei2;
957 adjan[tau[2]] = 4*MMG5_abs(newtet[k-1])+(nei2 %4);
958 }
959 else {
960 adja[tau[2]] = 4*MMG5_abs(newtet[k-1])+(nei2 %4);
961 adjan[tau[2]] = nei2;
962 }
963
964 assert((list[k+1]) / 6 == (nei3 / 4));
965 if ( MG_SMSGN(newtet[k],newtet[k+1]) ) {
966 adja[tau[3]] = nei3;
967 adjan[tau[3]] = 4*MMG5_abs(newtet[k+1])+(nei3 %4);
968 }
969 else {
970 adja[tau[3]] = 4*MMG5_abs(newtet[k+1])+(nei3 %4);
971 adjan[tau[3]] = nei3;
972 }
973 }
974
975 else {
976 assert((list[k-1] / 6) == (nei3 / 4));
977 if ( MG_SMSGN(newtet[k],newtet[k-1]) ) {
978 adja[tau[3]] = nei3;
979 adjan[tau[3]] = 4*MMG5_abs(newtet[k-1])+(nei3 %4);
980 }
981 else {
982 adja[tau[3]] = 4*MMG5_abs(newtet[k-1])+(nei3 %4);
983 adjan[tau[3]] = nei3;
984 }
985
986 assert((list[k+1]) / 6 == (nei2 / 4));
987 if ( MG_SMSGN(newtet[k],newtet[k+1]) ) {
988 adja[tau[2]] = nei2;
989 adjan[tau[2]] = 4*MMG5_abs(newtet[k+1])+(nei2 %4);
990 }
991 else {
992 adja[tau[2]] = 4*MMG5_abs(newtet[k+1])+(nei2 %4);
993 adjan[tau[2]] = nei2;
994 }
995 }
996 }
997
998 /* Internal adjacency relations update */
999 mel = adja[tau[0]] / 4;
1000 voy = adja[tau[0]] % 4;
1001 adja[tau[0]] = 4*jel + tau[1];
1002 adjan[tau[0]] = 4*mel + voy;
1003 adjan[tau[1]] = 4*iel + tau[0];
1004
1005 if ( mel ) {
1006 adjan = &mesh->adja[4*(mel -1) +1];
1007 adjan[voy] = 4*jel + tau[0];
1008 }
1009 /* Quality update */
1010 if ( (!metRidTyp) && met->m && met->size>1 ) {
1011 pt->qual=MMG5_caltet33_ani(mesh,met,pt);
1012 pt1->qual=MMG5_caltet33_ani(mesh,met,pt1);
1013 }
1014 else {
1015 pt->qual=MMG5_orcal(mesh,met,iel);
1016 pt1->qual=MMG5_orcal(mesh,met,jel);
1017 }
1018 pt->mark = mesh->mark;
1019 pt1->mark = mesh->mark;
1020 }
1021
1022 return 1;
1023}
1024
1036inline
1037void MMG3D_split2sf_cfg(MMG5_int flag,MMG5_int v[4],uint8_t *tau,const uint8_t **taued,uint8_t *imin) {
1038
1039 /* identity is case 48 */
1040 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
1041 *taued = &MMG5_permedge[0][0];
1042 switch(flag){
1043 case 24 :
1044 tau[0] = 0 ; tau[1] = 2 ; tau[2] = 3 ; tau[3] = 1;
1045 *taued = &MMG5_permedge[1][0];
1046 break;
1047 case 40 :
1048 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
1049 *taued = &MMG5_permedge[2][0];
1050 break;
1051 case 6 :
1052 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
1053 *taued = &MMG5_permedge[5][0];
1054 break;
1055 case 34 :
1056 tau[0] = 1 ; tau[1] = 0 ; tau[2] = 3 ; tau[3] = 2;
1057 *taued = &MMG5_permedge[3][0];
1058 break;
1059 case 36 :
1060 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
1061 *taued = &MMG5_permedge[4][0];
1062 break;
1063 case 20 :
1064 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
1065 *taued = &MMG5_permedge[6][0];
1066 break;
1067 case 5 :
1068 tau[0] = 2 ; tau[1] = 1 ; tau[2] = 3 ; tau[3] = 0;
1069 *taued = &MMG5_permedge[7][0];
1070 break;
1071 case 17 :
1072 tau[0] = 2 ; tau[1] = 3 ; tau[2] = 0 ; tau[3] = 1;
1073 *taued = &MMG5_permedge[8][0];
1074 break;
1075 case 9 :
1076 tau[0] = 3 ; tau[1] = 0 ; tau[2] = 2 ; tau[3] = 1;
1077 *taued = &MMG5_permedge[9][0];
1078 break;
1079 case 3 :
1080 tau[0] = 3 ; tau[1] = 2 ; tau[2] = 1 ; tau[3] = 0;
1081 *taued = &MMG5_permedge[11][0];
1082 break;
1083 case 10 :
1084 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
1085 *taued = &MMG5_permedge[10][0];
1086 break;
1087 }
1088
1089 (*imin) = (v[tau[1]] < v[tau[2]]) ? tau[1] : tau[2] ;
1090}
1091
1103int MMG3D_split2sf_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]){
1104 MMG5_pTetra pt,pt0;
1105 double vold,vnew;
1106 uint8_t tau[4],imin;
1107 const uint8_t *taued;
1108
1109 pt = &mesh->tetra[k];
1110 pt0 = &mesh->tetra[0];
1111 vold = MMG5_orvol(mesh->point,pt->v);
1112
1113 if ( vold < MMG5_EPSOK ) return 0;
1114
1115 MMG3D_split2sf_cfg(pt->flag,pt->v,tau,&taued,&imin);
1116
1117 /* Test orientation of the three tets to be created */
1118
1119 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1120 pt0->v[tau[1]] = vx[taued[4]];
1121 pt0->v[tau[2]] = vx[taued[5]];
1122 vnew = MMG5_orvol(mesh->point,pt0->v);
1123 if ( vnew < MMG5_EPSOK ) return 0;
1124
1125 if ( imin == tau[1] ) {
1126 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1127 pt0->v[tau[2]] = vx[taued[5]];
1128 pt0->v[tau[3]] = vx[taued[4]];
1129 vnew = MMG5_orvol(mesh->point,pt0->v);
1130 if ( vnew < MMG5_EPSOK ) return 0;
1131
1132 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1133 pt0->v[tau[3]] = vx[taued[5]];
1134 vnew = MMG5_orvol(mesh->point,pt0->v);
1135 if ( vnew < MMG5_EPSOK ) return 0;
1136 }
1137 else {
1138 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1139 pt0->v[tau[3]] = vx[taued[4]];
1140 vnew = MMG5_orvol(mesh->point,pt0->v);
1141 if ( vnew < MMG5_EPSOK ) return 0;
1142
1143 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1144 pt0->v[tau[1]] = vx[taued[4]];
1145 pt0->v[tau[3]] = vx[taued[5]];
1146 vnew = MMG5_orvol(mesh->point,pt0->v);
1147 if ( vnew < MMG5_EPSOK ) return 0;
1148 }
1149 return 1;
1150}
1151
1165static inline
1166int MMG3D_crea_newTetra(MMG5_pMesh mesh,const int ne,MMG5_int *newtet,
1167 MMG5_pTetra *pt,MMG5_xTetra *xt,MMG5_pxTetra *pxt0) {
1168 MMG5_int iel;
1169 int i,j;
1170
1171 /* The first tetra is the one that is splitted so it already exists */
1172 for ( i=1; i<ne; ++i ) {
1173 iel = MMG3D_newElt(mesh);
1174 if ( !iel ) {
1176 fprintf(stderr,"\n ## Error: %s: unable to allocate"
1177 " a new element.\n",__func__);
1179 fprintf(stderr," Exit program.\n");
1180 return 0);
1181 /* update pointer list */
1182 for ( j=0; j<i; ++j ) {
1183 pt[j] = &mesh->tetra[newtet[j]];
1184 }
1185 }
1186 pt[i] = &mesh->tetra[iel];
1187 memcpy(pt[i],pt[0],sizeof(MMG5_Tetra));
1188 newtet[i]=iel;
1189 }
1190
1191 /* If need copy the initial xtetra */
1192 if ( pt[0]->xt ) {
1193 *pxt0 = &mesh->xtetra[(pt[0])->xt];
1194 for ( i=0; i<ne; ++i ) {
1195 memcpy(&xt[i],*pxt0,sizeof(MMG5_xTetra));
1196 }
1197 }
1198 else {
1199 *pxt0 = 0;
1200 memset(xt,0x0,ne*sizeof(MMG5_xTetra));
1201 }
1202 return 1;
1203}
1204
1218static inline
1220 MMG5_int *newtet,MMG5_pTetra *pt,int8_t metRidTyp) {
1221 int i;
1222
1223 if ( (!metRidTyp) && met->m && met->size>1 ) {
1224 for (i=0; i<ne; i++) {
1225 pt[i]->qual=MMG5_caltet33_ani(mesh,met,pt[i]);
1226 }
1227 }
1228 else if ( (!met) || (!met->m) ) {
1229 /* in ls mode + -A option, orcal calls caltet_ani that fails */
1230 for (i=0; i<ne; i++) {
1231 pt[i]->qual=MMG5_caltet_iso(mesh,met,pt[i]);
1232 }
1233 }
1234 else
1235 {
1236 for (i=0; i<ne; i++) {
1237 pt[i]->qual=MMG5_orcal(mesh,met,newtet[i]);
1238 }
1239 }
1240
1241 return;
1242}
1243
1254int MMG5_split2sf(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp){
1255 MMG5_pTetra pt;
1256
1257 /* Tetra to be split */
1258 pt = &mesh->tetra[k];
1259
1260 return MMG5_split2sf_globNum(mesh,met,k,vx,pt->v,metRidTyp);
1261}
1262
1276int MMG5_split2sf_globNum(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],MMG5_int vGlobNum[4],int8_t metRidTyp){
1277 MMG5_pTetra pt[3];
1278 MMG5_xTetra xt[3];
1279 MMG5_pxTetra pxt0;
1280 int i,flg;
1281 MMG5_int newtet[3];
1282 int8_t firstxt,isxt[3];
1283 int16_t ftag[4];
1284 uint8_t tau[4],imin;
1285 const uint8_t *taued;
1286 const int ne=3;
1287
1288 pt[0] = &mesh->tetra[k];
1289 flg = pt[0]->flag;
1290 pt[0]->flag = 0;
1291 newtet[0]=k;
1292
1293 /* Determine tau, taued and imin the condition for vertices permutation */
1294 /* Remark: It is mandatory to call MMG3D_split2sf_cfg before MMG3D_crea_newTetra.
1295 Indeed, vGlobNum is set in MMG3D_split2sf as being pt->v. This value might
1296 point to a wrong memory address if the tetra array is reallocated
1297 in MMG3D_crea_newTetra before the use of vGlobNum */
1298 MMG3D_split2sf_cfg(flg,vGlobNum,tau,&taued,&imin);
1299
1300 /* Create 2 new tetra */
1301 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
1302 return 0;
1303 }
1304
1305 /* Store face tags and refs from split tetra*/
1306 for (i=0; i<4; i++) {
1307 ftag[i] = (xt[0].ftag[i] & ~MG_REF);
1308 }
1309
1310 /* Generic formulation for the split of 2 edges belonging to a common face */
1311 pt[0]->v[tau[1]] = vx[taued[4]] ; pt[0]->v[tau[2]] = vx[taued[5]];
1312 xt[0].tag[taued[0]] = ftag[tau[2]]; xt[0].tag[taued[1]] = ftag[tau[1]];
1313 xt[0].tag[taued[3]] = ftag[tau[0]]; xt[0].edg[taued[0]] = 0;
1314 xt[0].edg[taued[1]] = 0; xt[0].edg[taued[3]] = 0;
1315 xt[0].ref[ tau[3]] = 0; xt[0].ftag[ tau[3]] = 0; MG_SET(xt[0].ori, tau[3]);
1316
1317 if ( imin == tau[1] ) {
1318 pt[1]->v[tau[2]] = vx[taued[5]]; pt[1]->v[tau[3]] = vx[taued[4]];
1319 pt[2]->v[tau[3]] = vx[taued[5]];
1320
1321 xt[1].tag[taued[1]] = ftag[tau[1]]; xt[1].tag[taued[2]] = ftag[tau[2]];
1322 xt[1].tag[taued[3]] = ftag[tau[0]]; xt[1].tag[taued[5]] = ftag[tau[0]];
1323 xt[1].edg[taued[1]] = 0; xt[1].edg[taued[2]] = 0;
1324 xt[1].edg[taued[3]] = 0; xt[1].edg[taued[5]] = 0;
1325 xt[1].ref [ tau[1]] = 0; xt[1].ref [ tau[3]] = 0;
1326 xt[1].ftag[ tau[1]] = 0; xt[1].ftag[ tau[3]] = 0;
1327 MG_SET(xt[1].ori, tau[1]); MG_SET(xt[1].ori, tau[3]);
1328
1329 xt[2].tag[taued[2]] = ftag[tau[1]]; xt[2].tag[taued[4]] = ftag[tau[0]];
1330 xt[2].edg[taued[2]] = 0 ; xt[2].edg[taued[4]] = 0;
1331 xt[2].ref[ tau[2]] = 0; xt[2].ftag[ tau[2]] = 0; MG_SET(xt[2].ori, tau[2]);
1332 }
1333 else {
1334 pt[1]->v[tau[3]] = vx[taued[4]];
1335 pt[2]->v[tau[1]] = vx[taued[4]]; pt[2]->v[tau[3]] = vx[taued[5]];
1336
1337 xt[1].tag[taued[2]] = ftag[tau[2]]; xt[1].tag[taued[5]] = ftag[tau[0]];
1338 xt[1].edg[taued[2]] = 0 ; xt[1].edg[taued[5]] = 0;
1339 xt[1].ref[ tau[1]] = 0; xt[1].ftag[ tau[1]] = 0; MG_SET(xt[1].ori, tau[1]);
1340
1341 xt[2].tag[taued[0]] = ftag[tau[2]]; xt[2].tag[taued[2]] = ftag[tau[1]];
1342 xt[2].tag[taued[3]] = ftag[tau[0]]; xt[2].tag[taued[4]] = ftag[tau[0]];
1343 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[2]] = 0;
1344 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[4]] = 0;
1345 xt[2].ref [ tau[2]] = 0; xt[2].ref [ tau[3]] = 0;
1346 xt[2].ftag[ tau[2]] = 0; xt[2].ftag[ tau[3]] = 0;
1347 MG_SET(xt[2].ori, tau[2]); MG_SET(xt[2].ori, tau[3]);
1348 }
1349
1350 /* Assignation of the xt fields to the appropriate tets */
1351 isxt[0] = isxt[1] = isxt[2] = 0;
1352 for (i=0; i<4; i++) {
1353 if ( xt[0].ref[i] || xt[0].ftag[i] ) isxt[0] = 1;
1354 if ( xt[1].ref[i] || xt[1].ftag[i] ) isxt[1] = 1;
1355 if ( xt[2].ref[i] || xt[2].ftag[i] ) isxt[2] = 1;
1356 }
1357
1358 if ( pt[0]->xt ) {
1359 if ( isxt[0] ) {
1360 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
1361 pt[1]->xt = pt[2]->xt = 0;
1362 for (i=1; i<3; i++) {
1363 if ( isxt[i] ) {
1364 mesh->xt++;
1365 if ( mesh->xt > mesh->xtmax ) {
1366 /* realloc of xtetras table */
1368 "larger xtetra table",
1369 mesh->xt--;
1370 fprintf(stderr," Exit program.\n");
1371 return 0);
1372 }
1373 pt[i]->xt = mesh->xt;
1374 pxt0 = &mesh->xtetra[mesh->xt];
1375 memcpy(pxt0,&(xt[i]),sizeof(MMG5_xTetra));
1376 }
1377 }
1378 }
1379 else {
1380 firstxt = 1;
1381 pt[1]->xt = pt[2]->xt = 0;
1382 for (i=1; i<3; i++) {
1383 if ( isxt[i] ) {
1384 if ( firstxt ) {
1385 firstxt = 0;
1386 pt[i]->xt = pt[0]->xt;
1387 pxt0 = &mesh->xtetra[pt[i]->xt];
1388 memcpy(pxt0,&(xt[i]),sizeof(MMG5_xTetra));
1389 }
1390 else {
1391 mesh->xt++;
1392 if ( mesh->xt > mesh->xtmax ) {
1393 /* realloc of xtetras table */
1395 "larger xtetra table",
1396 mesh->xt--;
1397 fprintf(stderr," Exit program.\n");
1398 return 0);
1399 }
1400 pt[i]->xt = mesh->xt;
1401 pxt0 = &mesh->xtetra[mesh->xt];
1402 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1403 }
1404 }
1405 }
1406 pt[0]->xt = 0;
1407 }
1408 }
1409
1410 /* Quality update */
1411 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
1412
1413 return 1;
1414}
1415
1427int MMG3D_split2_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]){
1428 MMG5_pTetra pt,pt0;
1429 double vold,vnew;
1430 uint8_t tau[4];
1431 const uint8_t *taued;
1432
1433 pt = &mesh->tetra[k];
1434 pt0 = &mesh->tetra[0];
1435 vold = MMG5_orvol(mesh->point,pt->v);
1436
1437 if ( vold < MMG5_EPSOK ) return 0;
1438
1439 /* identity is case 33 */
1440 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
1441 taued = &MMG5_permedge[0][0];
1442 switch(pt->flag){
1443 case 18:
1444 tau[0] = 3; tau[1] = 1; tau[2] = 0; tau[3] = 2;
1445 taued = &MMG5_permedge[10][0];
1446 break;
1447 case 12:
1448 tau[0] = 0; tau[1] = 3; tau[2] = 1; tau[3] = 2;
1449 taued = &MMG5_permedge[2][0];
1450 break;
1451 }
1452
1453 /* Test orientation of the 4 tets to be created */
1454 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1455 pt0->v[tau[1]] = vx[taued[0]]; pt0->v[tau[2]] = vx[taued[5]];
1456 vnew = MMG5_orvol(mesh->point,pt0->v);
1457 if ( vnew < MMG5_EPSOK ) return 0;
1458
1459 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1460 pt0->v[tau[1]] = vx[taued[0]]; pt0->v[tau[3]] = vx[taued[5]];
1461 vnew = MMG5_orvol(mesh->point,pt0->v);
1462 if ( vnew < MMG5_EPSOK ) return 0;
1463
1464 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1465 pt0->v[tau[0]] = vx[taued[0]]; pt0->v[tau[2]] = vx[taued[5]];
1466 vnew = MMG5_orvol(mesh->point,pt0->v);
1467 if ( vnew < MMG5_EPSOK ) return 0;
1468
1469 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1470 pt0->v[tau[0]] = vx[taued[0]]; pt0->v[tau[3]] = vx[taued[5]];
1471 vnew = MMG5_orvol(mesh->point,pt0->v);
1472 if ( vnew < MMG5_EPSOK ) return 0;
1473
1474 return 1;
1475}
1476
1489int MMG5_split2(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
1490 MMG5_pTetra pt[4];
1491 MMG5_xTetra xt[4];
1492 MMG5_pxTetra pxt0;
1493 int i;
1494 MMG5_int newtet[4];
1495 int8_t flg,firstxt,isxt[4];
1496 int16_t ftag[4];
1497 uint8_t tau[4];
1498 const uint8_t *taued;
1499 const int ne=4;
1500
1501 pt[0] = &mesh->tetra[k];
1502 flg = pt[0]->flag;
1503 pt[0]->flag = 0;
1504 newtet[0]=k;
1505
1506 /* Create 3 new tetra */
1507 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
1508 return 0;
1509 }
1510
1511 /* identity : case 33 */
1512 tau[0] = 0; tau[1] = 1; tau[2] = 2; tau[3] = 3;
1513 taued = &MMG5_permedge[0][0];
1514 switch(flg){
1515 case 18:
1516 tau[0] = 3; tau[1] = 1; tau[2] = 0; tau[3] = 2;
1517 taued = &MMG5_permedge[10][0];
1518 break;
1519 case 12:
1520 tau[0] = 0; tau[1] = 3; tau[2] = 1; tau[3] = 2;
1521 taued = &MMG5_permedge[2][0];
1522 break;
1523 }
1524
1525 /* Store face tags and refs from split tetra*/
1526 for (i=0; i<4; i++) {
1527 ftag[i] = (xt[0].ftag[i] & ~MG_REF);
1528 }
1529
1530 /* Generic formulation for the split of 2 opposite edges */
1531 pt[0]->v[tau[1]] = vx[taued[0]]; pt[0]->v[tau[2]] = vx[taued[5]];
1532 pt[1]->v[tau[1]] = vx[taued[0]]; pt[1]->v[tau[3]] = vx[taued[5]];
1533 pt[2]->v[tau[0]] = vx[taued[0]]; pt[2]->v[tau[2]] = vx[taued[5]];
1534 pt[3]->v[tau[0]] = vx[taued[0]]; pt[3]->v[tau[3]] = vx[taued[5]];
1535
1536 xt[0].tag[taued[1]] = ftag[tau[1]]; xt[0].tag[taued[3]] = 0;
1537 xt[0].tag[taued[4]] = ftag[tau[2]]; xt[0].edg[taued[1]] = 0;
1538 xt[0].edg[taued[3]] = 0; xt[0].edg[taued[4]] = 0;
1539 xt[0].ref [ tau[0]] = 0; xt[0].ref [ tau[3]] = 0;
1540 xt[0].ftag[ tau[0]] = 0; xt[0].ftag[ tau[3]] = 0;
1541 MG_SET(xt[0].ori, tau[0]); MG_SET(xt[0].ori, tau[3]);
1542
1543 xt[1].tag[taued[2]] = ftag[tau[1]]; xt[1].tag[taued[3]] = ftag[tau[3]];
1544 xt[1].tag[taued[4]] = 0; xt[1].edg[taued[2]] = 0;
1545 xt[1].edg[taued[3]] = 0; xt[1].edg[taued[4]] = 0;
1546 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[2]] = 0;
1547 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[2]] = 0;
1548 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[2]);
1549
1550 xt[2].tag[taued[1]] = 0; xt[2].tag[taued[2]] = ftag[tau[2]];
1551 xt[2].tag[taued[3]] = ftag[tau[0]]; xt[2].edg[taued[1]] = 0;
1552 xt[2].edg[taued[2]] = 0; xt[2].edg[taued[3]] = 0;
1553 xt[2].ref [ tau[1]] = 0; xt[2].ref [ tau[3]] = 0;
1554 xt[2].ftag[ tau[1]] = 0; xt[2].ftag[ tau[3]] = 0;
1555 MG_SET(xt[2].ori, tau[1]); MG_SET(xt[2].ori, tau[3]);
1556
1557 xt[3].tag[taued[1]] = ftag[tau[3]]; xt[3].tag[taued[2]] = 0;
1558 xt[3].tag[taued[4]] = ftag[tau[0]]; xt[3].edg[taued[1]] = 0;
1559 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[4]] = 0;
1560 xt[3].ref [ tau[1]] = 0; xt[3].ref [ tau[2]] = 0;
1561 xt[3].ftag[ tau[1]] = 0; xt[3].ftag[ tau[2]] = 0;
1562 MG_SET(xt[3].ori, tau[1]); MG_SET(xt[3].ori, tau[2]);
1563
1564 /* Assignation of the xt fields to the appropriate tets */
1565 memset(isxt,0,4*sizeof(int8_t));
1566 for (i=0; i<4; i++) {
1567 int j;
1568 for (j=0; j<ne; j++) {
1569 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
1570 }
1571 }
1572
1573 if ( pt[0]->xt) {
1574 if ( isxt[0] ) {
1575 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
1576 for (i=1; i<4; i++) {
1577 if ( isxt[i] ) {
1578 mesh->xt++;
1579 if ( mesh->xt > mesh->xtmax ) {
1580 /* realloc of xtetras table */
1582 "larger xtetra table",
1583 mesh->xt--;
1584 fprintf(stderr," Exit program.\n");
1585 return 0);
1586 }
1587 pt[i]->xt = mesh->xt;
1588 pxt0 = &mesh->xtetra[mesh->xt];
1589 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1590 }
1591 else {
1592 pt[i]->xt = 0;
1593 }
1594 }
1595 }
1596 else {
1597 firstxt = 1;
1598 for (i=1; i<4; i++) {
1599 if ( isxt[i] ) {
1600 if ( firstxt ) {
1601 firstxt = 0;
1602 pt[i]->xt = pt[0]->xt;
1603 pxt0 = &mesh->xtetra[pt[i]->xt];
1604 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1605 }
1606 else {
1607 mesh->xt++;
1608 if ( mesh->xt > mesh->xtmax ) {
1609 /* realloc of xtetras table */
1611 "larger xtetra table",
1612 mesh->xt--;
1613 fprintf(stderr," Exit program.\n");
1614 return 0);
1615 }
1616 pt[i]->xt = mesh->xt;
1617 pxt0 = &mesh->xtetra[mesh->xt];
1618 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1619 }
1620 }
1621 else {
1622 pt[i]->xt = 0;
1623 }
1624 }
1625 pt[0]->xt = 0;
1626 }
1627 }
1628
1629 /* Quality update */
1630 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
1631
1632 return 1;
1633}
1634
1636int MMG3D_split3_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
1637 MMG5_pTetra pt,pt0;
1638 double vold,vnew;
1639 uint8_t tau[4];
1640 const uint8_t *taued;
1641
1642 pt = &mesh->tetra[k];
1643 pt0 = &mesh->tetra[0];
1644 vold = MMG5_orvol(mesh->point,pt->v);
1645
1646 if ( vold < MMG5_EPSOK ) return 0;
1647
1648 /* identity is case 11 */
1649 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
1650 taued = &MMG5_permedge[0][0];
1651 switch(pt->flag) {
1652 case 21:
1653 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
1654 taued = &MMG5_permedge[2][0];
1655 break;
1656 case 38:
1657 tau[0] = 3 ; tau[1] = 0 ; tau[2] = 2 ; tau[3] = 1;
1658 taued = &MMG5_permedge[9][0];
1659 break;
1660 case 56:
1661 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
1662 taued = &MMG5_permedge[5][0];
1663 break;
1664 }
1665
1666 /* Check orientation of the 4 newly created tets */
1667 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1668 pt0->v[tau[1]] = vx[taued[0]];
1669 pt0->v[tau[2]] = vx[taued[1]];
1670 vnew = MMG5_orvol(mesh->point,pt0->v);
1671 if ( vnew < MMG5_EPSOK ) return 0;
1672
1673 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1674 pt0->v[tau[0]] = vx[taued[0]];
1675 pt0->v[tau[2]] = vx[taued[3]];
1676 vnew = MMG5_orvol(mesh->point,pt0->v);
1677 if ( vnew < MMG5_EPSOK ) return 0;
1678
1679 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1680 pt0->v[tau[0]] = vx[taued[1]];
1681 pt0->v[tau[1]] = vx[taued[3]];
1682 vnew = MMG5_orvol(mesh->point,pt0->v);
1683 if ( vnew < MMG5_EPSOK ) return 0;
1684
1685 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1686 pt0->v[tau[0]] = vx[taued[0]];
1687 pt0->v[tau[1]] = vx[taued[3]];
1688 pt0->v[tau[2]] = vx[taued[1]];
1689 vnew = MMG5_orvol(mesh->point,pt0->v);
1690 if ( vnew < MMG5_EPSOK ) return 0;
1691
1692 return 1;
1693}
1694
1707int MMG5_split3(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
1708 MMG5_pTetra pt[4];
1709 MMG5_xTetra xt[4];
1710 MMG5_pxTetra pxt0;
1711 int i;
1712 MMG5_int newtet[4];
1713 int8_t flg,firstxt,isxt[4];
1714 int16_t ftag[4];
1715 uint8_t tau[4];
1716 const uint8_t *taued;
1717 const int ne=4;
1718
1719 pt[0] = &mesh->tetra[k];
1720 flg = pt[0]->flag;
1721 pt[0]->flag = 0;
1722 newtet[0]=k;
1723
1724 /* create 3 new tetras */
1725 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
1726 return 0;
1727 }
1728
1729 /* Store face tags and refs from split tetra*/
1730 for (i=0; i<4; i++) {
1731 ftag[i] = (xt[0].ftag[i] & ~MG_REF);
1732 }
1733
1734 /* update vertices, case 11 is default */
1735 tau[0] = 0; tau[1] = 1; tau[2] = 2; tau[3] = 3;
1736 taued = &MMG5_permedge[0][0];
1737 switch(flg) {
1738 case 21:
1739 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
1740 taued = &MMG5_permedge[2][0];
1741 break;
1742 case 38:
1743 tau[0] = 3 ; tau[1] = 0 ; tau[2] = 2 ; tau[3] = 1;
1744 taued = &MMG5_permedge[9][0];
1745 break;
1746 case 56:
1747 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
1748 taued = &MMG5_permedge[5][0];
1749 break;
1750 }
1751
1752 /* Generic formulation of split of 3 edges */
1753 pt[0]->v[tau[1]] = vx[taued[0]]; pt[0]->v[tau[2]] = vx[taued[1]];
1754 pt[1]->v[tau[0]] = vx[taued[0]]; pt[1]->v[tau[2]] = vx[taued[3]];
1755 pt[2]->v[tau[0]] = vx[taued[1]]; pt[2]->v[tau[1]] = vx[taued[3]];
1756 pt[3]->v[tau[0]] = vx[taued[0]]; pt[3]->v[tau[1]] = vx[taued[3]]; pt[3]->v[tau[2]] = vx[taued[1]];
1757
1758 xt[0].tag[taued[3]] = ftag[tau[3]]; xt[0].tag[taued[4]] = ftag[tau[2]];
1759 xt[0].tag[taued[5]] = ftag[tau[1]]; xt[0].edg[taued[3]] = 0;
1760 xt[0].edg[taued[4]] = 0; xt[0].edg[taued[5]] = 0;
1761 xt[0].ref[ tau[0]] = 0; xt[0].ftag[ tau[0]] = 0; MG_SET(xt[0].ori, tau[0]);
1762
1763 xt[1].tag[taued[1]] = ftag[tau[3]]; xt[1].tag[taued[2]] = ftag[tau[2]];
1764 xt[1].tag[taued[5]] = ftag[tau[0]]; xt[1].edg[taued[1]] = 0;
1765 xt[1].edg[taued[2]] = 0; xt[1].edg[taued[5]] = 0;
1766 xt[1].ref[ tau[1]] = 0; xt[1].ftag[ tau[1]] = 0; MG_SET(xt[1].ori, tau[1]);
1767
1768 xt[2].tag[taued[0]] = ftag[tau[3]]; xt[2].tag[taued[2]] = ftag[tau[1]];
1769 xt[2].tag[taued[4]] = ftag[tau[0]]; xt[2].edg[taued[0]] = 0;
1770 xt[2].edg[taued[2]] = 0; xt[2].edg[taued[4]] = 0;
1771 xt[2].ref[ tau[2]] = 0; xt[2].ftag[ tau[2]] = 0; MG_SET(xt[2].ori, tau[2]);
1772
1773 xt[3].tag[taued[0]] = ftag[tau[3]]; xt[3].tag[taued[1]] = ftag[tau[3]];
1774 xt[3].tag[taued[2]] = ftag[tau[2]]; xt[3].tag[taued[3]] = ftag[tau[3]];
1775 xt[3].tag[taued[4]] = ftag[tau[0]]; xt[3].tag[taued[5]] = ftag[tau[1]];
1776 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[1]] = 0;
1777 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[3]] = 0;
1778 xt[3].edg[taued[4]] = 0; xt[3].edg[taued[5]] = 0;
1779 xt[3].ref [ tau[0]] = 0; xt[3].ref [ tau[1]] = 0; xt[3].ref [tau[2]] = 0;
1780 xt[3].ftag[ tau[0]] = 0; xt[3].ftag[ tau[1]] = 0; xt[3].ftag[tau[2]] = 0;
1781 MG_SET(xt[3].ori, tau[0]); MG_SET(xt[3].ori, tau[1]); MG_SET(xt[3].ori, tau[2]);
1782
1783 /* Assignation of the xt fields to the appropriate tets */
1784 memset(isxt,0,4*sizeof(int8_t));
1785 for (i=0; i<4; i++) {
1786 int j;
1787 for (j=0; j<ne; j++) {
1788 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
1789 }
1790 }
1791
1792 if ( pt[0]->xt ) {
1793 if ( isxt[0] ) {
1794 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
1795 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
1796 for (i=1; i<4; i++) {
1797 if ( isxt[i] ) {
1798 mesh->xt++;
1799 if ( mesh->xt > mesh->xtmax ) {
1800 /* realloc of xtetras table */
1802 "larger xtetra table",
1803 mesh->xt--;
1804 fprintf(stderr," Exit program.\n");
1805 return 0);
1806 }
1807 pt[i]->xt = mesh->xt;
1808 pxt0 = &mesh->xtetra[mesh->xt];
1809 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1810 }
1811 }
1812 }
1813 else {
1814 firstxt = 1;
1815 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
1816 for (i=1; i<4; i++) {
1817 if ( isxt[i] ) {
1818 if ( firstxt ) {
1819 firstxt = 0;
1820 pt[i]->xt = pt[0]->xt;
1821 pxt0 = &mesh->xtetra[(pt[i])->xt];
1822 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1823 }
1824 else {
1825 mesh->xt++;
1826 if ( mesh->xt > mesh->xtmax ) {
1827 /* realloc of xtetras table */
1829 "larger xtetra table",
1830 mesh->xt--;
1831 fprintf(stderr," Exit program.\n");
1832 return 0);
1833 }
1834 pt[i]->xt = mesh->xt;
1835 pxt0 = &mesh->xtetra[mesh->xt];
1836 memcpy(pxt0,&(xt[i]),sizeof(MMG5_xTetra));
1837 }
1838 }
1839 }
1840 pt[0]->xt = 0;
1841 }
1842 }
1843
1844 /* Quality update */
1845 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
1846
1847 return 1;
1848}
1849
1862inline
1863void MMG3D_split3cone_cfg(MMG5_int flag,MMG5_int v[4],uint8_t tau[4],
1864 const uint8_t **taued,uint8_t *ia,uint8_t *ib) {
1865
1866
1867 /* Set permutation of vertices : reference configuration 7 */
1868 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
1869 (*taued) = &MMG5_permedge[0][0];
1870
1871 switch(flag) {
1872 case 25:
1873 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
1874 (*taued) = &MMG5_permedge[4][0];
1875 break;
1876
1877 case 42:
1878 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
1879 (*taued) = &MMG5_permedge[6][0];
1880 break;
1881
1882 case 52:
1883 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
1884 (*taued) = &MMG5_permedge[10][0];
1885 break;
1886 }
1887
1888 /* Determine the condition to choose split pattern to apply */
1889 /* Fill ia,ib,ic so that pt->v[ia] < pt->v[ib] < pt->v[ic] */
1890 if ( v[tau[1]] < v[tau[2]] ) {
1891 (*ia) = tau[1];
1892 (*ib) = tau[2];
1893 }
1894 else {
1895 (*ia) = tau[2];
1896 (*ib) = tau[1];
1897 }
1898
1899 if ( v[tau[3]] < v[(*ia)] ) {
1900 (*ib) = (*ia);
1901 (*ia) = tau[3];
1902 }
1903 else {
1904 if ( v[tau[3]] < v[(*ib)] ) {
1905 (*ib) = tau[3];
1906 }
1907 }
1908}
1909
1921int MMG3D_split3cone_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
1922 MMG5_pTetra pt,pt0;
1923 double vold,vnew;
1924 uint8_t tau[4],ia,ib;
1925 const uint8_t *taued;
1926
1927 pt = &mesh->tetra[k];
1928 pt0 = &mesh->tetra[0];
1929 vold = MMG5_orvol(mesh->point,pt->v);
1930
1931 if ( vold < MMG5_EPSOK ) return 0;
1932
1933 /* Determine tau, taued, ia and ib the conditions for vertices permutation */
1934 MMG3D_split3cone_cfg(pt->flag,pt->v,tau,&taued,&ia,&ib);
1935
1936 /* Check orientation of the 4 newly created tets */
1937 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1938 pt0->v[tau[1]] = vx[taued[0]];
1939 pt0->v[tau[2]] = vx[taued[1]];
1940 pt0->v[tau[3]] = vx[taued[2]];
1941 vnew = MMG5_orvol(mesh->point,pt0->v);
1942 if ( vnew < MMG5_EPSOK ) return 0;
1943
1944 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1945 if ( ia == tau[3] ) {
1946 pt0->v[tau[0]] = vx[taued[2]];
1947 pt0->v[tau[1]] = vx[taued[0]];
1948 pt0->v[tau[2]] = vx[taued[1]];
1949 vnew = MMG5_orvol(mesh->point,pt0->v);
1950 if ( vnew < MMG5_EPSOK ) return 0;
1951
1952 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1953 if ( ib == tau[1] ) {
1954 pt0->v[tau[0]] = vx[taued[0]];
1955 pt0->v[tau[2]] = vx[taued[1]];
1956 vnew = MMG5_orvol(mesh->point,pt0->v);
1957 if ( vnew < MMG5_EPSOK ) return 0;
1958
1959 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1960 pt0->v[tau[0]] = vx[taued[1]] ;
1961 vnew = MMG5_orvol(mesh->point,pt0->v);
1962 if ( vnew < MMG5_EPSOK ) return 0;
1963 }
1964 else {
1965 assert(ib == tau[2]);
1966 pt0->v[tau[0]] = vx[taued[1]];
1967 pt0->v[tau[1]] = vx[taued[0]];
1968 vnew = MMG5_orvol(mesh->point,pt0->v);
1969 if ( vnew < MMG5_EPSOK ) return 0;
1970
1971 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1972 pt0->v[tau[0]] = vx[taued[0]] ;
1973 vnew = MMG5_orvol(mesh->point,pt0->v);
1974 if ( vnew < MMG5_EPSOK ) return 0;
1975 }
1976 }
1977 else if (ia == tau[2] ) {
1978 pt0->v[tau[0]] = vx[taued[1]];
1979 pt0->v[tau[1]] = vx[taued[0]];
1980 pt0->v[tau[3]] = vx[taued[2]];
1981 vnew = MMG5_orvol(mesh->point,pt0->v);
1982 if ( vnew < MMG5_EPSOK ) return 0;
1983
1984 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1985 if ( ib == tau[3] ) {
1986 pt0->v[tau[0]] = vx[taued[2]];
1987 pt0->v[tau[1]] = vx[taued[0]];
1988 vnew = MMG5_orvol(mesh->point,pt0->v);
1989 if ( vnew < MMG5_EPSOK ) return 0;
1990
1991 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1992 pt0->v[tau[0]] = vx[taued[0]];
1993 vnew = MMG5_orvol(mesh->point,pt0->v);
1994 if ( vnew < MMG5_EPSOK ) return 0;
1995 }
1996 else {
1997 assert(ib == tau[1]);
1998 pt0->v[tau[0]] = vx[taued[0]];
1999 pt0->v[tau[3]] = vx[taued[2]];
2000 vnew = MMG5_orvol(mesh->point,pt0->v);
2001 if ( vnew < MMG5_EPSOK ) return 0;
2002
2003 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2004 pt0->v[tau[0]] = vx[taued[2]];
2005 vnew = MMG5_orvol(mesh->point,pt0->v);
2006 if ( vnew < MMG5_EPSOK ) return 0;
2007 }
2008 }
2009 else {
2010 assert(ia == tau[1]);
2011
2012 pt0->v[tau[0]] = vx[taued[0]];
2013 pt0->v[tau[2]] = vx[taued[1]];
2014 pt0->v[tau[3]] = vx[taued[2]];
2015 vnew = MMG5_orvol(mesh->point,pt0->v);
2016 if ( vnew < MMG5_EPSOK ) return 0;
2017
2018 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2019 if ( ib == tau[2] ) {
2020 pt0->v[tau[0]] = vx[taued[1]];
2021 pt0->v[tau[3]] = vx[taued[2]] ;
2022 vnew = MMG5_orvol(mesh->point,pt0->v);
2023 if ( vnew < MMG5_EPSOK ) return 0;
2024
2025 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2026 pt0->v[tau[0]] = vx[taued[2]] ;
2027 vnew = MMG5_orvol(mesh->point,pt0->v);
2028 if ( vnew < MMG5_EPSOK ) return 0;
2029
2030 }
2031 else {
2032 assert(ib == tau[3]);
2033
2034 pt0->v[tau[0]] = vx[taued[2]];
2035 pt0->v[tau[2]] = vx[taued[1]];
2036 vnew = MMG5_orvol(mesh->point,pt0->v);
2037 if ( vnew < MMG5_EPSOK ) return 0;
2038
2039 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2040 pt0->v[tau[0]] = vx[taued[1]];
2041 vnew = MMG5_orvol(mesh->point,pt0->v);
2042 if ( vnew < MMG5_EPSOK ) return 0;
2043 }
2044 }
2045
2046 return 1;
2047}
2048
2059int MMG5_split3cone(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
2060 MMG5_pTetra pt;
2061
2062 /* Tetra to be split */
2063 pt = &mesh->tetra[k];
2064
2065 return MMG5_split3cone_globNum(mesh,met,k,vx,pt->v,metRidTyp);
2066}
2067
2081int MMG5_split3cone_globNum(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],MMG5_int vGlobNum[4],int8_t metRidTyp){
2082 MMG5_pTetra pt[4];
2083 MMG5_xTetra xt[4];
2084 MMG5_pxTetra pxt0;
2085 int i;
2086 MMG5_int newtet[4];
2087 int8_t flg,firstxt,isxt[4];
2088 int16_t ftag[4];
2089 uint8_t tau[4],ia,ib;
2090 const uint8_t *taued;
2091 const int ne=4;
2092
2093 pt[0] = &mesh->tetra[k];
2094 flg = pt[0]->flag;
2095 pt[0]->flag = 0;
2096 newtet[0]=k;
2097
2098 /* Determine tau, taued, ia and ib the conditions for vertices permutation */
2099 /* Remark: It is mandatory to call MMG3D_split3cone_cfg before MMG3D_crea_newTetra.
2100 Indeed, vGlobNum is set in MMG3D_split3cone as being pt->v. This value might
2101 point to a wrong memory address if the tetra array is reallocated
2102 in MMG3D_crea_newTetra before the use of vGlobNum */
2103 MMG3D_split3cone_cfg(flg,vGlobNum,tau,&taued,&ia,&ib);
2104
2105 /* Create 3 new tetras */
2106 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
2107 return 0;
2108 }
2109
2110 /* Store face tags and refs from split tetra*/
2111 for (i=0; i<4; i++) {
2112 ftag[i] = (xt[0].ftag[i] & ~MG_REF);
2113 }
2114
2115 /* Generic formulation of split of 3 edges in cone configuration (edges 0,1,2 splitted) */
2116 pt[0]->v[tau[1]] = vx[taued[0]] ; pt[0]->v[tau[2]] = vx[taued[1]] ; pt[0]->v[tau[3]] = vx[taued[2]];
2117 xt[0].tag[taued[3]] = ftag[tau[3]]; xt[0].tag[taued[4]] = ftag[tau[2]];
2118 xt[0].tag[taued[5]] = ftag[tau[1]]; xt[0].edg[taued[3]] = 0;
2119 xt[0].edg[taued[4]] = 0; xt[0].edg[taued[5]] = 0;
2120 xt[0].ref [ tau[0]] = 0;
2121 xt[0].ftag[ tau[0]] = 0;
2122 MG_SET(xt[0].ori, tau[0]);
2123
2124 if ( ia == tau[3] ) {
2125 pt[1]->v[tau[0]] = vx[taued[2]] ; pt[1]->v[tau[1]] = vx[taued[0]] ; pt[1]->v[tau[2]] = vx[taued[1]];
2126 xt[1].tag[taued[0]] = ftag[tau[2]]; xt[1].tag[taued[1]] = ftag[tau[1]];
2127 xt[1].tag[taued[3]] = ftag[tau[3]]; xt[1].tag[taued[4]] = ftag[tau[2]];
2128 xt[1].tag[taued[5]] = ftag[tau[1]]; xt[1].edg[taued[0]] = 0;
2129 xt[1].edg[taued[1]] = 0; xt[1].edg[taued[3]] = 0;
2130 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
2131 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[3]] = 0;
2132 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[3]] = 0;
2133 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[3]);
2134
2135 if ( ib == tau[1] ) {
2136 pt[2]->v[tau[0]] = vx[taued[0]] ; pt[2]->v[tau[2]] = vx[taued[1]] ;
2137 xt[2].tag[taued[1]] = ftag[tau[3]]; xt[2].tag[taued[2]] = ftag[tau[2]];
2138 xt[2].tag[taued[3]] = ftag[tau[3]]; xt[2].tag[taued[5]] = ftag[tau[1]];
2139 xt[2].edg[taued[1]] = 0; xt[2].edg[taued[2]] = 0;
2140 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[5]] = 0;
2141 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[1]] = 0;
2142 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[1]] = 0;
2143 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[1]);
2144
2145 pt[3]->v[tau[0]] = vx[taued[1]] ;
2146 xt[3].tag[taued[0]] = ftag[tau[3]]; xt[3].tag[taued[2]] = ftag[tau[1]];
2147 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[2]] = 0;
2148 xt[3].ref [ tau[2]] = 0;
2149 xt[3].ftag[ tau[2]] = 0;
2150 MG_SET(xt[3].ori, tau[2]);
2151 }
2152 else {
2153 assert(ib == tau[2]);
2154
2155 pt[2]->v[tau[0]] = vx[taued[1]] ; pt[2]->v[tau[1]] = vx[taued[0]] ;
2156 xt[2].tag[taued[0]] = ftag[tau[3]]; xt[2].tag[taued[2]] = ftag[tau[1]];
2157 xt[2].tag[taued[3]] = ftag[tau[3]]; xt[2].tag[taued[4]] = ftag[tau[2]];
2158 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[2]] = 0;
2159 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[4]] = 0;
2160 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[2]] = 0;
2161 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[2]] = 0;
2162 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[2]);
2163
2164 pt[3]->v[tau[0]] = vx[taued[0]] ;
2165 xt[3].tag[taued[1]] = ftag[tau[3]]; xt[3].tag[taued[2]] = ftag[tau[2]];
2166 xt[3].edg[taued[1]] = 0; xt[3].edg[taued[2]] = 0;
2167 xt[3].ref [ tau[1]] = 0;
2168 xt[3].ftag[ tau[1]] = 0;
2169 MG_SET(xt[3].ori, tau[1]);
2170 }
2171 }
2172
2173 else if (ia == tau[2] ) {
2174 pt[1]->v[tau[0]] = vx[taued[1]] ; pt[1]->v[tau[1]] = vx[taued[0]] ; pt[1]->v[tau[3]] = vx[taued[2]];
2175 xt[1].tag[taued[0]] = ftag[tau[3]]; xt[1].tag[taued[2]] = ftag[tau[1]];
2176 xt[1].tag[taued[3]] = ftag[tau[3]]; xt[1].tag[taued[4]] = ftag[tau[2]];
2177 xt[1].tag[taued[5]] = ftag[tau[1]]; xt[1].edg[taued[0]] = 0;
2178 xt[1].edg[taued[2]] = 0; xt[1].edg[taued[3]] = 0;
2179 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
2180 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[2]] = 0;
2181 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[2]] = 0;
2182 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[2]);
2183
2184 if ( ib == tau[3] ) {
2185 pt[2]->v[tau[0]] = vx[taued[2]] ; pt[2]->v[tau[1]] = vx[taued[0]] ;
2186 xt[2].tag[taued[0]] = ftag[tau[2]]; xt[2].tag[taued[1]] = ftag[tau[1]];
2187 xt[2].tag[taued[3]] = ftag[tau[3]]; xt[2].tag[taued[4]] = ftag[tau[2]];
2188 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[1]] = 0;
2189 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[4]] = 0;
2190 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[3]] = 0;
2191 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[3]] = 0;
2192 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[3]);
2193
2194 pt[3]->v[tau[0]] = vx[taued[0]] ;
2195 xt[3].tag[taued[1]] = ftag[tau[3]]; xt[3].tag[taued[2]] = ftag[tau[2]];
2196 xt[3].edg[taued[1]] = 0; xt[3].edg[taued[2]] = 0;
2197 xt[3].ref [ tau[1]] = 0;
2198 xt[3].ftag[ tau[1]] = 0;
2199 MG_SET(xt[3].ori, tau[1]);
2200 }
2201 else {
2202 assert(ib == tau[1]);
2203
2204 pt[2]->v[tau[0]] = vx[taued[0]] ; pt[2]->v[tau[3]] = vx[taued[2]] ;
2205 xt[2].tag[taued[1]] = ftag[tau[3]]; xt[2].tag[taued[2]] = ftag[tau[2]];
2206 xt[2].tag[taued[4]] = ftag[tau[2]]; xt[2].tag[taued[5]] = ftag[tau[1]];
2207 xt[2].edg[taued[1]] = 0; xt[2].edg[taued[2]] = 0;
2208 xt[2].edg[taued[4]] = 0; xt[2].edg[taued[5]] = 0;
2209 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[1]] = 0;
2210 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[1]] = 0;
2211 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[1]);
2212
2213 pt[3]->v[tau[0]] = vx[taued[2]] ;
2214 xt[3].tag[taued[0]] = ftag[tau[2]]; xt[3].tag[taued[1]] = ftag[tau[1]];
2215 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[1]] = 0;
2216 xt[3].ref [ tau[3]] = 0;
2217 xt[3].ftag[ tau[3]] = 0;
2218 MG_SET(xt[3].ori, tau[3]);
2219 }
2220 }
2221 else {
2222 assert(ia == tau[1]);
2223
2224 pt[1]->v[tau[0]] = vx[taued[0]] ; pt[1]->v[tau[2]] = vx[taued[1]] ; pt[1]->v[tau[3]] = vx[taued[2]];
2225 xt[1].tag[taued[1]] = ftag[tau[3]]; xt[1].tag[taued[2]] = ftag[tau[2]];
2226 xt[1].tag[taued[3]] = ftag[tau[3]]; xt[1].tag[taued[4]] = ftag[tau[2]];
2227 xt[1].tag[taued[5]] = ftag[tau[1]]; xt[1].edg[taued[1]] = 0;
2228 xt[1].edg[taued[2]] = 0; xt[1].edg[taued[3]] = 0;
2229 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
2230 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[1]] = 0;
2231 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[1]] = 0;
2232 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[1]);
2233
2234 if ( ib == tau[2] ) {
2235 pt[2]->v[tau[0]] = vx[taued[1]] ; pt[2]->v[tau[3]] = vx[taued[2]] ;
2236 xt[2].tag[taued[0]] = ftag[tau[3]]; xt[2].tag[taued[2]] = ftag[tau[1]];
2237 xt[2].tag[taued[4]] = ftag[tau[2]]; xt[2].tag[taued[5]] = ftag[tau[1]];
2238 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[2]] = 0;
2239 xt[2].edg[taued[4]] = 0; xt[2].edg[taued[5]] = 0;
2240 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[2]] = 0;
2241 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[2]] = 0;
2242 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[2]);
2243
2244 pt[3]->v[tau[0]] = vx[taued[2]] ;
2245 xt[3].tag[taued[0]] = ftag[tau[2]]; xt[3].tag[taued[1]] = ftag[tau[1]];
2246 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[1]] = 0;
2247 xt[3].ref [ tau[3]] = 0;
2248 xt[3].ftag[ tau[3]] = 0;
2249 MG_SET(xt[3].ori, tau[3]);
2250 }
2251 else {
2252 assert(ib == tau[3]);
2253
2254 pt[2]->v[tau[0]] = vx[taued[2]] ; pt[2]->v[tau[2]] = vx[taued[1]] ;
2255 xt[2].tag[taued[0]] = ftag[tau[2]]; xt[2].tag[taued[1]] = ftag[tau[1]];
2256 xt[2].tag[taued[3]] = ftag[tau[3]]; xt[2].tag[taued[5]] = ftag[tau[1]];
2257 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[1]] = 0;
2258 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[5]] = 0;
2259 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[3]] = 0;
2260 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[3]] = 0;
2261 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[3]);
2262
2263 pt[3]->v[tau[0]] = vx[taued[1]] ;
2264 xt[3].tag[taued[0]] = ftag[tau[3]]; xt[3].tag[taued[2]] = ftag[tau[1]];
2265 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[2]] = 0;
2266 xt[3].ref [ tau[2]] = 0;
2267 xt[3].ftag[ tau[2]] = 0;
2268 MG_SET(xt[3].ori, tau[2]);
2269 }
2270 }
2271
2272 /* Assignation of the xt fields to the appropriate tets */
2273 isxt[0] = isxt[1] = isxt[2] = isxt[3] = 0;
2274
2275 for (i=0; i<4; i++) {
2276 int j;
2277 for (j=0; j<ne; j++) {
2278 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
2279 }
2280 }
2281
2282 if ( (pt[0])->xt ) {
2283 if ( isxt[0] ) {
2284 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
2285 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
2286 for (i=1; i<4; i++) {
2287 if ( isxt[i] ) {
2288 mesh->xt++;
2289 if ( mesh->xt > mesh->xtmax ) {
2290 /* realloc of xtetras table */
2292 "larger xtetra table",
2293 mesh->xt--;
2294 fprintf(stderr," Exit program.\n");
2295 return 0);
2296 }
2297 pt[i]->xt = mesh->xt;
2298 pxt0 = &mesh->xtetra[mesh->xt];
2299 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2300 }
2301 }
2302 }
2303 else {
2304 firstxt = 1;
2305 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
2306 for ( i=1; i<4; i++) {
2307 if ( isxt[i] ) {
2308 if ( firstxt ) {
2309 firstxt = 0;
2310 pt[i]->xt = pt[0]->xt;
2311 pxt0 = &mesh->xtetra[(pt[i])->xt];
2312 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2313 }
2314 else {
2315 mesh->xt++;
2316 if ( mesh->xt > mesh->xtmax ) {
2317 /* realloc of xtetras table */
2319 "larger xtetra table",
2320 mesh->xt--;
2321 fprintf(stderr," Exit program.\n");
2322 return 0);
2323 }
2324 pt[i]->xt = mesh->xt;
2325 pxt0 = &mesh->xtetra[mesh->xt];
2326 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2327 }
2328 }
2329 }
2330 (pt[0])->xt = 0;
2331 }
2332 }
2333
2334 /* Quality update */
2335 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
2336
2337 return 1;
2338}
2339
2364static inline
2365void MMG3D_split3op_cfg(MMG5_pTetra pt,MMG5_int vx[6],uint8_t tau[4],
2366 const uint8_t **taued,
2367 uint8_t sym[4],uint8_t symed[6],
2368 uint8_t *ip0,uint8_t *ip1,
2369 uint8_t *ip2,uint8_t *ip3,
2370 uint8_t *ie0,uint8_t *ie1,
2371 uint8_t *ie2,uint8_t *ie3,
2372 uint8_t *ie4,uint8_t *ie5,
2373 uint8_t *imin03,uint8_t *imin12) {
2374
2375 /* Set permutation /symmetry of vertices : generic case : 35 */
2376 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
2377 (*taued) = &MMG5_permedge[0][0];
2378
2379 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2380 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2381 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2382
2383 switch(pt->flag) {
2384 case 19:
2385 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
2386 (*taued) = &MMG5_permedge[0][0];
2387
2388 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2389 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2390 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2391 break;
2392
2393 case 13:
2394 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
2395 (*taued) = &MMG5_permedge[2][0];
2396
2397 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2398 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2399 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2400 break;
2401
2402 case 37:
2403 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
2404 (*taued) = &MMG5_permedge[2][0];
2405
2406 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2407 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2408 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2409 break;
2410
2411 case 22:
2412 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
2413 (*taued) = &MMG5_permedge[10][0];
2414
2415 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2416 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2417 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2418 break;
2419
2420 case 28:
2421 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
2422 (*taued) = &MMG5_permedge[10][0];
2423
2424 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2425 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2426 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2427 break;
2428
2429 case 26:
2430 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
2431 (*taued) = &MMG5_permedge[6][0];
2432
2433 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2434 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2435 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2436 break;
2437
2438 case 14:
2439 tau[0] = 0 ; tau[1] = 2 ; tau[2] = 3 ; tau[3] = 1;
2440 (*taued) = &MMG5_permedge[1][0];
2441
2442 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2443 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2444 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2445 break;
2446
2447 case 49:
2448 tau[0] = 3 ; tau[1] = 2 ; tau[2] = 1 ; tau[3] = 0;
2449 (*taued) = &MMG5_permedge[11][0];
2450
2451 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2452 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2453 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2454 break;
2455
2456 case 50:
2457 tau[0] = 3 ; tau[1] = 2 ; tau[2] = 1 ; tau[3] = 0;
2458 (*taued) = &MMG5_permedge[11][0];
2459
2460 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2461 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2462 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2463 break;
2464
2465 case 44:
2466 tau[0] = 3 ; tau[1] = 0 ; tau[2] = 2 ; tau[3] = 1;
2467 (*taued) = &MMG5_permedge[9][0];
2468
2469 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2470 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2471 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2472 break;
2473
2474 case 41:
2475 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
2476 (*taued) = &MMG5_permedge[4][0];
2477
2478 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2479 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2480 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2481 break;
2482 }
2483
2484 (*ip0) = tau[sym[0]];
2485 (*ip1) = tau[sym[1]];
2486 (*ip2) = tau[sym[2]];
2487 (*ip3) = tau[sym[3]];
2488
2489 (*ie0) = (*taued)[symed[0]];
2490 (*ie1) = (*taued)[symed[1]];
2491 (*ie2) = (*taued)[symed[2]];
2492 (*ie3) = (*taued)[symed[3]];
2493 (*ie4) = (*taued)[symed[4]];
2494 (*ie5) = (*taued)[symed[5]];
2495
2496 /* Test : to be removed eventually */
2497 assert(vx[(*ie0)] > 0);
2498 assert(vx[(*ie1)] > 0);
2499 assert(vx[(*ie5)] > 0);
2500 assert(vx[(*ie2)] <= 0);
2501 assert(vx[(*ie3)] <= 0);
2502 assert(vx[(*ie4)] <= 0);
2503
2504 /* Determine the condition to choose split pattern to apply */
2505 (*imin03) = (pt->v[(*ip0)] < pt->v[(*ip3)]) ? (*ip0) : (*ip3);
2506 (*imin12) = (pt->v[(*ip1)] < pt->v[(*ip2)]) ? (*ip1) : (*ip2);
2507
2508 return;
2509}
2510
2522int MMG3D_split3op_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
2523 MMG5_pTetra pt,pt0;
2524 double vold,vnew;
2525 uint8_t tau[4],sym[4],symed[6],ip0,ip1,ip2,ip3,ie0,ie1,ie2,ie3;
2526 uint8_t ie4,ie5,imin03,imin12;
2527 const uint8_t *taued=NULL;
2528
2529 pt = &mesh->tetra[k];
2530 pt0 = &mesh->tetra[0];
2531 vold = MMG5_orvol(mesh->point,pt->v);
2532
2533 if ( vold < MMG5_EPSOK ) return 0;
2534
2535 /* Set permutation /symmetry of vertices : generic case : 35 */
2536 MMG3D_split3op_cfg(pt,vx,tau,&taued,sym,symed,&ip0,&ip1,&ip2,&ip3,
2537 &ie0,&ie1,&ie2,&ie3,&ie4,&ie5,&imin03,&imin12);
2538
2539 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2540 if ( (imin12 == ip2) && (imin03 == ip0) ) {
2541 pt0->v[ip0] = vx[ie1] ; pt0->v[ip1] = vx[ie0] ; pt0->v[ip3] = vx[ie5] ;
2542 vnew = MMG5_orvol(mesh->point,pt0->v);
2543 if ( vnew < MMG5_EPSOK ) return 0;
2544
2545 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2546 pt0->v[ip0] = vx[ie0] ; pt0->v[ip3] = vx[ie5] ;
2547 vnew = MMG5_orvol(mesh->point,pt0->v);
2548 if ( vnew < MMG5_EPSOK ) return 0;
2549
2550 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2551 pt0->v[ip0] = vx[ie0] ; pt0->v[ip2] = vx[ie5] ;
2552 vnew = MMG5_orvol(mesh->point,pt0->v);
2553 if ( vnew < MMG5_EPSOK ) return 0;
2554
2555 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2556 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie1] ; pt0->v[ip3] = vx[ie5] ;
2557 vnew = MMG5_orvol(mesh->point,pt0->v);
2558 if ( vnew < MMG5_EPSOK ) return 0;
2559
2560 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2561 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie5];
2562 vnew = MMG5_orvol(mesh->point,pt0->v);
2563 if ( vnew < MMG5_EPSOK ) return 0;
2564 }
2565
2566 else if ( (imin12 == ip1) && (imin03 == ip0) ) {
2567 pt0->v[ip0] = vx[ie1] ; pt0->v[ip3] = vx[ie5] ;
2568 vnew = MMG5_orvol(mesh->point,pt0->v);
2569 if ( vnew < MMG5_EPSOK ) return 0;
2570
2571 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2572 pt0->v[ip0] = vx[ie0] ; pt0->v[ip2] = vx[ie1] ; pt0->v[ip3] = vx[ie5];
2573 vnew = MMG5_orvol(mesh->point,pt0->v);
2574 if ( vnew < MMG5_EPSOK ) return 0;
2575
2576 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2577 pt0->v[ip0] = vx[ie0] ; pt0->v[ip2] = vx[ie5] ;
2578 vnew = MMG5_orvol(mesh->point,pt0->v);
2579 if ( vnew < MMG5_EPSOK ) return 0;
2580
2581 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2582 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie5];
2583 vnew = MMG5_orvol(mesh->point,pt0->v);
2584 if ( vnew < MMG5_EPSOK ) return 0;
2585
2586 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2587 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie1]; pt0->v[ip3] = vx[ie5];
2588 vnew = MMG5_orvol(mesh->point,pt0->v);
2589 if ( vnew < MMG5_EPSOK ) return 0;
2590 }
2591 else if ( (imin12 == ip2) && (imin03 == ip3) ) {
2592 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie1] ;
2593 vnew = MMG5_orvol(mesh->point,pt0->v);
2594 if ( vnew < MMG5_EPSOK ) return 0;
2595
2596 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2597 pt0->v[ip0] = vx[ie1] ; pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie5];
2598 vnew = MMG5_orvol(mesh->point,pt0->v);
2599 if ( vnew < MMG5_EPSOK ) return 0;
2600
2601 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2602 pt0->v[ip0] = vx[ie0] ; pt0->v[ip2] = vx[ie5] ;
2603 vnew = MMG5_orvol(mesh->point,pt0->v);
2604 if ( vnew < MMG5_EPSOK ) return 0;
2605
2606 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2607 pt0->v[ip0] = vx[ie1] ; pt0->v[ip1] = vx[ie0]; pt0->v[ip3] = vx[ie5];
2608 vnew = MMG5_orvol(mesh->point,pt0->v);
2609 if ( vnew < MMG5_EPSOK ) return 0;
2610
2611 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2612 pt0->v[ip0] = vx[ie0] ; pt0->v[ip3] = vx[ie5];
2613 vnew = MMG5_orvol(mesh->point,pt0->v);
2614 if ( vnew < MMG5_EPSOK ) return 0;
2615 }
2616 else {
2617 assert((imin12 == ip1) && (imin03 == ip3)) ;
2618
2619 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie1] ;
2620 vnew = MMG5_orvol(mesh->point,pt0->v);
2621 if ( vnew < MMG5_EPSOK ) return 0;
2622
2623 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2624 pt0->v[ip0] = vx[ie1] ; pt0->v[ip3] = vx[ie5] ;
2625 vnew = MMG5_orvol(mesh->point,pt0->v);
2626 if ( vnew < MMG5_EPSOK ) return 0;
2627
2628 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2629 pt0->v[ip0] = vx[ie0] ; pt0->v[ip2] = vx[ie1] ;
2630 vnew = MMG5_orvol(mesh->point,pt0->v);
2631 if ( vnew < MMG5_EPSOK ) return 0;
2632
2633 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2634 pt0->v[ip0] = vx[ie1] ; pt0->v[ip2] = vx[ie5] ;
2635 vnew = MMG5_orvol(mesh->point,pt0->v);
2636 if ( vnew < MMG5_EPSOK ) return 0;
2637 }
2638
2639 return 1;
2640}
2641
2654int MMG5_split3op(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6],int8_t metRidTyp){
2655 MMG5_pTetra pt[5];
2656 MMG5_xTetra xt[5];
2657 MMG5_pxTetra pxt0;
2658 MMG5_int iel;
2659 MMG5_int newtet[5],ref[4];
2660 uint8_t imin12,imin03,tau[4],sym[4],symed[6],ip0,ip1,ip2,ip3,ie0,ie1;
2661 uint8_t ie2,ie3,ie4,ie5,isxt[5],firstxt,i;
2662 int16_t ftag[4];
2663 const uint8_t *taued=NULL;
2664 const int ne=4;
2665
2666 pt[0] = &mesh->tetra[k];
2667 newtet[0]=k;
2668
2669 /* Set permutation /symmetry of vertices : generic case : 35 */
2670 MMG3D_split3op_cfg(pt[0],vx,tau,&taued,sym,symed,&ip0,&ip1,&ip2,&ip3,
2671 &ie0,&ie1,&ie2,&ie3,&ie4,&ie5,&imin03,&imin12);
2672 pt[0]->flag = 0;
2673
2674 /* create 3 new tetras, the fifth being created only if needed. */
2675 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
2676 return 0;
2677 }
2678 newtet[4] = 0;
2679
2680 /* Store face tags and refs from split tetra*/
2681 for (i=0; i<4; i++) {
2682 ftag[i] = (xt[0].ftag[i] & ~MG_REF);
2683 }
2684
2685 if ( !((imin12 == ip1) && (imin03 == ip3)) ) {
2686 iel = MMG3D_newElt(mesh);
2687 if ( !iel ) {
2689 fprintf(stderr,"\n ## Error: %s: unable to allocate"
2690 " a new element.\n",__func__);
2692 fprintf(stderr," Exit program.\n");
2693 return 0);
2694 pt[0] = &mesh->tetra[newtet[0]];
2695 pt[1] = &mesh->tetra[newtet[1]];
2696 pt[2] = &mesh->tetra[newtet[2]];
2697 pt[3] = &mesh->tetra[newtet[3]];
2698 }
2699 pt[4] = &mesh->tetra[iel];
2700 pt[4] = memcpy(pt[4],pt[0],sizeof(MMG5_Tetra));
2701 newtet[4]=iel;
2702
2703 if ( pt[0]->xt ) {
2704 memcpy(&xt[4],pxt0, sizeof(MMG5_xTetra));
2705 }
2706
2707 else {
2708 memset(&xt[4],0, sizeof(MMG5_xTetra));
2709 }
2710 }
2711
2712 /* Generic formulation of split of 3 edges in op configuration (edges 0,1,5 splitted) */
2713 if ( (imin12 == ip2) && (imin03 == ip0) ) {
2714 pt[0]->v[ip0] = vx[ie1] ; pt[0]->v[ip1] = vx[ie0] ; pt[0]->v[ip3] = vx[ie5] ;
2715 xt[0].tag[ie0] = ftag[ip3]; xt[0].tag[ie2] = ftag[ip1];
2716 xt[0].tag[ie3] = ftag[ip3]; xt[0].tag[ie4] = 0;
2717 xt[0].edg[ie0] = 0; xt[0].edg[ie2] = 0;
2718 xt[0].edg[ie3] = 0; xt[0].edg[ie4] = 0;
2719 xt[0].ref [ip0] = 0 ; xt[0].ref [ip2] = 0 ;
2720 xt[0].ftag[ip0] = 0 ; xt[0].ftag[ip2] = 0 ;
2721 MG_SET(xt[0].ori, ip0); MG_SET(xt[0].ori, ip2);
2722
2723 pt[1]->v[ip0] = vx[ie0] ; pt[1]->v[ip3] = vx[ie5] ;
2724 xt[1].tag[ie1] = ftag[ip3]; xt[1].tag[ie2] = 0;
2725 xt[1].tag[ie4] = ftag[ip0]; xt[1].edg[ie1] = 0;
2726 xt[1].edg[ie2] = 0; xt[1].edg[ie4] = 0;
2727 xt[1].ref [ip1] = 0 ; xt[1] .ref[ip2] = 0 ;
2728 xt[1].ftag[ip1] = 0 ; xt[1].ftag[ip2] = 0 ;
2729 MG_SET(xt[1].ori, ip1); MG_SET(xt[1].ori, ip2);
2730
2731 pt[2]->v[ip0] = vx[ie0] ; pt[2]->v[ip2] = vx[ie5] ;
2732 xt[2].tag[ie1] = 0; xt[2].tag[ie2] = ftag[ip2];
2733 xt[2].tag[ie3] = ftag[ip0]; xt[2].edg[ie1] = 0;
2734 xt[2].edg[ie2] = 0; xt[2].edg[ie3] = 0;
2735 xt[2].ref [ip1] = 0 ; xt[2].ref [ip3] = 0 ;
2736 xt[2].ftag[ip1] = 0 ; xt[2].ftag[ip3] = 0 ;
2737 MG_SET(xt[2].ori, ip1); MG_SET(xt[2].ori, ip3);
2738
2739 pt[3]->v[ip1] = vx[ie0] ; pt[3]->v[ip2] = vx[ie1] ; pt[3]->v[ip3] = vx[ie5] ;
2740 xt[3].tag[ie2] = ftag[ip1]; xt[3].tag[ie3] = ftag[ip3];
2741 xt[3].tag[ie4] = 0; xt[3].tag[ie5] = ftag[ip1];
2742 xt[3].edg[ie2] = 0; xt[3].edg[ie3] = 0;
2743 xt[3].edg[ie4] = 0; xt[3].edg[ie5] = 0;
2744 xt[3].ref [ip0] = 0 ; xt[3].ref [ip2] = 0 ;
2745 xt[3].ftag[ip0] = 0 ; xt[3].ftag[ip2] = 0 ;
2746 MG_SET(xt[3].ori, ip0); MG_SET(xt[3].ori, ip2);
2747
2748 pt[4]->v[ip1] = vx[ie0] ; pt[4]->v[ip2] = vx[ie5];
2749 xt[4].tag[ie1] = ftag[ip1]; xt[4].tag[ie3] = 0;
2750 xt[4].tag[ie4] = ftag[ip2]; xt[4].edg[ie1] = 0;
2751 xt[4].edg[ie3] = 0; xt[4].edg[ie4] = 0;
2752 xt[4].ref [ip0] = 0 ; xt[4].ref [ip3] = 0 ;
2753 xt[4].ftag[ip0] = 0 ; xt[4].ftag[ip3] = 0 ;
2754 MG_SET(xt[4].ori, ip0); MG_SET(xt[4].ori, ip3);
2755 }
2756
2757 else if ( (imin12 == ip1) && (imin03 == ip0) ) {
2758 pt[0]->v[ip0] = vx[ie1] ; pt[0]->v[ip3] = vx[ie5] ;
2759 xt[0].tag[ie0] = ftag[ip3]; xt[0].tag[ie2] = ftag[ip1];
2760 xt[0].tag[ie4] = ftag[ip0]; xt[0].edg[ie0] = 0;
2761 xt[0].edg[ie2] = 0; xt[0].edg[ie4] = 0;
2762 xt[0].ref[ip2] = 0 ;
2763 xt[0].ftag[ip2] = 0 ;
2764 MG_SET(xt[0].ori, ip2);
2765
2766 pt[1]->v[ip0] = vx[ie0] ; pt[1]->v[ip2] = vx[ie1] ; pt[1]->v[ip3] = vx[ie5];
2767 xt[1].tag[ie1] = ftag[ip3]; xt[1].tag[ie2] = 0;
2768 xt[1].tag[ie3] = ftag[ip3]; xt[1].tag[ie4] = ftag[ip0];
2769 xt[1].tag[ie5] = ftag[ip1]; xt[1].edg[ie1] = 0;
2770 xt[1].edg[ie2] = 0; xt[1].edg[ie3] = 0;
2771 xt[1].edg[ie4] = 0; xt[1].edg[ie5] = 0;
2772 xt[1].ref [ip0] = 0 ; xt[1].ref [ip1] = 0 ; xt[1].ref [ip2] = 0 ;
2773 xt[1].ftag[ip0] = 0 ; xt[1].ftag[ip1] = 0 ; xt[1].ftag[ip2] = 0 ;
2774 MG_SET(xt[1].ori, ip0); MG_SET(xt[1].ori, ip1); MG_SET(xt[1].ori, ip2);
2775
2776 pt[2]->v[ip0] = vx[ie0] ; pt[2]->v[ip2] = vx[ie5] ;
2777 xt[2].tag[ie1] = 0; xt[2].tag[ie2] = ftag[ip2];
2778 xt[2].tag[ie3] = ftag[ip0]; xt[2].edg[ie1] = 0;
2779 xt[2].edg[ie2] = 0; xt[2].edg[ie3] = 0;
2780 xt[2].ref [ip1] = 0 ; xt[2].ref [ip3] = 0 ;
2781 xt[2].ftag[ip1] = 0 ; xt[2].ftag[ip3] = 0 ;
2782 MG_SET(xt[2].ori, ip1); MG_SET(xt[2].ori, ip3);
2783
2784 pt[3]->v[ip1] = vx[ie0] ; pt[3]->v[ip2] = vx[ie5];
2785 xt[3].tag[ie1] = ftag[ip1]; xt[3].tag[ie3] = 0;
2786 xt[3].tag[ie4] = ftag[ip2]; xt[3].edg[ie1] = 0;
2787 xt[3].edg[ie3] = 0; xt[3].edg[ie4] = 0;
2788 xt[3].ref [ip0] = 0 ; xt[3].ref [ip3] = 0 ;
2789 xt[3].ftag[ip0] = 0 ; xt[3].ftag[ip3] = 0 ;
2790 MG_SET(xt[3].ori, ip0); MG_SET(xt[3].ori, ip3);
2791
2792 pt[4]->v[ip1] = vx[ie0] ; pt[4]->v[ip2] = vx[ie1]; pt[4]->v[ip3] = vx[ie5];
2793 xt[4].tag[ie2] = ftag[ip1]; xt[4].tag[ie3] = ftag[ip3];
2794 xt[4].tag[ie4] = 0; xt[4].tag[ie5] = ftag[ip1];
2795 xt[4].edg[ie2] = 0; xt[4].edg[ie3] = 0;
2796 xt[4].edg[ie4] = 0; xt[4].edg[ie5] = 0;
2797 xt[4].ref [ip0] = 0 ; xt[4].ref [ip2] = 0 ;
2798 xt[4].ftag[ip0] = 0 ; xt[4].ftag[ip2] = 0 ;
2799 MG_SET(xt[4].ori, ip0); MG_SET(xt[4].ori, ip2);
2800 }
2801
2802 else if ( (imin12 == ip2) && (imin03 == ip3) ) {
2803 pt[0]->v[ip1] = vx[ie0] ; pt[0]->v[ip2] = vx[ie1] ;
2804 xt[0].tag[ie3] = ftag[ip3]; xt[0].tag[ie4] = ftag[ip2];
2805 xt[0].tag[ie5] = ftag[ip1]; xt[0].edg[ie3] = 0;
2806 xt[0].edg[ie4] = 0; xt[0].edg[ie5] = 0;
2807 xt[0].ref[ip0] = 0 ;
2808 xt[0].ftag[ip0] = 0 ;
2809 MG_SET(xt[0].ori, ip0);
2810
2811 pt[1]->v[ip0] = vx[ie1] ; pt[1]->v[ip1] = vx[ie0] ; pt[1]->v[ip2] = vx[ie5];
2812 xt[1].tag[ie0] = ftag[ip3]; xt[1].tag[ie1] = ftag[ip1];
2813 xt[1].tag[ie2] = ftag[ip1]; xt[1].tag[ie3] = 0;
2814 xt[1].tag[ie4] = ftag[ip2]; xt[1].edg[ie0] = 0;
2815 xt[1].edg[ie1] = 0; xt[1].edg[ie2] = 0;
2816 xt[1].edg[ie3] = 0; xt[1].edg[ie4] = 0;
2817 xt[1].ref [ip0] = 0 ; xt[1].ref [ip2] = 0 ; xt[1].ref [ip3] = 0 ;
2818 xt[1].ftag[ip0] = 0 ; xt[1].ftag[ip2] = 0 ; xt[1].ftag[ip3] = 0 ;
2819 MG_SET(xt[1].ori, ip1); MG_SET(xt[1].ori, ip2); MG_SET(xt[1].ori, ip3);
2820
2821 pt[2]->v[ip0] = vx[ie0] ; pt[2]->v[ip2] = vx[ie5] ;
2822 xt[2].tag[ie1] = 0; xt[2].tag[ie2] = ftag[ip2];
2823 xt[2].tag[ie3] = ftag[ip0]; xt[2].edg[ie1] = 0;
2824 xt[2].edg[ie2] = 0; xt[2].edg[ie3] = 0;
2825 xt[2].ref [ip1] = 0 ; xt[2].ref [ip3] = 0 ;
2826 xt[2].ftag[ip1] = 0 ; xt[2].ftag[ip3] = 0 ;
2827 MG_SET(xt[2].ori, ip1); MG_SET(xt[2].ori, ip3);
2828
2829 pt[3]->v[ip0] = vx[ie1] ; pt[3]->v[ip1] = vx[ie0]; pt[3]->v[ip3] = vx[ie5];
2830 xt[3].tag[ie0] = ftag[ip3]; xt[3].tag[ie2] = ftag[ip1];
2831 xt[3].tag[ie3] = ftag[ip3]; xt[3].tag[ie4] = 0;
2832 xt[3].edg[ie0] = 0; xt[3].edg[ie2] = 0;
2833 xt[3].edg[ie3] = 0; xt[3].edg[ie4] = 0;
2834 xt[3].ref [ip0] = 0 ; xt[3].ref [ip2] = 0 ;
2835 xt[3].ftag[ip0] = 0 ; xt[3].ftag[ip2] = 0 ;
2836 MG_SET(xt[3].ori, ip0); MG_SET(xt[3].ori, ip2);
2837
2838 pt[4]->v[ip0] = vx[ie0] ; pt[4]->v[ip3] = vx[ie5];
2839 xt[4].tag[ie1] = ftag[ip3]; xt[4].tag[ie2] = 0;
2840 xt[4].tag[ie4] = ftag[ip0]; xt[4].edg[ie1] = 0;
2841 xt[4].edg[ie2] = 0; xt[4].edg[ie4] = 0;
2842 xt[4].ref [ip1] = 0 ; xt[4].ref [ip2] = 0 ;
2843 xt[4].ftag[ip1] = 0 ; xt[4].ftag[ip2] = 0 ;
2844 MG_SET(xt[4].ori, ip1); MG_SET(xt[4].ori, ip2);
2845 }
2846 else {
2847 assert((imin12 == ip1) && (imin03 == ip3)) ;
2848
2849 pt[0]->v[ip1] = vx[ie0] ; pt[0]->v[ip2] = vx[ie1] ;
2850 xt[0].tag[ie3] = ftag[ip3]; xt[0].tag[ie4] = ftag[ip2];
2851 xt[0].tag[ie5] = ftag[ip1]; xt[0].edg[ie3] = 0;
2852 xt[0].edg[ie4] = 0; xt[0].edg[ie5] = 0;
2853 xt[0].ref [ip0] = 0 ;
2854 xt[0].ftag[ip0] = 0 ;
2855 MG_SET(xt[0].ori, ip0);
2856
2857 pt[1]->v[ip0] = vx[ie1] ; pt[1]->v[ip3] = vx[ie5] ;
2858 xt[1].tag[ie0] = ftag[ip3]; xt[1].tag[ie2] = ftag[ip1];
2859 xt[1].tag[ie4] = ftag[ip0]; xt[1].edg[ie0] = 0;
2860 xt[1].edg[ie2] = 0; xt[1].edg[ie4] = 0;
2861 xt[1].ref [ip2] = 0 ;
2862 xt[1].ftag[ip2] = 0 ;
2863 MG_SET(xt[1].ori, ip2);
2864
2865 pt[2]->v[ip0] = vx[ie0] ; pt[2]->v[ip2] = vx[ie1] ;
2866 xt[2].tag[ie1] = ftag[ip3]; xt[2].tag[ie2] = ftag[ip2];
2867 xt[2].tag[ie3] = ftag[ip3]; xt[2].tag[ie5] = ftag[ip1];
2868 xt[2].edg[ie1] = 0; xt[2].edg[ie2] = 0;
2869 xt[2].edg[ie3] = 0; xt[2].edg[ie5] = 0;
2870 xt[2].ref [ip0] = 0 ; xt[2].ref [ip1] = 0 ;
2871 xt[2].ftag[ip0] = 0 ; xt[2].ftag[ip1] = 0 ;
2872 MG_SET(xt[2].ori, ip0); MG_SET(xt[2].ori, ip1);
2873
2874 pt[3]->v[ip0] = vx[ie1] ; pt[3]->v[ip2] = vx[ie5] ;
2875 xt[3].tag[ie0] = ftag[ip3]; xt[3].tag[ie1] = ftag[ip1];
2876 xt[3].tag[ie2] = ftag[ip1]; xt[3].tag[ie3] = ftag[ip0];
2877 xt[3].edg[ie0] = 0; xt[3].edg[ie1] = 0;
2878 xt[3].edg[ie2] = 0; xt[3].edg[ie3] = 0;
2879 xt[3].ref [ip2] = 0 ; xt[3].ref [ip3] = 0 ;
2880 xt[3].ftag[ip2] = 0 ; xt[3].ftag[ip3] = 0 ;
2881 MG_SET(xt[3].ori, ip2); MG_SET(xt[3].ori, ip3);
2882 }
2883
2884 /* Assignation of the xt fields to the appropriate tets */
2885 if ( (imin12 == ip1) && (imin03 == ip3) ) {
2886 isxt[0] = isxt[1] = isxt[2] = isxt[3] = 0;
2887
2888 for (i=0; i<4; i++) {
2889 int j;
2890 for (j=0; j<ne; j++) {
2891 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
2892 }
2893 }
2894
2895 if ( pt[0]->xt ) {
2896 if ( isxt[0] ) {
2897 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
2898 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
2899
2900 for (i=1; i<4; i++) {
2901 if ( isxt[i] ) {
2902 mesh->xt++;
2903 if ( mesh->xt >= mesh->xtmax ) {
2904 /* realloc of xtetras table */
2906 "larger xtetra table",
2907 mesh->xt--;
2908 fprintf(stderr," Exit program.\n");
2909 return 0);
2910 }
2911 pt[i]->xt = mesh->xt;
2912 pxt0 = &mesh->xtetra[mesh->xt];
2913 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2914 }
2915 }
2916 }
2917 else {
2918 firstxt = 1;
2919 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
2920
2921 for (i=1; i<4; i++) {
2922 if ( isxt[i] ) {
2923 if ( firstxt ) {
2924 firstxt = 0;
2925 pt[i]->xt = pt[0]->xt;
2926 pxt0 = &mesh->xtetra[(pt[i])->xt];
2927 memcpy(pxt0,&(xt[i]),sizeof(MMG5_xTetra));
2928 }
2929 else {
2930 mesh->xt++;
2931 if ( mesh->xt > mesh->xtmax ) {
2932 /* realloc of xtetras table */
2934 "larger xtetra table",
2935 mesh->xt--;
2936 fprintf(stderr," Exit program.\n");
2937 return 0);
2938 }
2939 pt[i]->xt = mesh->xt;
2940 pxt0 = &mesh->xtetra[mesh->xt];
2941 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2942 }
2943 }
2944 }
2945 pt[0]->xt = 0;
2946 }
2947 }
2948
2949 }
2950 else {
2951 isxt[0] = isxt[1] = isxt[2] = isxt[3] = isxt[4] = 0;
2952
2953 for (i=0; i<4; i++) {
2954 int j;
2955 for (j=0; j<=ne; j++) {
2956 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
2957 }
2958 }
2959
2960 if ( pt[0]->xt ) {
2961 if ( isxt[0] ) {
2962 memcpy(pxt0,&(xt[0]),sizeof(MMG5_xTetra));
2963 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = 0;
2964
2965 for(i=1; i<5; i++) {
2966 if ( isxt[i] ) {
2967 mesh->xt++;
2968 if ( mesh->xt > mesh->xtmax ) {
2969 /* realloc of xtetras table */
2971 "larger xtetra table",
2972 mesh->xt--;
2973 fprintf(stderr," Exit program.\n");
2974 return 0);
2975 }
2976 pt[i]->xt = mesh->xt;
2977 pxt0 = &mesh->xtetra[mesh->xt];
2978 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2979 }
2980 }
2981 }
2982 else {
2983 firstxt = 1;
2984 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = 0;
2985
2986 for (i=1; i<5; i++) {
2987 if ( isxt[i] ) {
2988 if ( firstxt ) {
2989 firstxt = 0;
2990 pt[i]->xt = pt[0]->xt;
2991 pxt0 = &mesh->xtetra[pt[i]->xt];
2992 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2993 }
2994 else {
2995 mesh->xt++;
2996 if ( mesh->xt > mesh->xtmax ) {
2997 /* realloc of xtetras table */
2999 "larger xtetra table",
3000 mesh->xt--;
3001 fprintf(stderr," Exit program.\n");
3002 return 0);
3003 }
3004 pt[i]->xt = mesh->xt;
3005 pxt0 = &mesh->xtetra[mesh->xt];
3006 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3007 }
3008 }
3009 }
3010 pt[0]->xt = 0;
3011 }
3012 }
3013 }
3014
3015 /* Quality update */
3016 if ( (!metRidTyp) && met->m && met->size>1 ) {
3017 pt[0]->qual=MMG5_caltet33_ani(mesh,met,pt[0]);
3018 pt[1]->qual=MMG5_caltet33_ani(mesh,met,pt[1]);
3019 pt[2]->qual=MMG5_caltet33_ani(mesh,met,pt[2]);
3020 pt[3]->qual=MMG5_caltet33_ani(mesh,met,pt[3]);
3021 if ( !((imin12 == ip1) && (imin03 == ip3)) ) {
3022 pt[4]->qual=MMG5_caltet33_ani(mesh,met,pt[4]);
3023 }
3024 }
3025 else {
3026 pt[0]->qual=MMG5_orcal(mesh,met,newtet[0]);
3027 pt[1]->qual=MMG5_orcal(mesh,met,newtet[1]);
3028 pt[2]->qual=MMG5_orcal(mesh,met,newtet[2]);
3029 pt[3]->qual=MMG5_orcal(mesh,met,newtet[3]);
3030 if ( !((imin12 == ip1) && (imin03 == ip3)) ) {
3031 pt[4]->qual=MMG5_orcal(mesh,met,newtet[4]);
3032 }
3033 }
3034 return 1;
3035}
3036
3037
3050MMG5_int MMG5_split4bar(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k,int8_t metRidTyp) {
3051 MMG5_pTetra pt[4];
3052 MMG5_pPoint ppt;
3053 MMG5_xTetra xt[4];
3054 MMG5_pxTetra pxt0;
3055 double o[3],cb[4];
3056 MMG5_int ib,iadr,*adja,adj1,adj2,adj3,newtet[4],src;
3057 int i;
3058 uint8_t isxt[4],firstxt;
3059 const int ne=4;
3060
3061 pt[0] = &mesh->tetra[k];
3062 pt[0]->flag = 0;
3063 newtet[0]=k;
3064
3065 o[0] = o[1] = o[2] = 0.0;
3066 for (i=0; i<4; i++) {
3067 ib = pt[0]->v[i];
3068 ppt = &mesh->point[ib];
3069 o[0] += ppt->c[0];
3070 o[1] += ppt->c[1];
3071 o[2] += ppt->c[2];
3072 }
3073 o[0] *= 0.25;
3074 o[1] *= 0.25;
3075 o[2] *= 0.25;
3076
3077 cb[0] = 0.25; cb[1] = 0.25; cb[2] = 0.25; cb[3] = 0.25;
3078#ifdef USE_POINTMAP
3079 src = mesh->point[pt[0]->v[0]].src;
3080#else
3081 src = 1;
3082#endif
3083 ib = MMG3D_newPt(mesh,o,0,src);
3084 if ( !ib ) {
3086 fprintf(stderr,"\n ## Error: %s: unable to allocate"
3087 " a new point\n",__func__);
3089 return 0
3090 ,o,0,src);
3091 }
3092 if ( met->m ) {
3093 if ( !metRidTyp && met->size > 1 )
3094 MMG5_interp4bar33_ani(mesh,met,k,ib,cb);
3095 else
3096 MMG5_interp4bar(mesh,met,k,ib,cb);
3097 }
3098
3099 /* create 3 new tetras */
3100 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
3101 return 0;
3102 }
3103
3104 /* Update adjacency */
3105 if ( mesh->adja ) {
3106 iadr = 4*(newtet[0]-1)+1;
3107 adja = &mesh->adja[iadr];
3108
3109 /* Store the old adjacents */
3110 adj1 = mesh->adja[iadr+1];
3111 adj2 = mesh->adja[iadr+2];
3112 adj3 = mesh->adja[iadr+3];
3113
3114 /* Update the new ones */
3115 adja[1] = 4*newtet[1];
3116 adja[2] = 4*newtet[2];
3117 adja[3] = 4*newtet[3];
3118
3119 iadr = 4*(newtet[1]-1)+1;
3120 adja = &mesh->adja[iadr];
3121 adja[0] = 4*newtet[0] + 1;
3122 adja[1] = adj1;
3123 adja[2] = 4*newtet[2] + 1;
3124 adja[3] = 4*newtet[3] + 1;
3125 if ( adj1 )
3126 mesh->adja[4*(adj1/4-1) + 1+adj1%4] = 4*newtet[1]+1;
3127
3128 iadr = 4*(newtet[2]-1)+1;
3129 adja = &mesh->adja[iadr];
3130 adja[0] = 4*newtet[0] + 2;
3131 adja[1] = 4*newtet[1] + 2;
3132 adja[2] = adj2;
3133 adja[3] = 4*newtet[3] + 2;
3134 if ( adj2 )
3135 mesh->adja[4*(adj2/4-1) + 1+adj2%4] = 4*newtet[2]+2;
3136
3137 iadr = 4*(newtet[3]-1)+1;
3138 adja = &mesh->adja[iadr];
3139 adja[0] = 4*newtet[0] + 3;
3140 adja[1] = 4*newtet[1] + 3;
3141 adja[2] = 4*newtet[2] + 3;
3142 adja[3] = adj3;
3143 if ( adj3 )
3144 mesh->adja[4*(adj3/4-1) + 1+adj3%4] = 4*newtet[3]+3;
3145 }
3146
3147 /* Update vertices and xt fields */
3148 pt[0]->v[0] = pt[1]->v[1] = pt[2]->v[2] = pt[3]->v[3] = ib;
3149
3150 xt[0].tag[0] = 0; xt[0].edg[0] = 0;
3151 xt[0].tag[1] = 0; xt[0].edg[1] = 0;
3152 xt[0].tag[2] = 0; xt[0].edg[2] = 0;
3153 xt[0].ref [1] = 0; xt[0].ref [2] = 0; xt[0].ref [3] = 0;
3154 xt[0].ftag[1] = 0; xt[0].ftag[2] = 0; xt[0].ftag[3] = 0;
3155 MG_SET(xt[0].ori, 1); MG_SET(xt[0].ori, 2); MG_SET(xt[0].ori, 3);
3156
3157 xt[1].tag[0] = 0; xt[1].edg[0] = 0;
3158 xt[1].tag[3] = 0; xt[1].edg[3] = 0;
3159 xt[1].tag[4] = 0; xt[1].edg[4] = 0;
3160 xt[1].ref [0] = 0; xt[1].ref [2] = 0; xt[1].ref [3] = 0;
3161 xt[1].ftag[0] = 0; xt[1].ftag[2] = 0; xt[1].ftag[3] = 0;
3162 MG_SET(xt[1].ori, 0); MG_SET(xt[1].ori, 2); MG_SET(xt[1].ori, 3);
3163
3164 xt[2].tag[1] = 0; xt[2].edg[1] = 0;
3165 xt[2].tag[3] = 0; xt[2].edg[3] = 0;
3166 xt[2].tag[5] = 0; xt[2].edg[5] = 0;
3167 xt[2].ref [0] = 0; xt[2].ref [1] = 0; xt[2].ref [3] = 0;
3168 xt[2].ftag[0] = 0; xt[2].ftag[1] = 0; xt[2].ftag[3] = 0;
3169 MG_SET(xt[2].ori, 0); MG_SET(xt[2].ori, 1); MG_SET(xt[2].ori, 3);
3170
3171 xt[3].tag[2] = 0; xt[3].edg[2] = 0;
3172 xt[3].tag[4] = 0; xt[3].edg[4] = 0;
3173 xt[3].tag[5] = 0; xt[3].edg[5] = 0;
3174 xt[3].ref [0] = 0; xt[3].ref [1] = 0; xt[3].ref [2] = 0;
3175 xt[3].ftag[0] = 0; xt[3].ftag[1] = 0; xt[3].ftag[2] = 0;
3176 MG_SET(xt[3].ori, 0); MG_SET(xt[3].ori, 1); MG_SET(xt[3].ori, 2);
3177
3178 /* Assignation of the xt fields to the appropriate tets */
3179 memset(isxt,0,ne*sizeof(int8_t));
3180 for (i=0; i<ne; i++) {
3181 int j;
3182 for (j=0; j<ne; j++) {
3183 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
3184 }
3185 }
3186
3187 if ( pt[0]->xt ) {
3188 if ( isxt[0] ) {
3189 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
3190 for (i=1; i<4; i++) {
3191 if ( isxt[i] ) {
3192 mesh->xt++;
3193 if ( mesh->xt > mesh->xtmax ) {
3194 /* realloc of xtetras table */
3196 "larger xtetra table",
3197 mesh->xt--;
3198 return 0);
3199 }
3200 pt[i]->xt = mesh->xt;
3201 pxt0 = &mesh->xtetra[mesh->xt];
3202 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3203 }
3204 else {
3205 pt[i]->xt = 0;
3206 }
3207 }
3208 }
3209 else {
3210 firstxt = 1;
3211 for (i=1; i<4; i++) {
3212 if ( isxt[i] ) {
3213 if ( firstxt ) {
3214 firstxt = 0;
3215 pt[i]->xt = pt[0]->xt;
3216 pxt0 = &mesh->xtetra[(pt[i])->xt];
3217 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3218 }
3219 else {
3220 mesh->xt++;
3221 if ( mesh->xt > mesh->xtmax ) {
3222 /* realloc of xtetras table */
3224 "larger xtetra table",
3225 mesh->xt--;
3226 return 0);
3227 }
3228 pt[i]->xt = mesh->xt;
3229 pxt0 = &mesh->xtetra[mesh->xt];
3230 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3231 }
3232 }
3233 else {
3234 pt[i]->xt = 0;
3235 }
3236 }
3237 pt[0]->xt = 0;
3238 }
3239 }
3240
3241 /* Quality update */
3242 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
3243
3244 return ib;
3245}
3246
3259static inline
3260void MMG3D_split4sf_cfg(MMG5_pTetra pt,MMG5_int vx[6],uint8_t tau[4],
3261 const uint8_t **taued, uint8_t *imin23,uint8_t *imin12) {
3262
3263 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
3264 (*taued) = &MMG5_permedge[0][0];
3265 switch(pt->flag){
3266 case 29:
3267 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
3268 (*taued) = &MMG5_permedge[5][0];
3269 break;
3270
3271 case 53:
3272 tau[0] = 3 ; tau[1] = 0 ; tau[2] = 2 ; tau[3] = 1;
3273 (*taued) = &MMG5_permedge[9][0];
3274 break;
3275
3276 case 60:
3277 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
3278 (*taued) = &MMG5_permedge[10][0];
3279 break;
3280
3281 case 57:
3282 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
3283 (*taued) = &MMG5_permedge[4][0];
3284 break;
3285
3286 case 58:
3287 tau[0] = 2 ; tau[1] = 3 ; tau[2] = 0 ; tau[3] = 1;
3288 (*taued) = &MMG5_permedge[8][0];
3289 break;
3290
3291 case 27:
3292 tau[0] = 1 ; tau[1] = 0 ; tau[2] = 3 ; tau[3] = 2;
3293 (*taued) = &MMG5_permedge[3][0];
3294 break;
3295
3296 case 15:
3297 tau[0] = 0 ; tau[1] = 2 ; tau[2] = 3 ; tau[3] = 1;
3298 (*taued) = &MMG5_permedge[1][0];
3299 break;
3300
3301 case 43:
3302 tau[0] = 2 ; tau[1] = 1 ; tau[2] = 3 ; tau[3] = 0;
3303 (*taued) = &MMG5_permedge[7][0];
3304 break;
3305
3306 case 39:
3307 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
3308 (*taued) = &MMG5_permedge[2][0];
3309 break;
3310
3311 case 54:
3312 tau[0] = 3 ; tau[1] = 2 ; tau[2] = 1 ; tau[3] = 0;
3313 (*taued) = &MMG5_permedge[11][0];
3314 break;
3315
3316 case 46:
3317 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
3318 (*taued) = &MMG5_permedge[6][0];
3319 break;
3320 }
3321
3322 (*imin23) = (pt->v[tau[2]] < pt->v[tau[3]]) ? tau[2] : tau[3];
3323 (*imin12) = (pt->v[tau[1]] < pt->v[tau[2]]) ? tau[1] : tau[2];
3324}
3325
3337int MMG3D_split4sf_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
3338 MMG5_pTetra pt,pt0;
3339 double vold,vnew;
3340 uint8_t tau[4];
3341 uint8_t imin23,imin12;
3342 const uint8_t *taued = NULL;
3343
3344 pt = &mesh->tetra[k];
3345 pt0 = &mesh->tetra[0];
3346 vold = MMG5_orvol(mesh->point,pt->v);
3347
3348 if ( vold < MMG5_EPSOK ) return 0;
3349
3350 /* Set permutation of vertices : reference configuration : 23 */
3351 MMG3D_split4sf_cfg(pt,vx,tau,&taued,&imin23,&imin12);
3352
3353 /* Generic formulation of split of 4 edges (with 3 on same face) */
3354 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3355 pt0->v[tau[1]] = vx[taued[0]];
3356 pt0->v[tau[2]] = vx[taued[1]];
3357 pt0->v[tau[3]] = vx[taued[2]];
3358 vnew = MMG5_orvol(mesh->point,pt0->v);
3359 if ( vnew < MMG5_EPSOK ) return 0;
3360
3361 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3362 pt0->v[tau[0]] = vx[taued[2]];
3363 pt0->v[tau[1]] = vx[taued[0]];
3364 pt0->v[tau[2]] = vx[taued[1]];
3365 pt0->v[tau[3]] = vx[taued[4]] ;
3366 vnew = MMG5_orvol(mesh->point,pt0->v);
3367 if ( vnew < MMG5_EPSOK ) return 0;
3368
3369 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3370 if ( imin12 == tau[1] ) {
3371 pt0->v[tau[0]] = vx[taued[0]];
3372 pt0->v[tau[2]] = vx[taued[1]];
3373 pt0->v[tau[3]] = vx[taued[4]];
3374 vnew = MMG5_orvol(mesh->point,pt0->v);
3375 if ( vnew < MMG5_EPSOK ) return 0;
3376
3377 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3378 pt0->v[tau[0]] = vx[taued[1]];
3379 pt0->v[tau[3]] = vx[taued[4]];
3380 vnew = MMG5_orvol(mesh->point,pt0->v);
3381 if ( vnew < MMG5_EPSOK ) return 0;
3382 }
3383 else {
3384 pt0->v[tau[0]] = vx[taued[1]];
3385 pt0->v[tau[1]] = vx[taued[0]];
3386 pt0->v[tau[3]] = vx[taued[4]] ;
3387 vnew = MMG5_orvol(mesh->point,pt0->v);
3388 if ( vnew < MMG5_EPSOK ) return 0;
3389
3390 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3391 pt0->v[tau[0]] = vx[taued[0]];
3392 pt0->v[tau[3]] = vx[taued[4]] ;
3393 vnew = MMG5_orvol(mesh->point,pt0->v);
3394 if ( vnew < MMG5_EPSOK ) return 0;
3395 }
3396
3397 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3398 if ( imin23 == tau[2] ) {
3399 pt0->v[tau[0]] = vx[taued[1]];
3400 pt0->v[tau[1]] = vx[taued[4]];
3401 pt0->v[tau[3]] = vx[taued[2]];
3402 vnew = MMG5_orvol(mesh->point,pt0->v);
3403 if ( vnew < MMG5_EPSOK ) return 0;
3404
3405 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3406 pt0->v[tau[0]] = vx[taued[2]];
3407 pt0->v[tau[1]] = vx[taued[4]];
3408 vnew = MMG5_orvol(mesh->point,pt0->v);
3409 if ( vnew < MMG5_EPSOK ) return 0;
3410 }
3411 else {
3412 pt0->v[tau[0]] = vx[taued[2]];
3413 pt0->v[tau[1]] = vx[taued[4]];
3414 pt0->v[tau[2]] = vx[taued[1]];
3415 vnew = MMG5_orvol(mesh->point,pt0->v);
3416 if ( vnew < MMG5_EPSOK ) return 0;
3417
3418 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3419 pt0->v[tau[0]] = vx[taued[1]];
3420 pt0->v[tau[1]] = vx[taued[4]];
3421 vnew = MMG5_orvol(mesh->point,pt0->v);
3422 if ( vnew < MMG5_EPSOK ) return 0;
3423 }
3424
3425 return 1;
3426}
3427
3440int MMG5_split4sf(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
3441 MMG5_pTetra pt[6];
3442 MMG5_xTetra xt[6];
3443 MMG5_pxTetra pxt0;
3444 MMG5_int newtet[6];
3445 int8_t firstxt,isxt[6],j,i;
3446 int16_t ftag[4];
3447 uint8_t tau[4],imin23,imin12;
3448 const uint8_t *taued = NULL;
3449 const int ne=6;
3450
3451 pt[0] = &mesh->tetra[k];
3452 newtet[0]=k;
3453
3454 /* Set permutation of vertices : reference configuration : 23 */
3455 MMG3D_split4sf_cfg(pt[0],vx,tau,&taued,&imin23,&imin12);
3456 pt[0]->flag = 0;
3457
3458 /* create 5 new tetras */
3459 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
3460 return 0;
3461 }
3462
3463 /* Store face tags and refs from split tetra*/
3464 for (i=0; i<4; i++) {
3465 ftag[i] = (xt[0].ftag[i] & ~MG_REF);
3466 }
3467
3468 /* Generic formulation of split of 4 edges (with 3 on same face) */
3469 pt[0]->v[tau[1]] = vx[taued[0]] ; pt[0]->v[tau[2]] = vx[taued[1]] ; pt[0]->v[tau[3]] = vx[taued[2]];
3470 xt[0].tag[taued[3]] = ftag[tau[3]]; xt[0].tag[taued[4]] = ftag[tau[2]];
3471 xt[0].tag[taued[5]] = ftag[tau[1]]; xt[0].edg[taued[3]] = 0;
3472 xt[0].edg[taued[4]] = 0; xt[0].edg[taued[5]] = 0;
3473 xt[0].ref [ tau[0]] = 0 ;
3474 xt[0].ftag[ tau[0]] = 0 ;
3475 MG_SET(xt[0].ori, tau[0]);
3476
3477 pt[1]->v[tau[0]] = vx[taued[2]] ; pt[1]->v[tau[1]] = vx[taued[0]] ;
3478 pt[1]->v[tau[2]] = vx[taued[1]] ; pt[1]->v[tau[3]] = vx[taued[4]] ;
3479 xt[1].tag[taued[0]] = ftag[tau[2]]; xt[1].tag[taued[1]] = ftag[tau[1]];
3480 xt[1].tag[taued[2]] = ftag[tau[2]]; xt[1].tag[taued[3]] = ftag[tau[3]];
3481 xt[1].tag[taued[4]] = ftag[tau[2]]; xt[1].tag[taued[5]] = 0;
3482 xt[1].edg[taued[0]] = 0; xt[1].edg[taued[1]] = 0;
3483 xt[1].edg[taued[2]] = 0; xt[1].edg[taued[3]] = 0;
3484 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
3485 xt[1].ref [ tau[0]] = 0 ; xt[1].ref [ tau[1]] = 0 ; xt[1].ref [tau[3]] = 0 ;
3486 xt[1].ftag[ tau[0]] = 0 ; xt[1].ftag[ tau[1]] = 0 ; xt[1].ftag[tau[3]] = 0 ;
3487 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[1]); MG_SET(xt[1].ori, tau[3]);
3488
3489 if ( imin12 == tau[1] ) {
3490 pt[2]->v[tau[0]] = vx[taued[0]] ; pt[2]->v[tau[2]] = vx[taued[1]] ; pt[2]->v[tau[3]] = vx[taued[4]] ;
3491 xt[2].tag[taued[1]] = ftag[tau[3]]; xt[2].tag[taued[2]] = ftag[tau[2]];
3492 xt[2].tag[taued[3]] = ftag[tau[3]]; xt[2].tag[taued[5]] = 0;
3493 xt[2].edg[taued[1]] = 0; xt[2].edg[taued[2]] = 0;
3494 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[5]] = 0;
3495 xt[2].ref [ tau[0]] = 0 ; xt[2].ref [ tau[1]] = 0 ;
3496 xt[2].ftag[ tau[0]] = 0 ; xt[2].ftag[ tau[1]] = 0 ;
3497 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[1]);
3498
3499 pt[3]->v[tau[0]] = vx[taued[1]] ; pt[3]->v[tau[3]] = vx[taued[4]] ;
3500 xt[3].tag[taued[0]] = ftag[tau[3]]; xt[3].tag[taued[2]] = 0;
3501 xt[3].tag[taued[5]] = ftag[tau[0]]; xt[3].edg[taued[0]] = 0;
3502 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[5]] = 0;
3503 xt[3].ref [ tau[1]] = 0 ; xt[3].ref [ tau[2]] = 0 ;
3504 xt[3].ftag[ tau[1]] = 0 ; xt[3].ftag[ tau[2]] = 0 ;
3505 MG_SET(xt[3].ori, tau[1]); MG_SET(xt[3].ori, tau[2]);
3506 }
3507 else {
3508 pt[2]->v[tau[0]] = vx[taued[1]] ; pt[2]->v[tau[1]] = vx[taued[0]] ; pt[2]->v[tau[3]] = vx[taued[4]] ;
3509 xt[2].tag[taued[0]] = ftag[tau[3]]; xt[2].tag[taued[2]] = 0;
3510 xt[2].tag[taued[3]] = ftag[tau[3]]; xt[2].tag[taued[4]] = ftag[tau[2]];
3511 xt[2].tag[taued[5]] = ftag[tau[0]]; xt[2].edg[taued[0]] = 0;
3512 xt[2].edg[taued[2]] = 0; xt[2].edg[taued[3]] = 0;
3513 xt[2].edg[taued[4]] = 0; xt[2].edg[taued[5]] = 0;
3514 xt[2].ref [ tau[0]] = 0 ; xt[2].ref [ tau[1]] = 0 ; xt[2].ref [tau[2]] = 0 ;
3515 xt[2].ftag[ tau[0]] = 0 ; xt[2].ftag[ tau[1]] = 0 ; xt[2].ftag[tau[2]] = 0 ;
3516 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[1]); MG_SET(xt[2].ori, tau[2]);
3517
3518 pt[3]->v[tau[0]] = vx[taued[0]] ; pt[3]->v[tau[3]] = vx[taued[4]] ;
3519 xt[3].tag[taued[1]] = ftag[tau[3]]; xt[3].tag[taued[2]] = ftag[tau[2]];
3520 xt[3].tag[taued[5]] = ftag[tau[0]]; xt[3].edg[taued[1]] = 0;
3521 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[5]] = 0;
3522 xt[3].ref [ tau[1]] = 0 ;
3523 xt[3].ftag[ tau[1]] = 0 ;
3524 MG_SET(xt[3].ori, tau[1]);
3525 }
3526
3527 if ( imin23 == tau[2] ) {
3528 pt[4]->v[tau[0]] = vx[taued[1]] ; pt[4]->v[tau[1]] = vx[taued[4]] ; pt[4]->v[tau[3]] = vx[taued[2]] ;
3529 xt[4].tag[taued[0]] = 0; xt[4].tag[taued[2]] = ftag[tau[1]];
3530 xt[4].tag[taued[3]] = ftag[tau[0]]; xt[4].tag[taued[4]] = ftag[tau[2]];
3531 xt[4].tag[taued[5]] = ftag[tau[1]];
3532 xt[4].edg[taued[0]] = 0; xt[4].edg[taued[2]] = 0;
3533 xt[4].edg[taued[3]] = 0; xt[4].edg[taued[4]] = 0;
3534 xt[4].edg[taued[5]] = 0;
3535 xt[4].ref [ tau[0]] = 0; xt[4].ref [ tau[2]] = 0 ;
3536 xt[4].ref [ tau[3]] = 0 ;
3537 xt[4].ftag[ tau[0]] = 0; xt[4].ftag[ tau[2]] = 0 ;
3538 xt[4].ftag[ tau[3]] = 0 ;
3539 MG_SET(xt[4].ori, tau[0]); MG_SET(xt[4].ori, tau[2]); MG_SET(xt[4].ori, tau[3]);
3540
3541 pt[5]->v[tau[0]] = vx[taued[2]] ; pt[5]->v[tau[1]] = vx[taued[4]] ;
3542 xt[5].tag[taued[0]] = ftag[tau[2]]; xt[5].tag[taued[1]] = ftag[tau[1]];
3543 xt[5].tag[taued[3]] = ftag[tau[0]]; xt[5].edg[taued[0]] = 0;
3544 xt[5].edg[taued[1]] = 0; xt[5].edg[taued[3]] = 0;
3545 xt[5].ref [ tau[3]] = 0 ;
3546 xt[5].ftag[ tau[3]] = 0 ;
3547 MG_SET(xt[5].ori, tau[3]);
3548 }
3549 else {
3550 pt[4]->v[tau[0]] = vx[taued[2]] ; pt[4]->v[tau[1]] = vx[taued[4]] ; pt[4]->v[tau[2]] = vx[taued[1]] ;
3551 xt[4].tag[taued[0]] = ftag[tau[2]]; xt[4].tag[taued[1]] = ftag[tau[1]];
3552 xt[4].tag[taued[3]] = 0; xt[4].tag[taued[5]] = ftag[tau[1]];
3553 xt[4].edg[taued[0]] = 0; xt[4].edg[taued[1]] = 0;
3554 xt[4].edg[taued[3]] = 0; xt[4].edg[taued[5]] = 0;
3555 xt[4].ref [ tau[0]] = 0; xt[4].ref [ tau[3]] = 0 ;
3556 xt[4].ftag[ tau[0]] = 0; xt[4].ftag[ tau[3]] = 0 ;
3557 MG_SET(xt[4].ori, tau[0]); MG_SET(xt[4].ori, tau[3]);
3558
3559 pt[5]->v[tau[0]] = vx[taued[1]] ; pt[5]->v[tau[1]] = vx[taued[4]] ;
3560 xt[5].tag[taued[0]] = 0; xt[5].tag[taued[2]] = ftag[tau[1]];
3561 xt[5].tag[taued[3]] = ftag[tau[0]]; xt[5].edg[taued[0]] = 0;
3562 xt[5].edg[taued[2]] = 0; xt[5].edg[taued[3]] = 0;
3563 xt[5].ref [ tau[2]] = 0; xt[5].ref [ tau[3]] = 0 ;
3564 xt[5].ftag[ tau[2]] = 0; xt[5].ftag[ tau[3]] = 0 ;
3565 MG_SET(xt[5].ori, tau[2]); MG_SET(xt[5].ori, tau[3]);
3566 }
3567
3568 /* Assignation of the xt fields to the appropriate tets */
3569 memset(isxt,0,ne*sizeof(int8_t));
3570 for (i=0; i<4; i++) {
3571 for (j=0; j<ne; j++) {
3572 if ( (xt[j]).ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
3573 }
3574 }
3575
3576 if ( pt[0]->xt ) {
3577 if ( isxt[0] ) {
3578 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
3579 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = 0;
3580
3581 for (i=1; i<6; i++) {
3582 if ( isxt[i] ) {
3583 mesh->xt++;
3584 if ( mesh->xt > mesh->xtmax ) {
3585 /* realloc of xtetras table */
3587 "larger xtetra table",
3588 mesh->xt--;
3589 fprintf(stderr," Exit program.\n");
3590 return 0);
3591 }
3592 pt[i]->xt = mesh->xt;
3593 pxt0 = &mesh->xtetra[mesh->xt];
3594 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3595 }
3596 }
3597 }
3598 else {
3599 firstxt = 1;
3600 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = 0;
3601
3602 for (i=1; i<6; i++) {
3603 if ( isxt[i] ) {
3604 if ( firstxt ) {
3605 firstxt = 0;
3606 pt[i]->xt = pt[0]->xt;
3607 pxt0 = &mesh->xtetra[(pt[i])->xt];
3608 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3609 }
3610 else {
3611 mesh->xt++;
3612 if ( mesh->xt > mesh->xtmax ) {
3613 /* realloc of xtetras table */
3615 "larger xtetra table",
3616 mesh->xt--;
3617 fprintf(stderr," Exit program.\n");
3618 return 0);
3619 }
3620 pt[i]->xt = mesh->xt;
3621 pxt0 = &mesh->xtetra[mesh->xt];
3622 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3623 }
3624 }
3625 }
3626 pt[0]->xt = 0;
3627 }
3628 }
3629
3630 /* Quality update */
3631 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
3632
3633 return 1;
3634}
3635
3648inline
3649void MMG3D_split4op_cfg(MMG5_int flag,MMG5_int v[4],uint8_t tau[4],
3650 const uint8_t **taued, uint8_t *imin01,uint8_t *imin23) {
3651
3652
3653 /* Set permutation of vertices : reference configuration 30 */
3654 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
3655 (*taued) = &MMG5_permedge[0][0];
3656
3657 switch(flag){
3658 case 45:
3659 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
3660 (*taued) = &MMG5_permedge[5][0];
3661 break;
3662
3663 case 51:
3664 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
3665 (*taued) = &MMG5_permedge[4][0];
3666 break;
3667 }
3668
3669 /* Determine the condition to choose split pattern to apply */
3670 (*imin01) = (v[tau[0]] < v[tau[1]]) ? tau[0] : tau[1];
3671 (*imin23) = (v[tau[2]] < v[tau[3]]) ? tau[2] : tau[3];
3672}
3673
3685int MMG3D_split4op_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
3686 MMG5_pTetra pt,pt0;
3687 double vold,vnew;
3688 uint8_t tau[4];
3689 uint8_t imin01,imin23;
3690 const uint8_t *taued;
3691
3692 pt = &mesh->tetra[k];
3693 pt0 = &mesh->tetra[0];
3694 vold = MMG5_orvol(mesh->point,pt->v);
3695
3696 if ( vold < MMG5_EPSOK ) return 0;
3697
3698 /* Set permutation of vertices : reference configuration 30 */
3699 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
3700 taued = &MMG5_permedge[0][0];
3701
3702 switch(pt->flag){
3703 case 45:
3704 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
3705 taued = &MMG5_permedge[5][0];
3706 break;
3707
3708 case 51:
3709 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
3710 taued = &MMG5_permedge[4][0];
3711 break;
3712 }
3713
3714 imin01 = (pt->v[tau[0]] < pt->v[tau[1]]) ? tau[0] : tau[1];
3715 imin23 = (pt->v[tau[2]] < pt->v[tau[3]]) ? tau[2] : tau[3];
3716
3717 /* Generic formulation for split of 4 edges, with no 3 edges lying on the same
3718 * face */
3719 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3720 if ( imin01 == tau[0] ) {
3721 pt0->v[tau[2]] = vx[taued[3]]; pt0->v[tau[3]] = vx[taued[4]];
3722 vnew = MMG5_orvol(mesh->point,pt0->v);
3723 if ( vnew < MMG5_EPSOK ) return 0;
3724
3725 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3726 pt0->v[tau[1]] = vx[taued[4]]; pt0->v[tau[2]] = vx[taued[3]];
3727 pt0->v[tau[3]] = vx[taued[2]];
3728 vnew = MMG5_orvol(mesh->point,pt0->v);
3729 if ( vnew < MMG5_EPSOK ) return 0;
3730
3731 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3732 pt0->v[tau[1]] = vx[taued[3]]; pt0->v[tau[2]] = vx[taued[1]];
3733 pt0->v[tau[3]] = vx[taued[2]];
3734 vnew = MMG5_orvol(mesh->point,pt0->v);
3735 if ( vnew < MMG5_EPSOK ) return 0;
3736 }
3737 else {
3738 pt0->v[tau[2]] = vx[taued[1]]; pt0->v[tau[3]] = vx[taued[2]];
3739 vnew = MMG5_orvol(mesh->point,pt0->v);
3740 if ( vnew < MMG5_EPSOK ) return 0;
3741
3742 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3743 pt0->v[tau[0]] = vx[taued[1]]; pt0->v[tau[2]] = vx[taued[3]];
3744 pt0->v[tau[3]] = vx[taued[2]];
3745 vnew = MMG5_orvol(mesh->point,pt0->v);
3746 if ( vnew < MMG5_EPSOK ) return 0;
3747
3748 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3749 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[2]] = vx[taued[3]];
3750 pt0->v[tau[3]] = vx[taued[4]];
3751 vnew = MMG5_orvol(mesh->point,pt0->v);
3752 if ( vnew < MMG5_EPSOK ) return 0;
3753 }
3754
3755 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3756 if ( imin23 == tau[2] ) {
3757 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[4]];
3758 vnew = MMG5_orvol(mesh->point,pt0->v);
3759 if ( vnew < MMG5_EPSOK ) return 0;
3760
3761 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3762 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[3]];
3763 pt0->v[tau[3]] = vx[taued[4]];
3764 vnew = MMG5_orvol(mesh->point,pt0->v);
3765 if ( vnew < MMG5_EPSOK ) return 0;
3766
3767 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3768 pt0->v[tau[0]] = vx[taued[1]]; pt0->v[tau[1]] = vx[taued[3]];
3769 pt0->v[tau[3]] = vx[taued[2]];
3770 vnew = MMG5_orvol(mesh->point,pt0->v);
3771 if ( vnew < MMG5_EPSOK ) return 0;
3772 }
3773 else {
3774 pt0->v[tau[0]] = vx[taued[1]]; pt0->v[tau[1]] = vx[taued[3]];
3775 vnew = MMG5_orvol(mesh->point,pt0->v);
3776 if ( vnew < MMG5_EPSOK ) return 0;
3777
3778 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3779 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[3]];
3780 pt0->v[tau[2]] = vx[taued[1]];
3781 vnew = MMG5_orvol(mesh->point,pt0->v);
3782 if ( vnew < MMG5_EPSOK ) return 0;
3783
3784 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3785 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[4]];
3786 pt0->v[tau[2]] = vx[taued[3]];
3787 vnew = MMG5_orvol(mesh->point,pt0->v);
3788 if ( vnew < MMG5_EPSOK ) return 0;
3789 }
3790
3791 return 1;
3792}
3793
3804int MMG5_split4op(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
3805 MMG5_pTetra pt;
3806
3807 /* Tetra to be split */
3808 pt = &mesh->tetra[k];
3809
3810 return MMG5_split4op_globNum(mesh,met,k,vx,pt->v,metRidTyp);
3811}
3812
3826int MMG5_split4op_globNum(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],MMG5_int vGlobNum[4],int8_t metRidTyp) {
3827 MMG5_pTetra pt[6];
3828 MMG5_xTetra xt[6];
3829 MMG5_pxTetra pxt0;
3830 MMG5_int newtet[6];
3831 int8_t flg,firstxt,isxt[6],i,j;
3832 int16_t ftag[4];
3833 uint8_t tau[4],imin01,imin23;
3834 const uint8_t *taued;
3835 const int ne=6;
3836
3837 /* Store the initial tetra and flag */
3838 pt[0] = &mesh->tetra[k];
3839 flg = pt[0]->flag;
3840
3841 /* Reinitialize the flag of the initial tetra */
3842 pt[0]->flag = 0;
3843
3844 /* Store the id of the initial tetra */
3845 newtet[0] = k;
3846
3847 /* Determine tau, taued, imin01 and imin23 the conditions for vertices permutation */
3848 /* Remark: It is mandatory to call MMG3D_split4op_cfg before MMG3D_crea_newTetra.
3849 Indeed, vGlobNum is set in MMG3D_split4op as being pt->v. This value might
3850 point to a wrong memory address if the tetra array is reallocated
3851 in MMG3D_crea_newTetra before the use of vGlobNum */
3852 MMG3D_split4op_cfg(flg,vGlobNum,tau,&taued,&imin01,&imin23);
3853
3854 /* Create 5 new tetras */
3855 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
3856 return 0;
3857 }
3858
3859 /* Store face tags and refs from split tetra*/
3860 for (i=0; i<4; i++) {
3861 ftag[i] = (xt[0].ftag[i] & ~MG_REF);
3862 }
3863
3864 /* Generic formulation for split of 4 edges, with no 3 edges lying on the same face */
3865 if ( imin01 == tau[0] ) {
3866 pt[0]->v[tau[2]] = vx[taued[3]] ; pt[0]->v[tau[3]] = vx[taued[4]];
3867 xt[0].tag[taued[1]] = ftag[tau[3]]; xt[0].tag[taued[5]] = ftag[tau[0]];
3868 xt[0].tag[taued[2]] = ftag[tau[2]]; xt[0].edg[taued[1]] = 0;
3869 xt[0].edg[taued[5]] = 0; xt[0].edg[taued[2]] = 0;
3870 xt[0].ref [ tau[1]] = 0;
3871 xt[0].ftag[ tau[1]] = 0;
3872 MG_SET(xt[0].ori, tau[1]);
3873
3874 pt[1]->v[tau[1]] = vx[taued[4]] ; pt[1]->v[tau[2]] = vx[taued[3]] ; pt[1]->v[tau[3]] = vx[taued[2]];
3875 xt[1].tag[taued[0]] = ftag[tau[2]]; xt[1].tag[taued[1]] = ftag[tau[3]];
3876 xt[1].tag[taued[3]] = ftag[tau[0]]; xt[1].tag[taued[4]] = ftag[tau[2]];
3877 xt[1].tag[taued[5]] = 0; xt[1].edg[taued[0]] = 0;
3878 xt[1].edg[taued[1]] = 0; xt[1].edg[taued[3]] = 0;
3879 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
3880 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[1]] = 0; xt[1].ref [tau[3]] = 0;
3881 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[1]] = 0; xt[1].ftag[tau[3]] = 0;
3882 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[1]); MG_SET(xt[1].ori, tau[3]);
3883
3884 pt[2]->v[tau[1]] = vx[taued[3]] ; pt[2]->v[tau[2]] = vx[taued[1]] ; pt[2]->v[tau[3]] = vx[taued[2]];
3885 xt[2].tag[taued[0]] = ftag[tau[3]]; xt[2].tag[taued[3]] = ftag[tau[3]];
3886 xt[2].tag[taued[4]] = 0; xt[2].tag[taued[5]] = ftag[tau[1]];
3887 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[3]] = 0;
3888 xt[2].edg[taued[4]] = 0; xt[2].edg[taued[5]] = 0;
3889 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[2]] = 0;
3890 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[2]] = 0;
3891 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[2]);
3892 }
3893 else {
3894 pt[0]->v[tau[2]] = vx[taued[1]] ; pt[0]->v[tau[3]] = vx[taued[2]];
3895 xt[0].tag[taued[3]] = ftag[tau[3]]; xt[0].tag[taued[4]] = ftag[tau[2]];
3896 xt[0].tag[taued[5]] = ftag[tau[1]]; xt[0].edg[taued[3]] = 0;
3897 xt[0].edg[taued[4]] = 0; xt[0].edg[taued[5]] = 0;
3898 xt[0].ref [ tau[0]] = 0;
3899 xt[0].ftag[ tau[0]] = 0;
3900 MG_SET(xt[0].ori, tau[0]);
3901
3902 pt[1]->v[tau[0]] = vx[taued[1]] ; pt[1]->v[tau[2]] = vx[taued[3]] ; pt[1]->v[tau[3]] = vx[taued[2]];
3903 xt[1].tag[taued[0]] = ftag[tau[3]]; xt[1].tag[taued[1]] = ftag[tau[3]];
3904 xt[1].tag[taued[2]] = ftag[tau[1]]; xt[1].tag[taued[4]] = ftag[tau[2]];
3905 xt[1].tag[taued[5]] = 0; xt[1].edg[taued[0]] = 0;
3906 xt[1].edg[taued[1]] = 0; xt[1].edg[taued[2]] = 0;
3907 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
3908 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[1]] = 0; xt[1].ref [tau[2]] = 0;
3909 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[1]] = 0; xt[1].ftag[tau[2]] = 0;
3910 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[1]); MG_SET(xt[1].ori, tau[2]);
3911
3912 pt[2]->v[tau[0]] = vx[taued[2]] ; pt[2]->v[tau[2]] = vx[taued[3]] ; pt[2]->v[tau[3]] = vx[taued[4]];
3913 xt[2].tag[taued[0]] = ftag[tau[2]]; xt[2].tag[taued[1]] = 0;
3914 xt[2].tag[taued[2]] = ftag[tau[2]]; xt[2].tag[taued[5]] = ftag[tau[0]];
3915 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[1]] = 0;
3916 xt[2].edg[taued[2]] = 0; xt[2].edg[taued[5]] = 0;
3917 xt[2].ref [ tau[1]] = 0; xt[2].ref [ tau[3]] = 0;
3918 xt[2].ftag[ tau[1]] = 0; xt[2].ftag[ tau[3]] = 0;
3919 MG_SET(xt[2].ori, tau[1]); MG_SET(xt[2].ori, tau[3]);
3920 }
3921
3922 if ( imin23 == tau[2] ) {
3923 pt[3]->v[tau[0]] = vx[taued[2]] ; pt[3]->v[tau[1]] = vx[taued[4]];
3924 xt[3].tag[taued[0]] = ftag[tau[2]]; xt[3].tag[taued[1]] = ftag[tau[1]];
3925 xt[3].tag[taued[3]] = ftag[tau[0]]; xt[3].edg[taued[0]] = 0;
3926 xt[3].edg[taued[1]] = 0; xt[3].edg[taued[3]] = 0;
3927 xt[3].ref [ tau[3]] = 0;
3928 xt[3].ftag[ tau[3]] = 0;
3929 MG_SET(xt[3].ori, tau[3]);
3930
3931 pt[4]->v[tau[0]] = vx[taued[2]] ; pt[4]->v[tau[1]] = vx[taued[3]] ; pt[4]->v[tau[3]] = vx[taued[4]];
3932 xt[4].tag[taued[0]] = 0; xt[4].tag[taued[1]] = ftag[tau[1]];
3933 xt[4].tag[taued[2]] = ftag[tau[2]]; xt[4].tag[taued[4]] = ftag[tau[0]];
3934 xt[4].tag[taued[5]] = ftag[tau[0]]; xt[4].edg[taued[0]] = 0;
3935 xt[4].edg[taued[1]] = 0; xt[4].edg[taued[2]] = 0;
3936 xt[4].edg[taued[4]] = 0; xt[4].edg[taued[5]] = 0;
3937 xt[4].ref [ tau[1]] = 0; xt[4].ref [ tau[2]] = 0; xt[4].ref [tau[3]] = 0;
3938 xt[4].ftag[ tau[1]] = 0; xt[4].ftag[ tau[2]] = 0; xt[4].ftag[tau[3]] = 0;
3939 MG_SET(xt[4].ori, tau[1]); MG_SET(xt[4].ori, tau[2]); MG_SET(xt[4].ori, tau[3]);
3940
3941 pt[5]->v[tau[0]] = vx[taued[1]] ; pt[5]->v[tau[1]] = vx[taued[3]] ; pt[5]->v[tau[3]] = vx[taued[2]];
3942 xt[5].tag[taued[0]] = ftag[tau[3]]; xt[5].tag[taued[2]] = ftag[tau[1]];
3943 xt[5].tag[taued[4]] = 0; xt[5].tag[taued[5]] = ftag[tau[1]];
3944 xt[5].edg[taued[0]] = 0; xt[5].edg[taued[2]] = 0;
3945 xt[5].edg[taued[4]] = 0; xt[5].edg[taued[5]] = 0;
3946 xt[5].ref [ tau[0]] = 0; xt[5].ref [ tau[2]] = 0;
3947 xt[5].ftag[ tau[0]] = 0; xt[5].ftag[ tau[2]] = 0;
3948 MG_SET(xt[5].ori, tau[0]); MG_SET(xt[5].ori, tau[2]);
3949 }
3950 else {
3951 pt[3]->v[tau[0]] = vx[taued[1]] ; pt[3]->v[tau[1]] = vx[taued[3]];
3952 xt[3].tag[taued[0]] = ftag[tau[3]]; xt[3].tag[taued[2]] = ftag[tau[1]];
3953 xt[3].tag[taued[4]] = ftag[tau[0]]; xt[3].edg[taued[0]] = 0;
3954 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[4]] = 0;
3955 xt[3].ref [ tau[2]] = 0;
3956 xt[3].ftag[ tau[2]] = 0;
3957 MG_SET(xt[3].ori, tau[2]);
3958
3959 pt[4]->v[tau[0]] = vx[taued[2]] ; pt[4]->v[tau[1]] = vx[taued[3]] ; pt[4]->v[tau[2]] = vx[taued[1]];
3960 xt[4].tag[taued[0]] = 0; xt[4].tag[taued[1]] = ftag[tau[1]];
3961 xt[4].tag[taued[3]] = ftag[tau[3]]; xt[4].tag[taued[4]] = ftag[tau[0]];
3962 xt[4].tag[taued[5]] = ftag[tau[1]]; xt[4].edg[taued[0]] = 0;
3963 xt[4].edg[taued[1]] = 0; xt[4].edg[taued[3]] = 0;
3964 xt[4].edg[taued[4]] = 0; xt[4].edg[taued[5]] = 0;
3965 xt[4].ref [ tau[0]] = 0; xt[4].ref [ tau[2]] = 0; xt[4].ref [tau[3]] = 0;
3966 xt[4].ftag[ tau[0]] = 0; xt[4].ftag[ tau[2]] = 0; xt[4].ftag[tau[3]] = 0;
3967 MG_SET(xt[4].ori, tau[0]); MG_SET(xt[4].ori, tau[2]); MG_SET(xt[4].ori, tau[3]);
3968
3969 pt[5]->v[tau[0]] = vx[taued[2]] ; pt[5]->v[tau[1]] = vx[taued[4]] ; pt[5]->v[tau[2]] = vx[taued[3]];
3970 xt[5].tag[taued[0]] = ftag[tau[2]]; xt[5].tag[taued[1]] = 0;
3971 xt[5].tag[taued[3]] = ftag[tau[0]]; xt[5].tag[taued[5]] = ftag[tau[0]];
3972 xt[5].edg[taued[0]] = 0; xt[5].edg[taued[1]] = 0;
3973 xt[5].edg[taued[3]] = 0; xt[5].edg[taued[5]] = 0;
3974 xt[5].ref [ tau[1]] = 0; xt[5].ref [ tau[3]] = 0;
3975 xt[5].ftag[ tau[1]] = 0; xt[5].ftag[ tau[3]] = 0;
3976 MG_SET(xt[5].ori, tau[1]); MG_SET(xt[5].ori, tau[3]);
3977 }
3978
3979 /* Assignation of the xt fields to the appropriate tets */
3980 memset(isxt,0,ne*sizeof(int8_t));
3981
3982 for (i=0; i<4; i++) {
3983 for(j=0;j<ne;j++ ) {
3984 if ( (xt[j]).ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
3985 }
3986 }
3987
3988 // In this case, at least one of the 4 created tets must have a special field
3989 if ( pt[0]->xt ) {
3990 if ( isxt[0] ) {
3991 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
3992 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = 0;
3993
3994 for (i=1; i<6; i++) {
3995 if ( isxt[i] ) {
3996 mesh->xt++;
3997 if ( mesh->xt > mesh->xtmax ) {
3998 /* realloc of xtetras table */
4000 "larger xtetra table",
4001 mesh->xt--;
4002 fprintf(stderr," Exit program.\n");
4003 return 0);
4004 }
4005 pt[i]->xt = mesh->xt;
4006 pxt0 = &mesh->xtetra[mesh->xt];
4007 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
4008 }
4009 }
4010 }
4011 else {
4012 firstxt = 1;
4013 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = 0;
4014
4015 for (i=1; i<6; i++) {
4016 if ( isxt[i] ) {
4017 if ( firstxt ) {
4018 firstxt = 0;
4019 pt[i]->xt = pt[0]->xt;
4020 pxt0 = &mesh->xtetra[ pt[i]->xt];
4021 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
4022 }
4023 else {
4024 mesh->xt++;
4025 if ( mesh->xt > mesh->xtmax ) {
4026 /* realloc of xtetras table */
4028 "larger xtetra table",
4029 mesh->xt--;
4030 fprintf(stderr," Exit program.\n");
4031 return 0);
4032 }
4033 pt[i]->xt = mesh->xt;
4034 pxt0 = &mesh->xtetra[mesh->xt];
4035 memcpy(pxt0,&(xt[i]),sizeof(MMG5_xTetra));
4036 }
4037 }
4038 }
4039 pt[0]->xt = 0;
4040
4041 }
4042 }
4043
4044 /* Quality update */
4045 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
4046
4047 return 1;
4048}
4049
4061static inline
4062void MMG3D_split5_cfg(MMG5_pTetra pt,MMG5_int vx[6],uint8_t tau[4],
4063 const uint8_t **taued,uint8_t *imin) {
4064
4065 /* set permutation of vertices and edges ; reference configuration : 62 */
4066 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
4067 (*taued) = &MMG5_permedge[0][0];
4068
4069 switch(pt->flag) {
4070 case 61:
4071 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
4072 (*taued) = &MMG5_permedge[6][0];
4073 break;
4074
4075 case 59:
4076 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
4077 (*taued) = &MMG5_permedge[2][0];
4078 break;
4079
4080 case 55:
4081 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
4082 (*taued) = &MMG5_permedge[4][0];
4083 break;
4084
4085 case 47:
4086 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
4087 (*taued) = &MMG5_permedge[10][0];
4088 break;
4089
4090 case 31:
4091 tau[0] = 3 ; tau[1] = 2 ; tau[2] = 1 ; tau[3] = 0;
4092 (*taued) = &MMG5_permedge[11][0];
4093 break;
4094 }
4095
4096 /* Generic formulation of split of 5 edges */
4097 (*imin) = (pt->v[tau[0]] < pt->v[tau[1]]) ? tau[0] : tau[1];
4098}
4099
4111int MMG3D_split5_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
4112 MMG5_pTetra pt,pt0;
4113 double vold,vnew;
4114 uint8_t tau[4];
4115 uint8_t imin;
4116 const uint8_t *taued=NULL;
4117
4118 pt = &mesh->tetra[k];
4119 pt0 = &mesh->tetra[0];
4120 vold = MMG5_orvol(mesh->point,pt->v);
4121
4122 if ( vold < MMG5_EPSOK ) return 0;
4123
4124 /* Set permutation of vertices : reference configuration : 62 */
4125 MMG3D_split5_cfg(pt,vx,tau,&taued,&imin);
4126
4127 /* Generic formulation of split of 5 edges */
4128 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4129 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[4]];
4130 pt0->v[tau[2]] = vx[taued[5]];
4131 vnew = MMG5_orvol(mesh->point,pt0->v);
4132 if ( vnew < MMG5_EPSOK ) return 0;
4133
4134 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4135 pt0->v[tau[0]] = vx[taued[1]]; pt0->v[tau[1]] = vx[taued[3]];
4136 pt0->v[tau[3]] = vx[taued[5]];
4137 vnew = MMG5_orvol(mesh->point,pt0->v);
4138 if ( vnew < MMG5_EPSOK ) return 0;
4139
4140 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4141 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[4]];
4142 pt0->v[tau[2]] = vx[taued[3]]; pt0->v[tau[3]] = vx[taued[5]];
4143 vnew = MMG5_orvol(mesh->point,pt0->v);
4144 if ( vnew < MMG5_EPSOK ) return 0;
4145
4146 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4147 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[3]];
4148 pt0->v[tau[2]] = vx[taued[1]]; pt0->v[tau[3]] = vx[taued[5]];
4149 vnew = MMG5_orvol(mesh->point,pt0->v);
4150 if ( vnew < MMG5_EPSOK ) return 0;
4151
4152 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4153 if ( imin == tau[0] ) {
4154 pt0->v[tau[2]] = vx[taued[3]]; pt0->v[tau[3]] = vx[taued[4]];
4155 vnew = MMG5_orvol(mesh->point,pt0->v);
4156 if ( vnew < MMG5_EPSOK ) return 0;
4157
4158 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4159 pt0->v[tau[1]] = vx[taued[4]]; pt0->v[tau[2]] = vx[taued[3]];
4160 pt0->v[tau[3]] = vx[taued[2]];
4161 vnew = MMG5_orvol(mesh->point,pt0->v);
4162 if ( vnew < MMG5_EPSOK ) return 0;
4163
4164 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4165 pt0->v[tau[1]] = vx[taued[3]]; pt0->v[tau[2]] = vx[taued[1]];
4166 pt0->v[tau[3]] = vx[taued[2]];
4167 vnew = MMG5_orvol(mesh->point,pt0->v);
4168 if ( vnew < MMG5_EPSOK ) return 0;
4169 }
4170 else {
4171 pt0->v[tau[2]] = vx[taued[1]]; pt0->v[tau[3]] = vx[taued[2]];
4172 vnew = MMG5_orvol(mesh->point,pt0->v);
4173 if ( vnew < MMG5_EPSOK ) return 0;
4174
4175 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4176 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[2]] = vx[taued[3]];
4177 pt0->v[tau[3]] = vx[taued[4]];
4178 vnew = MMG5_orvol(mesh->point,pt0->v);
4179 if ( vnew < MMG5_EPSOK ) return 0;
4180
4181 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4182 pt0->v[tau[0]] = vx[taued[1]]; pt0->v[tau[2]] = vx[taued[3]];
4183 pt0->v[tau[3]] = vx[taued[2]];
4184 vnew = MMG5_orvol(mesh->point,pt0->v);
4185 if ( vnew < MMG5_EPSOK ) return 0;
4186 }
4187
4188 return 1;
4189}
4190
4203int MMG5_split5(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
4204 MMG5_pTetra pt[7];
4205 MMG5_xTetra xt[7];
4206 MMG5_pxTetra pxt0;
4207 int i,j;
4208 MMG5_int newtet[7];
4209 int8_t firstxt,isxt[7];
4210 int16_t ftag[4];
4211 uint8_t tau[4],imin;
4212 const uint8_t *taued=NULL;
4213 const int ne=7;
4214
4215 pt[0] = &mesh->tetra[k];
4216 newtet[0]=k;
4217
4218 /* set permutation of vertices and edges ; reference configuration : 62 */
4219 MMG3D_split5_cfg(pt[0],vx,tau,&taued,&imin);
4220 pt[0]->flag = 0;
4221
4222 /* create 6 new tetras */
4223 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
4224 return 0;
4225 }
4226
4227 /* Store face tags and refs from split tetra*/
4228 for (i=0; i<4; i++) {
4229 ftag[i] = (xt[0].ftag[i] & ~MG_REF);
4230 }
4231
4232 /* Generic formulation of split of 5 edges */
4233 pt[0]->v[tau[0]] = vx[taued[2]] ; pt[0]->v[tau[1]] = vx[taued[4]] ; pt[0]->v[tau[2]] = vx[taued[5]];
4234 xt[0].tag[taued[0]] = ftag[tau[2]]; xt[0].tag[taued[1]] = ftag[tau[1]];
4235 xt[0].tag[taued[3]] = ftag[tau[0]]; xt[0].edg[taued[0]] = 0;
4236 xt[0].edg[taued[1]] = 0; xt[0].edg[taued[3]] = 0;
4237 xt[0].ref [ tau[3]] = 0;
4238 xt[0].ftag[ tau[3]] = 0;
4239 MG_SET(xt[0].ori, tau[3]);
4240
4241 pt[1]->v[tau[0]] = vx[taued[1]] ; pt[1]->v[tau[1]] = vx[taued[3]] ; pt[1]->v[tau[3]] = vx[taued[5]];
4242 xt[1].tag[taued[0]] = ftag[tau[3]]; xt[1].tag[taued[2]] = ftag[tau[1]];
4243 xt[1].tag[taued[4]] = ftag[tau[0]]; xt[1].edg[taued[0]] = 0;
4244 xt[1].edg[taued[2]] = 0; xt[1].edg[taued[4]] = 0;
4245 xt[1].ref [ tau[2]] = 0;
4246 xt[1].ftag[ tau[2]] = 0;
4247 MG_SET(xt[1].ori, tau[2]);
4248
4249 pt[2]->v[tau[0]] = vx[taued[2]] ; pt[2]->v[tau[1]] = vx[taued[4]];
4250 pt[2]->v[tau[2]] = vx[taued[3]] ; pt[2]->v[tau[3]] = vx[taued[5]];
4251 xt[2].tag[taued[0]] = ftag[tau[2]]; xt[2].tag[taued[1]] = 0;
4252 xt[2].tag[taued[2]] = ftag[tau[1]]; xt[2].tag[taued[3]] = ftag[tau[0]];
4253 xt[2].tag[taued[4]] = ftag[tau[0]]; xt[2].tag[taued[5]] = ftag[tau[0]];
4254 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[1]] = 0;
4255 xt[2].edg[taued[2]] = 0; xt[2].edg[taued[3]] = 0;
4256 xt[2].edg[taued[4]] = 0; xt[2].edg[taued[5]] = 0;
4257 xt[2].ref [tau[1]] = 0 ; xt[2].ref [ tau[2]] = 0; xt[2].ref [tau[3]] = 0 ;
4258 xt[2].ftag[tau[1]] = 0 ; xt[2].ftag[ tau[2]] = 0; xt[2].ftag[tau[3]] = 0 ;
4259 MG_SET(xt[2].ori, tau[1]); MG_SET(xt[2].ori, tau[2]); MG_SET(xt[2].ori, tau[3]);
4260
4261 pt[3]->v[tau[0]] = vx[taued[2]] ; pt[3]->v[tau[1]] = vx[taued[3]];
4262 pt[3]->v[tau[2]] = vx[taued[1]] ; pt[3]->v[tau[3]] = vx[taued[5]];
4263 xt[3].tag[taued[0]] = 0; xt[3].tag[taued[1]] = ftag[tau[1]];
4264 xt[3].tag[taued[2]] = ftag[tau[1]]; xt[3].tag[taued[3]] = ftag[tau[3]];
4265 xt[3].tag[taued[4]] = ftag[tau[0]]; xt[3].tag[taued[5]] = ftag[tau[1]];
4266 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[1]] = 0;
4267 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[3]] = 0;
4268 xt[3].edg[taued[4]] = 0; xt[3].edg[taued[5]] = 0;
4269 xt[3].ref [ tau[0]] = 0; xt[3].ref [ tau[2]] = 0; xt[3].ref [tau[3]] = 0 ;
4270 xt[3].ftag[ tau[0]] = 0; xt[3].ftag[ tau[2]] = 0; xt[3].ftag[tau[3]] = 0 ;
4271 MG_SET(xt[3].ori, tau[0]); MG_SET(xt[3].ori, tau[2]); MG_SET(xt[3].ori, tau[3]);
4272
4273 if ( imin == tau[0] ) {
4274 pt[4]->v[tau[2]] = vx[taued[3]] ; pt[4]->v[tau[3]] = vx[taued[4]];
4275 xt[4].tag[taued[1]] = ftag[tau[3]]; xt[4].tag[taued[2]] = ftag[tau[2]];
4276 xt[4].tag[taued[5]] = ftag[tau[0]]; xt[4].edg[taued[1]] = 0;
4277 xt[4].edg[taued[2]] = 0; xt[4].edg[taued[5]] = 0;
4278 xt[4].ref [ tau[1]] = 0;
4279 xt[4].ftag[ tau[1]] = 0;
4280 MG_SET(xt[4].ori, tau[1]);
4281
4282 pt[5]->v[tau[1]] = vx[taued[4]] ; pt[5]->v[tau[2]] = vx[taued[3]]; pt[5]->v[tau[3]] = vx[taued[2]];
4283 xt[5].tag[taued[0]] = ftag[tau[2]];
4284 xt[5].tag[taued[1]] = ftag[tau[3]]; xt[5].tag[taued[3]] = ftag[tau[0]];
4285 xt[5].tag[taued[4]] = ftag[tau[2]]; xt[5].tag[taued[5]] = 0;
4286 xt[5].edg[taued[0]] = 0;
4287 xt[5].edg[taued[1]] = 0; xt[5].edg[taued[3]] = 0;
4288 xt[5].edg[taued[4]] = 0; xt[5].edg[taued[5]] = 0;
4289 xt[5].ref [ tau[0]] = 0; xt[5].ref [ tau[1]] = 0; xt[5].ref [tau[3]] = 0 ;
4290 xt[5].ftag[ tau[0]] = 0; xt[5].ftag[ tau[1]] = 0; xt[5].ftag[tau[3]] = 0 ;
4291 MG_SET(xt[5].ori, tau[0]); MG_SET(xt[5].ori, tau[1]); MG_SET(xt[5].ori, tau[3]);
4292
4293 pt[6]->v[tau[1]] = vx[taued[3]] ; pt[6]->v[tau[2]] = vx[taued[1]]; pt[6]->v[tau[3]] = vx[taued[2]];
4294 xt[6].tag[taued[0]] = ftag[tau[3]];
4295 xt[6].tag[taued[3]] = ftag[tau[3]]; xt[6].tag[taued[4]] = 0;
4296 xt[6].tag[taued[5]] = ftag[tau[1]]; xt[6].edg[taued[0]] = 0;
4297 xt[6].edg[taued[3]] = 0;
4298 xt[6].edg[taued[4]] = 0; xt[6].edg[taued[5]] = 0;
4299 xt[6].ref [ tau[0]] = 0; xt[6].ref [ tau[2]] = 0;
4300 xt[6].ftag[ tau[0]] = 0; xt[6].ftag[ tau[2]] = 0;
4301 MG_SET(xt[6].ori, tau[0]); MG_SET(xt[6].ori, tau[2]);
4302
4303 }
4304 else {
4305 pt[4]->v[tau[2]] = vx[taued[1]] ; pt[4]->v[tau[3]] = vx[taued[2]];
4306 xt[4].tag[taued[3]] = ftag[tau[3]]; xt[4].tag[taued[4]] = ftag[tau[2]];
4307 xt[4].tag[taued[5]] = ftag[tau[1]]; xt[4].edg[taued[3]] = 0;
4308 xt[4].edg[taued[4]] = 0; xt[4].edg[taued[5]] = 0;
4309 xt[4].ref [ tau[0]] = 0;
4310 xt[4].ftag[ tau[0]] = 0;
4311 MG_SET(xt[4].ori, tau[0]);
4312
4313 pt[5]->v[tau[0]] = vx[taued[2]] ; pt[5]->v[tau[2]] = vx[taued[3]]; pt[5]->v[tau[3]] = vx[taued[4]];
4314 xt[5].tag[taued[0]] = ftag[tau[2]]; xt[5].tag[taued[1]] = 0;
4315 xt[5].tag[taued[2]] = ftag[tau[2]]; xt[5].tag[taued[5]] = ftag[tau[0]];
4316 xt[5].edg[taued[0]] = 0; xt[5].edg[taued[1]] = 0;
4317 xt[5].edg[taued[2]] = 0; xt[5].edg[taued[5]] = 0;
4318 xt[5].ref [ tau[1]] = 0; xt[5].ref [ tau[3]] = 0;
4319 xt[5].ftag[ tau[1]] = 0; xt[5].ftag[ tau[3]] = 0;
4320 MG_SET(xt[5].ori, tau[1]); MG_SET(xt[5].ori, tau[3]);
4321
4322 pt[6]->v[tau[0]] = vx[taued[1]] ; pt[6]->v[tau[2]] = vx[taued[3]]; pt[6]->v[tau[3]] = vx[taued[2]];
4323 xt[6].tag[taued[0]] = ftag[tau[3]]; xt[6].tag[taued[1]] = ftag[tau[3]];
4324 xt[6].tag[taued[2]] = ftag[tau[1]]; xt[6].tag[taued[4]] = ftag[tau[2]];
4325 xt[6].tag[taued[5]] = 0; xt[6].edg[taued[0]] = 0;
4326 xt[6].edg[taued[1]] = 0; xt[6].edg[taued[2]] = 0;
4327 xt[6].edg[taued[4]] = 0; xt[6].edg[taued[5]] = 0;
4328 xt[6].ref [ tau[0]] = 0; xt[6].ref [ tau[1]] = 0; xt[6].ref [tau[2]] = 0 ;
4329 xt[6].ftag[ tau[0]] = 0; xt[6].ftag[ tau[1]] = 0; xt[6].ftag[tau[2]] = 0 ;
4330 MG_SET(xt[6].ori, tau[0]); MG_SET(xt[6].ori, tau[1]); MG_SET(xt[6].ori, tau[2]);
4331 }
4332
4333 /* Assignation of the xt fields to the appropriate tets */
4334 memset(isxt,0,ne*sizeof(int8_t));
4335
4336 for (i=0; i<4; i++) {
4337 for (j=0; j<ne; j++) {
4338 if ( (xt[j]).ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
4339 }
4340 }
4341
4342 if ( pt[0]->xt ) {
4343 if ( isxt[0] ) {
4344 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
4345 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = pt[6]->xt = 0;
4346
4347 for (i=1; i<7; i++) {
4348 if ( isxt[i] ) {
4349 mesh->xt++;
4350 if ( mesh->xt > mesh->xtmax ) {
4351 /* realloc of xtetras table */
4353 "larger xtetra table",
4354 mesh->xt--;
4355 fprintf(stderr," Exit program.\n");
4356 return 0);
4357 }
4358 pt[i]->xt = mesh->xt;
4359 pxt0 = &mesh->xtetra[mesh->xt];
4360 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
4361 }
4362 }
4363 }
4364 else {
4365 firstxt = 1;
4366 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = pt[6]->xt = 0;
4367
4368 for (i=1; i<7; i++) {
4369 if ( isxt[i] ) {
4370 if ( firstxt ) {
4371 firstxt = 0;
4372 pt[i]->xt = pt[0]->xt;
4373 pxt0 = &mesh->xtetra[(pt[i])->xt];
4374 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
4375 }
4376 else {
4377 mesh->xt++;
4378 if ( mesh->xt > mesh->xtmax ) {
4379 /* realloc of xtetras table */
4381 "larger xtetra table",
4382 mesh->xt--;
4383 fprintf(stderr," Exit program.\n");
4384 return 0);
4385 }
4386 pt[i]->xt = mesh->xt;
4387 pxt0 = &mesh->xtetra[mesh->xt];
4388 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
4389 }
4390 }
4391 }
4392 pt[0]->xt = 0;
4393
4394 }
4395 }
4396
4397 /* Quality update */
4398 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
4399
4400 return 1;
4401}
4402
4414int MMG3D_split6_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
4415 MMG5_pTetra pt,pt0;
4416 double vold,vnew;
4417
4418 pt = &mesh->tetra[k];
4419 pt0 = &mesh->tetra[0];
4420 vold = MMG5_orvol(mesh->point,pt->v);
4421
4422 if ( vold < MMG5_EPSOK ) return 0;
4423
4424 /* Modify first tetra */
4425 pt0->v[0] = pt->v[0]; pt0->v[1] = vx[0]; pt0->v[2] = vx[1]; pt0->v[3] = vx[2];
4426 vnew = MMG5_orvol(mesh->point,pt0->v);
4427 if ( vnew < MMG5_EPSOK ) return 0;
4428
4429 /* Modify second tetra */
4430 pt0->v[0] = vx[0]; pt0->v[1] = pt->v[1]; pt0->v[2] = vx[3]; pt0->v[3] = vx[4];
4431 vnew = MMG5_orvol(mesh->point,pt0->v);
4432 if ( vnew < MMG5_EPSOK ) return 0;
4433
4434 /* Modify 3rd tetra */
4435 pt0->v[0] = vx[1]; pt0->v[1] = vx[3]; pt0->v[2] = pt->v[2]; pt0->v[3] = vx[5];
4436 vnew = MMG5_orvol(mesh->point,pt0->v);
4437 if ( vnew < MMG5_EPSOK ) return 0;
4438
4439 /* Modify 4th tetra */
4440 pt0->v[0] = vx[2]; pt0->v[1] = vx[4]; pt0->v[2] = vx[5]; pt0->v[3] = pt->v[3];
4441 vnew = MMG5_orvol(mesh->point,pt0->v);
4442 if ( vnew < MMG5_EPSOK ) return 0;
4443
4444 /* Modify 5th tetra */
4445 pt0->v[0] = vx[0]; pt0->v[1] = vx[3]; pt0->v[2] = vx[1];
4446 pt0->v[3] = vx[2];
4447 vnew = MMG5_orvol(mesh->point,pt0->v);
4448 if ( vnew < MMG5_EPSOK ) return 0;
4449
4450 /* Modify 6th tetra */
4451 pt0->v[0] = vx[2]; pt0->v[1] = vx[0]; pt0->v[2] = vx[3];
4452 pt0->v[3] = vx[4];
4453 vnew = MMG5_orvol(mesh->point,pt0->v);
4454 if ( vnew < MMG5_EPSOK ) return 0;
4455
4456 /* Modify 7th tetra */
4457 pt0->v[0] = vx[2]; pt0->v[1] = vx[3]; pt0->v[2] = vx[1];
4458 pt0->v[3] = vx[5];
4459 vnew = MMG5_orvol(mesh->point,pt0->v);
4460 if ( vnew < MMG5_EPSOK ) return 0;
4461
4462 /* Modify last tetra */
4463 pt0->v[0] = vx[2]; pt0->v[1] = vx[3]; pt0->v[2] = vx[5];
4464 pt0->v[3] = vx[4];
4465 vnew = MMG5_orvol(mesh->point,pt0->v);
4466 if ( vnew < MMG5_EPSOK ) return 0;
4467
4468 return 1;
4469}
4470
4483int MMG5_split6(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
4484 MMG5_pTetra pt[8];
4485 MMG5_xTetra xt0,xt;
4486 MMG5_pxTetra pxt;
4487 int i,j;
4488 MMG5_int iel,newtet[8],nxt0;
4489 int8_t isxt0,isxt;
4490 int16_t ftag[4];
4491 const int8_t ne=8;
4492
4493 pt[0] = &mesh->tetra[k];
4494 pt[0]->flag = 0;
4495 newtet[0]=k;
4496
4497 nxt0 = pt[0]->xt;
4498 pxt = &mesh->xtetra[nxt0];
4499 memcpy(&xt0,pxt,sizeof(MMG5_xTetra));
4500
4501 /* create 7 new tetras */
4502 for (i=1; i<ne; i++) {
4503 iel = MMG3D_newElt(mesh);
4504 if ( !iel ) {
4506 fprintf(stderr,"\n ## Error: %s: unable to allocate"
4507 " a new element.\n",__func__);
4509 fprintf(stderr," Exit program.\n");
4510 return 0);
4511 for ( j=0; j<i; j++ )
4512 pt[j] = &mesh->tetra[newtet[j]];
4513 }
4514 pt[i] = &mesh->tetra[iel];
4515 pt[i] = memcpy(pt[i],pt[0],sizeof(MMG5_Tetra));
4516 newtet[i]=iel;
4517 }
4518
4519 /* Store face tags and refs from split tetra*/
4520 for (i=0; i<4; i++) {
4521 ftag[i] = (xt.ftag[i] & ~MG_REF);
4522 }
4523
4524 /* Modify first tetra */
4525 pt[0]->v[1] = vx[0] ; pt[0]->v[2] = vx[1]; pt[0]->v[3] = vx[2];
4526 if ( nxt0 ) {
4527 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4528 xt.tag[3] = ftag[3]; xt.tag[4] = ftag[2];
4529 xt.tag[5] = ftag[1]; xt.edg[3] = 0;
4530 xt.edg[4] = 0; xt.edg[5] = 0;
4531 xt.ref[0] = 0; xt.ftag[0] = 0; MG_SET(xt.ori, 0);
4532 isxt0 = 0;
4533 for(i=0;i<4;i++ ) {
4534 if ( (xt.ref[i]) || xt.ftag[i] ) isxt0 = 1;
4535 }
4536
4537 if ( isxt0 ) {
4538 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4539 }
4540 else {
4541 pt[0]->xt = 0;
4542 }
4543 }
4544
4545 /* Modify second tetra */
4546 pt[1]->v[0] = vx[0] ; pt[1]->v[2] = vx[3]; pt[1]->v[3] = vx[4];
4547
4548 if ( nxt0 ) {
4549 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4550 xt.tag[1] = ftag[3]; xt.tag[2] = ftag[2];
4551 xt.tag[5] = ftag[0]; xt.edg[1] = 0;
4552 xt.edg[2] = 0; xt.edg[5] = 0;
4553 xt.ref[1] = 0; xt.ftag[1] = 0; MG_SET(xt.ori, 1);
4554
4555 isxt = 0;
4556
4557 for (i=0; i<4; i++) {
4558 if ( (xt.ref[i]) || xt.ftag[i]) isxt = 1;
4559 }
4560
4561 pt[1]->xt = 0;
4562 if ( isxt ) {
4563 if ( !isxt0 ) {
4564 isxt0 = 1;
4565 pt[1]->xt = nxt0;
4566 pxt = &mesh->xtetra[pt[1]->xt];
4567 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4568 }
4569 else {
4570 mesh->xt++;
4571 if ( mesh->xt > mesh->xtmax ) {
4572 /* realloc of xtetras table */
4574 "larger xtetra table",
4575 mesh->xt--;
4576 fprintf(stderr," Exit program.\n");
4577 return 0);
4578 }
4579 pt[1]->xt = mesh->xt;
4580 pxt = &mesh->xtetra[pt[1]->xt];
4581 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4582 }
4583 }
4584 }
4585
4586 /* Modify 3rd tetra */
4587 pt[2]->v[0] = vx[1] ; pt[2]->v[1] = vx[3]; pt[2]->v[3] = vx[5];
4588
4589 if ( nxt0 ) {
4590 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4591 xt.tag[0] = ftag[3]; xt.tag[2] = ftag[1];
4592 xt.tag[4] = ftag[0]; xt.edg[0] = 0;
4593 xt.edg[2] = 0; xt.edg[4] = 0;
4594 xt.ref[2] = 0; xt.ftag[2] = 0; MG_SET(xt.ori, 2);
4595 isxt = 0;
4596
4597 for (i=0; i<4;i++) {
4598 if ( (xt.ref[i]) || xt.ftag[i]) isxt = 1;
4599 }
4600
4601 pt[2]->xt = 0;
4602 if ( isxt ) {
4603 if ( !isxt0 ) {
4604 isxt0 = 1;
4605 pt[2]->xt = nxt0;
4606 pxt = &mesh->xtetra[pt[2]->xt];
4607 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4608 }
4609 else {
4610 mesh->xt++;
4611 if ( mesh->xt > mesh->xtmax ) {
4612 /* realloc of xtetras table */
4614 "larger xtetra table",
4615 mesh->xt--;
4616 fprintf(stderr," Exit program.\n");
4617 return 0);
4618 }
4619 pt[2]->xt = mesh->xt;
4620 pxt = &mesh->xtetra[pt[2]->xt];
4621 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4622 }
4623 }
4624 }
4625
4626 /* Modify 4th tetra */
4627 pt[3]->v[0] = vx[2] ; pt[3]->v[1] = vx[4]; pt[3]->v[2] = vx[5];
4628
4629 if ( nxt0 ) {
4630 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4631 xt.tag[0] = ftag[2]; xt.tag[1] = ftag[1];
4632 xt.tag[3] = ftag[0]; xt.edg[0] = 0;
4633 xt.edg[1] = 0; xt.edg[3] = 0;
4634 xt.ref[3] = 0; xt.ftag[3] = 0; MG_SET(xt.ori, 3);
4635
4636 isxt = 0;
4637
4638 for (i=0; i<4; i++) {
4639 if ( (xt.ref[i]) || xt.ftag[i]) isxt = 1;
4640 }
4641
4642 pt[3]->xt = 0;
4643 if ( isxt ) {
4644 if ( !isxt0 ) {
4645 isxt0 = 1;
4646 pt[3]->xt = nxt0;
4647 pxt = &mesh->xtetra[pt[3]->xt];
4648 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4649 }
4650 else {
4651 mesh->xt++;
4652 if ( mesh->xt > mesh->xtmax ) {
4653 /* realloc of xtetras table */
4655 "larger xtetra table",
4656 mesh->xt--;
4657 fprintf(stderr," Exit program.\n");
4658 return 0);
4659 }
4660 pt[3]->xt = mesh->xt;
4661 pxt = &mesh->xtetra[pt[3]->xt];
4662 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4663 }
4664 }
4665 }
4666
4667 /* Modify 5th tetra */
4668 pt[4]->v[0] = vx[0] ; pt[4]->v[1] = vx[3]; pt[4]->v[2] = vx[1] ; pt[4]->v[3] = vx[2];
4669
4670 if ( nxt0 ) {
4671 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4672 xt.tag[0] = ftag[3]; xt.tag[1] = ftag[3];
4673 xt.tag[2] = ftag[2]; xt.tag[3] = ftag[3];
4674 xt.edg[0] = 0; xt.edg[1] = 0;
4675 xt.edg[2] = 0; xt.edg[3] = 0;
4676 xt.tag[4] = 0; xt.edg[4] = 0;
4677 xt.tag[5] = ftag[1]; xt.edg[5] = 0;
4678 xt.ref [0] = 0 ; xt.ref [1] = 0 ; xt.ref [2] = 0;
4679 xt.ftag[0] = 0 ; xt.ftag[1] = 0 ; xt.ftag[2] = 0;
4680 MG_SET(xt.ori, 0); MG_SET(xt.ori, 1); MG_SET(xt.ori, 2);
4681
4682 isxt = 0;
4683
4684 if ( (xt.ref[3]) || xt.ftag[3]) isxt = 1;
4685
4686 pt[4]->xt = 0;
4687 if ( isxt ) {
4688 if ( !isxt0 ) {
4689 isxt0 = 1;
4690 pt[4]->xt = nxt0;
4691 pxt = &mesh->xtetra[(pt[4])->xt];
4692 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4693 }
4694 else {
4695 mesh->xt++;
4696 if ( mesh->xt > mesh->xtmax ) {
4697 /* realloc of xtetras table */
4699 "larger xtetra table",
4700 mesh->xt--;
4701 fprintf(stderr," Exit program.\n");
4702 return 0);
4703 }
4704 pt[4]->xt = mesh->xt;
4705 pxt = &mesh->xtetra[pt[4]->xt];
4706 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4707 }
4708 }
4709 }
4710
4711 /* Modify 6th tetra */
4712 pt[5]->v[0] = vx[2] ; pt[5]->v[1] = vx[0]; pt[5]->v[2] = vx[3] ; pt[5]->v[3] = vx[4];
4713
4714 if ( nxt0 ) {
4715 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4716 xt.tag[0] = ftag[2]; xt.tag[1] = 0;
4717 xt.tag[2] = ftag[2]; xt.tag[3] = ftag[3];
4718 xt.tag[4] = ftag[2]; xt.tag[5] = ftag[0];
4719 xt.edg[0] = 0; xt.edg[1] = 0;
4720 xt.edg[2] = 0; xt.edg[3] = 0;
4721 xt.edg[4] = 0; xt.edg[5] = 0;
4722 xt.ref [0] = 0 ; xt.ref [1] = 0 ; xt.ref [3] = 0;
4723 xt.ftag[0] = 0 ; xt.ftag[1] = 0 ; xt.ftag[3] = 0;
4724 MG_SET(xt.ori, 0); MG_SET(xt.ori, 1); MG_SET(xt.ori, 3);
4725
4726 isxt = 0;
4727
4728 if ( (xt.ref[2]) || xt.ftag[2]) isxt = 1;
4729
4730 pt[5]->xt = 0;
4731 if ( isxt ) {
4732 if ( !isxt0 ) {
4733 isxt0 = 1;
4734 pt[5]->xt = nxt0;
4735 pxt = &mesh->xtetra[pt[5]->xt];
4736 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4737 }
4738 else {
4739 mesh->xt++;
4740 if ( mesh->xt > mesh->xtmax ) {
4741 /* realloc of xtetras table */
4743 "larger xtetra table",
4744 mesh->xt--;
4745 fprintf(stderr," Exit program.\n");
4746 return 0);
4747 }
4748 pt[5]->xt = mesh->xt;
4749 pxt = &mesh->xtetra[pt[5]->xt];
4750 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4751 }
4752 }
4753 }
4754
4755 /* Modify 7th tetra */
4756 pt[6]->v[0] = vx[2] ; pt[6]->v[1] = vx[3]; pt[6]->v[2] = vx[1] ; pt[6]->v[3] = vx[5];
4757
4758 if ( nxt0 ) {
4759 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4760 xt.tag[0] = 0; xt.edg[0] = 0;
4761 xt.tag[1] = ftag[1]; xt.tag[2] = ftag[1];
4762 xt.tag[3] = ftag[3]; xt.tag[4] = ftag[0];
4763 xt.edg[1] = 0; xt.edg[2] = 0;
4764 xt.edg[3] = 0; xt.edg[4] = 0;
4765 xt.tag[5] = ftag[3]; xt.edg[5] = 0;
4766 xt.ref [0] = 0 ; xt.ref [2] = 0 ; xt.ref [3] = 0;
4767 xt.ftag[0] = 0 ; xt.ftag[2] = 0 ; xt.ftag[3] = 0;
4768 MG_SET(xt.ori, 0); MG_SET(xt.ori, 2); MG_SET(xt.ori, 3);
4769
4770 isxt = 0;
4771
4772 if ( (xt.ref[1]) || xt.ftag[1]) isxt = 1;
4773
4774 pt[6]->xt = 0;
4775 if ( isxt ) {
4776 if ( !isxt0 ) {
4777 isxt0 = 1;
4778 pt[6]->xt = nxt0;
4779 pxt = &mesh->xtetra[pt[6]->xt];
4780 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4781 }
4782 else {
4783 mesh->xt++;
4784 if ( mesh->xt > mesh->xtmax ) {
4785 /* realloc of xtetras table */
4787 "larger xtetra table",
4788 mesh->xt--;
4789 fprintf(stderr," Exit program.\n");
4790 return 0);
4791 }
4792 pt[6]->xt = mesh->xt;
4793 pxt = &mesh->xtetra[pt[6]->xt];
4794 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4795 }
4796 }
4797 }
4798
4799 /* Modify last tetra */
4800 pt[7]->v[0] = vx[2] ; pt[7]->v[1] = vx[3]; pt[7]->v[2] = vx[5] ; pt[7]->v[3] = vx[4];
4801
4802 if ( nxt0 ) {
4803 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4804 xt.tag[0] = 0; xt.tag[1] = ftag[1];
4805 xt.tag[2] = ftag[2]; xt.tag[3] = ftag[0];
4806 xt.tag[4] = ftag[0]; xt.tag[5] = ftag[0];
4807 xt.edg[0] = 0; xt.edg[1] = 0;
4808 xt.edg[2] = 0; xt.edg[3] = 0;
4809 xt.edg[4] = 0; xt.edg[5] = 0;
4810 xt.ref [1] = 0 ; xt.ref [2] = 0 ; xt.ref [3] = 0;
4811 xt.ftag[1] = 0 ; xt.ftag[2] = 0 ; xt.ftag[3] = 0;
4812 MG_SET(xt.ori, 1); MG_SET(xt.ori, 2); MG_SET(xt.ori, 3);
4813
4814 isxt = 0;
4815
4816 if ( (xt.ref[0]) || xt.ftag[0]) isxt = 1;
4817
4818 pt[7]->xt = 0;
4819 if ( isxt ) {
4820 if ( !isxt0 ) {
4821 pt[7]->xt = nxt0;
4822 pxt = &mesh->xtetra[pt[7]->xt];
4823 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4824 }
4825 else {
4826 mesh->xt++;
4827 if ( mesh->xt > mesh->xtmax ) {
4828 /* realloc of xtetras table */
4830 "larger xtetra table",
4831 mesh->xt--;
4832 fprintf(stderr," Exit program.\n");
4833 return 0);
4834 }
4835 pt[7]->xt = mesh->xt;
4836 pxt = &mesh->xtetra[pt[7]->xt];
4837 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4838 }
4839 }
4840 }
4841
4842 /* Quality update */
4843 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
4844
4845 return 1;
4846}
4847
4848
4861static inline
4863 int64_t* list,int ret,double crit) {
4864 MMG5_pTetra pt0,pt1;
4865 double cal,critloc;
4866 int l,ipb,lon;
4867 MMG5_int jel,na;
4868
4869 lon = ret/2;
4870 critloc = 1.;
4871 for (l=0; l<lon; l++) {
4872 jel = list[l] / 6;
4873 pt1 = &mesh->tetra[jel];
4874 if(pt1->qual < critloc) critloc = pt1->qual;
4875 }
4876 critloc *= crit;
4877
4878 pt0 = &mesh->tetra[0];
4879 for (l=0; l<lon; l++) {
4880 jel = list[l] / 6;
4881 na = list[l] % 6;
4882 pt1 = &mesh->tetra[jel];
4883
4884 memcpy(pt0->v,pt1->v,4*sizeof(MMG5_int));
4885 ipb = MMG5_iare[na][0];
4886 pt0->v[ipb] = ip;
4887 cal = MMG5_caltet(mesh,met,pt0);
4888 if ( cal < critloc ) {
4889 MMG3D_delPt(mesh,ip);
4890 return 0;
4891 }
4892
4893 memcpy(pt0->v,pt1->v,4*sizeof(MMG5_int));
4894 ipb = MMG5_iare[na][1];
4895 pt0->v[ipb] = ip;
4896 cal = MMG5_caltet(mesh,met,pt0);
4897 if ( cal < critloc ) {
4898 MMG3D_delPt(mesh,ip);
4899 return 0;
4900 }
4901 }
4902 return 1;
4903}
4904
4916MMG5_int MMG5_splitedg(MMG5_pMesh mesh, MMG5_pSol met,MMG5_int iel, int iar, double crit){
4917 MMG5_pTetra pt;
4918 MMG5_pxTetra pxt;
4919 MMG5_pPoint p0,p1;
4920 double o[3];
4921 int warn,lon,ier;
4922 int64_t list[MMG3D_LMAX+2];
4923 MMG5_int src,i0,i1,ip;
4924 uint16_t tag;
4925
4926 warn = 0;
4927 pt = &mesh->tetra[iel];
4928
4929 int8_t isbdy;
4930 lon = MMG5_coquil(mesh,iel,iar,list,&isbdy);
4931 if ( (!lon || lon<0) )
4932 return 0;
4933
4934 /* Skip edges along an external boundary (test on open shell) */
4935 if(lon%2) return 0;
4936
4937 i0 = pt->v[MMG5_iare[iar][0]];
4938 i1 = pt->v[MMG5_iare[iar][1]];
4939 p0 = &mesh->point[i0];
4940 p1 = &mesh->point[i1];
4941
4942 tag = MG_NOTAG;
4943 if ( pt->xt ){
4944 pxt = &mesh->xtetra[pt->xt];
4945 if ( (pxt->ftag[MMG5_ifar[iar][0]] & MG_BDY) ||
4946 (pxt->ftag[MMG5_ifar[iar][1]] & MG_BDY) ) {
4947 tag = pxt->tag[iar];
4948 tag |= MG_BDY;
4949 }
4950 }
4951
4952 /* Do not split a required edge */
4953 if ( pt->tag & MG_REQ || tag & MG_REQ ) {
4954 return 0;
4955 }
4956
4957 /* Skip edge if it connects bdy point (edge can be internal or external) */
4958 if ( isbdy ) {
4959 return 0;
4960 }
4961
4962 o[0] = 0.5*(p0->c[0] + p1->c[0]);
4963 o[1] = 0.5*(p0->c[1] + p1->c[1]);
4964 o[2] = 0.5*(p0->c[2] + p1->c[2]);
4965
4966#ifdef USE_POINTMAP
4967 src = mesh->point[i0].src;
4968#else
4969 src = 1;
4970#endif
4971 ip = MMG3D_newPt(mesh,o,tag,src);
4972
4973 if ( !ip ) {
4974 assert ( mesh );
4975 /* reallocation of point table */
4977 warn=1;
4978 break
4979 ,o,tag,src);
4980 }
4981
4982 if ( warn ) {
4983 fprintf(stderr,"\n ## Warning: %s:",__func__);
4984 fprintf(stderr," unable to allocate a new point in last call"
4985 " of MMG5_adpspl.\n");
4987 }
4988
4989 ier = MMG5_intmet(mesh,met,iel,iar,ip,0.5);
4990 if ( !ier ) {
4991 MMG3D_delPt(mesh,ip);
4992 return 0;
4993 }
4994 else if (ier < 0 ) {
4995 MMG3D_delPt(mesh,ip);
4996 return 0;
4997 }
4998
4999 ier = MMG3D_simbulgept(mesh,met,list,lon,ip);
5000 assert ( (!mesh->info.ddebug) || (mesh->info.ddebug && ier != -1) );
5001 if ( ier <= 0 || ier == 2 ) return 0;
5002
5003 ier = MMG3D_chksplit(mesh,met,ip,&list[0],lon,crit);
5004 if(!ier) return 0;
5005 ier = MMG5_split1b(mesh,met,list,lon,ip,0,1,0);
5006 if ( ier < 0 ) {
5007 fprintf(stderr,"\n ## Error: %s: unable to split.\n",__func__);
5008 return -1;
5009 }
5010 else if ( !ier ) {
5011 MMG3D_delPt(mesh,ip);
5012 return 0;
5013 }
5014
5015 return ip;
5016}
int ier
MMG5_pMesh * mesh
int MMG3D_chk4ridVertices(MMG5_pMesh mesh, MMG5_pTetra pt)
Definition: anisosiz_3d.c:113
int MMG5_coquilface(MMG5_pMesh mesh, MMG5_int start, int8_t iface, int ia, int64_t *list, MMG5_int *it1, MMG5_int *it2, int silent)
Definition: boulep_3d.c:1846
int MMG5_coquil(MMG5_pMesh mesh, MMG5_int start, int ia, int64_t *list, int8_t *isbdy)
Definition: boulep_3d.c:1406
static double MMG5_caltet_iso(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pTetra pt)
static double MMG5_lenedg33_ani(MMG5_pMesh mesh, MMG5_pSol met, int ia, MMG5_pTetra pt)
static double MMG5_lenedgspl33_ani(MMG5_pMesh mesh, MMG5_pSol met, int ia, MMG5_pTetra pt)
static double MMG5_orcal(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int iel)
int MMG5_interp4bar33_ani(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int ip, double cb[4])
Definition: intmet_3d.c:522
API headers and documentation for the mmg3d library, for volumetric meshes in 3D.
#define MMG3D_LMAX
Definition: libmmg3d.h:130
MMG5_int MMG3D_newElt(MMG5_pMesh mesh)
Definition: zaldy_3d.c:99
static const uint8_t MMG5_isar[6][2]
isar[i][]: vertices of extremities of the edge opposite to the ith edge
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
static const int8_t MMG5_iarfinv[4][6]
num of the j^th edge in the i^th face
int MMG3D_delElt(MMG5_pMesh mesh, MMG5_int iel)
Definition: zaldy_3d.c:122
static const int8_t MMG5_iarf[4][3]
iarf[i]: edges of face opposite to vertex i
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
static const uint8_t MMG5_ifar[6][2]
ifar[i][]: faces sharing the ith edge 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
#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
#define MG_REQ
#define MMG5_EPSOK
#define MMG5_INCREASE_MEM_MESSAGE()
#define MG_MIN(a, b)
#define MG_MAX(a, b)
#define MMG5_GAP
#define MG_NOTAG
static const uint8_t MMG5_iprv2[3]
#define MMG5_TAB_RECALLOC(mesh, ptr, initSize, wantedGap, type, message, law)
#define MG_GEO_OR_NOM(tag)
static const uint8_t MMG5_inxt2[6]
int MMG5_devangle(double *n1, double *n2, double crit)
Definition: tools.c:103
int MMG5_nortri(MMG5_pMesh mesh, MMG5_pTria pt, double *n)
Definition: tools.c:209
double MMG5_orvol(MMG5_pPoint point, MMG5_int *v)
Definition: tools.c:951
#define MG_BDY
#define MG_SMSGN(a, b)
#define MG_SET(flag, bit)
void MMG3D_split4op_cfg(MMG5_int flag, MMG5_int v[4], uint8_t tau[4], const uint8_t **taued, uint8_t *imin01, uint8_t *imin23)
Definition: split_3d.c:3649
static int MMG3D_crea_newTetra(MMG5_pMesh mesh, const int ne, MMG5_int *newtet, MMG5_pTetra *pt, MMG5_xTetra *xt, MMG5_pxTetra *pxt0)
Definition: split_3d.c:1166
int MMG3D_split6_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:4414
MMG5_int MMG5_splitedg(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int iel, int iar, double crit)
Definition: split_3d.c:4916
int MMG3D_split3_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:1636
int MMG5_split2sf_globNum(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], MMG5_int vGlobNum[4], int8_t metRidTyp)
Definition: split_3d.c:1276
int MMG3D_split3cone_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:1921
int MMG5_split6(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:4483
int MMG5_split4op(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:3804
int MMG3D_simbulgept(MMG5_pMesh mesh, MMG5_pSol met, int64_t *list, int ret, MMG5_int ip)
Definition: split_3d.c:330
void MMG3D_split3cone_cfg(MMG5_int flag, MMG5_int v[4], uint8_t tau[4], const uint8_t **taued, uint8_t *ia, uint8_t *ib)
Definition: split_3d.c:1863
static int MMG3D_chksplit(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int ip, int64_t *list, int ret, double crit)
Definition: split_3d.c:4862
int MMG5_split1(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:134
static int MMG3D_normalDeviation(MMG5_pMesh mesh, MMG5_int start, int8_t iface, int8_t ia, MMG5_int idx, MMG5_int ip, double n0[3])
Definition: split_3d.c:272
int MMG3D_normalAdjaTri(MMG5_pMesh mesh, MMG5_int start, int8_t iface, int ia, double n[3])
Definition: split_3d.c:472
int MMG3D_split2sf_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:1103
int MMG3D_split4op_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:3685
static void MMG3D_split3op_cfg(MMG5_pTetra pt, MMG5_int vx[6], uint8_t tau[4], const uint8_t **taued, uint8_t sym[4], uint8_t symed[6], uint8_t *ip0, uint8_t *ip1, uint8_t *ip2, uint8_t *ip3, uint8_t *ie0, uint8_t *ie1, uint8_t *ie2, uint8_t *ie3, uint8_t *ie4, uint8_t *ie5, uint8_t *imin03, uint8_t *imin12)
Definition: split_3d.c:2365
int MMG5_split2(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:1489
int MMG5_split4op_globNum(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], MMG5_int vGlobNum[4], int8_t metRidTyp)
Definition: split_3d.c:3826
MMG5_int MMG5_split4bar(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t metRidTyp)
Definition: split_3d.c:3050
int MMG3D_split1_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:94
int MMG5_split1b(MMG5_pMesh mesh, MMG5_pSol met, int64_t *list, int ret, MMG5_int ip, int cas, int8_t metRidTyp, int8_t chkRidTet)
Definition: split_3d.c:629
static void MMG3D_split4sf_cfg(MMG5_pTetra pt, MMG5_int vx[6], uint8_t tau[4], const uint8_t **taued, uint8_t *imin23, uint8_t *imin12)
Definition: split_3d.c:3260
int MMG5_split2sf(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:1254
int8_t ddb
Definition: mmg3d1_delone.c:42
void MMG3D_split1_cfg(MMG5_int flag, uint8_t *tau, const uint8_t **taued)
Definition: split_3d.c:53
static void MMG3D_split5_cfg(MMG5_pTetra pt, MMG5_int vx[6], uint8_t tau[4], const uint8_t **taued, uint8_t *imin)
Definition: split_3d.c:4062
int MMG3D_split4sf_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:3337
static void MMG3D_update_qual(MMG5_pMesh mesh, MMG5_pSol met, const int ne, MMG5_int *newtet, MMG5_pTetra *pt, int8_t metRidTyp)
Definition: split_3d.c:1219
void MMG3D_split2sf_cfg(MMG5_int flag, MMG5_int v[4], uint8_t *tau, const uint8_t **taued, uint8_t *imin)
Definition: split_3d.c:1037
int MMG3D_split5_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:4111
int MMG5_split5(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:4203
int MMG5_split3op(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:2654
static int MMG5_split1b_eltspl(MMG5_pMesh mesh, MMG5_int ip, MMG5_int k, int64_t *list, MMG5_int *newtet, uint8_t tau[4])
Definition: split_3d.c:519
int MMG3D_split3op_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:2522
int MMG5_split3cone(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:2059
int MMG5_split3(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:1707
int MMG3D_split2_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:1427
int MMG5_split3cone_globNum(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], MMG5_int vGlobNum[4], int8_t metRidTyp)
Definition: split_3d.c:2081
int MMG5_split4sf(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:3440
int8_t ddebug
Definition: libmmgtypes.h:539
double dhd
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
Structure to store vertices of an MMG mesh.
Definition: libmmgtypes.h:276
double c[3]
Definition: libmmgtypes.h:277
uint16_t tag
Definition: libmmgtypes.h:290
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 flag
Definition: libmmgtypes.h:416
MMG5_int mark
Definition: libmmgtypes.h:412
uint16_t tag
Definition: libmmgtypes.h:417
double qual
Definition: libmmgtypes.h:408
Structure to store triangles of a MMG mesh.
Definition: libmmgtypes.h:338
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