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
52static inline
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
136int MMG5_split1(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
137 MMG5_pTetra pt,pt1;
138 MMG5_xTetra xt,xt1;
139 MMG5_pxTetra pxt0;
140 MMG5_int iel;
141 int8_t i,isxt,isxt1;
142 uint8_t tau[4];
143 const uint8_t *taued;
144
145 /* create a new tetra */
146 pt = &mesh->tetra[k];
147 iel = MMG3D_newElt(mesh);
148 if ( !iel ) {
150 fprintf(stderr,"\n ## Error: %s: unable to allocate"
151 " a new element.\n",__func__);
153 fprintf(stderr," Exit program.\n");
154 return 0);
155 pt = &mesh->tetra[k];
156 }
157
158 pt1 = &mesh->tetra[iel];
159 pt1 = memcpy(pt1,pt,sizeof(MMG5_Tetra));
160 pxt0 = NULL;
161 if ( pt->xt ) {
162 pxt0 = &mesh->xtetra[pt->xt];
163 memcpy(&xt,pxt0,sizeof(MMG5_xTetra));
164 memcpy(&xt1,pxt0,sizeof(MMG5_xTetra));
165 }
166 else {
167 memset(&xt,0,sizeof(MMG5_xTetra));
168 memset(&xt1,0,sizeof(MMG5_xTetra));
169 }
170
171 MMG3D_split1_cfg(pt->flag,tau,&taued);
172
173 /* Generic formulation of split of 1 edge */
174 pt->v[tau[1]] = pt1->v[tau[0]] = vx[taued[0]];
175
176 if ( pt->xt ) {
177 /* Reset edge tag */
178 xt.tag [taued[3]] = 0; xt.tag [taued[4]] = 0;
179 xt1.tag[taued[1]] = 0; xt1.tag[taued[2]] = 0;
180 xt.edg [taued[3]] = 0; xt.edg [taued[4]] = 0;
181 xt1.edg[taued[1]] = 0; xt1.edg[taued[2]] = 0;
182 xt.ref [ tau[0]] = 0; xt.ftag [ tau[0]] = 0; MG_SET( xt.ori, tau[0]);
183 xt1.ref[ tau[1]] = 0; xt1.ftag[ tau[1]] = 0; MG_SET(xt1.ori, tau[1]);
184 }
185
186 pt->flag = pt1->flag = 0;
187 isxt = 0 ;
188 isxt1 = 0;
189 for (i=0; i<4; i++) {
190 if ( xt.ref[i] || xt.ftag[i] ) isxt = 1;
191 if ( xt1.ref[i] || xt1.ftag[i] ) isxt1 = 1;
192 if ( isxt && isxt1 ) goto nextstep1;
193 }
194
195nextstep1:
196 if ( pt->xt ) {
197 if ( isxt && !isxt1 ) {
198 pt1->xt = 0;
199 memcpy(pxt0,&xt,sizeof(MMG5_xTetra));
200 }
201 else if ( !isxt && isxt1 ) {
202 pt1->xt = pt->xt;
203 pt->xt = 0;
204 pxt0 = &mesh->xtetra[pt1->xt];
205 memcpy(pxt0,&xt1,sizeof(MMG5_xTetra));
206 }
207 else if ( isxt && isxt1 ) {
208 mesh->xt++;
209 if ( mesh->xt > mesh->xtmax ) {
210 /* realloc of xtetras table */
212 "larger xtetra table",
213 mesh->xt--;
214 fprintf(stderr," Exit program.\n");
215 return 0);
216 pxt0 = &mesh->xtetra[pt->xt];
217 }
218 pt1->xt = mesh->xt;
219
220 assert ( pxt0 );
221 memcpy(pxt0,&xt,sizeof(MMG5_xTetra));
222 pxt0 = &mesh->xtetra[mesh->xt];
223 assert ( pxt0 );
224 memcpy(pxt0,&xt1,sizeof(MMG5_xTetra));
225 }
226 else {
227 pt->xt = 0;
228 pt1->xt = 0;
229 }
230 }
231 /* Quality update */
232 if ( (!metRidTyp) && met->m && met->size>1 ) {
233 pt->qual=MMG5_caltet33_ani(mesh,met,pt);
234 pt1->qual=MMG5_caltet33_ani(mesh,met,pt1);
235 }
236 else if ( (!met) || (!met->m) ) {
237 /* in ls mode + -A option, orcal calls caltet_ani that fails */
238 pt->qual=MMG5_caltet_iso(mesh,met,pt);
239 pt1->qual=MMG5_caltet_iso(mesh,met,pt1);
240 }
241 else {
242 pt->qual=MMG5_orcal(mesh,met,k);
243 pt1->qual=MMG5_orcal(mesh,met,iel);
244 }
245 return 1;
246}
266static inline
267int MMG3D_normalDeviation(MMG5_pMesh mesh , MMG5_int start, int8_t iface, int8_t ia,
268 MMG5_int idx , MMG5_int ip , double n0[3])
269{
270 MMG5_Tria tt0;
271 double n1[3];
272 int iedge,iploc,ier;
273
276 assert(iface >=0 && iface < 4 && "local face idx");
277
278 MMG5_tet2tri(mesh,start,iface,&tt0);
279
280 iedge = MMG5_iarfinv[iface][ia];
281
282 switch (idx)
283 {
284 case 0:
285 iploc = MMG5_iprv2[iedge];
286 break;
287 case 1:
288 iploc = MMG5_inxt2[iedge];
289 break;
290 }
291
292 tt0.v[iploc] = ip;
293
295 if ( !MMG5_nortri(mesh, &tt0, n0) ) return -1;
296
297 if ( MG_GEO_OR_NOM(tt0.tag[iploc]) ) return 1;
298
301 ier = MMG3D_normalAdjaTri(mesh,start,iface,iploc,n1);
302 if ( ier<0 ) return -1;
303 else if ( !ier ) return 0;
304
305 ier = MMG5_devangle( n0, n1, mesh->info.dhd );
306
307 return ier;
308}
324int MMG3D_simbulgept(MMG5_pMesh mesh,MMG5_pSol met,int64_t *list,int ret,MMG5_int ip) {
325 MMG5_pTetra pt,pt0;
326 MMG5_pxTetra pxt;
327 MMG5_pPoint ppt0;
328 double calold,calnew,caltmp;
329 double n0[6],n1[6];
330 int j,k,ilist,idx,iface,ier;
331 MMG5_int iel,sum1,sum2,mins1,mins2,maxs1,maxs2;
332 MMG5_int is0,is1,is2;
333 int8_t ie,ia,ib,complete,wrongOri;
334
335 ilist = ret / 2;
336 pt0 = &mesh->tetra[0];
337 ppt0 = &mesh->point[0];
338 memcpy(ppt0->c ,&mesh->point[ip].c , 3*sizeof(double));
339 ppt0->tag = mesh->point[ip].tag;
340
341 memcpy(&met->m[0],&met->m[met->size*ip], met->size*sizeof(double));
342
343 calold = calnew = DBL_MAX;
344 for (k=0; k<ilist; k++) {
345 iel = list[k] / 6;
346 ie = list[k] % 6;
347 ia = MMG5_iare[ie][0];
348 ib = MMG5_iare[ie][1];
349
350 pt = &mesh->tetra[iel];
351 memcpy(pt0,pt,sizeof(MMG5_Tetra));
352 pt0->v[ia] = 0;
353 calold = MG_MIN(calold,pt->qual);
354 caltmp = MMG5_orcal(mesh,met,0);
355 if ( caltmp < MMG5_EPSOK ) return 0;
356 calnew = MG_MIN(calnew,caltmp);
357
358 memcpy(pt0,pt,sizeof(MMG5_Tetra));
359 pt0->v[ib] = 0;
360 caltmp = MMG5_orcal(mesh,met,0);
361 if ( caltmp < MMG5_EPSOK ) return 0;
362 calnew = MG_MIN(calnew,caltmp);
363 }
364 if ( calnew <= MMG5_EPSOK ) {
365 return 0;
366 }
367
368 /* if ( calnew < 0.3*calold ) return 0;*/
369
371 /* analyze surfacic ball of p */
372 wrongOri = complete = idx = 0;
373 maxs1 = mins1 = sum1 = 0;
374 for (k=0; k<ilist; k++) {
375 iel = list[k] / 6;
376 ie = list[k] % 6;
377
378 pt = &mesh->tetra[iel];
379 if(!pt->xt) continue;
380
381 pxt = &mesh->xtetra[pt->xt];
382
383 for ( j=0; j<2; ++j ) {
384 iface = MMG5_ifar[ie][j];
385 if ( !(pxt->ftag[iface] & MG_BDY) ) continue;
386
387 is0 = pt->v[MMG5_idir[iface][0]];
388 is1 = pt->v[MMG5_idir[iface][1]];
389 is2 = pt->v[MMG5_idir[iface][2]];
390
391 /* Normal deviation between the two new triangles and their neighbors */
392 ier = MMG3D_normalDeviation(mesh,iel,iface,ie,0,ip,&n0[idx]);
393 if ( ier < 0 ) return -1;
394 else if ( ier == 0 ) return 2;
395
396 ier = MMG3D_normalDeviation(mesh,iel,iface,ie,1,ip,&n1[idx]);
397 if ( ier < 0 ) return -1;
398 else if ( ier == 0 ) return 2;
399
400 /* Test sharp angle creation along the new edge */
401 if ( !MMG5_devangle(&n0[idx],&n1[idx],mesh->info.dhd) ) {
402 return 2;
403 }
404
405 if ( !idx ) {
406 sum1 = is0 + is1 + is2;
407 mins1 = MG_MIN(is0, MG_MIN(is1,is2));
408 maxs1 = MG_MAX(is0, MG_MAX(is1,is2));
409 idx = 3;
410 }
411 else {
412 /* don't check if it is a ridge edge or if we have already cross 2
413 * boundaries */
414 if ( complete || MG_GEO_OR_NOM(pxt->tag[ie]) )
415 continue;
416
417 /* We are manifold thus we have exactly two faces in our shell: check
418 * that we don't see twice a boundary face (multidomain case) */
419 sum2 = is0 + is1 + is2;
420 mins2 = MG_MIN(is0, MG_MIN(is1,is2));
421 maxs2 = MG_MAX(is0, MG_MAX(is1,is2));
422
423 if ( (sum2 == sum1 && mins2 == mins1 && maxs2 == maxs1) ) {
424 /* Multidomain: we see the tria for the second time (and from another
425 * side), this means that the next seen tria will be seen from the
426 * wrong side. */
427 wrongOri = 1;
428 continue;
429 }
430 else if ( wrongOri ) {
431 /* We skeep this tria because it is seen from a wrong side. The next
432 * will be ok */
433 wrongOri = 0;
434 continue;
435 }
436 complete = 1;
437
438 /* Test sharp angle creation along the splitted edge */
439 if ( !MMG5_devangle(&n0[0],&n1[idx],mesh->info.dhd) ) {
440 return 2;
441 }
442 if ( !MMG5_devangle(&n1[0],&n0[idx],mesh->info.dhd) ) {
443 return 2;
444 }
445 }
446 }
447 }
448
449 return 1;
450}
451
466int MMG3D_normalAdjaTri(MMG5_pMesh mesh , MMG5_int start, int8_t iface, int ia,
467 double n[3] )
468{
469 MMG5_Tria tt;
470 int iedgeOpp;
471 int64_t list[MMG3D_LMAX+2];
472 MMG5_int it1,it2,it;
473
474 iedgeOpp = MMG5_iarf[iface][ia];
475
478 if ( MMG5_coquilface( mesh,start,iface,iedgeOpp,list,&it1,&it2,0) <= 0 )
479 return -1;
480
481 if ( it1/4 != start || it1%4 != iface ) {
482 //assert ( it2/4==start && it2%4==iface );
483 if ( it2/4!=start || it2%4!=iface ) return 0;
484
485 it = it1;
486 }
487 else {
488 it = it2;
489 }
490 assert ( it/4>0 && 0<=it%4 && it%4<4 && "unexpected idx for tetra or local face idx" );
491 MMG5_tet2tri(mesh,it/4,it%4,&tt);
492
494 if ( !MMG5_nortri(mesh, &tt, n) ) return 0;
495
496 return 1;
497}
498
512static inline
513int MMG5_split1b_eltspl(MMG5_pMesh mesh,MMG5_int ip,MMG5_int k,int64_t *list,MMG5_int *newtet,uint8_t tau[4]) {
514 MMG5_pTetra pt,pt1;
515 MMG5_xTetra xt,xt1;
516 MMG5_pxTetra pxt0;
517 MMG5_int iel;
518 MMG5_int jel;
519 int8_t ie,isxt,isxt1,i;
520 const uint8_t *taued;
521
522 iel = list[k] / 6;
523 ie = list[k] % 6;
524 pt = &mesh->tetra[iel];
525 jel = MMG5_abs(newtet[k]);
526 pt1 = &mesh->tetra[jel];
527
528 pxt0 = 0;
529 if ( pt->xt ) {
530 pxt0 = &mesh->xtetra[pt->xt];
531 memcpy(&xt,pxt0,sizeof(MMG5_xTetra));
532 memcpy(&xt1,pxt0,sizeof(MMG5_xTetra));
533 }
534 else {
535 memset(&xt,0, sizeof(MMG5_xTetra));
536 memset(&xt1,0, sizeof(MMG5_xTetra));
537 }
538
539 MMG5_int flag = 0;
540 MG_SET(flag,ie);
541 MMG3D_split1_cfg(flag,tau,&taued);
542
543 /* Generic formulation of split of 1 edge */
544 pt->v[tau[1]] = pt1->v[tau[0]] = ip;
545 if ( pt->xt ) {
546 /* Reset edge tag */
547 xt.tag [taued[3]] = 0; xt.tag [taued[4]] = 0;
548 xt1.tag[taued[1]] = 0; xt1.tag[taued[2]] = 0;
549 xt.edg [taued[3]] = 0; xt.edg [taued[4]] = 0;
550 xt1.edg[taued[1]] = 0; xt1.edg[taued[2]] = 0;
551 xt.ref [ tau[0]] = 0; xt.ftag [ tau[0]] = 0; MG_SET( xt.ori, tau[0]);
552 xt1.ref[ tau[1]] = 0; xt1.ftag[ tau[1]] = 0; MG_SET(xt1.ori, tau[1]);
553 }
554
555 pt->flag = pt1->flag = 0;
556
557 isxt = 0 ;
558 isxt1 = 0;
559
560 for (i=0; i<4; i++) {
561 if ( xt.ref[i] || xt.ftag[i] ) isxt = 1;
562 if ( xt1.ref[i] || xt1.ftag[i] ) isxt1 = 1;
563 }
564
565 if ( pt->xt ) {
566 if ( (isxt)&&(!isxt1) ) {
567 pt1->xt = 0;
568 pxt0 = &mesh->xtetra[pt->xt];
569 memcpy(pxt0,&xt,sizeof(MMG5_xTetra));
570 }
571 else if ((!isxt)&&(isxt1) ) {
572 pt1->xt = pt->xt;
573 pt->xt = 0;
574 pxt0 = &mesh->xtetra[pt1->xt];
575 memcpy(pxt0,&xt1,sizeof(MMG5_xTetra));
576 }
577 else if (isxt && isxt1 ) {
578 mesh->xt++;
579 if ( mesh->xt > mesh->xtmax ) {
580 /* realloc of xtetras table */
582 "larger xtetra table",
583 mesh->xt--;
584 return 0);
585 }
586 pt1->xt = mesh->xt;
587 pxt0 = &mesh->xtetra[pt->xt];
588 memcpy(pxt0,&xt,sizeof(MMG5_xTetra));
589 pxt0 = &mesh->xtetra[pt1->xt];
590 memcpy(pxt0,&xt1,sizeof(MMG5_xTetra));
591 }
592 else {
593 pt->xt = 0;
594 pt1->xt = 0;
595 }
596 }
597 return 1;
598}
599
617int MMG5_split1b(MMG5_pMesh mesh, MMG5_pSol met,int64_t *list, int ret, MMG5_int ip,
618 int cas,int8_t metRidTyp,int8_t chkRidTet){
619 MMG5_pTetra pt,pt1,pt0;
620 double lmin,lmax,len;
621 int ilist,k,open,j;
622 MMG5_int iel,jel,newtet[MMG3D_LMAX+2],nump,*adja;
623 MMG5_int *adjan,nei2,nei3,mel;
624 int8_t ie,i,voy;
625 uint8_t tau[4];
626 const uint8_t *taued;
627
628 ilist = ret / 2;
629 open = ret % 2;
630
631
632 if ( cas && met->m ) {
633 lmin = 0.6;
634 lmax = 1.3;
635 for (j=0; j<ilist; j++) {
636 for (i=0; i<6; i++) {
637 pt = &mesh->tetra[list[j]/6];
638 if ( (!metRidTyp) && met->m && met->size>1 )
639 len = MMG5_lenedg33_ani(mesh,met,i,pt);
640 else
641 len = MMG5_lenedg(mesh,met,i,pt);
642 if ( len < lmin) {
643 lmin = len;
644 }
645 else if ( len > lmax) {
646 lmax = len;
647 }
648 }
649 }
650 assert( lmin!=0 );
651
657 for (j=0; j<ilist; j++) {
658 iel = list[j] / 6;
659 pt = &mesh->tetra[iel];
660 ie = list[j] % 6;
661 pt0 = &mesh->tetra[0];
662 memcpy(pt0,pt,sizeof(MMG5_Tetra));
663
664 MMG5_int flag = 0;
665 MG_SET(flag,ie);
666 MMG3D_split1_cfg(flag,tau,&taued);
667
668 pt0->v[MMG5_isar[ie][1]] = ip;
669 if ( chkRidTet ) {
670 if ( !MMG3D_chk4ridVertices(mesh,pt0) ) {
671 break;
672 }
673 }
674 if ( (!metRidTyp) && met->m && met->size>1 )
675 len = MMG5_lenedgspl33_ani(mesh,met,taued[5],pt0);
676 else
677 len = MMG5_lenedgspl(mesh,met,taued[5],pt0);
678 if ( len < lmin ) break;
679 memcpy(pt0,pt,sizeof(MMG5_Tetra));
680
681 pt0->v[MMG5_isar[ie][0]] = ip;
682 if ( chkRidTet ) {
683 if ( !MMG3D_chk4ridVertices(mesh,pt0) ) {
684 break;
685 }
686 }
687
688 if ( (!metRidTyp) && met->m && met->size>1 )
689 len = MMG5_lenedgspl33_ani(mesh,met,taued[5],pt0);
690 else
691 len = MMG5_lenedgspl(mesh,met,taued[5],pt0);
692 if ( len < lmin ) break;
693 }
694 if ( j < ilist ) return 0;
695 }
696
697 iel = list[0] / 6;
698 ie = list[0] % 6;
699 pt = &mesh->tetra[iel];
700
701 nump = pt->v[MMG5_iare[ie][0]];
702
703 /* Fill list newtet[k] = +_created tetra for list[k]/6 : + if kept tetra (= one associated to
704 pt->v[tau[0]]) is associated with nump, - if with numq */
705 for (k=0; k<ilist; k++) {
706 iel = list[k] / 6;
707 ie = list[k] % 6;
708 pt = &mesh->tetra[iel];
709
710 MMG5_int flag = 0;
711 MG_SET(flag,ie);
712 MMG3D_split1_cfg(flag,tau,&taued);
713
714 jel = MMG3D_newElt(mesh);
715 if ( !jel ) {
717 fprintf(stderr,"\n ## Error: %s: unable to allocate"
718 " a new element.\n",__func__);
720 k--;
721 for ( ; k>=0 ; --k ) {
722 if ( !MMG3D_delElt(mesh,MMG5_abs(newtet[k])) ) return -1;
723 }
724 return -1);
725 pt = &mesh->tetra[iel];
726 }
727 pt1 = &mesh->tetra[jel];
728 memcpy(pt1,pt,sizeof(MMG5_Tetra));
729
730 if ( pt->v[tau[0]] == nump )
731 newtet[k] = jel;
732 else
733 newtet[k] = -jel;
734 }
735
736 /* Special case : only one element in the shell */
737 if ( ilist == 1 ) {
738 assert(open);
739
740 if ( !MMG5_split1b_eltspl(mesh,ip,0,list,newtet,tau) ) {
741 return -1;
742 }
743
744 /* Update of adjacency relations */
745 iel = list[0] / 6;
746 pt = &mesh->tetra[iel];
747 jel = MMG5_abs(newtet[0]);
748 pt1 = &mesh->tetra[jel];
749
750 adja = &mesh->adja[4*(iel-1)+1];
751 adjan = &mesh->adja[4*(jel-1)+1];
752
753 adja[tau[2]] = 0;
754 adja[tau[3]] = 0;
755 adjan[tau[2]] = 0;
756 adjan[tau[3]] = 0;
757
758 mel = adja[tau[0]] / 4;
759 voy = adja[tau[0]] % 4;
760 adja[tau[0]] = 4*jel + tau[1];
761 adjan[tau[0]] = 4*mel + voy;
762 adjan[tau[1]] = 4*iel + tau[0];
763
764 if ( mel ) {
765 adjan = &mesh->adja[4*(mel -1) +1];
766 adjan[voy] = 4*jel + tau[0];
767 }
768 /* Quality update */
769 if ( (!metRidTyp) && met->m && met->size>1 ) {
770 pt->qual=MMG5_caltet33_ani(mesh,met,pt);
771 pt1->qual=MMG5_caltet33_ani(mesh,met,pt1);
772 }
773 else {
774 pt->qual=MMG5_orcal(mesh,met,iel);
775 pt1->qual=MMG5_orcal(mesh,met,jel);
776 }
777 pt->mark = mesh->mark;
778 pt1->mark = mesh->mark;
779
780 return 1;
781 }
782
783 /* General case : update each element of the shell */
784 for (k=0; k<ilist; k++) {
785 if ( !MMG5_split1b_eltspl(mesh,ip,k,list,newtet,tau) ) {
786 return -1;
787 }
788
789 /* Update of adjacency relations */
790 iel = list[k] / 6;
791 ie = list[k] % 6;
792 pt = &mesh->tetra[iel];
793 jel = MMG5_abs(newtet[k]);
794 pt1 = &mesh->tetra[jel];
795
796 adja = &mesh->adja[4*(iel-1)+1];
797 adjan = &mesh->adja[4*(jel-1)+1];
798
799 nei2 = adja[tau[2]];
800 nei3 = adja[tau[3]];
801
802 /* Adjacency relations through both splitted faces */
803 if ( k == 0 ) {
804 if ( (list[1] / 6) == (nei2 / 4) ) {
805 if ( MG_SMSGN(newtet[0],newtet[1]) ) { //new elt of list[0] goes with new elt of list[1]
806 adja[tau[2]] = nei2;
807 adjan[tau[2]] = 4*MMG5_abs(newtet[1])+(nei2 %4);
808 }
809 else {
810 adja[tau[2]] = 4*MMG5_abs(newtet[1])+(nei2 %4);
811 adjan[tau[2]] = nei2;
812 }
813
814 if ( open ) {
815 adja[tau[3]] = 0;
816 adjan[tau[3]] = 0;
817 }
818
819 else {
820 assert((list[ilist-1] / 6) == (nei3 / 4));
821 if ( MG_SMSGN(newtet[0],newtet[ilist-1]) ) {
822 adja[tau[3]] = nei3;
823 adjan[tau[3]] = 4*MMG5_abs(newtet[ilist-1])+(nei3 %4);
824 }
825 else {
826 adja[tau[3]] = 4*MMG5_abs(newtet[ilist-1])+(nei3 %4);
827 adjan[tau[3]] = nei3;
828 }
829 }
830 }
831
832 else {
833 assert((list[1] / 6) == (nei3 / 4));
834 if ( MG_SMSGN(newtet[0],newtet[1]) ) {
835 adja[tau[3]] = nei3;
836 adjan[tau[3]] = 4*MMG5_abs(newtet[1])+(nei3 %4);
837 }
838 else {
839 adja[tau[3]] = 4*MMG5_abs(newtet[1])+(nei3 %4);
840 adjan[tau[3]] = nei3;
841 }
842
843 if ( open ) {
844 adja[tau[2]] = 0;
845 adjan[tau[2]] = 0;
846 }
847
848 else {
849 assert((list[ilist-1]) / 6 == (nei2 / 4));
850 if ( MG_SMSGN(newtet[0],newtet[ilist-1]) ) {
851 adja[tau[2]] = nei2;
852 adjan[tau[2]] = 4*MMG5_abs(newtet[ilist-1])+(nei2 %4);
853 }
854 else {
855 adja[tau[2]] = 4*MMG5_abs(newtet[ilist-1])+(nei2 %4);
856 adjan[tau[2]] = nei2;
857 }
858 }
859 }
860 }
861
862 else if ( k==ilist-1 ) {
863 if ( (list[ilist-2] / 6) == (nei2 / 4) ) {
864 if ( MG_SMSGN(newtet[ilist-1],newtet[ilist-2]) ) {
865 adja[tau[2]] = nei2;
866 adjan[tau[2]] = 4*MMG5_abs(newtet[ilist-2])+(nei2 %4);
867 }
868 else {
869 adja[tau[2]] = 4*MMG5_abs(newtet[ilist-2])+(nei2 %4);
870 adjan[tau[2]] = nei2;
871 }
872
873 if ( open ) {
874 adja[tau[3]] = 0;
875 adjan[tau[3]] = 0;
876 }
877
878 else {
879 assert((list[0]) / 6 == (nei3 / 4));
880 if ( MG_SMSGN(newtet[ilist-1],newtet[0]) ) {
881 adja[tau[3]] = nei3;
882 adjan[tau[3]] = 4*MMG5_abs(newtet[0])+(nei3 %4);
883 }
884 else {
885 adja[tau[3]] = 4*MMG5_abs(newtet[0])+(nei3 %4);
886 adjan[tau[3]] = nei3;
887 }
888 }
889 }
890
891 else {
892 assert((list[ilist-2] / 6) == (nei3 / 4));
893 if ( MG_SMSGN(newtet[ilist-1],newtet[ilist-2]) ) {
894 adja[tau[3]] = nei3;
895 adjan[tau[3]] = 4*MMG5_abs(newtet[ilist-2])+(nei3 %4);
896 }
897 else {
898 adja[tau[3]] = 4*MMG5_abs(newtet[ilist-2])+(nei3 %4);
899 adjan[tau[3]] = nei3;
900 }
901
902 if ( open ) {
903 adja[tau[2]] = 0;
904 adjan[tau[2]] = 0;
905 }
906
907 else {
908 assert((list[0]) / 6 == (nei2 / 4));
909 if ( MG_SMSGN(newtet[ilist-1],newtet[0]) ) {
910 adja[tau[2]] = nei2;
911 adjan[tau[2]] = 4*MMG5_abs(newtet[0])+(nei2 %4);
912 }
913 else {
914 adja[tau[2]] = 4*MMG5_abs(newtet[0])+(nei2 %4);
915 adjan[tau[2]] = nei2;
916 }
917 }
918 }
919 }
920
921 else {
922 if ( (list[k-1] / 6) == (nei2 / 4) ) {
923 if ( MG_SMSGN(newtet[k],newtet[k-1]) ) {
924 adja[tau[2]] = nei2;
925 adjan[tau[2]] = 4*MMG5_abs(newtet[k-1])+(nei2 %4);
926 }
927 else {
928 adja[tau[2]] = 4*MMG5_abs(newtet[k-1])+(nei2 %4);
929 adjan[tau[2]] = nei2;
930 }
931
932 assert((list[k+1]) / 6 == (nei3 / 4));
933 if ( MG_SMSGN(newtet[k],newtet[k+1]) ) {
934 adja[tau[3]] = nei3;
935 adjan[tau[3]] = 4*MMG5_abs(newtet[k+1])+(nei3 %4);
936 }
937 else {
938 adja[tau[3]] = 4*MMG5_abs(newtet[k+1])+(nei3 %4);
939 adjan[tau[3]] = nei3;
940 }
941 }
942
943 else {
944 assert((list[k-1] / 6) == (nei3 / 4));
945 if ( MG_SMSGN(newtet[k],newtet[k-1]) ) {
946 adja[tau[3]] = nei3;
947 adjan[tau[3]] = 4*MMG5_abs(newtet[k-1])+(nei3 %4);
948 }
949 else {
950 adja[tau[3]] = 4*MMG5_abs(newtet[k-1])+(nei3 %4);
951 adjan[tau[3]] = nei3;
952 }
953
954 assert((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 }
965
966 /* Internal adjacency relations update */
967 mel = adja[tau[0]] / 4;
968 voy = adja[tau[0]] % 4;
969 adja[tau[0]] = 4*jel + tau[1];
970 adjan[tau[0]] = 4*mel + voy;
971 adjan[tau[1]] = 4*iel + tau[0];
972
973 if ( mel ) {
974 adjan = &mesh->adja[4*(mel -1) +1];
975 adjan[voy] = 4*jel + tau[0];
976 }
977 /* Quality update */
978 if ( (!metRidTyp) && met->m && met->size>1 ) {
979 pt->qual=MMG5_caltet33_ani(mesh,met,pt);
980 pt1->qual=MMG5_caltet33_ani(mesh,met,pt1);
981 }
982 else {
983 pt->qual=MMG5_orcal(mesh,met,iel);
984 pt1->qual=MMG5_orcal(mesh,met,jel);
985 }
986 pt->mark = mesh->mark;
987 pt1->mark = mesh->mark;
988 }
989
990 return 1;
991}
992
1004static inline
1005uint8_t MMG3D_split2sf_cfg(MMG5_int flag,uint8_t *tau,const uint8_t **taued,MMG5_pTetra pt) {
1006 uint8_t imin;
1007
1008 /* identity is case 48 */
1009 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
1010 *taued = &MMG5_permedge[0][0];
1011 switch(flag){
1012 case 24 :
1013 tau[0] = 0 ; tau[1] = 2 ; tau[2] = 3 ; tau[3] = 1;
1014 *taued = &MMG5_permedge[1][0];
1015 break;
1016 case 40 :
1017 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
1018 *taued = &MMG5_permedge[2][0];
1019 break;
1020 case 6 :
1021 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
1022 *taued = &MMG5_permedge[5][0];
1023 break;
1024 case 34 :
1025 tau[0] = 1 ; tau[1] = 0 ; tau[2] = 3 ; tau[3] = 2;
1026 *taued = &MMG5_permedge[3][0];
1027 break;
1028 case 36 :
1029 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
1030 *taued = &MMG5_permedge[4][0];
1031 break;
1032 case 20 :
1033 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
1034 *taued = &MMG5_permedge[6][0];
1035 break;
1036 case 5 :
1037 tau[0] = 2 ; tau[1] = 1 ; tau[2] = 3 ; tau[3] = 0;
1038 *taued = &MMG5_permedge[7][0];
1039 break;
1040 case 17 :
1041 tau[0] = 2 ; tau[1] = 3 ; tau[2] = 0 ; tau[3] = 1;
1042 *taued = &MMG5_permedge[8][0];
1043 break;
1044 case 9 :
1045 tau[0] = 3 ; tau[1] = 0 ; tau[2] = 2 ; tau[3] = 1;
1046 *taued = &MMG5_permedge[9][0];
1047 break;
1048 case 3 :
1049 tau[0] = 3 ; tau[1] = 2 ; tau[2] = 1 ; tau[3] = 0;
1050 *taued = &MMG5_permedge[11][0];
1051 break;
1052 case 10 :
1053 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
1054 *taued = &MMG5_permedge[10][0];
1055 break;
1056 }
1057
1058 imin = (pt->v[tau[1]] < pt->v[tau[2]]) ? tau[1] : tau[2] ;
1059
1060 return imin;
1061}
1062
1063
1075int MMG3D_split2sf_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]){
1076 MMG5_pTetra pt,pt0;
1077 double vold,vnew;
1078 uint8_t tau[4],imin;
1079 const uint8_t *taued;
1080
1081 pt = &mesh->tetra[k];
1082 pt0 = &mesh->tetra[0];
1083 vold = MMG5_orvol(mesh->point,pt->v);
1084
1085 if ( vold < MMG5_EPSOK ) return 0;
1086
1087 imin = MMG3D_split2sf_cfg(pt->flag,tau,&taued,pt);
1088
1089 /* Test orientation of the three tets to be created */
1090
1091 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1092 pt0->v[tau[1]] = vx[taued[4]];
1093 pt0->v[tau[2]] = vx[taued[5]];
1094 vnew = MMG5_orvol(mesh->point,pt0->v);
1095 if ( vnew < MMG5_EPSOK ) return 0;
1096
1097 if ( imin == tau[1] ) {
1098 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1099 pt0->v[tau[2]] = vx[taued[5]];
1100 pt0->v[tau[3]] = vx[taued[4]];
1101 vnew = MMG5_orvol(mesh->point,pt0->v);
1102 if ( vnew < MMG5_EPSOK ) return 0;
1103
1104 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1105 pt0->v[tau[3]] = vx[taued[5]];
1106 vnew = MMG5_orvol(mesh->point,pt0->v);
1107 if ( vnew < MMG5_EPSOK ) return 0;
1108 }
1109 else {
1110 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1111 pt0->v[tau[3]] = vx[taued[4]];
1112 vnew = MMG5_orvol(mesh->point,pt0->v);
1113 if ( vnew < MMG5_EPSOK ) return 0;
1114
1115 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1116 pt0->v[tau[1]] = vx[taued[4]];
1117 pt0->v[tau[3]] = vx[taued[5]];
1118 vnew = MMG5_orvol(mesh->point,pt0->v);
1119 if ( vnew < MMG5_EPSOK ) return 0;
1120 }
1121 return 1;
1122}
1123
1137static inline
1138int MMG3D_crea_newTetra(MMG5_pMesh mesh,const int ne,MMG5_int *newtet,
1139 MMG5_pTetra *pt,MMG5_xTetra *xt,MMG5_pxTetra *pxt0) {
1140 MMG5_int iel;
1141 int i,j;
1142
1143 /* The first tetra is the one that is splitted so it already exists */
1144 for ( i=1; i<ne; ++i ) {
1145 iel = MMG3D_newElt(mesh);
1146 if ( !iel ) {
1148 fprintf(stderr,"\n ## Error: %s: unable to allocate"
1149 " a new element.\n",__func__);
1151 fprintf(stderr," Exit program.\n");
1152 return 0);
1153 /* update pointer list */
1154 for ( j=0; j<i; ++j ) {
1155 pt[j] = &mesh->tetra[newtet[j]];
1156 }
1157 }
1158 pt[i] = &mesh->tetra[iel];
1159 memcpy(pt[i],pt[0],sizeof(MMG5_Tetra));
1160 newtet[i]=iel;
1161 }
1162
1163 /* If need copy the initial xtetra */
1164 if ( pt[0]->xt ) {
1165 *pxt0 = &mesh->xtetra[(pt[0])->xt];
1166 for ( i=0; i<ne; ++i ) {
1167 memcpy(&xt[i],*pxt0,sizeof(MMG5_xTetra));
1168 }
1169 }
1170 else {
1171 *pxt0 = 0;
1172 memset(xt,0x0,ne*sizeof(MMG5_xTetra));
1173 }
1174 return 1;
1175}
1176
1190static inline
1192 MMG5_int *newtet,MMG5_pTetra *pt,int8_t metRidTyp) {
1193 int i;
1194
1195 if ( (!metRidTyp) && met->m && met->size>1 ) {
1196 for (i=0; i<ne; i++) {
1197 pt[i]->qual=MMG5_caltet33_ani(mesh,met,pt[i]);
1198 }
1199 }
1200 else if ( (!met) || (!met->m) ) {
1201 /* in ls mode + -A option, orcal calls caltet_ani that fails */
1202 for (i=0; i<ne; i++) {
1203 pt[i]->qual=MMG5_caltet_iso(mesh,met,pt[i]);
1204 }
1205 }
1206 else
1207 {
1208 for (i=0; i<ne; i++) {
1209 pt[i]->qual=MMG5_orcal(mesh,met,newtet[i]);
1210 }
1211 }
1212
1213 return;
1214}
1215
1228int MMG5_split2sf(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp){
1229 MMG5_pTetra pt[3];
1230 MMG5_xTetra xt[3];
1231 MMG5_pxTetra pxt0;
1232 int i,flg;
1233 MMG5_int newtet[3];
1234 int8_t imin,firstxt,isxt[3];
1235 uint8_t tau[4];
1236 const uint8_t *taued;
1237 const int ne=3;
1238
1239 pt[0] = &mesh->tetra[k];
1240 flg = pt[0]->flag;
1241 pt[0]->flag = 0;
1242 newtet[0]=k;
1243
1244 /* Create 2 new tetra */
1245 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
1246 return 0;
1247 }
1248
1249 imin = MMG3D_split2sf_cfg(flg,tau,&taued,pt[0]);
1250
1251 /* Generic formulation for the split of 2 edges belonging to a common face */
1252 pt[0]->v[tau[1]] = vx[taued[4]] ; pt[0]->v[tau[2]] = vx[taued[5]];
1253 xt[0].tag[taued[0]] = 0; xt[0].tag[taued[1]] = 0;
1254 xt[0].tag[taued[3]] = 0; xt[0].edg[taued[0]] = 0;
1255 xt[0].edg[taued[1]] = 0; xt[0].edg[taued[3]] = 0;
1256 xt[0].ref[ tau[3]] = 0; xt[0].ftag[ tau[3]] = 0; MG_SET(xt[0].ori, tau[3]);
1257
1258 if ( imin == tau[1] ) {
1259 pt[1]->v[tau[2]] = vx[taued[5]]; pt[1]->v[tau[3]] = vx[taued[4]];
1260 pt[2]->v[tau[3]] = vx[taued[5]];
1261
1262 xt[1].tag[taued[1]] = 0; xt[1].tag[taued[2]] = 0;
1263 xt[1].tag[taued[3]] = 0; xt[1].tag[taued[5]] = 0;
1264 xt[1].edg[taued[1]] = 0; xt[1].edg[taued[2]] = 0;
1265 xt[1].edg[taued[3]] = 0; xt[1].edg[taued[5]] = 0;
1266 xt[1].ref [ tau[1]] = 0; xt[1].ref [ tau[3]] = 0;
1267 xt[1].ftag[ tau[1]] = 0; xt[1].ftag[ tau[3]] = 0;
1268 MG_SET(xt[1].ori, tau[1]); MG_SET(xt[1].ori, tau[3]);
1269
1270 xt[2].tag[taued[2]] = 0; xt[2].tag[taued[4]] = 0;
1271 xt[2].edg[taued[2]] = 0; xt[2].edg[taued[4]] = 0;
1272 xt[2].ref[ tau[2]] = 0; xt[2].ftag[ tau[2]] = 0; MG_SET(xt[2].ori, tau[2]);
1273 }
1274 else {
1275 pt[1]->v[tau[3]] = vx[taued[4]];
1276 pt[2]->v[tau[1]] = vx[taued[4]]; pt[2]->v[tau[3]] = vx[taued[5]];
1277
1278 xt[1].tag[taued[2]] = 0; xt[1].tag[taued[5]] = 0;
1279 xt[1].edg[taued[2]] = 0; xt[1].edg[taued[5]] = 0;
1280 xt[1].ref[ tau[1]] = 0; xt[1].ftag[ tau[1]] = 0; MG_SET(xt[1].ori, tau[1]);
1281
1282 xt[2].tag[taued[0]] = 0; xt[2].tag[taued[2]] = 0;
1283 xt[2].tag[taued[3]] = 0; xt[2].tag[taued[4]] = 0;
1284 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[2]] = 0;
1285 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[4]] = 0;
1286 xt[2].ref [ tau[2]] = 0; xt[2].ref [ tau[3]] = 0;
1287 xt[2].ftag[ tau[2]] = 0; xt[2].ftag[ tau[3]] = 0;
1288 MG_SET(xt[2].ori, tau[2]); MG_SET(xt[2].ori, tau[3]);
1289 }
1290
1291 /* Assignation of the xt fields to the appropriate tets */
1292 isxt[0] = isxt[1] = isxt[2] = 0;
1293 for (i=0; i<4; i++) {
1294 if ( xt[0].ref[i] || xt[0].ftag[i] ) isxt[0] = 1;
1295 if ( xt[1].ref[i] || xt[1].ftag[i] ) isxt[1] = 1;
1296 if ( xt[2].ref[i] || xt[2].ftag[i] ) isxt[2] = 1;
1297 }
1298
1299 if ( pt[0]->xt ) {
1300 if ( isxt[0] ) {
1301 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
1302 pt[1]->xt = pt[2]->xt = 0;
1303 for (i=1; i<3; i++) {
1304 if ( isxt[i] ) {
1305 mesh->xt++;
1306 if ( mesh->xt > mesh->xtmax ) {
1307 /* realloc of xtetras table */
1309 "larger xtetra table",
1310 mesh->xt--;
1311 fprintf(stderr," Exit program.\n");
1312 return 0);
1313 }
1314 pt[i]->xt = mesh->xt;
1315 pxt0 = &mesh->xtetra[mesh->xt];
1316 memcpy(pxt0,&(xt[i]),sizeof(MMG5_xTetra));
1317 }
1318 }
1319 }
1320 else {
1321 firstxt = 1;
1322 pt[1]->xt = pt[2]->xt = 0;
1323 for (i=1; i<3; i++) {
1324 if ( isxt[i] ) {
1325 if ( firstxt ) {
1326 firstxt = 0;
1327 pt[i]->xt = pt[0]->xt;
1328 pxt0 = &mesh->xtetra[pt[i]->xt];
1329 memcpy(pxt0,&(xt[i]),sizeof(MMG5_xTetra));
1330 }
1331 else {
1332 mesh->xt++;
1333 if ( mesh->xt > mesh->xtmax ) {
1334 /* realloc of xtetras table */
1336 "larger xtetra table",
1337 mesh->xt--;
1338 fprintf(stderr," Exit program.\n");
1339 return 0);
1340 }
1341 pt[i]->xt = mesh->xt;
1342 pxt0 = &mesh->xtetra[mesh->xt];
1343 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1344 }
1345 }
1346 }
1347 pt[0]->xt = 0;
1348 }
1349 }
1350
1351 /* Quality update */
1352 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
1353
1354 return 1;
1355}
1356
1368int MMG3D_split2_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]){
1369 MMG5_pTetra pt,pt0;
1370 double vold,vnew;
1371 uint8_t tau[4];
1372 const uint8_t *taued;
1373
1374 pt = &mesh->tetra[k];
1375 pt0 = &mesh->tetra[0];
1376 vold = MMG5_orvol(mesh->point,pt->v);
1377
1378 if ( vold < MMG5_EPSOK ) return 0;
1379
1380 /* identity is case 33 */
1381 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
1382 taued = &MMG5_permedge[0][0];
1383 switch(pt->flag){
1384 case 18:
1385 tau[0] = 3; tau[1] = 1; tau[2] = 0; tau[3] = 2;
1386 taued = &MMG5_permedge[10][0];
1387 break;
1388 case 12:
1389 tau[0] = 0; tau[1] = 3; tau[2] = 1; tau[3] = 2;
1390 taued = &MMG5_permedge[2][0];
1391 break;
1392 }
1393
1394 /* Test orientation of the 4 tets to be created */
1395 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1396 pt0->v[tau[1]] = vx[taued[0]]; pt0->v[tau[2]] = vx[taued[5]];
1397 vnew = MMG5_orvol(mesh->point,pt0->v);
1398 if ( vnew < MMG5_EPSOK ) return 0;
1399
1400 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1401 pt0->v[tau[1]] = vx[taued[0]]; pt0->v[tau[3]] = vx[taued[5]];
1402 vnew = MMG5_orvol(mesh->point,pt0->v);
1403 if ( vnew < MMG5_EPSOK ) return 0;
1404
1405 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1406 pt0->v[tau[0]] = vx[taued[0]]; pt0->v[tau[2]] = vx[taued[5]];
1407 vnew = MMG5_orvol(mesh->point,pt0->v);
1408 if ( vnew < MMG5_EPSOK ) return 0;
1409
1410 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1411 pt0->v[tau[0]] = vx[taued[0]]; pt0->v[tau[3]] = vx[taued[5]];
1412 vnew = MMG5_orvol(mesh->point,pt0->v);
1413 if ( vnew < MMG5_EPSOK ) return 0;
1414
1415 return 1;
1416}
1417
1430int MMG5_split2(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
1431 MMG5_pTetra pt[4];
1432 MMG5_xTetra xt[4];
1433 MMG5_pxTetra pxt0;
1434 int i;
1435 MMG5_int newtet[4];
1436 int8_t flg,firstxt,isxt[4];
1437 uint8_t tau[4];
1438 const uint8_t *taued;
1439 const int ne=4;
1440
1441 pt[0] = &mesh->tetra[k];
1442 flg = pt[0]->flag;
1443 pt[0]->flag = 0;
1444 newtet[0]=k;
1445
1446 /* Create 3 new tetra */
1447 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
1448 return 0;
1449 }
1450
1451 /* identity : case 33 */
1452 tau[0] = 0; tau[1] = 1; tau[2] = 2; tau[3] = 3;
1453 taued = &MMG5_permedge[0][0];
1454 switch(flg){
1455 case 18:
1456 tau[0] = 3; tau[1] = 1; tau[2] = 0; tau[3] = 2;
1457 taued = &MMG5_permedge[10][0];
1458 break;
1459 case 12:
1460 tau[0] = 0; tau[1] = 3; tau[2] = 1; tau[3] = 2;
1461 taued = &MMG5_permedge[2][0];
1462 break;
1463 }
1464
1465 /* Generic formulation for the split of 2 opposite edges */
1466 pt[0]->v[tau[1]] = vx[taued[0]]; pt[0]->v[tau[2]] = vx[taued[5]];
1467 pt[1]->v[tau[1]] = vx[taued[0]]; pt[1]->v[tau[3]] = vx[taued[5]];
1468 pt[2]->v[tau[0]] = vx[taued[0]]; pt[2]->v[tau[2]] = vx[taued[5]];
1469 pt[3]->v[tau[0]] = vx[taued[0]]; pt[3]->v[tau[3]] = vx[taued[5]];
1470
1471 xt[0].tag[taued[1]] = 0; xt[0].tag[taued[3]] = 0;
1472 xt[0].tag[taued[4]] = 0; xt[0].edg[taued[1]] = 0;
1473 xt[0].edg[taued[3]] = 0; xt[0].edg[taued[4]] = 0;
1474 xt[0].ref [ tau[0]] = 0; xt[0].ref [ tau[3]] = 0;
1475 xt[0].ftag[ tau[0]] = 0; xt[0].ftag[ tau[3]] = 0;
1476 MG_SET(xt[0].ori, tau[0]); MG_SET(xt[0].ori, tau[3]);
1477
1478 xt[1].tag[taued[2]] = 0; xt[1].tag[taued[3]] = 0;
1479 xt[1].tag[taued[4]] = 0; xt[1].edg[taued[2]] = 0;
1480 xt[1].edg[taued[3]] = 0; xt[1].edg[taued[4]] = 0;
1481 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[2]] = 0;
1482 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[2]] = 0;
1483 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[2]);
1484
1485 xt[2].tag[taued[1]] = 0; xt[2].tag[taued[2]] = 0;
1486 xt[2].tag[taued[3]] = 0; xt[2].edg[taued[1]] = 0;
1487 xt[2].edg[taued[2]] = 0; xt[2].edg[taued[3]] = 0;
1488 xt[2].ref [ tau[1]] = 0; xt[2].ref [ tau[3]] = 0;
1489 xt[2].ftag[ tau[1]] = 0; xt[2].ftag[ tau[3]] = 0;
1490 MG_SET(xt[2].ori, tau[1]); MG_SET(xt[2].ori, tau[3]);
1491
1492 xt[3].tag[taued[1]] = 0; xt[3].tag[taued[2]] = 0;
1493 xt[3].tag[taued[4]] = 0; xt[3].edg[taued[1]] = 0;
1494 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[4]] = 0;
1495 xt[3].ref [ tau[1]] = 0; xt[3].ref [ tau[2]] = 0;
1496 xt[3].ftag[ tau[1]] = 0; xt[3].ftag[ tau[2]] = 0;
1497 MG_SET(xt[3].ori, tau[1]); MG_SET(xt[3].ori, tau[2]);
1498
1499 /* Assignation of the xt fields to the appropriate tets */
1500 memset(isxt,0,4*sizeof(int8_t));
1501 for (i=0; i<4; i++) {
1502 int j;
1503 for (j=0; j<ne; j++) {
1504 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
1505 }
1506 }
1507
1508 if ( pt[0]->xt) {
1509 if ( isxt[0] ) {
1510 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
1511 for (i=1; i<4; i++) {
1512 if ( isxt[i] ) {
1513 mesh->xt++;
1514 if ( mesh->xt > mesh->xtmax ) {
1515 /* realloc of xtetras table */
1517 "larger xtetra table",
1518 mesh->xt--;
1519 fprintf(stderr," Exit program.\n");
1520 return 0);
1521 }
1522 pt[i]->xt = mesh->xt;
1523 pxt0 = &mesh->xtetra[mesh->xt];
1524 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1525 }
1526 else {
1527 pt[i]->xt = 0;
1528 }
1529 }
1530 }
1531 else {
1532 firstxt = 1;
1533 for (i=1; i<4; i++) {
1534 if ( isxt[i] ) {
1535 if ( firstxt ) {
1536 firstxt = 0;
1537 pt[i]->xt = pt[0]->xt;
1538 pxt0 = &mesh->xtetra[pt[i]->xt];
1539 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1540 }
1541 else {
1542 mesh->xt++;
1543 if ( mesh->xt > mesh->xtmax ) {
1544 /* realloc of xtetras table */
1546 "larger xtetra table",
1547 mesh->xt--;
1548 fprintf(stderr," Exit program.\n");
1549 return 0);
1550 }
1551 pt[i]->xt = mesh->xt;
1552 pxt0 = &mesh->xtetra[mesh->xt];
1553 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1554 }
1555 }
1556 else {
1557 pt[i]->xt = 0;
1558 }
1559 }
1560 pt[0]->xt = 0;
1561 }
1562 }
1563
1564 /* Quality update */
1565 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
1566
1567 return 1;
1568}
1569
1571int MMG3D_split3_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
1572 MMG5_pTetra pt,pt0;
1573 double vold,vnew;
1574 uint8_t tau[4];
1575 const uint8_t *taued;
1576
1577 pt = &mesh->tetra[k];
1578 pt0 = &mesh->tetra[0];
1579 vold = MMG5_orvol(mesh->point,pt->v);
1580
1581 if ( vold < MMG5_EPSOK ) return 0;
1582
1583 /* identity is case 11 */
1584 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
1585 taued = &MMG5_permedge[0][0];
1586 switch(pt->flag) {
1587 case 21:
1588 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
1589 taued = &MMG5_permedge[2][0];
1590 break;
1591 case 38:
1592 tau[0] = 3 ; tau[1] = 0 ; tau[2] = 2 ; tau[3] = 1;
1593 taued = &MMG5_permedge[9][0];
1594 break;
1595 case 56:
1596 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
1597 taued = &MMG5_permedge[5][0];
1598 break;
1599 }
1600
1601 /* Check orientation of the 4 newly created tets */
1602 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1603 pt0->v[tau[1]] = vx[taued[0]];
1604 pt0->v[tau[2]] = vx[taued[1]];
1605 vnew = MMG5_orvol(mesh->point,pt0->v);
1606 if ( vnew < MMG5_EPSOK ) return 0;
1607
1608 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1609 pt0->v[tau[0]] = vx[taued[0]];
1610 pt0->v[tau[2]] = vx[taued[3]];
1611 vnew = MMG5_orvol(mesh->point,pt0->v);
1612 if ( vnew < MMG5_EPSOK ) return 0;
1613
1614 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1615 pt0->v[tau[0]] = vx[taued[1]];
1616 pt0->v[tau[1]] = vx[taued[3]];
1617 vnew = MMG5_orvol(mesh->point,pt0->v);
1618 if ( vnew < MMG5_EPSOK ) return 0;
1619
1620 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1621 pt0->v[tau[0]] = vx[taued[0]];
1622 pt0->v[tau[1]] = vx[taued[3]];
1623 pt0->v[tau[2]] = vx[taued[1]];
1624 vnew = MMG5_orvol(mesh->point,pt0->v);
1625 if ( vnew < MMG5_EPSOK ) return 0;
1626
1627 return 1;
1628}
1629
1642int MMG5_split3(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
1643 MMG5_pTetra pt[4];
1644 MMG5_xTetra xt[4];
1645 MMG5_pxTetra pxt0;
1646 int i;
1647 MMG5_int newtet[4];
1648 int8_t flg,firstxt,isxt[4];
1649 uint8_t tau[4];
1650 const uint8_t *taued;
1651 const int ne=4;
1652
1653 pt[0] = &mesh->tetra[k];
1654 flg = pt[0]->flag;
1655 pt[0]->flag = 0;
1656 newtet[0]=k;
1657
1658 /* create 3 new tetras */
1659 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
1660 return 0;
1661 }
1662
1663 /* update vertices, case 11 is default */
1664 tau[0] = 0; tau[1] = 1; tau[2] = 2; tau[3] = 3;
1665 taued = &MMG5_permedge[0][0];
1666 switch(flg) {
1667 case 21:
1668 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
1669 taued = &MMG5_permedge[2][0];
1670 break;
1671 case 38:
1672 tau[0] = 3 ; tau[1] = 0 ; tau[2] = 2 ; tau[3] = 1;
1673 taued = &MMG5_permedge[9][0];
1674 break;
1675 case 56:
1676 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
1677 taued = &MMG5_permedge[5][0];
1678 break;
1679 }
1680
1681 /* Generic formulation of split of 3 edges */
1682 pt[0]->v[tau[1]] = vx[taued[0]]; pt[0]->v[tau[2]] = vx[taued[1]];
1683 pt[1]->v[tau[0]] = vx[taued[0]]; pt[1]->v[tau[2]] = vx[taued[3]];
1684 pt[2]->v[tau[0]] = vx[taued[1]]; pt[2]->v[tau[1]] = vx[taued[3]];
1685 pt[3]->v[tau[0]] = vx[taued[0]]; pt[3]->v[tau[1]] = vx[taued[3]]; pt[3]->v[tau[2]] = vx[taued[1]];
1686
1687 xt[0].tag[taued[3]] = 0; xt[0].tag[taued[4]] = 0;
1688 xt[0].tag[taued[5]] = 0; xt[0].edg[taued[3]] = 0;
1689 xt[0].edg[taued[4]] = 0; xt[0].edg[taued[5]] = 0;
1690 xt[0].ref[ tau[0]] = 0; xt[0].ftag[ tau[0]] = 0; MG_SET(xt[0].ori, tau[0]);
1691
1692 xt[1].tag[taued[1]] = 0; xt[1].tag[taued[2]] = 0;
1693 xt[1].tag[taued[5]] = 0; xt[1].edg[taued[1]] = 0;
1694 xt[1].edg[taued[2]] = 0; xt[1].edg[taued[5]] = 0;
1695 xt[1].ref[ tau[1]] = 0; xt[1].ftag[ tau[1]] = 0; MG_SET(xt[1].ori, tau[1]);
1696
1697 xt[2].tag[taued[0]] = 0; xt[2].tag[taued[2]] = 0;
1698 xt[2].tag[taued[4]] = 0; xt[2].edg[taued[0]] = 0;
1699 xt[2].edg[taued[2]] = 0; xt[2].edg[taued[4]] = 0;
1700 xt[2].ref[ tau[2]] = 0; xt[2].ftag[ tau[2]] = 0; MG_SET(xt[2].ori, tau[2]);
1701
1702 xt[3].tag[taued[0]] = 0; xt[3].tag[taued[1]] = 0;
1703 xt[3].tag[taued[2]] = 0; xt[3].tag[taued[3]] = 0;
1704 xt[3].tag[taued[4]] = 0; xt[3].tag[taued[5]] = 0;
1705 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[1]] = 0;
1706 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[3]] = 0;
1707 xt[3].edg[taued[4]] = 0; xt[3].edg[taued[5]] = 0;
1708 xt[3].ref [ tau[0]] = 0; xt[3].ref [ tau[1]] = 0; xt[3].ref [tau[2]] = 0;
1709 xt[3].ftag[ tau[0]] = 0; xt[3].ftag[ tau[1]] = 0; xt[3].ftag[tau[2]] = 0;
1710 MG_SET(xt[3].ori, tau[0]); MG_SET(xt[3].ori, tau[1]); MG_SET(xt[3].ori, tau[2]);
1711
1712 /* Assignation of the xt fields to the appropriate tets */
1713 memset(isxt,0,4*sizeof(int8_t));
1714 for (i=0; i<4; i++) {
1715 int j;
1716 for (j=0; j<ne; j++) {
1717 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
1718 }
1719 }
1720
1721 if ( pt[0]->xt ) {
1722 if ( isxt[0] ) {
1723 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
1724 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
1725 for (i=1; i<4; i++) {
1726 if ( isxt[i] ) {
1727 mesh->xt++;
1728 if ( mesh->xt > mesh->xtmax ) {
1729 /* realloc of xtetras table */
1731 "larger xtetra table",
1732 mesh->xt--;
1733 fprintf(stderr," Exit program.\n");
1734 return 0);
1735 }
1736 pt[i]->xt = mesh->xt;
1737 pxt0 = &mesh->xtetra[mesh->xt];
1738 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1739 }
1740 }
1741 }
1742 else {
1743 firstxt = 1;
1744 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
1745 for (i=1; i<4; i++) {
1746 if ( isxt[i] ) {
1747 if ( firstxt ) {
1748 firstxt = 0;
1749 pt[i]->xt = pt[0]->xt;
1750 pxt0 = &mesh->xtetra[(pt[i])->xt];
1751 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
1752 }
1753 else {
1754 mesh->xt++;
1755 if ( mesh->xt > mesh->xtmax ) {
1756 /* realloc of xtetras table */
1758 "larger xtetra table",
1759 mesh->xt--;
1760 fprintf(stderr," Exit program.\n");
1761 return 0);
1762 }
1763 pt[i]->xt = mesh->xt;
1764 pxt0 = &mesh->xtetra[mesh->xt];
1765 memcpy(pxt0,&(xt[i]),sizeof(MMG5_xTetra));
1766 }
1767 }
1768 }
1769 pt[0]->xt = 0;
1770 }
1771 }
1772
1773 /* Quality update */
1774 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
1775
1776 return 1;
1777}
1778
1790int MMG3D_split3cone_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
1791 MMG5_pTetra pt,pt0;
1792 double vold,vnew;
1793 uint8_t tau[4],ia,ib;
1794 const uint8_t *taued;
1795
1796 pt = &mesh->tetra[k];
1797 pt0 = &mesh->tetra[0];
1798 vold = MMG5_orvol(mesh->point,pt->v);
1799
1800 if ( vold < MMG5_EPSOK ) return 0;
1801
1802 /* identity is case 7 */
1803 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
1804 taued = &MMG5_permedge[0][0];
1805
1806 switch(pt->flag) {
1807 case 25:
1808 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
1809 taued = &MMG5_permedge[4][0];
1810 break;
1811
1812 case 42:
1813 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
1814 taued = &MMG5_permedge[6][0];
1815 break;
1816
1817 case 52:
1818 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
1819 taued = &MMG5_permedge[10][0];
1820 break;
1821 }
1822
1823 /* Generic formulation of split of 3 edges in cone configuration (edges 0,1,2 splitted) */
1824 /* Fill ia,ib,ic so that pt->v[ia] < pt->v[ib] < pt->v[ic] */
1825 if ( pt->v[tau[1]] < pt->v[tau[2]] ) {
1826 ia = tau[1];
1827 ib = tau[2];
1828 }
1829 else {
1830 ia = tau[2];
1831 ib = tau[1];
1832 }
1833
1834 if ( pt->v[tau[3]] < pt->v[ia] ) {
1835 ib = ia;
1836 ia = tau[3];
1837 }
1838 else {
1839 if ( pt->v[tau[3]] < pt->v[ib] ) {
1840 ib = tau[3];
1841 }
1842 else {
1843 }
1844 }
1845
1846 /* Check orientation of the 4 newly created tets */
1847 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1848 pt0->v[tau[1]] = vx[taued[0]];
1849 pt0->v[tau[2]] = vx[taued[1]];
1850 pt0->v[tau[3]] = vx[taued[2]];
1851 vnew = MMG5_orvol(mesh->point,pt0->v);
1852 if ( vnew < MMG5_EPSOK ) return 0;
1853
1854 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1855 if ( ia == tau[3] ) {
1856 pt0->v[tau[0]] = vx[taued[2]];
1857 pt0->v[tau[1]] = vx[taued[0]];
1858 pt0->v[tau[2]] = vx[taued[1]];
1859 vnew = MMG5_orvol(mesh->point,pt0->v);
1860 if ( vnew < MMG5_EPSOK ) return 0;
1861
1862 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1863 if ( ib == tau[1] ) {
1864 pt0->v[tau[0]] = vx[taued[0]];
1865 pt0->v[tau[2]] = vx[taued[1]];
1866 vnew = MMG5_orvol(mesh->point,pt0->v);
1867 if ( vnew < MMG5_EPSOK ) return 0;
1868
1869 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1870 pt0->v[tau[0]] = vx[taued[1]] ;
1871 vnew = MMG5_orvol(mesh->point,pt0->v);
1872 if ( vnew < MMG5_EPSOK ) return 0;
1873 }
1874 else {
1875 assert(ib == tau[2]);
1876 pt0->v[tau[0]] = vx[taued[1]];
1877 pt0->v[tau[1]] = vx[taued[0]];
1878 vnew = MMG5_orvol(mesh->point,pt0->v);
1879 if ( vnew < MMG5_EPSOK ) return 0;
1880
1881 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1882 pt0->v[tau[0]] = vx[taued[0]] ;
1883 vnew = MMG5_orvol(mesh->point,pt0->v);
1884 if ( vnew < MMG5_EPSOK ) return 0;
1885 }
1886 }
1887 else if (ia == tau[2] ) {
1888 pt0->v[tau[0]] = vx[taued[1]];
1889 pt0->v[tau[1]] = vx[taued[0]];
1890 pt0->v[tau[3]] = vx[taued[2]];
1891 vnew = MMG5_orvol(mesh->point,pt0->v);
1892 if ( vnew < MMG5_EPSOK ) return 0;
1893
1894 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1895 if ( ib == tau[3] ) {
1896 pt0->v[tau[0]] = vx[taued[2]];
1897 pt0->v[tau[1]] = vx[taued[0]];
1898 vnew = MMG5_orvol(mesh->point,pt0->v);
1899 if ( vnew < MMG5_EPSOK ) return 0;
1900
1901 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1902 pt0->v[tau[0]] = vx[taued[0]];
1903 vnew = MMG5_orvol(mesh->point,pt0->v);
1904 if ( vnew < MMG5_EPSOK ) return 0;
1905 }
1906 else {
1907 assert(ib == tau[1]);
1908 pt0->v[tau[0]] = vx[taued[0]];
1909 pt0->v[tau[3]] = vx[taued[2]];
1910 vnew = MMG5_orvol(mesh->point,pt0->v);
1911 if ( vnew < MMG5_EPSOK ) return 0;
1912
1913 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1914 pt0->v[tau[0]] = vx[taued[2]];
1915 vnew = MMG5_orvol(mesh->point,pt0->v);
1916 if ( vnew < MMG5_EPSOK ) return 0;
1917 }
1918 }
1919 else {
1920 assert(ia == tau[1]);
1921
1922 pt0->v[tau[0]] = vx[taued[0]];
1923 pt0->v[tau[2]] = vx[taued[1]];
1924 pt0->v[tau[3]] = vx[taued[2]];
1925 vnew = MMG5_orvol(mesh->point,pt0->v);
1926 if ( vnew < MMG5_EPSOK ) return 0;
1927
1928 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1929 if ( ib == tau[2] ) {
1930 pt0->v[tau[0]] = vx[taued[1]];
1931 pt0->v[tau[3]] = vx[taued[2]] ;
1932 vnew = MMG5_orvol(mesh->point,pt0->v);
1933 if ( vnew < MMG5_EPSOK ) return 0;
1934
1935 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1936 pt0->v[tau[0]] = vx[taued[2]] ;
1937 vnew = MMG5_orvol(mesh->point,pt0->v);
1938 if ( vnew < MMG5_EPSOK ) return 0;
1939
1940 }
1941 else {
1942 assert(ib == tau[3]);
1943
1944 pt0->v[tau[0]] = vx[taued[2]];
1945 pt0->v[tau[2]] = vx[taued[1]];
1946 vnew = MMG5_orvol(mesh->point,pt0->v);
1947 if ( vnew < MMG5_EPSOK ) return 0;
1948
1949 memcpy(pt0,pt,sizeof(MMG5_Tetra));
1950 pt0->v[tau[0]] = vx[taued[1]];
1951 vnew = MMG5_orvol(mesh->point,pt0->v);
1952 if ( vnew < MMG5_EPSOK ) return 0;
1953 }
1954 }
1955
1956 return 1;
1957}
1958
1971int MMG5_split3cone(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
1972 MMG5_pTetra pt[4];
1973 MMG5_xTetra xt[4];
1974 MMG5_pxTetra pxt0;
1975 int i;
1976 MMG5_int newtet[4];
1977 int8_t flg,firstxt,isxt[4],ia,ib;
1978 uint8_t tau[4];
1979 const uint8_t *taued;
1980 const int ne=4;
1981
1982 pt[0] = &mesh->tetra[k];
1983 flg = pt[0]->flag;
1984 pt[0]->flag = 0;
1985 newtet[0]=k;
1986
1987 /* create 3 new tetras */
1988 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
1989 return 0;
1990 }
1991
1992 /* Set permutation of vertices : reference configuration is 7 */
1993 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
1994 taued = &MMG5_permedge[0][0];
1995
1996 switch(flg) {
1997 case 25:
1998 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
1999 taued = &MMG5_permedge[4][0];
2000 break;
2001
2002 case 42:
2003 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
2004 taued = &MMG5_permedge[6][0];
2005 break;
2006
2007 case 52:
2008 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
2009 taued = &MMG5_permedge[10][0];
2010 break;
2011 }
2012
2013 /* Generic formulation of split of 3 edges in cone configuration (edges 0,1,2 splitted) */
2014 /* Fill ia,ib,ic so that pt->v[ia] < pt->v[ib] < pt->v[ic] */
2015 if ( (pt[0])->v[tau[1]] < (pt[0])->v[tau[2]] ) {
2016 ia = tau[1];
2017 ib = tau[2];
2018 }
2019 else {
2020 ia = tau[2];
2021 ib = tau[1];
2022 }
2023
2024 if ( (pt[0])->v[tau[3]] < (pt[0])->v[ia] ) {
2025 ib = ia;
2026 ia = tau[3];
2027 }
2028 else {
2029 if ( (pt[0])->v[tau[3]] < (pt[0])->v[ib] ) {
2030 ib = tau[3];
2031 }
2032 else {
2033 }
2034 }
2035
2036 pt[0]->v[tau[1]] = vx[taued[0]] ; pt[0]->v[tau[2]] = vx[taued[1]] ; pt[0]->v[tau[3]] = vx[taued[2]];
2037 xt[0].tag[taued[3]] = 0; xt[0].tag[taued[4]] = 0;
2038 xt[0].tag[taued[5]] = 0; xt[0].edg[taued[3]] = 0;
2039 xt[0].edg[taued[4]] = 0; xt[0].edg[taued[5]] = 0;
2040 xt[0].ref [ tau[0]] = 0;
2041 xt[0].ftag[ tau[0]] = 0;
2042 MG_SET(xt[0].ori, tau[0]);
2043
2044 if ( ia == tau[3] ) {
2045 pt[1]->v[tau[0]] = vx[taued[2]] ; pt[1]->v[tau[1]] = vx[taued[0]] ; pt[1]->v[tau[2]] = vx[taued[1]];
2046 xt[1].tag[taued[0]] = 0; xt[1].tag[taued[1]] = 0;
2047 xt[1].tag[taued[3]] = 0; xt[1].tag[taued[4]] = 0;
2048 xt[1].tag[taued[5]] = 0; xt[1].edg[taued[0]] = 0;
2049 xt[1].edg[taued[1]] = 0; xt[1].edg[taued[3]] = 0;
2050 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
2051 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[3]] = 0;
2052 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[3]] = 0;
2053 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[3]);
2054
2055 if ( ib == tau[1] ) {
2056 pt[2]->v[tau[0]] = vx[taued[0]] ; pt[2]->v[tau[2]] = vx[taued[1]] ;
2057 xt[2].tag[taued[1]] = 0; xt[2].tag[taued[2]] = 0;
2058 xt[2].tag[taued[3]] = 0; xt[2].tag[taued[5]] = 0;
2059 xt[2].edg[taued[1]] = 0; xt[2].edg[taued[2]] = 0;
2060 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[5]] = 0;
2061 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[1]] = 0;
2062 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[1]] = 0;
2063 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[1]);
2064
2065 pt[3]->v[tau[0]] = vx[taued[1]] ;
2066 xt[3].tag[taued[0]] = 0; xt[3].tag[taued[2]] = 0;
2067 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[2]] = 0;
2068 xt[3].ref [ tau[2]] = 0;
2069 xt[3].ftag[ tau[2]] = 0;
2070 MG_SET(xt[3].ori, tau[2]);
2071 }
2072 else {
2073 assert(ib == tau[2]);
2074
2075 pt[2]->v[tau[0]] = vx[taued[1]] ; pt[2]->v[tau[1]] = vx[taued[0]] ;
2076 xt[2].tag[taued[0]] = 0; xt[2].tag[taued[2]] = 0;
2077 xt[2].tag[taued[3]] = 0; xt[2].tag[taued[4]] = 0;
2078 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[2]] = 0;
2079 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[4]] = 0;
2080 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[2]] = 0;
2081 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[2]] = 0;
2082 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[2]);
2083
2084 pt[3]->v[tau[0]] = vx[taued[0]] ;
2085 xt[3].tag[taued[1]] = 0; xt[3].tag[taued[2]] = 0;
2086 xt[3].edg[taued[1]] = 0; xt[3].edg[taued[2]] = 0;
2087 xt[3].ref [ tau[1]] = 0;
2088 xt[3].ftag[ tau[1]] = 0;
2089 MG_SET(xt[3].ori, tau[1]);
2090 }
2091 }
2092
2093 else if (ia == tau[2] ) {
2094 pt[1]->v[tau[0]] = vx[taued[1]] ; pt[1]->v[tau[1]] = vx[taued[0]] ; pt[1]->v[tau[3]] = vx[taued[2]];
2095 xt[1].tag[taued[0]] = 0; xt[1].tag[taued[2]] = 0;
2096 xt[1].tag[taued[3]] = 0; xt[1].tag[taued[4]] = 0;
2097 xt[1].tag[taued[5]] = 0; xt[1].edg[taued[0]] = 0;
2098 xt[1].edg[taued[2]] = 0; xt[1].edg[taued[3]] = 0;
2099 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
2100 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[2]] = 0;
2101 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[2]] = 0;
2102 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[2]);
2103
2104 if ( ib == tau[3] ) {
2105 pt[2]->v[tau[0]] = vx[taued[2]] ; pt[2]->v[tau[1]] = vx[taued[0]] ;
2106 xt[2].tag[taued[0]] = 0; xt[2].tag[taued[1]] = 0;
2107 xt[2].tag[taued[3]] = 0; xt[2].tag[taued[4]] = 0;
2108 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[1]] = 0;
2109 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[4]] = 0;
2110 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[3]] = 0;
2111 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[3]] = 0;
2112 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[3]);
2113
2114 pt[3]->v[tau[0]] = vx[taued[0]] ;
2115 xt[3].tag[taued[1]] = 0; xt[3].tag[taued[2]] = 0;
2116 xt[3].edg[taued[1]] = 0; xt[3].edg[taued[2]] = 0;
2117 xt[3].ref [ tau[1]] = 0;
2118 xt[3].ftag[ tau[1]] = 0;
2119 MG_SET(xt[3].ori, tau[1]);
2120 }
2121 else {
2122 assert(ib == tau[1]);
2123
2124 pt[2]->v[tau[0]] = vx[taued[0]] ; pt[2]->v[tau[3]] = vx[taued[2]] ;
2125 xt[2].tag[taued[1]] = 0; xt[2].tag[taued[2]] = 0;
2126 xt[2].tag[taued[4]] = 0; xt[2].tag[taued[5]] = 0;
2127 xt[2].edg[taued[1]] = 0; xt[2].edg[taued[2]] = 0;
2128 xt[2].edg[taued[4]] = 0; xt[2].edg[taued[5]] = 0;
2129 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[1]] = 0;
2130 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[1]] = 0;
2131 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[1]);
2132
2133 pt[3]->v[tau[0]] = vx[taued[2]] ;
2134 xt[3].tag[taued[0]] = 0; xt[3].tag[taued[1]] = 0;
2135 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[1]] = 0;
2136 xt[3].ref [ tau[3]] = 0;
2137 xt[3].ftag[ tau[3]] = 0;
2138 MG_SET(xt[3].ori, tau[3]);
2139 }
2140 }
2141 else {
2142 assert(ia == tau[1]);
2143
2144 pt[1]->v[tau[0]] = vx[taued[0]] ; pt[1]->v[tau[2]] = vx[taued[1]] ; pt[1]->v[tau[3]] = vx[taued[2]];
2145 xt[1].tag[taued[1]] = 0; xt[1].tag[taued[2]] = 0;
2146 xt[1].tag[taued[3]] = 0; xt[1].tag[taued[4]] = 0;
2147 xt[1].tag[taued[5]] = 0; xt[1].edg[taued[1]] = 0;
2148 xt[1].edg[taued[2]] = 0; xt[1].edg[taued[3]] = 0;
2149 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
2150 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[1]] = 0;
2151 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[1]] = 0;
2152 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[1]);
2153
2154 if ( ib == tau[2] ) {
2155 pt[2]->v[tau[0]] = vx[taued[1]] ; pt[2]->v[tau[3]] = vx[taued[2]] ;
2156 xt[2].tag[taued[0]] = 0; xt[2].tag[taued[2]] = 0;
2157 xt[2].tag[taued[4]] = 0; xt[2].tag[taued[5]] = 0;
2158 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[2]] = 0;
2159 xt[2].edg[taued[4]] = 0; xt[2].edg[taued[5]] = 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[2]] ;
2165 xt[3].tag[taued[0]] = 0; xt[3].tag[taued[1]] = 0;
2166 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[1]] = 0;
2167 xt[3].ref [ tau[3]] = 0;
2168 xt[3].ftag[ tau[3]] = 0;
2169 MG_SET(xt[3].ori, tau[3]);
2170 }
2171 else {
2172 assert(ib == tau[3]);
2173
2174 pt[2]->v[tau[0]] = vx[taued[2]] ; pt[2]->v[tau[2]] = vx[taued[1]] ;
2175 xt[2].tag[taued[0]] = 0; xt[2].tag[taued[1]] = 0;
2176 xt[2].tag[taued[3]] = 0; xt[2].tag[taued[5]] = 0;
2177 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[1]] = 0;
2178 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[5]] = 0;
2179 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[3]] = 0;
2180 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[3]] = 0;
2181 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[3]);
2182
2183 pt[3]->v[tau[0]] = vx[taued[1]] ;
2184 xt[3].tag[taued[0]] = 0; xt[3].tag[taued[2]] = 0;
2185 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[2]] = 0;
2186 xt[3].ref [ tau[2]] = 0;
2187 xt[3].ftag[ tau[2]] = 0;
2188 MG_SET(xt[3].ori, tau[2]);
2189 }
2190 }
2191
2192 /* Assignation of the xt fields to the appropriate tets */
2193 isxt[0] = isxt[1] = isxt[2] = isxt[3] = 0;
2194
2195 for (i=0; i<4; i++) {
2196 int j;
2197 for (j=0; j<ne; j++) {
2198 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
2199 }
2200 }
2201
2202 if ( (pt[0])->xt ) {
2203 if ( isxt[0] ) {
2204 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
2205 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
2206 for (i=1; i<4; i++) {
2207 if ( isxt[i] ) {
2208 mesh->xt++;
2209 if ( mesh->xt > mesh->xtmax ) {
2210 /* realloc of xtetras table */
2212 "larger xtetra table",
2213 mesh->xt--;
2214 fprintf(stderr," Exit program.\n");
2215 return 0);
2216 }
2217 pt[i]->xt = mesh->xt;
2218 pxt0 = &mesh->xtetra[mesh->xt];
2219 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2220 }
2221 }
2222 }
2223 else {
2224 firstxt = 1;
2225 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
2226 for ( i=1; i<4; i++) {
2227 if ( isxt[i] ) {
2228 if ( firstxt ) {
2229 firstxt = 0;
2230 pt[i]->xt = pt[0]->xt;
2231 pxt0 = &mesh->xtetra[(pt[i])->xt];
2232 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2233 }
2234 else {
2235 mesh->xt++;
2236 if ( mesh->xt > mesh->xtmax ) {
2237 /* realloc of xtetras table */
2239 "larger xtetra table",
2240 mesh->xt--;
2241 fprintf(stderr," Exit program.\n");
2242 return 0);
2243 }
2244 pt[i]->xt = mesh->xt;
2245 pxt0 = &mesh->xtetra[mesh->xt];
2246 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2247 }
2248 }
2249 }
2250 (pt[0])->xt = 0;
2251 }
2252 }
2253
2254 /* Quality update */
2255 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
2256
2257
2258 return 1;
2259}
2260
2285static inline
2286void MMG3D_configSplit3op(MMG5_pTetra pt,MMG5_int vx[6],uint8_t tau[4],
2287 const uint8_t **taued,
2288 uint8_t sym[4],uint8_t symed[6],
2289 uint8_t *ip0,uint8_t *ip1,
2290 uint8_t *ip2,uint8_t *ip3,
2291 uint8_t *ie0,uint8_t *ie1,
2292 uint8_t *ie2,uint8_t *ie3,
2293 uint8_t *ie4,uint8_t *ie5,
2294 uint8_t *imin03,uint8_t *imin12) {
2295
2296 /* Set permutation /symmetry of vertices : generic case : 35 */
2297 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
2298 (*taued) = &MMG5_permedge[0][0];
2299
2300 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2301 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2302 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2303
2304 switch(pt->flag) {
2305 case 19:
2306 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
2307 (*taued) = &MMG5_permedge[0][0];
2308
2309 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2310 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2311 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2312 break;
2313
2314 case 13:
2315 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
2316 (*taued) = &MMG5_permedge[2][0];
2317
2318 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2319 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2320 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2321 break;
2322
2323 case 37:
2324 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
2325 (*taued) = &MMG5_permedge[2][0];
2326
2327 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2328 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2329 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2330 break;
2331
2332 case 22:
2333 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
2334 (*taued) = &MMG5_permedge[10][0];
2335
2336 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2337 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2338 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2339 break;
2340
2341 case 28:
2342 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
2343 (*taued) = &MMG5_permedge[10][0];
2344
2345 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2346 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2347 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2348 break;
2349
2350 case 26:
2351 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
2352 (*taued) = &MMG5_permedge[6][0];
2353
2354 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2355 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2356 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2357 break;
2358
2359 case 14:
2360 tau[0] = 0 ; tau[1] = 2 ; tau[2] = 3 ; tau[3] = 1;
2361 (*taued) = &MMG5_permedge[1][0];
2362
2363 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2364 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2365 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2366 break;
2367
2368 case 49:
2369 tau[0] = 3 ; tau[1] = 2 ; tau[2] = 1 ; tau[3] = 0;
2370 (*taued) = &MMG5_permedge[11][0];
2371
2372 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2373 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2374 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2375 break;
2376
2377 case 50:
2378 tau[0] = 3 ; tau[1] = 2 ; tau[2] = 1 ; tau[3] = 0;
2379 (*taued) = &MMG5_permedge[11][0];
2380
2381 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2382 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2383 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2384 break;
2385
2386 case 44:
2387 tau[0] = 3 ; tau[1] = 0 ; tau[2] = 2 ; tau[3] = 1;
2388 (*taued) = &MMG5_permedge[9][0];
2389
2390 sym[0] = 0; sym[1] = 1 ; sym[2] = 2 ; sym[3] = 3;
2391 symed[0] = 0 ; symed[1] = 1 ; symed[2] = 2;
2392 symed[3] = 3 ; symed[4] = 4 ; symed[5] = 5;
2393 break;
2394
2395 case 41:
2396 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
2397 (*taued) = &MMG5_permedge[4][0];
2398
2399 sym[0] = 0; sym[1] = 2 ; sym[2] = 1 ; sym[3] = 3;
2400 symed[0] = 1 ; symed[1] = 0 ; symed[2] = 2;
2401 symed[3] = 3 ; symed[4] = 5 ; symed[5] = 4;
2402 break;
2403 }
2404
2405 (*ip0) = tau[sym[0]];
2406 (*ip1) = tau[sym[1]];
2407 (*ip2) = tau[sym[2]];
2408 (*ip3) = tau[sym[3]];
2409
2410 (*ie0) = (*taued)[symed[0]];
2411 (*ie1) = (*taued)[symed[1]];
2412 (*ie2) = (*taued)[symed[2]];
2413 (*ie3) = (*taued)[symed[3]];
2414 (*ie4) = (*taued)[symed[4]];
2415 (*ie5) = (*taued)[symed[5]];
2416
2417 /* Test : to be removed eventually */
2418 assert(vx[(*ie0)] > 0);
2419 assert(vx[(*ie1)] > 0);
2420 assert(vx[(*ie5)] > 0);
2421 assert(vx[(*ie2)] <= 0);
2422 assert(vx[(*ie3)] <= 0);
2423 assert(vx[(*ie4)] <= 0);
2424
2425 (*imin03) = (pt->v[(*ip0)] < pt->v[(*ip3)]) ? (*ip0) : (*ip3);
2426 (*imin12) = (pt->v[(*ip1)] < pt->v[(*ip2)]) ? (*ip1) : (*ip2);
2427
2428 return;
2429}
2430
2442int MMG3D_split3op_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
2443 MMG5_pTetra pt,pt0;
2444 double vold,vnew;
2445 uint8_t tau[4],sym[4],symed[6],ip0,ip1,ip2,ip3,ie0,ie1,ie2,ie3;
2446 uint8_t ie4,ie5,imin03,imin12;
2447 const uint8_t *taued=NULL;
2448
2449 pt = &mesh->tetra[k];
2450 pt0 = &mesh->tetra[0];
2451 vold = MMG5_orvol(mesh->point,pt->v);
2452
2453 if ( vold < MMG5_EPSOK ) return 0;
2454
2455 /* Set permutation /symmetry of vertices : generic case : 35 */
2456 MMG3D_configSplit3op(pt,vx,tau,&taued,sym,symed,&ip0,&ip1,&ip2,&ip3,
2457 &ie0,&ie1,&ie2,&ie3,&ie4,&ie5,&imin03,&imin12);
2458
2459 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2460 if ( (imin12 == ip2) && (imin03 == ip0) ) {
2461 pt0->v[ip0] = vx[ie1] ; pt0->v[ip1] = vx[ie0] ; pt0->v[ip3] = vx[ie5] ;
2462 vnew = MMG5_orvol(mesh->point,pt0->v);
2463 if ( vnew < MMG5_EPSOK ) return 0;
2464
2465 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2466 pt0->v[ip0] = vx[ie0] ; pt0->v[ip3] = vx[ie5] ;
2467 vnew = MMG5_orvol(mesh->point,pt0->v);
2468 if ( vnew < MMG5_EPSOK ) return 0;
2469
2470 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2471 pt0->v[ip0] = vx[ie0] ; pt0->v[ip2] = vx[ie5] ;
2472 vnew = MMG5_orvol(mesh->point,pt0->v);
2473 if ( vnew < MMG5_EPSOK ) return 0;
2474
2475 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2476 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie1] ; pt0->v[ip3] = vx[ie5] ;
2477 vnew = MMG5_orvol(mesh->point,pt0->v);
2478 if ( vnew < MMG5_EPSOK ) return 0;
2479
2480 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2481 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie5];
2482 vnew = MMG5_orvol(mesh->point,pt0->v);
2483 if ( vnew < MMG5_EPSOK ) return 0;
2484 }
2485
2486 else if ( (imin12 == ip1) && (imin03 == ip0) ) {
2487 pt0->v[ip0] = vx[ie1] ; pt0->v[ip3] = vx[ie5] ;
2488 vnew = MMG5_orvol(mesh->point,pt0->v);
2489 if ( vnew < MMG5_EPSOK ) return 0;
2490
2491 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2492 pt0->v[ip0] = vx[ie0] ; pt0->v[ip2] = vx[ie1] ; pt0->v[ip3] = vx[ie5];
2493 vnew = MMG5_orvol(mesh->point,pt0->v);
2494 if ( vnew < MMG5_EPSOK ) return 0;
2495
2496 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2497 pt0->v[ip0] = vx[ie0] ; pt0->v[ip2] = vx[ie5] ;
2498 vnew = MMG5_orvol(mesh->point,pt0->v);
2499 if ( vnew < MMG5_EPSOK ) return 0;
2500
2501 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2502 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie5];
2503 vnew = MMG5_orvol(mesh->point,pt0->v);
2504 if ( vnew < MMG5_EPSOK ) return 0;
2505
2506 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2507 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie1]; pt0->v[ip3] = vx[ie5];
2508 vnew = MMG5_orvol(mesh->point,pt0->v);
2509 if ( vnew < MMG5_EPSOK ) return 0;
2510 }
2511 else if ( (imin12 == ip2) && (imin03 == ip3) ) {
2512 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie1] ;
2513 vnew = MMG5_orvol(mesh->point,pt0->v);
2514 if ( vnew < MMG5_EPSOK ) return 0;
2515
2516 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2517 pt0->v[ip0] = vx[ie1] ; pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie5];
2518 vnew = MMG5_orvol(mesh->point,pt0->v);
2519 if ( vnew < MMG5_EPSOK ) return 0;
2520
2521 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2522 pt0->v[ip0] = vx[ie0] ; pt0->v[ip2] = vx[ie5] ;
2523 vnew = MMG5_orvol(mesh->point,pt0->v);
2524 if ( vnew < MMG5_EPSOK ) return 0;
2525
2526 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2527 pt0->v[ip0] = vx[ie1] ; pt0->v[ip1] = vx[ie0]; pt0->v[ip3] = vx[ie5];
2528 vnew = MMG5_orvol(mesh->point,pt0->v);
2529 if ( vnew < MMG5_EPSOK ) return 0;
2530
2531 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2532 pt0->v[ip0] = vx[ie0] ; pt0->v[ip3] = vx[ie5];
2533 vnew = MMG5_orvol(mesh->point,pt0->v);
2534 if ( vnew < MMG5_EPSOK ) return 0;
2535 }
2536 else {
2537 assert((imin12 == ip1) && (imin03 == ip3)) ;
2538
2539 pt0->v[ip1] = vx[ie0] ; pt0->v[ip2] = vx[ie1] ;
2540 vnew = MMG5_orvol(mesh->point,pt0->v);
2541 if ( vnew < MMG5_EPSOK ) return 0;
2542
2543 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2544 pt0->v[ip0] = vx[ie1] ; pt0->v[ip3] = vx[ie5] ;
2545 vnew = MMG5_orvol(mesh->point,pt0->v);
2546 if ( vnew < MMG5_EPSOK ) return 0;
2547
2548 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2549 pt0->v[ip0] = vx[ie0] ; pt0->v[ip2] = vx[ie1] ;
2550 vnew = MMG5_orvol(mesh->point,pt0->v);
2551 if ( vnew < MMG5_EPSOK ) return 0;
2552
2553 memcpy(pt0,pt,sizeof(MMG5_Tetra));
2554 pt0->v[ip0] = vx[ie1] ; pt0->v[ip2] = vx[ie5] ;
2555 vnew = MMG5_orvol(mesh->point,pt0->v);
2556 if ( vnew < MMG5_EPSOK ) return 0;
2557 }
2558
2559 return 1;
2560}
2561
2574int MMG5_split3op(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6],int8_t metRidTyp){
2575 MMG5_pTetra pt[5];
2576 MMG5_xTetra xt[5];
2577 MMG5_pxTetra pxt0;
2578 MMG5_int iel;
2579 MMG5_int newtet[5];
2580 uint8_t imin12,imin03,tau[4],sym[4],symed[6],ip0,ip1,ip2,ip3,ie0,ie1;
2581 uint8_t ie2,ie3,ie4,ie5,isxt[5],firstxt,i;
2582 const uint8_t *taued=NULL;
2583 const int ne=4;
2584
2585 pt[0] = &mesh->tetra[k];
2586 newtet[0]=k;
2587
2588 /* Set permutation /symmetry of vertices : generic case : 35 */
2589 MMG3D_configSplit3op(pt[0],vx,tau,&taued,sym,symed,&ip0,&ip1,&ip2,&ip3,
2590 &ie0,&ie1,&ie2,&ie3,&ie4,&ie5,&imin03,&imin12);
2591 pt[0]->flag = 0;
2592
2593 /* create 3 new tetras, the fifth being created only if needed. */
2594 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
2595 return 0;
2596 }
2597 newtet[4] = 0;
2598
2599 if ( !((imin12 == ip1) && (imin03 == ip3)) ) {
2600 iel = MMG3D_newElt(mesh);
2601 if ( !iel ) {
2603 fprintf(stderr,"\n ## Error: %s: unable to allocate"
2604 " a new element.\n",__func__);
2606 fprintf(stderr," Exit program.\n");
2607 return 0);
2608 pt[0] = &mesh->tetra[newtet[0]];
2609 pt[1] = &mesh->tetra[newtet[1]];
2610 pt[2] = &mesh->tetra[newtet[2]];
2611 pt[3] = &mesh->tetra[newtet[3]];
2612 }
2613 pt[4] = &mesh->tetra[iel];
2614 pt[4] = memcpy(pt[4],pt[0],sizeof(MMG5_Tetra));
2615 newtet[4]=iel;
2616
2617 if ( pt[0]->xt ) {
2618 memcpy(&xt[4],pxt0, sizeof(MMG5_xTetra));
2619 }
2620
2621 else {
2622 memset(&xt[4],0, sizeof(MMG5_xTetra));
2623 }
2624 }
2625
2626 /* Generic formulation of split of 3 edges in op configuration (edges 0,1,5 splitted) */
2627 if ( (imin12 == ip2) && (imin03 == ip0) ) {
2628 pt[0]->v[ip0] = vx[ie1] ; pt[0]->v[ip1] = vx[ie0] ; pt[0]->v[ip3] = vx[ie5] ;
2629 xt[0].tag[ie0] = 0; xt[0].tag[ie2] = 0;
2630 xt[0].tag[ie3] = 0; xt[0].tag[ie4] = 0;
2631 xt[0].edg[ie0] = 0; xt[0].edg[ie2] = 0;
2632 xt[0].edg[ie3] = 0; xt[0].edg[ie4] = 0;
2633 xt[0].ref [ip0] = 0 ; xt[0].ref [ip2] = 0 ;
2634 xt[0].ftag[ip0] = 0 ; xt[0].ftag[ip2] = 0 ;
2635 MG_SET(xt[0].ori, ip0); MG_SET(xt[0].ori, ip2);
2636
2637 pt[1]->v[ip0] = vx[ie0] ; pt[1]->v[ip3] = vx[ie5] ;
2638 xt[1].tag[ie1] = 0; xt[1].tag[ie2] = 0;
2639 xt[1].tag[ie4] = 0; xt[1].edg[ie1] = 0;
2640 xt[1].edg[ie2] = 0; xt[1].edg[ie4] = 0;
2641 xt[1].ref [ip1] = 0 ; xt[1] .ref[ip2] = 0 ;
2642 xt[1].ftag[ip1] = 0 ; xt[1].ftag[ip2] = 0 ;
2643 MG_SET(xt[1].ori, ip1); MG_SET(xt[1].ori, ip2);
2644
2645 pt[2]->v[ip0] = vx[ie0] ; pt[2]->v[ip2] = vx[ie5] ;
2646 xt[2].tag[ie1] = 0; xt[2].tag[ie2] = 0;
2647 xt[2].tag[ie3] = 0; xt[2].edg[ie2] = 0;
2648 xt[2].edg[ie3] = 0;
2649 xt[2].ref [ip1] = 0 ; xt[2].ref [ip3] = 0 ;
2650 xt[2].ftag[ip1] = 0 ; xt[2].ftag[ip3] = 0 ;
2651 MG_SET(xt[2].ori, ip1); MG_SET(xt[2].ori, ip3);
2652
2653 pt[3]->v[ip1] = vx[ie0] ; pt[3]->v[ip2] = vx[ie1] ; pt[3]->v[ip3] = vx[ie5] ;
2654 xt[3].tag[ie2] = 0; xt[3].tag[ie3] = 0;
2655 xt[3].tag[ie4] = 0; xt[3].tag[ie5] = 0;
2656 xt[3].edg[ie2] = 0; xt[3].edg[ie3] = 0;
2657 xt[3].edg[ie4] = 0; xt[3].edg[ie5] = 0;
2658 xt[3].ref [ip0] = 0 ; xt[3].ref [ip2] = 0 ;
2659 xt[3].ftag[ip0] = 0 ; xt[3].ftag[ip2] = 0 ;
2660 MG_SET(xt[3].ori, ip0); MG_SET(xt[3].ori, ip2);
2661
2662 pt[4]->v[ip1] = vx[ie0] ; pt[4]->v[ip2] = vx[ie5];
2663 xt[4].tag[ie1] = 0; xt[4].tag[ie3] = 0;
2664 xt[4].tag[ie4] = 0; xt[4].edg[ie1] = 0;
2665 xt[4].edg[ie3] = 0; xt[4].edg[ie4] = 0;
2666 xt[4].ref [ip0] = 0 ; xt[4].ref [ip3] = 0 ;
2667 xt[4].ftag[ip0] = 0 ; xt[4].ftag[ip3] = 0 ;
2668 MG_SET(xt[4].ori, ip0); MG_SET(xt[4].ori, ip3);
2669 }
2670
2671 else if ( (imin12 == ip1) && (imin03 == ip0) ) {
2672 pt[0]->v[ip0] = vx[ie1] ; pt[0]->v[ip3] = vx[ie5] ;
2673 xt[0].tag[ie0] = 0; xt[0].tag[ie2] = 0;
2674 xt[0].tag[ie4] = 0; xt[0].edg[ie0] = 0;
2675 xt[0].edg[ie2] = 0; xt[0].edg[ie4] = 0;
2676 xt[0].ref[ip2] = 0 ;
2677 xt[0].ftag[ip2] = 0 ;
2678 MG_SET(xt[0].ori, ip2);
2679
2680 pt[1]->v[ip0] = vx[ie0] ; pt[1]->v[ip2] = vx[ie1] ; pt[1]->v[ip3] = vx[ie5];
2681 xt[1].tag[ie1] = 0; xt[1].tag[ie2] = 0;
2682 xt[1].tag[ie3] = 0; xt[1].tag[ie4] = 0;
2683 xt[1].tag[ie5] = 0; xt[1].edg[ie1] = 0;
2684 xt[1].edg[ie2] = 0; xt[1].edg[ie3] = 0;
2685 xt[1].edg[ie4] = 0; xt[1].edg[ie5] = 0;
2686 xt[1].ref [ip0] = 0 ; xt[1].ref [ip1] = 0 ; xt[1].ref [ip2] = 0 ;
2687 xt[1].ftag[ip0] = 0 ; xt[1].ftag[ip1] = 0 ; xt[1].ftag[ip2] = 0 ;
2688 MG_SET(xt[1].ori, ip0); MG_SET(xt[1].ori, ip1); MG_SET(xt[1].ori, ip2);
2689
2690 pt[2]->v[ip0] = vx[ie0] ; pt[2]->v[ip2] = vx[ie5] ;
2691 xt[2].tag[ie1] = 0; xt[2].tag[ie2] = 0;
2692 xt[2].tag[ie3] = 0; xt[2].edg[ie1] = 0;
2693 xt[2].edg[ie2] = 0; xt[2].edg[ie3] = 0;
2694 xt[2].ref [ip1] = 0 ; xt[2].ref [ip3] = 0 ;
2695 xt[2].ftag[ip1] = 0 ; xt[2].ftag[ip3] = 0 ;
2696 MG_SET(xt[2].ori, ip1); MG_SET(xt[2].ori, ip3);
2697
2698 pt[3]->v[ip1] = vx[ie0] ; pt[3]->v[ip2] = vx[ie5];
2699 xt[3].tag[ie1] = 0; xt[3].tag[ie3] = 0;
2700 xt[3].tag[ie4] = 0; xt[3].edg[ie1] = 0;
2701 xt[3].edg[ie3] = 0; xt[3].edg[ie4] = 0;
2702 xt[3].ref [ip0] = 0 ; xt[3].ref [ip3] = 0 ;
2703 xt[3].ftag[ip0] = 0 ; xt[3].ftag[ip3] = 0 ;
2704 MG_SET(xt[3].ori, ip0); MG_SET(xt[3].ori, ip3);
2705
2706 pt[4]->v[ip1] = vx[ie0] ; pt[4]->v[ip2] = vx[ie1]; pt[4]->v[ip3] = vx[ie5];
2707 xt[4].tag[ie2] = 0; xt[4].tag[ie3] = 0;
2708 xt[4].tag[ie4] = 0; xt[4].tag[ie5] = 0;
2709 xt[4].edg[ie2] = 0; xt[4].edg[ie3] = 0;
2710 xt[4].edg[ie4] = 0; xt[4].edg[ie5] = 0;
2711 xt[4].ref [ip0] = 0 ; xt[4].ref [ip2] = 0 ;
2712 xt[4].ftag[ip0] = 0 ; xt[4].ftag[ip2] = 0 ;
2713 MG_SET(xt[4].ori, ip0); MG_SET(xt[4].ori, ip2);
2714 }
2715
2716 else if ( (imin12 == ip2) && (imin03 == ip3) ) {
2717 pt[0]->v[ip1] = vx[ie0] ; pt[0]->v[ip2] = vx[ie1] ;
2718 xt[0].tag[ie3] = 0; xt[0].tag[ie4] = 0;
2719 xt[0].tag[ie5] = 0; xt[0].edg[ie3] = 0;
2720 xt[0].edg[ie4] = 0; xt[0].edg[ie5] = 0;
2721 xt[0].ref[ip0] = 0 ;
2722 xt[0].ftag[ip0] = 0 ;
2723 MG_SET(xt[0].ori, ip0);
2724
2725 pt[1]->v[ip0] = vx[ie1] ; pt[1]->v[ip1] = vx[ie0] ; pt[1]->v[ip2] = vx[ie5];
2726 xt[1].tag[ie0] = 0; xt[1].tag[ie1] = 0;
2727 xt[1].tag[ie2] = 0; xt[1].tag[ie3] = 0;
2728 xt[1].tag[ie4] = 0; xt[1].edg[ie0] = 0;
2729 xt[1].edg[ie1] = 0; xt[1].edg[ie2] = 0;
2730 xt[1].edg[ie3] = 0; xt[1].edg[ie4] = 0;
2731 xt[1].ref [ip0] = 0 ; xt[1].ref [ip2] = 0 ; xt[1].ref [ip3] = 0 ;
2732 xt[1].ftag[ip0] = 0 ; xt[1].ftag[ip2] = 0 ; xt[1].ftag[ip3] = 0 ;
2733 MG_SET(xt[1].ori, ip1); MG_SET(xt[1].ori, ip2); MG_SET(xt[1].ori, ip3);
2734
2735 pt[2]->v[ip0] = vx[ie0] ; pt[2]->v[ip2] = vx[ie5] ;
2736 xt[2].tag[ie1] = 0; xt[2].tag[ie2] = 0;
2737 xt[2].tag[ie3] = 0; xt[2].edg[ie1] = 0;
2738 xt[2].edg[ie2] = 0; xt[2].edg[ie3] = 0;
2739 xt[2].ref [ip1] = 0 ; xt[2].ref [ip3] = 0 ;
2740 xt[2].ftag[ip1] = 0 ; xt[2].ftag[ip3] = 0 ;
2741 MG_SET(xt[2].ori, ip1); MG_SET(xt[2].ori, ip3);
2742
2743 pt[3]->v[ip0] = vx[ie1] ; pt[3]->v[ip1] = vx[ie0]; pt[3]->v[ip3] = vx[ie5];
2744 xt[3].tag[ie0] = 0; xt[3].tag[ie2] = 0;
2745 xt[3].tag[ie3] = 0; xt[3].tag[ie4] = 0;
2746 xt[3].edg[ie0] = 0; xt[3].edg[ie2] = 0;
2747 xt[3].edg[ie3] = 0; xt[3].edg[ie4] = 0;
2748 xt[3].ref [ip0] = 0 ; xt[3].ref [ip2] = 0 ;
2749 xt[3].ftag[ip0] = 0 ; xt[3].ftag[ip2] = 0 ;
2750 MG_SET(xt[3].ori, ip0); MG_SET(xt[3].ori, ip2);
2751
2752 pt[4]->v[ip0] = vx[ie0] ; pt[4]->v[ip3] = vx[ie5];
2753 xt[4].tag[ie1] = 0; xt[4].tag[ie2] = 0;
2754 xt[4].tag[ie4] = 0; xt[4].edg[ie1] = 0;
2755 xt[4].edg[ie2] = 0; xt[4].edg[ie4] = 0;
2756 xt[4].ref [ip1] = 0 ; xt[4].ref [ip2] = 0 ;
2757 xt[4].ftag[ip1] = 0 ; xt[4].ftag[ip2] = 0 ;
2758 MG_SET(xt[4].ori, ip1); MG_SET(xt[4].ori, ip2);
2759 }
2760 else {
2761 assert((imin12 == ip1) && (imin03 == ip3)) ;
2762
2763 pt[0]->v[ip1] = vx[ie0] ; pt[0]->v[ip2] = vx[ie1] ;
2764 xt[0].tag[ie3] = 0; xt[0].tag[ie4] = 0;
2765 xt[0].tag[ie5] = 0; xt[0].edg[ie3] = 0;
2766 xt[0].edg[ie4] = 0; xt[0].edg[ie5] = 0;
2767 xt[0].ref [ip0] = 0 ;
2768 xt[0].ftag[ip0] = 0 ;
2769 MG_SET(xt[0].ori, ip0);
2770
2771 pt[1]->v[ip0] = vx[ie1] ; pt[1]->v[ip3] = vx[ie5] ;
2772 xt[1].tag[ie0] = 0; xt[1].tag[ie2] = 0;
2773 xt[1].tag[ie4] = 0; xt[1].edg[ie0] = 0;
2774 xt[1].edg[ie2] = 0; xt[1].edg[ie4] = 0;
2775 xt[1].ref [ip2] = 0 ;
2776 xt[1].ftag[ip2] = 0 ;
2777 MG_SET(xt[1].ori, ip2);
2778
2779 pt[2]->v[ip0] = vx[ie0] ; pt[2]->v[ip2] = vx[ie1] ;
2780 xt[2].tag[ie1] = 0; xt[2].tag[ie2] = 0;
2781 xt[2].tag[ie3] = 0; xt[2].tag[ie5] = 0;
2782 xt[2].edg[ie1] = 0; xt[2].edg[ie2] = 0;
2783 xt[2].edg[ie3] = 0; xt[2].edg[ie5] = 0;
2784 xt[2].ref [ip0] = 0 ; xt[2].ref [ip1] = 0 ;
2785 xt[2].ftag[ip0] = 0 ; xt[2].ftag[ip1] = 0 ;
2786 MG_SET(xt[2].ori, ip0); MG_SET(xt[2].ori, ip1);
2787
2788 pt[3]->v[ip0] = vx[ie1] ; pt[3]->v[ip2] = vx[ie5] ;
2789 xt[3].tag[ie0] = 0; xt[3].tag[ie1] = 0;
2790 xt[3].tag[ie2] = 0; xt[3].tag[ie3] = 0;
2791 xt[3].edg[ie0] = 0; xt[3].edg[ie1] = 0;
2792 xt[3].edg[ie2] = 0; xt[3].edg[ie3] = 0;
2793 xt[3].ref [ip2] = 0 ; xt[3].ref [ip3] = 0 ;
2794 xt[3].ftag[ip2] = 0 ; xt[3].ftag[ip3] = 0 ;
2795 MG_SET(xt[3].ori, ip2); MG_SET(xt[3].ori, ip3);
2796 }
2797
2798 /* Assignation of the xt fields to the appropriate tets */
2799 if ( (imin12 == ip1) && (imin03 == ip3) ) {
2800 isxt[0] = isxt[1] = isxt[2] = isxt[3] = 0;
2801
2802 for (i=0; i<4; i++) {
2803 int j;
2804 for (j=0; j<ne; j++) {
2805 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
2806 }
2807 }
2808
2809 if ( pt[0]->xt ) {
2810 if ( isxt[0] ) {
2811 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
2812 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
2813
2814 for (i=1; i<4; i++) {
2815 if ( isxt[i] ) {
2816 mesh->xt++;
2817 if ( mesh->xt >= mesh->xtmax ) {
2818 /* realloc of xtetras table */
2820 "larger xtetra table",
2821 mesh->xt--;
2822 fprintf(stderr," Exit program.\n");
2823 return 0);
2824 }
2825 pt[i]->xt = mesh->xt;
2826 pxt0 = &mesh->xtetra[mesh->xt];
2827 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2828 }
2829 }
2830 }
2831 else {
2832 firstxt = 1;
2833 pt[1]->xt = pt[2]->xt = pt[3]->xt = 0;
2834
2835 for (i=1; i<4; i++) {
2836 if ( isxt[i] ) {
2837 if ( firstxt ) {
2838 firstxt = 0;
2839 pt[i]->xt = pt[0]->xt;
2840 pxt0 = &mesh->xtetra[(pt[i])->xt];
2841 memcpy(pxt0,&(xt[i]),sizeof(MMG5_xTetra));
2842 }
2843 else {
2844 mesh->xt++;
2845 if ( mesh->xt > mesh->xtmax ) {
2846 /* realloc of xtetras table */
2848 "larger xtetra table",
2849 mesh->xt--;
2850 fprintf(stderr," Exit program.\n");
2851 return 0);
2852 }
2853 pt[i]->xt = mesh->xt;
2854 pxt0 = &mesh->xtetra[mesh->xt];
2855 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2856 }
2857 }
2858 }
2859 pt[0]->xt = 0;
2860 }
2861 }
2862
2863 }
2864 else {
2865 isxt[0] = isxt[1] = isxt[2] = isxt[3] = isxt[4] = 0;
2866
2867 for (i=0; i<4; i++) {
2868 int j;
2869 for (j=0; j<=ne; j++) {
2870 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
2871 }
2872 }
2873
2874 if ( pt[0]->xt ) {
2875 if ( isxt[0] ) {
2876 memcpy(pxt0,&(xt[0]),sizeof(MMG5_xTetra));
2877 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = 0;
2878
2879 for(i=1; i<5; i++) {
2880 if ( isxt[i] ) {
2881 mesh->xt++;
2882 if ( mesh->xt > mesh->xtmax ) {
2883 /* realloc of xtetras table */
2885 "larger xtetra table",
2886 mesh->xt--;
2887 fprintf(stderr," Exit program.\n");
2888 return 0);
2889 }
2890 pt[i]->xt = mesh->xt;
2891 pxt0 = &mesh->xtetra[mesh->xt];
2892 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2893 }
2894 }
2895 }
2896 else {
2897 firstxt = 1;
2898 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = 0;
2899
2900 for (i=1; i<5; i++) {
2901 if ( isxt[i] ) {
2902 if ( firstxt ) {
2903 firstxt = 0;
2904 pt[i]->xt = pt[0]->xt;
2905 pxt0 = &mesh->xtetra[pt[i]->xt];
2906 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2907 }
2908 else {
2909 mesh->xt++;
2910 if ( mesh->xt > mesh->xtmax ) {
2911 /* realloc of xtetras table */
2913 "larger xtetra table",
2914 mesh->xt--;
2915 fprintf(stderr," Exit program.\n");
2916 return 0);
2917 }
2918 pt[i]->xt = mesh->xt;
2919 pxt0 = &mesh->xtetra[mesh->xt];
2920 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
2921 }
2922 }
2923 }
2924 pt[0]->xt = 0;
2925 }
2926 }
2927 }
2928
2929 /* Quality update */
2930 if ( (!metRidTyp) && met->m && met->size>1 ) {
2931 pt[0]->qual=MMG5_caltet33_ani(mesh,met,pt[0]);
2932 pt[1]->qual=MMG5_caltet33_ani(mesh,met,pt[1]);
2933 pt[2]->qual=MMG5_caltet33_ani(mesh,met,pt[2]);
2934 pt[3]->qual=MMG5_caltet33_ani(mesh,met,pt[3]);
2935 if ( !((imin12 == ip1) && (imin03 == ip3)) ) {
2936 pt[4]->qual=MMG5_caltet33_ani(mesh,met,pt[4]);
2937 }
2938 }
2939 else {
2940 pt[0]->qual=MMG5_orcal(mesh,met,newtet[0]);
2941 pt[1]->qual=MMG5_orcal(mesh,met,newtet[1]);
2942 pt[2]->qual=MMG5_orcal(mesh,met,newtet[2]);
2943 pt[3]->qual=MMG5_orcal(mesh,met,newtet[3]);
2944 if ( !((imin12 == ip1) && (imin03 == ip3)) ) {
2945 pt[4]->qual=MMG5_orcal(mesh,met,newtet[4]);
2946 }
2947 }
2948 return 1;
2949}
2950
2951
2964MMG5_int MMG5_split4bar(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k,int8_t metRidTyp) {
2965 MMG5_pTetra pt[4];
2966 MMG5_pPoint ppt;
2967 MMG5_xTetra xt[4];
2968 MMG5_pxTetra pxt0;
2969 double o[3],cb[4];
2970 MMG5_int ib,iadr,*adja,adj1,adj2,adj3,newtet[4],src;
2971 int i;
2972 uint8_t isxt[4],firstxt;
2973 const int ne=4;
2974
2975 pt[0] = &mesh->tetra[k];
2976 pt[0]->flag = 0;
2977 newtet[0]=k;
2978
2979 o[0] = o[1] = o[2] = 0.0;
2980 for (i=0; i<4; i++) {
2981 ib = pt[0]->v[i];
2982 ppt = &mesh->point[ib];
2983 o[0] += ppt->c[0];
2984 o[1] += ppt->c[1];
2985 o[2] += ppt->c[2];
2986 }
2987 o[0] *= 0.25;
2988 o[1] *= 0.25;
2989 o[2] *= 0.25;
2990
2991 cb[0] = 0.25; cb[1] = 0.25; cb[2] = 0.25; cb[3] = 0.25;
2992#ifdef USE_POINTMAP
2993 src = mesh->point[pt[0]->v[0]].src;
2994#else
2995 src = 1;
2996#endif
2997 ib = MMG3D_newPt(mesh,o,0,src);
2998 if ( !ib ) {
3000 fprintf(stderr,"\n ## Error: %s: unable to allocate"
3001 " a new point\n",__func__);
3003 return 0
3004 ,o,0,src);
3005 }
3006 if ( met->m ) {
3007 if ( !metRidTyp && met->size > 1 )
3008 MMG5_interp4bar33_ani(mesh,met,k,ib,cb);
3009 else
3010 MMG5_interp4bar(mesh,met,k,ib,cb);
3011 }
3012
3013 /* create 3 new tetras */
3014 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
3015 return 0;
3016 }
3017
3018 /* Update adjacency */
3019 if ( mesh->adja ) {
3020 iadr = 4*(newtet[0]-1)+1;
3021 adja = &mesh->adja[iadr];
3022
3023 /* Store the old adjacents */
3024 adj1 = mesh->adja[iadr+1];
3025 adj2 = mesh->adja[iadr+2];
3026 adj3 = mesh->adja[iadr+3];
3027
3028 /* Update the new ones */
3029 adja[1] = 4*newtet[1];
3030 adja[2] = 4*newtet[2];
3031 adja[3] = 4*newtet[3];
3032
3033 iadr = 4*(newtet[1]-1)+1;
3034 adja = &mesh->adja[iadr];
3035 adja[0] = 4*newtet[0] + 1;
3036 adja[1] = adj1;
3037 adja[2] = 4*newtet[2] + 1;
3038 adja[3] = 4*newtet[3] + 1;
3039 if ( adj1 )
3040 mesh->adja[4*(adj1/4-1) + 1+adj1%4] = 4*newtet[1]+1;
3041
3042 iadr = 4*(newtet[2]-1)+1;
3043 adja = &mesh->adja[iadr];
3044 adja[0] = 4*newtet[0] + 2;
3045 adja[1] = 4*newtet[1] + 2;
3046 adja[2] = adj2;
3047 adja[3] = 4*newtet[3] + 2;
3048 if ( adj2 )
3049 mesh->adja[4*(adj2/4-1) + 1+adj2%4] = 4*newtet[2]+2;
3050
3051 iadr = 4*(newtet[3]-1)+1;
3052 adja = &mesh->adja[iadr];
3053 adja[0] = 4*newtet[0] + 3;
3054 adja[1] = 4*newtet[1] + 3;
3055 adja[2] = 4*newtet[2] + 3;
3056 adja[3] = adj3;
3057 if ( adj3 )
3058 mesh->adja[4*(adj3/4-1) + 1+adj3%4] = 4*newtet[3]+3;
3059 }
3060
3061 /* Update vertices and xt fields */
3062 pt[0]->v[0] = pt[1]->v[1] = pt[2]->v[2] = pt[3]->v[3] = ib;
3063
3064 xt[0].tag[0] = 0; xt[0].edg[0] = 0;
3065 xt[0].tag[1] = 0; xt[0].edg[1] = 0;
3066 xt[0].tag[2] = 0; xt[0].edg[2] = 0;
3067 xt[0].ref [1] = 0; xt[0].ref [2] = 0; xt[0].ref [3] = 0;
3068 xt[0].ftag[1] = 0; xt[0].ftag[2] = 0; xt[0].ftag[3] = 0;
3069 MG_SET(xt[0].ori, 1); MG_SET(xt[0].ori, 2); MG_SET(xt[0].ori, 3);
3070
3071 xt[1].tag[0] = 0; xt[1].edg[0] = 0;
3072 xt[1].tag[3] = 0; xt[1].edg[3] = 0;
3073 xt[1].tag[4] = 0; xt[1].edg[4] = 0;
3074 xt[1].ref [0] = 0; xt[1].ref [2] = 0; xt[1].ref [3] = 0;
3075 xt[1].ftag[0] = 0; xt[1].ftag[2] = 0; xt[1].ftag[3] = 0;
3076 MG_SET(xt[1].ori, 0); MG_SET(xt[1].ori, 2); MG_SET(xt[1].ori, 3);
3077
3078 xt[2].tag[1] = 0; xt[2].edg[1] = 0;
3079 xt[2].tag[3] = 0; xt[2].edg[3] = 0;
3080 xt[2].tag[5] = 0; xt[2].edg[5] = 0;
3081 xt[2].ref [0] = 0; xt[2].ref [1] = 0; xt[2].ref [3] = 0;
3082 xt[2].ftag[0] = 0; xt[2].ftag[1] = 0; xt[2].ftag[3] = 0;
3083 MG_SET(xt[2].ori, 0); MG_SET(xt[2].ori, 1); MG_SET(xt[2].ori, 3);
3084
3085 xt[3].tag[2] = 0; xt[3].edg[2] = 0;
3086 xt[3].tag[4] = 0; xt[3].edg[4] = 0;
3087 xt[3].tag[5] = 0; xt[3].edg[5] = 0;
3088 xt[3].ref [0] = 0; xt[3].ref [1] = 0; xt[3].ref [2] = 0;
3089 xt[3].ftag[0] = 0; xt[3].ftag[1] = 0; xt[3].ftag[2] = 0;
3090 MG_SET(xt[3].ori, 0); MG_SET(xt[3].ori, 1); MG_SET(xt[3].ori, 2);
3091
3092 /* Assignation of the xt fields to the appropriate tets */
3093 memset(isxt,0,ne*sizeof(int8_t));
3094 for (i=0; i<ne; i++) {
3095 int j;
3096 for (j=0; j<ne; j++) {
3097 if ( xt[j].ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
3098 }
3099 }
3100
3101 if ( pt[0]->xt ) {
3102 if ( isxt[0] ) {
3103 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
3104 for (i=1; i<4; i++) {
3105 if ( isxt[i] ) {
3106 mesh->xt++;
3107 if ( mesh->xt > mesh->xtmax ) {
3108 /* realloc of xtetras table */
3110 "larger xtetra table",
3111 mesh->xt--;
3112 return 0);
3113 }
3114 pt[i]->xt = mesh->xt;
3115 pxt0 = &mesh->xtetra[mesh->xt];
3116 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3117 }
3118 else {
3119 pt[i]->xt = 0;
3120 }
3121 }
3122 }
3123 else {
3124 firstxt = 1;
3125 for (i=1; i<4; i++) {
3126 if ( isxt[i] ) {
3127 if ( firstxt ) {
3128 firstxt = 0;
3129 pt[i]->xt = pt[0]->xt;
3130 pxt0 = &mesh->xtetra[(pt[i])->xt];
3131 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3132 }
3133 else {
3134 mesh->xt++;
3135 if ( mesh->xt > mesh->xtmax ) {
3136 /* realloc of xtetras table */
3138 "larger xtetra table",
3139 mesh->xt--;
3140 return 0);
3141 }
3142 pt[i]->xt = mesh->xt;
3143 pxt0 = &mesh->xtetra[mesh->xt];
3144 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3145 }
3146 }
3147 else {
3148 pt[i]->xt = 0;
3149 }
3150 }
3151 pt[0]->xt = 0;
3152 }
3153 }
3154
3155 /* Quality update */
3156 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
3157
3158 return ib;
3159}
3160
3173static inline
3174void MMG3D_configSplit4sf(MMG5_pTetra pt,MMG5_int vx[6],uint8_t tau[4],
3175 const uint8_t **taued, uint8_t *imin23,uint8_t *imin12) {
3176
3177 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
3178 (*taued) = &MMG5_permedge[0][0];
3179 switch(pt->flag){
3180 case 29:
3181 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
3182 (*taued) = &MMG5_permedge[5][0];
3183 break;
3184
3185 case 53:
3186 tau[0] = 3 ; tau[1] = 0 ; tau[2] = 2 ; tau[3] = 1;
3187 (*taued) = &MMG5_permedge[9][0];
3188 break;
3189
3190 case 60:
3191 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
3192 (*taued) = &MMG5_permedge[10][0];
3193 break;
3194
3195 case 57:
3196 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
3197 (*taued) = &MMG5_permedge[4][0];
3198 break;
3199
3200 case 58:
3201 tau[0] = 2 ; tau[1] = 3 ; tau[2] = 0 ; tau[3] = 1;
3202 (*taued) = &MMG5_permedge[8][0];
3203 break;
3204
3205 case 27:
3206 tau[0] = 1 ; tau[1] = 0 ; tau[2] = 3 ; tau[3] = 2;
3207 (*taued) = &MMG5_permedge[3][0];
3208 break;
3209
3210 case 15:
3211 tau[0] = 0 ; tau[1] = 2 ; tau[2] = 3 ; tau[3] = 1;
3212 (*taued) = &MMG5_permedge[1][0];
3213 break;
3214
3215 case 43:
3216 tau[0] = 2 ; tau[1] = 1 ; tau[2] = 3 ; tau[3] = 0;
3217 (*taued) = &MMG5_permedge[7][0];
3218 break;
3219
3220 case 39:
3221 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
3222 (*taued) = &MMG5_permedge[2][0];
3223 break;
3224
3225 case 54:
3226 tau[0] = 3 ; tau[1] = 2 ; tau[2] = 1 ; tau[3] = 0;
3227 (*taued) = &MMG5_permedge[11][0];
3228 break;
3229
3230 case 46:
3231 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
3232 (*taued) = &MMG5_permedge[6][0];
3233 break;
3234 }
3235
3236 (*imin23) = (pt->v[tau[2]] < pt->v[tau[3]]) ? tau[2] : tau[3];
3237 (*imin12) = (pt->v[tau[1]] < pt->v[tau[2]]) ? tau[1] : tau[2];
3238}
3239
3251int MMG3D_split4sf_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
3252 MMG5_pTetra pt,pt0;
3253 double vold,vnew;
3254 uint8_t tau[4];
3255 uint8_t imin23,imin12;
3256 const uint8_t *taued = NULL;
3257
3258 pt = &mesh->tetra[k];
3259 pt0 = &mesh->tetra[0];
3260 vold = MMG5_orvol(mesh->point,pt->v);
3261
3262 if ( vold < MMG5_EPSOK ) return 0;
3263
3264 /* Set permutation of vertices : reference configuration : 23 */
3265 MMG3D_configSplit4sf(pt,vx,tau,&taued,&imin23,&imin12);
3266
3267 /* Generic formulation of split of 4 edges (with 3 on same face) */
3268 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3269 pt0->v[tau[1]] = vx[taued[0]];
3270 pt0->v[tau[2]] = vx[taued[1]];
3271 pt0->v[tau[3]] = vx[taued[2]];
3272 vnew = MMG5_orvol(mesh->point,pt0->v);
3273 if ( vnew < MMG5_EPSOK ) return 0;
3274
3275 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3276 pt0->v[tau[0]] = vx[taued[2]];
3277 pt0->v[tau[1]] = vx[taued[0]];
3278 pt0->v[tau[2]] = vx[taued[1]];
3279 pt0->v[tau[3]] = vx[taued[4]] ;
3280 vnew = MMG5_orvol(mesh->point,pt0->v);
3281 if ( vnew < MMG5_EPSOK ) return 0;
3282
3283 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3284 if ( imin12 == tau[1] ) {
3285 pt0->v[tau[0]] = vx[taued[0]];
3286 pt0->v[tau[2]] = vx[taued[1]];
3287 pt0->v[tau[3]] = vx[taued[4]];
3288 vnew = MMG5_orvol(mesh->point,pt0->v);
3289 if ( vnew < MMG5_EPSOK ) return 0;
3290
3291 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3292 pt0->v[tau[0]] = vx[taued[1]];
3293 pt0->v[tau[3]] = vx[taued[4]];
3294 vnew = MMG5_orvol(mesh->point,pt0->v);
3295 if ( vnew < MMG5_EPSOK ) return 0;
3296 }
3297 else {
3298 pt0->v[tau[0]] = vx[taued[1]];
3299 pt0->v[tau[1]] = vx[taued[0]];
3300 pt0->v[tau[3]] = vx[taued[4]] ;
3301 vnew = MMG5_orvol(mesh->point,pt0->v);
3302 if ( vnew < MMG5_EPSOK ) return 0;
3303
3304 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3305 pt0->v[tau[0]] = vx[taued[0]];
3306 pt0->v[tau[3]] = vx[taued[4]] ;
3307 vnew = MMG5_orvol(mesh->point,pt0->v);
3308 if ( vnew < MMG5_EPSOK ) return 0;
3309 }
3310
3311 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3312 if ( imin23 == tau[2] ) {
3313 pt0->v[tau[0]] = vx[taued[1]];
3314 pt0->v[tau[1]] = vx[taued[4]];
3315 pt0->v[tau[3]] = vx[taued[2]];
3316 vnew = MMG5_orvol(mesh->point,pt0->v);
3317 if ( vnew < MMG5_EPSOK ) return 0;
3318
3319 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3320 pt0->v[tau[0]] = vx[taued[2]];
3321 pt0->v[tau[1]] = vx[taued[4]];
3322 vnew = MMG5_orvol(mesh->point,pt0->v);
3323 if ( vnew < MMG5_EPSOK ) return 0;
3324 }
3325 else {
3326 pt0->v[tau[0]] = vx[taued[2]];
3327 pt0->v[tau[1]] = vx[taued[4]];
3328 pt0->v[tau[2]] = vx[taued[1]];
3329 vnew = MMG5_orvol(mesh->point,pt0->v);
3330 if ( vnew < MMG5_EPSOK ) return 0;
3331
3332 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3333 pt0->v[tau[0]] = vx[taued[1]];
3334 pt0->v[tau[1]] = vx[taued[4]];
3335 vnew = MMG5_orvol(mesh->point,pt0->v);
3336 if ( vnew < MMG5_EPSOK ) return 0;
3337 }
3338
3339 return 1;
3340}
3341
3354int MMG5_split4sf(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
3355 MMG5_pTetra pt[6];
3356 MMG5_xTetra xt[6];
3357 MMG5_pxTetra pxt0;
3358 MMG5_int newtet[6];
3359 int8_t firstxt,isxt[6],j,i;
3360 uint8_t tau[4],imin23,imin12;
3361 const uint8_t *taued = NULL;
3362 const int ne=6;
3363
3364 pt[0] = &mesh->tetra[k];
3365 newtet[0]=k;
3366
3367 /* Set permutation of vertices : reference configuration : 23 */
3368 MMG3D_configSplit4sf(pt[0],vx,tau,&taued,&imin23,&imin12);
3369 pt[0]->flag = 0;
3370
3371 /* create 5 new tetras */
3372 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
3373 return 0;
3374 }
3375
3376 /* Generic formulation of split of 4 edges (with 3 on same face) */
3377 pt[0]->v[tau[1]] = vx[taued[0]] ; pt[0]->v[tau[2]] = vx[taued[1]] ; pt[0]->v[tau[3]] = vx[taued[2]];
3378 xt[0].tag[taued[3]] = 0; xt[0].tag[taued[4]] = 0;
3379 xt[0].tag[taued[5]] = 0; xt[0].edg[taued[3]] = 0;
3380 xt[0].edg[taued[4]] = 0; xt[0].edg[taued[5]] = 0;
3381 xt[0].ref [ tau[0]] = 0 ;
3382 xt[0].ftag[ tau[0]] = 0 ;
3383 MG_SET(xt[0].ori, tau[0]);
3384
3385 pt[1]->v[tau[0]] = vx[taued[2]] ; pt[1]->v[tau[1]] = vx[taued[0]] ;
3386 pt[1]->v[tau[2]] = vx[taued[1]] ; pt[1]->v[tau[3]] = vx[taued[4]] ;
3387 xt[1].tag[taued[0]] = 0; xt[1].tag[taued[1]] = 0;
3388 xt[1].tag[taued[2]] = 0; xt[1].tag[taued[3]] = 0;
3389 xt[1].tag[taued[4]] = 0; xt[1].tag[taued[5]] = 0;
3390 xt[1].edg[taued[0]] = 0; xt[1].edg[taued[1]] = 0;
3391 xt[1].edg[taued[2]] = 0; xt[1].edg[taued[3]] = 0;
3392 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
3393 xt[1].ref [ tau[0]] = 0 ; xt[1].ref [ tau[1]] = 0 ; xt[1].ref [tau[3]] = 0 ;
3394 xt[1].ftag[ tau[0]] = 0 ; xt[1].ftag[ tau[1]] = 0 ; xt[1].ftag[tau[3]] = 0 ;
3395 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[1]); MG_SET(xt[1].ori, tau[3]);
3396
3397 if ( imin12 == tau[1] ) {
3398 pt[2]->v[tau[0]] = vx[taued[0]] ; pt[2]->v[tau[2]] = vx[taued[1]] ; pt[2]->v[tau[3]] = vx[taued[4]] ;
3399 xt[2].tag[taued[1]] = 0; xt[2].tag[taued[2]] = 0;
3400 xt[2].tag[taued[3]] = 0; xt[2].tag[taued[5]] = 0;
3401 xt[2].edg[taued[1]] = 0; xt[2].edg[taued[2]] = 0;
3402 xt[2].edg[taued[3]] = 0; xt[2].edg[taued[5]] = 0;
3403 xt[2].ref [ tau[0]] = 0 ; xt[2].ref [ tau[1]] = 0 ;
3404 xt[2].ftag[ tau[0]] = 0 ; xt[2].ftag[ tau[1]] = 0 ;
3405 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[1]);
3406
3407 pt[3]->v[tau[0]] = vx[taued[1]] ; pt[3]->v[tau[3]] = vx[taued[4]] ;
3408 xt[3].tag[taued[0]] = 0; xt[3].tag[taued[2]] = 0;
3409 xt[3].tag[taued[5]] = 0; xt[3].edg[taued[0]] = 0;
3410 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[5]] = 0;
3411 xt[3].ref [ tau[1]] = 0 ; xt[3].ref [ tau[2]] = 0 ;
3412 xt[3].ftag[ tau[1]] = 0 ; xt[3].ftag[ tau[2]] = 0 ;
3413 MG_SET(xt[3].ori, tau[1]); MG_SET(xt[3].ori, tau[2]);
3414 }
3415 else {
3416 pt[2]->v[tau[0]] = vx[taued[1]] ; pt[2]->v[tau[1]] = vx[taued[0]] ; pt[2]->v[tau[3]] = vx[taued[4]] ;
3417 xt[2].tag[taued[0]] = 0; xt[2].tag[taued[2]] = 0;
3418 xt[2].tag[taued[3]] = 0; xt[2].tag[taued[4]] = 0;
3419 xt[2].tag[taued[5]] = 0; xt[2].edg[taued[0]] = 0;
3420 xt[2].edg[taued[2]] = 0; xt[2].edg[taued[3]] = 0;
3421 xt[2].edg[taued[4]] = 0; xt[2].edg[taued[5]] = 0;
3422 xt[2].ref [ tau[0]] = 0 ; xt[2].ref [ tau[1]] = 0 ; xt[2].ref [tau[2]] = 0 ;
3423 xt[2].ftag[ tau[0]] = 0 ; xt[2].ftag[ tau[1]] = 0 ; xt[2].ftag[tau[2]] = 0 ;
3424 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[1]); MG_SET(xt[2].ori, tau[2]);
3425
3426 pt[3]->v[tau[0]] = vx[taued[0]] ; pt[3]->v[tau[3]] = vx[taued[4]] ;
3427 xt[3].tag[taued[1]] = 0; xt[3].tag[taued[2]] = 0;
3428 xt[3].tag[taued[5]] = 0; xt[3].edg[taued[1]] = 0;
3429 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[5]] = 0;
3430 xt[3].ref [ tau[1]] = 0 ;
3431 xt[3].ftag[ tau[1]] = 0 ;
3432 MG_SET(xt[3].ori, tau[1]);
3433 }
3434
3435 if ( imin23 == tau[2] ) {
3436 pt[4]->v[tau[0]] = vx[taued[1]] ; pt[4]->v[tau[1]] = vx[taued[4]] ; pt[4]->v[tau[3]] = vx[taued[2]] ;
3437 xt[4].tag[taued[0]] = 0; xt[4].tag[taued[2]] = 0;
3438 xt[4].tag[taued[3]] = 0; xt[4].tag[taued[4]] = 0;
3439 xt[4].tag[taued[5]] = 0;
3440 xt[4].edg[taued[0]] = 0; xt[4].edg[taued[2]] = 0;
3441 xt[4].edg[taued[3]] = 0; xt[4].edg[taued[4]] = 0;
3442 xt[4].edg[taued[5]] = 0;
3443 xt[4].ref [ tau[0]] = 0; xt[4].ref [ tau[2]] = 0 ;
3444 xt[4].ref [ tau[3]] = 0 ;
3445 xt[4].ftag[ tau[0]] = 0; xt[4].ftag[ tau[2]] = 0 ;
3446 xt[4].ftag[ tau[3]] = 0 ;
3447 MG_SET(xt[4].ori, tau[0]); MG_SET(xt[4].ori, tau[2]); MG_SET(xt[4].ori, tau[3]);
3448
3449 pt[5]->v[tau[0]] = vx[taued[2]] ; pt[5]->v[tau[1]] = vx[taued[4]] ;
3450 xt[5].tag[taued[0]] = 0; xt[5].tag[taued[1]] = 0;
3451 xt[5].tag[taued[3]] = 0; xt[5].edg[taued[0]] = 0;
3452 xt[5].edg[taued[1]] = 0; xt[5].edg[taued[3]] = 0;
3453 xt[5].ref [ tau[3]] = 0 ;
3454 xt[5].ftag[ tau[3]] = 0 ;
3455 MG_SET(xt[5].ori, tau[3]);
3456 }
3457 else {
3458 pt[4]->v[tau[0]] = vx[taued[2]] ; pt[4]->v[tau[1]] = vx[taued[4]] ; pt[4]->v[tau[2]] = vx[taued[1]] ;
3459 xt[4].tag[taued[0]] = 0; xt[4].tag[taued[1]] = 0;
3460 xt[4].tag[taued[3]] = 0; xt[4].tag[taued[5]] = 0;
3461 xt[4].edg[taued[0]] = 0; xt[4].edg[taued[1]] = 0;
3462 xt[4].edg[taued[3]] = 0; xt[4].edg[taued[5]] = 0;
3463 xt[4].ref [ tau[0]] = 0; xt[4].ref [ tau[3]] = 0 ;
3464 xt[4].ftag[ tau[0]] = 0; xt[4].ftag[ tau[3]] = 0 ;
3465 MG_SET(xt[4].ori, tau[0]); MG_SET(xt[4].ori, tau[3]);
3466
3467 pt[5]->v[tau[0]] = vx[taued[1]] ; pt[5]->v[tau[1]] = vx[taued[4]] ;
3468 xt[5].tag[taued[0]] = 0; xt[5].tag[taued[2]] = 0;
3469 xt[5].tag[taued[3]] = 0; xt[5].edg[taued[0]] = 0;
3470 xt[5].edg[taued[2]] = 0; xt[5].edg[taued[3]] = 0;
3471 xt[5].ref [ tau[2]] = 0; xt[5].ref [ tau[3]] = 0 ;
3472 xt[5].ftag[ tau[2]] = 0; xt[5].ftag[ tau[3]] = 0 ;
3473 MG_SET(xt[5].ori, tau[2]); MG_SET(xt[5].ori, tau[3]);
3474 }
3475
3476 /* Assignation of the xt fields to the appropriate tets */
3477 memset(isxt,0,ne*sizeof(int8_t));
3478 for (i=0; i<4; i++) {
3479 for (j=0; j<ne; j++) {
3480 if ( (xt[j]).ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
3481 }
3482 }
3483
3484 if ( pt[0]->xt ) {
3485 if ( isxt[0] ) {
3486 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
3487 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = 0;
3488
3489 for (i=1; i<6; i++) {
3490 if ( isxt[i] ) {
3491 mesh->xt++;
3492 if ( mesh->xt > mesh->xtmax ) {
3493 /* realloc of xtetras table */
3495 "larger xtetra table",
3496 mesh->xt--;
3497 fprintf(stderr," Exit program.\n");
3498 return 0);
3499 }
3500 pt[i]->xt = mesh->xt;
3501 pxt0 = &mesh->xtetra[mesh->xt];
3502 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3503 }
3504 }
3505 }
3506 else {
3507 firstxt = 1;
3508 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = 0;
3509
3510 for (i=1; i<6; i++) {
3511 if ( isxt[i] ) {
3512 if ( firstxt ) {
3513 firstxt = 0;
3514 pt[i]->xt = pt[0]->xt;
3515 pxt0 = &mesh->xtetra[(pt[i])->xt];
3516 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3517 }
3518 else {
3519 mesh->xt++;
3520 if ( mesh->xt > mesh->xtmax ) {
3521 /* realloc of xtetras table */
3523 "larger xtetra table",
3524 mesh->xt--;
3525 fprintf(stderr," Exit program.\n");
3526 return 0);
3527 }
3528 pt[i]->xt = mesh->xt;
3529 pxt0 = &mesh->xtetra[mesh->xt];
3530 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3531 }
3532 }
3533 }
3534 pt[0]->xt = 0;
3535 }
3536 }
3537
3538 /* Quality update */
3539 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
3540
3541 return 1;
3542}
3543
3555int MMG3D_split4op_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
3556 MMG5_pTetra pt,pt0;
3557 double vold,vnew;
3558 uint8_t tau[4];
3559 uint8_t imin01,imin23;
3560 const uint8_t *taued;
3561
3562 pt = &mesh->tetra[k];
3563 pt0 = &mesh->tetra[0];
3564 vold = MMG5_orvol(mesh->point,pt->v);
3565
3566 if ( vold < MMG5_EPSOK ) return 0;
3567
3568 /* Set permutation of vertices : reference configuration 30 */
3569 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
3570 taued = &MMG5_permedge[0][0];
3571
3572 switch(pt->flag){
3573 case 45:
3574 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
3575 taued = &MMG5_permedge[5][0];
3576 break;
3577
3578 case 51:
3579 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
3580 taued = &MMG5_permedge[4][0];
3581 break;
3582 }
3583
3584 imin01 = (pt->v[tau[0]] < pt->v[tau[1]]) ? tau[0] : tau[1];
3585 imin23 = (pt->v[tau[2]] < pt->v[tau[3]]) ? tau[2] : tau[3];
3586
3587 /* Generic formulation for split of 4 edges, with no 3 edges lying on the same
3588 * face */
3589 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3590 if ( imin01 == tau[0] ) {
3591 pt0->v[tau[2]] = vx[taued[3]]; pt0->v[tau[3]] = vx[taued[4]];
3592 vnew = MMG5_orvol(mesh->point,pt0->v);
3593 if ( vnew < MMG5_EPSOK ) return 0;
3594
3595 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3596 pt0->v[tau[1]] = vx[taued[4]]; pt0->v[tau[2]] = vx[taued[3]];
3597 pt0->v[tau[3]] = vx[taued[2]];
3598 vnew = MMG5_orvol(mesh->point,pt0->v);
3599 if ( vnew < MMG5_EPSOK ) return 0;
3600
3601 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3602 pt0->v[tau[1]] = vx[taued[3]]; pt0->v[tau[2]] = vx[taued[1]];
3603 pt0->v[tau[3]] = vx[taued[2]];
3604 vnew = MMG5_orvol(mesh->point,pt0->v);
3605 if ( vnew < MMG5_EPSOK ) return 0;
3606 }
3607 else {
3608 pt0->v[tau[2]] = vx[taued[1]]; pt0->v[tau[3]] = vx[taued[2]];
3609 vnew = MMG5_orvol(mesh->point,pt0->v);
3610 if ( vnew < MMG5_EPSOK ) return 0;
3611
3612 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3613 pt0->v[tau[0]] = vx[taued[1]]; pt0->v[tau[2]] = vx[taued[3]];
3614 pt0->v[tau[3]] = vx[taued[2]];
3615 vnew = MMG5_orvol(mesh->point,pt0->v);
3616 if ( vnew < MMG5_EPSOK ) return 0;
3617
3618 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3619 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[2]] = vx[taued[3]];
3620 pt0->v[tau[3]] = vx[taued[4]];
3621 vnew = MMG5_orvol(mesh->point,pt0->v);
3622 if ( vnew < MMG5_EPSOK ) return 0;
3623 }
3624
3625 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3626 if ( imin23 == tau[2] ) {
3627 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[4]];
3628 vnew = MMG5_orvol(mesh->point,pt0->v);
3629 if ( vnew < MMG5_EPSOK ) return 0;
3630
3631 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3632 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[3]];
3633 pt0->v[tau[3]] = vx[taued[4]];
3634 vnew = MMG5_orvol(mesh->point,pt0->v);
3635 if ( vnew < MMG5_EPSOK ) return 0;
3636
3637 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3638 pt0->v[tau[0]] = vx[taued[1]]; pt0->v[tau[1]] = vx[taued[3]];
3639 pt0->v[tau[3]] = vx[taued[2]];
3640 vnew = MMG5_orvol(mesh->point,pt0->v);
3641 if ( vnew < MMG5_EPSOK ) return 0;
3642 }
3643 else {
3644 pt0->v[tau[0]] = vx[taued[1]]; pt0->v[tau[1]] = vx[taued[3]];
3645 vnew = MMG5_orvol(mesh->point,pt0->v);
3646 if ( vnew < MMG5_EPSOK ) return 0;
3647
3648 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3649 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[3]];
3650 pt0->v[tau[2]] = vx[taued[1]];
3651 vnew = MMG5_orvol(mesh->point,pt0->v);
3652 if ( vnew < MMG5_EPSOK ) return 0;
3653
3654 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3655 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[4]];
3656 pt0->v[tau[2]] = vx[taued[3]];
3657 vnew = MMG5_orvol(mesh->point,pt0->v);
3658 if ( vnew < MMG5_EPSOK ) return 0;
3659 }
3660
3661 return 1;
3662}
3663
3676int MMG5_split4op(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
3677 MMG5_pTetra pt[6];
3678 MMG5_xTetra xt[6];
3679 MMG5_pxTetra pxt0;
3680 MMG5_int newtet[6];
3681 int8_t flg,firstxt,isxt[6],i,j,imin01,imin23;
3682 uint8_t tau[4];
3683 const uint8_t *taued;
3684 const int ne=6;
3685
3686 pt[0] = &mesh->tetra[k];
3687 flg = pt[0]->flag;
3688 pt[0]->flag = 0;
3689 newtet[0]=k;
3690
3691 /* Set permutation of vertices : reference configuration 30 */
3692 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
3693 taued = &MMG5_permedge[0][0];
3694
3695 switch(flg){
3696 case 45:
3697 tau[0] = 1 ; tau[1] = 3 ; tau[2] = 2 ; tau[3] = 0;
3698 taued = &MMG5_permedge[5][0];
3699 break;
3700
3701 case 51:
3702 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
3703 taued = &MMG5_permedge[4][0];
3704 break;
3705 }
3706
3707 imin01 = ((pt[0])->v[tau[0]] < (pt[0])->v[tau[1]]) ? tau[0] : tau[1];
3708 imin23 = ((pt[0])->v[tau[2]] < (pt[0])->v[tau[3]]) ? tau[2] : tau[3];
3709
3710 /* create 5 new tetras */
3711 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
3712 return 0;
3713 }
3714
3715 /* Generic formulation for split of 4 edges, with no 3 edges lying on the same face */
3716 if ( imin01 == tau[0] ) {
3717 pt[0]->v[tau[2]] = vx[taued[3]] ; pt[0]->v[tau[3]] = vx[taued[4]];
3718 xt[0].tag[taued[1]] = 0; xt[0].tag[taued[5]] = 0;
3719 xt[0].tag[taued[2]] = 0; xt[0].edg[taued[1]] = 0;
3720 xt[0].edg[taued[5]] = 0; xt[0].edg[taued[2]] = 0;
3721 xt[0].ref [ tau[1]] = 0;
3722 xt[0].ftag[ tau[1]] = 0;
3723 MG_SET(xt[0].ori, tau[1]);
3724
3725 pt[1]->v[tau[1]] = vx[taued[4]] ; pt[1]->v[tau[2]] = vx[taued[3]] ; pt[1]->v[tau[3]] = vx[taued[2]];
3726 xt[1].tag[taued[0]] = 0; xt[1].tag[taued[1]] = 0;
3727 xt[1].tag[taued[3]] = 0; xt[1].tag[taued[4]] = 0;
3728 xt[1].tag[taued[5]] = 0; xt[1].edg[taued[0]] = 0;
3729 xt[1].edg[taued[1]] = 0; xt[1].edg[taued[3]] = 0;
3730 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
3731 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[1]] = 0; xt[1].ref [tau[3]] = 0;
3732 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[1]] = 0; xt[1].ftag[tau[3]] = 0;
3733 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[1]); MG_SET(xt[1].ori, tau[3]);
3734
3735 pt[2]->v[tau[1]] = vx[taued[3]] ; pt[2]->v[tau[2]] = vx[taued[1]] ; pt[2]->v[tau[3]] = vx[taued[2]];
3736 xt[2].tag[taued[0]] = 0; xt[2].tag[taued[3]] = 0;
3737 xt[2].tag[taued[4]] = 0; xt[2].tag[taued[5]] = 0;
3738 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[3]] = 0;
3739 xt[2].edg[taued[4]] = 0; xt[2].edg[taued[5]] = 0;
3740 xt[2].ref [ tau[0]] = 0; xt[2].ref [ tau[2]] = 0;
3741 xt[2].ftag[ tau[0]] = 0; xt[2].ftag[ tau[2]] = 0;
3742 MG_SET(xt[2].ori, tau[0]); MG_SET(xt[2].ori, tau[2]);
3743 }
3744 else {
3745 pt[0]->v[tau[2]] = vx[taued[1]] ; pt[0]->v[tau[3]] = vx[taued[2]];
3746 xt[0].tag[taued[3]] = 0; xt[0].tag[taued[4]] = 0;
3747 xt[0].tag[taued[5]] = 0; xt[0].edg[taued[3]] = 0;
3748 xt[0].edg[taued[4]] = 0; xt[0].edg[taued[5]] = 0;
3749 xt[0].ref [ tau[0]] = 0;
3750 xt[0].ftag[ tau[0]] = 0;
3751 MG_SET(xt[0].ori, tau[0]);
3752
3753 pt[1]->v[tau[0]] = vx[taued[1]] ; pt[1]->v[tau[2]] = vx[taued[3]] ; pt[1]->v[tau[3]] = vx[taued[2]];
3754 xt[1].tag[taued[0]] = 0; xt[1].tag[taued[1]] = 0;
3755 xt[1].tag[taued[2]] = 0; xt[1].tag[taued[4]] = 0;
3756 xt[1].tag[taued[5]] = 0; xt[1].edg[taued[0]] = 0;
3757 xt[1].edg[taued[1]] = 0; xt[1].edg[taued[2]] = 0;
3758 xt[1].edg[taued[4]] = 0; xt[1].edg[taued[5]] = 0;
3759 xt[1].ref [ tau[0]] = 0; xt[1].ref [ tau[1]] = 0; xt[1].ref [tau[2]] = 0;
3760 xt[1].ftag[ tau[0]] = 0; xt[1].ftag[ tau[1]] = 0; xt[1].ftag[tau[2]] = 0;
3761 MG_SET(xt[1].ori, tau[0]); MG_SET(xt[1].ori, tau[1]); MG_SET(xt[1].ori, tau[2]);
3762
3763 pt[2]->v[tau[0]] = vx[taued[2]] ; pt[2]->v[tau[2]] = vx[taued[3]] ; pt[2]->v[tau[3]] = vx[taued[4]];
3764 xt[2].tag[taued[0]] = 0; xt[2].tag[taued[1]] = 0;
3765 xt[2].tag[taued[2]] = 0; xt[2].tag[taued[5]] = 0;
3766 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[1]] = 0;
3767 xt[2].edg[taued[2]] = 0; xt[2].edg[taued[5]] = 0;
3768 xt[2].ref [ tau[1]] = 0; xt[2].ref [ tau[3]] = 0;
3769 xt[2].ftag[ tau[1]] = 0; xt[2].ftag[ tau[3]] = 0;
3770 MG_SET(xt[2].ori, tau[1]); MG_SET(xt[2].ori, tau[3]);
3771 }
3772
3773 if ( imin23 == tau[2] ) {
3774 pt[3]->v[tau[0]] = vx[taued[2]] ; pt[3]->v[tau[1]] = vx[taued[4]];
3775 xt[3].tag[taued[0]] = 0; xt[3].tag[taued[1]] = 0;
3776 xt[3].tag[taued[3]] = 0; xt[3].edg[taued[0]] = 0;
3777 xt[3].edg[taued[1]] = 0; xt[3].edg[taued[3]] = 0;
3778 xt[3].ref [ tau[3]] = 0;
3779 xt[3].ftag[ tau[3]] = 0;
3780 MG_SET(xt[3].ori, tau[3]);
3781
3782 pt[4]->v[tau[0]] = vx[taued[2]] ; pt[4]->v[tau[1]] = vx[taued[3]] ; pt[4]->v[tau[3]] = vx[taued[4]];
3783 xt[4].tag[taued[0]] = 0; xt[4].tag[taued[1]] = 0;
3784 xt[4].tag[taued[2]] = 0; xt[4].tag[taued[4]] = 0;
3785 xt[4].tag[taued[5]] = 0; xt[4].edg[taued[0]] = 0;
3786 xt[4].edg[taued[1]] = 0; xt[4].edg[taued[2]] = 0;
3787 xt[4].edg[taued[4]] = 0; xt[4].edg[taued[5]] = 0;
3788 xt[4].ref [ tau[1]] = 0; xt[4].ref [ tau[2]] = 0; xt[4].ref [tau[3]] = 0;
3789 xt[4].ftag[ tau[1]] = 0; xt[4].ftag[ tau[2]] = 0; xt[4].ftag[tau[3]] = 0;
3790 MG_SET(xt[4].ori, tau[1]); MG_SET(xt[4].ori, tau[2]); MG_SET(xt[4].ori, tau[3]);
3791
3792 pt[5]->v[tau[0]] = vx[taued[1]] ; pt[5]->v[tau[1]] = vx[taued[3]] ; pt[5]->v[tau[3]] = vx[taued[2]];
3793 xt[5].tag[taued[0]] = 0; xt[5].tag[taued[2]] = 0;
3794 xt[5].tag[taued[4]] = 0; xt[5].tag[taued[5]] = 0;
3795 xt[5].edg[taued[0]] = 0; xt[5].edg[taued[2]] = 0;
3796 xt[5].edg[taued[4]] = 0; xt[5].edg[taued[5]] = 0;
3797 xt[5].ref [ tau[0]] = 0; xt[5].ref [ tau[2]] = 0;
3798 xt[5].ftag[ tau[0]] = 0; xt[5].ftag[ tau[2]] = 0;
3799 MG_SET(xt[5].ori, tau[0]); MG_SET(xt[5].ori, tau[2]);
3800 }
3801 else {
3802 pt[3]->v[tau[0]] = vx[taued[1]] ; pt[3]->v[tau[1]] = vx[taued[3]];
3803 xt[3].tag[taued[0]] = 0; xt[3].tag[taued[2]] = 0;
3804 xt[3].tag[taued[4]] = 0; xt[3].edg[taued[0]] = 0;
3805 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[4]] = 0;
3806 xt[3].ref [ tau[2]] = 0;
3807 xt[3].ftag[ tau[2]] = 0;
3808 MG_SET(xt[3].ori, tau[2]);
3809
3810 pt[4]->v[tau[0]] = vx[taued[2]] ; pt[4]->v[tau[1]] = vx[taued[3]] ; pt[4]->v[tau[2]] = vx[taued[1]];
3811 xt[4].tag[taued[0]] = 0; xt[4].tag[taued[1]] = 0;
3812 xt[4].tag[taued[3]] = 0; xt[4].tag[taued[4]] = 0;
3813 xt[4].tag[taued[5]] = 0; xt[4].edg[taued[0]] = 0;
3814 xt[4].edg[taued[1]] = 0; xt[4].edg[taued[3]] = 0;
3815 xt[4].edg[taued[4]] = 0; xt[4].edg[taued[5]] = 0;
3816 xt[4].ref [ tau[0]] = 0; xt[4].ref [ tau[2]] = 0; xt[4].ref [tau[3]] = 0;
3817 xt[4].ftag[ tau[0]] = 0; xt[4].ftag[ tau[2]] = 0; xt[4].ftag[tau[3]] = 0;
3818 MG_SET(xt[4].ori, tau[0]); MG_SET(xt[4].ori, tau[2]); MG_SET(xt[4].ori, tau[3]);
3819
3820 pt[5]->v[tau[0]] = vx[taued[2]] ; pt[5]->v[tau[1]] = vx[taued[4]] ; pt[5]->v[tau[2]] = vx[taued[3]];
3821 xt[5].tag[taued[0]] = 0; xt[5].tag[taued[1]] = 0;
3822 xt[5].tag[taued[3]] = 0; xt[5].tag[taued[5]] = 0;
3823 xt[5].edg[taued[0]] = 0; xt[5].edg[taued[1]] = 0;
3824 xt[5].edg[taued[3]] = 0; xt[5].edg[taued[5]] = 0;
3825 xt[5].ref [ tau[1]] = 0; xt[5].ref [ tau[3]] = 0;
3826 xt[5].ftag[ tau[1]] = 0; xt[5].ftag[ tau[3]] = 0;
3827 MG_SET(xt[5].ori, tau[1]); MG_SET(xt[5].ori, tau[3]);
3828 }
3829
3830 /* Assignation of the xt fields to the appropriate tets */
3831 memset(isxt,0,ne*sizeof(int8_t));
3832
3833 for (i=0; i<4; i++) {
3834 for(j=0;j<ne;j++ ) {
3835 if ( (xt[j]).ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
3836 }
3837 }
3838
3839 // In this case, at least one of the 4 created tets must have a special field
3840 if ( pt[0]->xt ) {
3841 if ( isxt[0] ) {
3842 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
3843 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = 0;
3844
3845 for (i=1; i<6; i++) {
3846 if ( isxt[i] ) {
3847 mesh->xt++;
3848 if ( mesh->xt > mesh->xtmax ) {
3849 /* realloc of xtetras table */
3851 "larger xtetra table",
3852 mesh->xt--;
3853 fprintf(stderr," Exit program.\n");
3854 return 0);
3855 }
3856 pt[i]->xt = mesh->xt;
3857 pxt0 = &mesh->xtetra[mesh->xt];
3858 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3859 }
3860 }
3861 }
3862 else {
3863 firstxt = 1;
3864 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = 0;
3865
3866 for (i=1; i<6; i++) {
3867 if ( isxt[i] ) {
3868 if ( firstxt ) {
3869 firstxt = 0;
3870 pt[i]->xt = pt[0]->xt;
3871 pxt0 = &mesh->xtetra[ pt[i]->xt];
3872 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
3873 }
3874 else {
3875 mesh->xt++;
3876 if ( mesh->xt > mesh->xtmax ) {
3877 /* realloc of xtetras table */
3879 "larger xtetra table",
3880 mesh->xt--;
3881 fprintf(stderr," Exit program.\n");
3882 return 0);
3883 }
3884 pt[i]->xt = mesh->xt;
3885 pxt0 = &mesh->xtetra[mesh->xt];
3886 memcpy(pxt0,&(xt[i]),sizeof(MMG5_xTetra));
3887 }
3888 }
3889 }
3890 pt[0]->xt = 0;
3891
3892 }
3893 }
3894
3895 /* Quality update */
3896 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
3897
3898 return 1;
3899}
3900
3912static inline
3913void MMG3D_configSplit5(MMG5_pTetra pt,MMG5_int vx[6],uint8_t tau[4],
3914 const uint8_t **taued,uint8_t *imin) {
3915
3916 /* set permutation of vertices and edges ; reference configuration : 62 */
3917 tau[0] = 0 ; tau[1] = 1 ; tau[2] = 2 ; tau[3] = 3;
3918 (*taued) = &MMG5_permedge[0][0];
3919
3920 switch(pt->flag) {
3921 case 61:
3922 tau[0] = 2 ; tau[1] = 0 ; tau[2] = 1 ; tau[3] = 3;
3923 (*taued) = &MMG5_permedge[6][0];
3924 break;
3925
3926 case 59:
3927 tau[0] = 0 ; tau[1] = 3 ; tau[2] = 1 ; tau[3] = 2;
3928 (*taued) = &MMG5_permedge[2][0];
3929 break;
3930
3931 case 55:
3932 tau[0] = 1 ; tau[1] = 2 ; tau[2] = 0 ; tau[3] = 3;
3933 (*taued) = &MMG5_permedge[4][0];
3934 break;
3935
3936 case 47:
3937 tau[0] = 3 ; tau[1] = 1 ; tau[2] = 0 ; tau[3] = 2;
3938 (*taued) = &MMG5_permedge[10][0];
3939 break;
3940
3941 case 31:
3942 tau[0] = 3 ; tau[1] = 2 ; tau[2] = 1 ; tau[3] = 0;
3943 (*taued) = &MMG5_permedge[11][0];
3944 break;
3945 }
3946
3947 /* Generic formulation of split of 5 edges */
3948 (*imin) = (pt->v[tau[0]] < pt->v[tau[1]]) ? tau[0] : tau[1];
3949}
3950
3962int MMG3D_split5_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
3963 MMG5_pTetra pt,pt0;
3964 double vold,vnew;
3965 uint8_t tau[4];
3966 uint8_t imin;
3967 const uint8_t *taued=NULL;
3968
3969 pt = &mesh->tetra[k];
3970 pt0 = &mesh->tetra[0];
3971 vold = MMG5_orvol(mesh->point,pt->v);
3972
3973 if ( vold < MMG5_EPSOK ) return 0;
3974
3975 /* Set permutation of vertices : reference configuration : 62 */
3976 MMG3D_configSplit5(pt,vx,tau,&taued,&imin);
3977
3978 /* Generic formulation of split of 5 edges */
3979 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3980 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[4]];
3981 pt0->v[tau[2]] = vx[taued[5]];
3982 vnew = MMG5_orvol(mesh->point,pt0->v);
3983 if ( vnew < MMG5_EPSOK ) return 0;
3984
3985 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3986 pt0->v[tau[0]] = vx[taued[1]]; pt0->v[tau[1]] = vx[taued[3]];
3987 pt0->v[tau[3]] = vx[taued[5]];
3988 vnew = MMG5_orvol(mesh->point,pt0->v);
3989 if ( vnew < MMG5_EPSOK ) return 0;
3990
3991 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3992 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[4]];
3993 vnew = MMG5_orvol(mesh->point,pt0->v);
3994 if ( vnew < MMG5_EPSOK ) return 0;
3995
3996 memcpy(pt0,pt,sizeof(MMG5_Tetra));
3997 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[1]] = vx[taued[3]];
3998 pt0->v[tau[2]] = vx[taued[1]]; pt0->v[tau[3]] = vx[taued[5]];
3999 vnew = MMG5_orvol(mesh->point,pt0->v);
4000 if ( vnew < MMG5_EPSOK ) return 0;
4001
4002 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4003 if ( imin == tau[0] ) {
4004 pt0->v[tau[2]] = vx[taued[3]]; pt0->v[tau[3]] = vx[taued[4]];
4005 vnew = MMG5_orvol(mesh->point,pt0->v);
4006 if ( vnew < MMG5_EPSOK ) return 0;
4007
4008 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4009 pt0->v[tau[1]] = vx[taued[4]]; pt0->v[tau[2]] = vx[taued[3]];
4010 pt0->v[tau[3]] = vx[taued[2]];
4011 vnew = MMG5_orvol(mesh->point,pt0->v);
4012 if ( vnew < MMG5_EPSOK ) return 0;
4013
4014 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4015 pt0->v[tau[1]] = vx[taued[3]]; pt0->v[tau[2]] = vx[taued[1]];
4016 pt0->v[tau[3]] = vx[taued[2]];
4017 vnew = MMG5_orvol(mesh->point,pt0->v);
4018 if ( vnew < MMG5_EPSOK ) return 0;
4019 }
4020 else {
4021 pt0->v[tau[2]] = vx[taued[1]]; pt0->v[tau[3]] = vx[taued[2]];
4022 vnew = MMG5_orvol(mesh->point,pt0->v);
4023 if ( vnew < MMG5_EPSOK ) return 0;
4024
4025 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4026 pt0->v[tau[0]] = vx[taued[2]]; pt0->v[tau[2]] = vx[taued[3]];
4027 pt0->v[tau[3]] = vx[taued[4]];
4028 vnew = MMG5_orvol(mesh->point,pt0->v);
4029 if ( vnew < MMG5_EPSOK ) return 0;
4030
4031 memcpy(pt0,pt,sizeof(MMG5_Tetra));
4032 pt0->v[tau[0]] = vx[taued[1]]; pt0->v[tau[2]] = vx[taued[3]];
4033 pt0->v[tau[3]] = vx[taued[2]];
4034 vnew = MMG5_orvol(mesh->point,pt0->v);
4035 if ( vnew < MMG5_EPSOK ) return 0;
4036 }
4037
4038 return 1;
4039}
4040
4053int MMG5_split5(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
4054 MMG5_pTetra pt[7];
4055 MMG5_xTetra xt[7];
4056 MMG5_pxTetra pxt0;
4057 int i,j;
4058 MMG5_int newtet[7];
4059 int8_t firstxt,isxt[7];
4060 uint8_t tau[4],imin;
4061 const uint8_t *taued=NULL;
4062 const int ne=7;
4063
4064 pt[0] = &mesh->tetra[k];
4065 newtet[0]=k;
4066
4067 /* set permutation of vertices and edges ; reference configuration : 62 */
4068 MMG3D_configSplit5(pt[0],vx,tau,&taued,&imin);
4069 pt[0]->flag = 0;
4070
4071 /* create 6 new tetras */
4072 if ( !MMG3D_crea_newTetra(mesh,ne,newtet,pt,xt,&pxt0) ) {
4073 return 0;
4074 }
4075
4076 /* Generic formulation of split of 5 edges */
4077 pt[0]->v[tau[0]] = vx[taued[2]] ; pt[0]->v[tau[1]] = vx[taued[4]] ; pt[0]->v[tau[2]] = vx[taued[5]];
4078 xt[0].tag[taued[0]] = 0; xt[0].tag[taued[1]] = 0;
4079 xt[0].tag[taued[3]] = 0; xt[0].edg[taued[0]] = 0;
4080 xt[0].edg[taued[1]] = 0; xt[0].edg[taued[3]] = 0;
4081 xt[0].ref [ tau[3]] = 0;
4082 xt[0].ftag[ tau[3]] = 0;
4083 MG_SET(xt[0].ori, tau[3]);
4084
4085 pt[1]->v[tau[0]] = vx[taued[1]] ; pt[1]->v[tau[1]] = vx[taued[3]] ; pt[1]->v[tau[3]] = vx[taued[5]];
4086 xt[1].tag[taued[0]] = 0; xt[1].tag[taued[2]] = 0;
4087 xt[1].tag[taued[4]] = 0; xt[1].edg[taued[0]] = 0;
4088 xt[1].edg[taued[2]] = 0; xt[1].edg[taued[4]] = 0;
4089 xt[1].ref [ tau[2]] = 0;
4090 xt[1].ftag[ tau[2]] = 0;
4091 MG_SET(xt[1].ori, tau[2]);
4092
4093 pt[2]->v[tau[0]] = vx[taued[2]] ; pt[2]->v[tau[1]] = vx[taued[4]];
4094 pt[2]->v[tau[2]] = vx[taued[3]] ; pt[2]->v[tau[3]] = vx[taued[5]];
4095 xt[2].tag[taued[0]] = 0; xt[2].tag[taued[1]] = 0;
4096 xt[2].tag[taued[2]] = 0; xt[2].tag[taued[3]] = 0;
4097 xt[2].tag[taued[4]] = 0; xt[2].tag[taued[5]] = 0;
4098 xt[2].edg[taued[0]] = 0; xt[2].edg[taued[1]] = 0;
4099 xt[2].edg[taued[2]] = 0; xt[2].edg[taued[3]] = 0;
4100 xt[2].edg[taued[4]] = 0; xt[2].edg[taued[5]] = 0;
4101 xt[2].ref [tau[1]] = 0 ; xt[2].ref [ tau[2]] = 0; xt[2].ref [tau[3]] = 0 ;
4102 xt[2].ftag[tau[1]] = 0 ; xt[2].ftag[ tau[2]] = 0; xt[2].ftag[tau[3]] = 0 ;
4103 MG_SET(xt[2].ori, tau[1]); MG_SET(xt[2].ori, tau[2]); MG_SET(xt[2].ori, tau[3]);
4104
4105 pt[3]->v[tau[0]] = vx[taued[2]] ; pt[3]->v[tau[1]] = vx[taued[3]];
4106 pt[3]->v[tau[2]] = vx[taued[1]] ; pt[3]->v[tau[3]] = vx[taued[5]];
4107 xt[3].tag[taued[0]] = 0; xt[3].tag[taued[1]] = 0;
4108 xt[3].tag[taued[2]] = 0; xt[3].tag[taued[3]] = 0;
4109 xt[3].tag[taued[4]] = 0; xt[3].tag[taued[5]] = 0;
4110 xt[3].edg[taued[0]] = 0; xt[3].edg[taued[1]] = 0;
4111 xt[3].edg[taued[2]] = 0; xt[3].edg[taued[3]] = 0;
4112 xt[3].edg[taued[4]] = 0; xt[3].edg[taued[5]] = 0;
4113 xt[3].ref [ tau[0]] = 0; xt[3].ref [ tau[2]] = 0; xt[3].ref [tau[3]] = 0 ;
4114 xt[3].ftag[ tau[0]] = 0; xt[3].ftag[ tau[2]] = 0; xt[3].ftag[tau[3]] = 0 ;
4115 MG_SET(xt[3].ori, tau[0]); MG_SET(xt[3].ori, tau[2]); MG_SET(xt[3].ori, tau[3]);
4116
4117 if ( imin == tau[0] ) {
4118 pt[4]->v[tau[2]] = vx[taued[3]] ; pt[4]->v[tau[3]] = vx[taued[4]];
4119 xt[4].tag[taued[1]] = 0; xt[4].tag[taued[2]] = 0;
4120 xt[4].tag[taued[5]] = 0; xt[4].edg[taued[1]] = 0;
4121 xt[4].edg[taued[2]] = 0; xt[4].edg[taued[5]] = 0;
4122 xt[4].ref [ tau[1]] = 0;
4123 xt[4].ftag[ tau[1]] = 0;
4124 MG_SET(xt[4].ori, tau[1]);
4125
4126 pt[5]->v[tau[1]] = vx[taued[4]] ; pt[5]->v[tau[2]] = vx[taued[3]]; pt[5]->v[tau[3]] = vx[taued[2]];
4127 xt[5].tag[taued[0]] = 0;
4128 xt[5].tag[taued[1]] = 0; xt[5].tag[taued[3]] = 0;
4129 xt[5].tag[taued[4]] = 0; xt[5].tag[taued[5]] = 0;
4130 xt[5].edg[taued[0]] = 0;
4131 xt[5].edg[taued[1]] = 0; xt[5].edg[taued[3]] = 0;
4132 xt[5].edg[taued[4]] = 0; xt[5].edg[taued[5]] = 0;
4133 xt[5].ref [ tau[0]] = 0; xt[5].ref [ tau[1]] = 0; xt[5].ref [tau[3]] = 0 ;
4134 xt[5].ftag[ tau[0]] = 0; xt[5].ftag[ tau[1]] = 0; xt[5].ftag[tau[3]] = 0 ;
4135 MG_SET(xt[5].ori, tau[0]); MG_SET(xt[5].ori, tau[1]); MG_SET(xt[5].ori, tau[3]);
4136
4137 pt[6]->v[tau[1]] = vx[taued[3]] ; pt[6]->v[tau[2]] = vx[taued[1]]; pt[6]->v[tau[3]] = vx[taued[2]];
4138 xt[6].tag[taued[0]] = 0;
4139 xt[6].tag[taued[3]] = 0; xt[6].tag[taued[4]] = 0;
4140 xt[6].tag[taued[5]] = 0; xt[6].edg[taued[0]] = 0;
4141 xt[6].edg[taued[3]] = 0;
4142 xt[6].edg[taued[4]] = 0; xt[6].edg[taued[5]] = 0;
4143 xt[6].ref [ tau[0]] = 0; xt[6].ref [ tau[2]] = 0;
4144 xt[6].ftag[ tau[0]] = 0; xt[6].ftag[ tau[2]] = 0;
4145 MG_SET(xt[6].ori, tau[0]); MG_SET(xt[6].ori, tau[2]);
4146
4147 }
4148 else {
4149 pt[4]->v[tau[2]] = vx[taued[1]] ; pt[4]->v[tau[3]] = vx[taued[2]];
4150 xt[4].tag[taued[3]] = 0; xt[4].tag[taued[4]] = 0;
4151 xt[4].tag[taued[5]] = 0; xt[4].edg[taued[3]] = 0;
4152 xt[4].edg[taued[4]] = 0; xt[4].edg[taued[5]] = 0;
4153 xt[4].ref [ tau[0]] = 0;
4154 xt[4].ftag[ tau[0]] = 0;
4155 MG_SET(xt[4].ori, tau[0]);
4156
4157 pt[5]->v[tau[0]] = vx[taued[2]] ; pt[5]->v[tau[2]] = vx[taued[3]]; pt[5]->v[tau[3]] = vx[taued[4]];
4158 xt[5].tag[taued[0]] = 0; xt[5].tag[taued[1]] = 0;
4159 xt[5].tag[taued[2]] = 0; xt[5].tag[taued[5]] = 0;
4160 xt[5].edg[taued[0]] = 0; xt[5].edg[taued[1]] = 0;
4161 xt[5].edg[taued[2]] = 0; xt[5].edg[taued[5]] = 0;
4162 xt[5].ref [ tau[1]] = 0; xt[5].ref [ tau[3]] = 0;
4163 xt[5].ftag[ tau[1]] = 0; xt[5].ftag[ tau[3]] = 0;
4164 MG_SET(xt[5].ori, tau[1]); MG_SET(xt[5].ori, tau[3]);
4165
4166 pt[6]->v[tau[0]] = vx[taued[1]] ; pt[6]->v[tau[2]] = vx[taued[3]]; pt[6]->v[tau[3]] = vx[taued[2]];
4167 xt[6].tag[taued[0]] = 0; xt[6].tag[taued[1]] = 0;
4168 xt[6].tag[taued[2]] = 0; xt[6].tag[taued[4]] = 0;
4169 xt[6].tag[taued[5]] = 0; xt[6].edg[taued[0]] = 0;
4170 xt[6].edg[taued[1]] = 0; xt[6].edg[taued[2]] = 0;
4171 xt[6].edg[taued[4]] = 0; xt[6].edg[taued[5]] = 0;
4172 xt[6].ref [ tau[0]] = 0; xt[6].ref [ tau[1]] = 0; xt[6].ref [tau[2]] = 0 ;
4173 xt[6].ftag[ tau[0]] = 0; xt[6].ftag[ tau[1]] = 0; xt[6].ftag[tau[2]] = 0 ;
4174 MG_SET(xt[6].ori, tau[0]); MG_SET(xt[6].ori, tau[1]); MG_SET(xt[6].ori, tau[2]);
4175 }
4176
4177 /* Assignation of the xt fields to the appropriate tets */
4178 memset(isxt,0,ne*sizeof(int8_t));
4179
4180 for (i=0; i<4; i++) {
4181 for (j=0; j<ne; j++) {
4182 if ( (xt[j]).ref[i] || xt[j].ftag[i] ) isxt[j] = 1;
4183 }
4184 }
4185
4186 if ( pt[0]->xt ) {
4187 if ( isxt[0] ) {
4188 memcpy(pxt0,&xt[0],sizeof(MMG5_xTetra));
4189 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = pt[6]->xt = 0;
4190
4191 for (i=1; i<7; i++) {
4192 if ( isxt[i] ) {
4193 mesh->xt++;
4194 if ( mesh->xt > mesh->xtmax ) {
4195 /* realloc of xtetras table */
4197 "larger xtetra table",
4198 mesh->xt--;
4199 fprintf(stderr," Exit program.\n");
4200 return 0);
4201 }
4202 pt[i]->xt = mesh->xt;
4203 pxt0 = &mesh->xtetra[mesh->xt];
4204 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
4205 }
4206 }
4207 }
4208 else {
4209 firstxt = 1;
4210 pt[1]->xt = pt[2]->xt = pt[3]->xt = pt[4]->xt = pt[5]->xt = pt[6]->xt = 0;
4211
4212 for (i=1; i<7; i++) {
4213 if ( isxt[i] ) {
4214 if ( firstxt ) {
4215 firstxt = 0;
4216 pt[i]->xt = pt[0]->xt;
4217 pxt0 = &mesh->xtetra[(pt[i])->xt];
4218 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
4219 }
4220 else {
4221 mesh->xt++;
4222 if ( mesh->xt > mesh->xtmax ) {
4223 /* realloc of xtetras table */
4225 "larger xtetra table",
4226 mesh->xt--;
4227 fprintf(stderr," Exit program.\n");
4228 return 0);
4229 }
4230 pt[i]->xt = mesh->xt;
4231 pxt0 = &mesh->xtetra[mesh->xt];
4232 memcpy(pxt0,&xt[i],sizeof(MMG5_xTetra));
4233 }
4234 }
4235 }
4236 pt[0]->xt = 0;
4237
4238 }
4239 }
4240
4241 /* Quality update */
4242 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
4243
4244 return 1;
4245}
4246
4258int MMG3D_split6_sim(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6]) {
4259 MMG5_pTetra pt,pt0;
4260 double vold,vnew;
4261
4262 pt = &mesh->tetra[k];
4263 pt0 = &mesh->tetra[0];
4264 vold = MMG5_orvol(mesh->point,pt->v);
4265
4266 if ( vold < MMG5_EPSOK ) return 0;
4267
4268 /* Modify first tetra */
4269 pt0->v[1] = vx[0]; pt0->v[2] = vx[1]; pt0->v[3] = vx[2];
4270 vnew = MMG5_orvol(mesh->point,pt0->v);
4271 if ( vnew < MMG5_EPSOK ) return 0;
4272
4273 /* Modify second tetra */
4274 pt0->v[0] = vx[0]; pt0->v[2] = vx[3]; pt0->v[3] = vx[4];
4275 vnew = MMG5_orvol(mesh->point,pt0->v);
4276 if ( vnew < MMG5_EPSOK ) return 0;
4277
4278 /* Modify 3rd tetra */
4279 pt0->v[0] = vx[1]; pt0->v[1] = vx[3]; pt0->v[3] = vx[5];
4280 vnew = MMG5_orvol(mesh->point,pt0->v);
4281 if ( vnew < MMG5_EPSOK ) return 0;
4282
4283 /* Modify 4th tetra */
4284 pt0->v[0] = vx[2]; pt0->v[1] = vx[4]; pt0->v[2] = vx[5];
4285 vnew = MMG5_orvol(mesh->point,pt0->v);
4286 if ( vnew < MMG5_EPSOK ) return 0;
4287
4288 /* Modify 5th tetra */
4289 pt0->v[0] = vx[0]; pt0->v[1] = vx[3]; pt0->v[2] = vx[1];
4290 pt0->v[3] = vx[2];
4291 vnew = MMG5_orvol(mesh->point,pt0->v);
4292 if ( vnew < MMG5_EPSOK ) return 0;
4293
4294 /* Modify 6th tetra */
4295 pt0->v[0] = vx[2]; pt0->v[1] = vx[0]; pt0->v[2] = vx[3];
4296 pt0->v[3] = vx[4];
4297 vnew = MMG5_orvol(mesh->point,pt0->v);
4298 if ( vnew < MMG5_EPSOK ) return 0;
4299
4300 /* Modify 7th tetra */
4301 pt0->v[0] = vx[2]; pt0->v[1] = vx[3]; pt0->v[2] = vx[1];
4302 pt0->v[3] = vx[5];
4303 vnew = MMG5_orvol(mesh->point,pt0->v);
4304 if ( vnew < MMG5_EPSOK ) return 0;
4305
4306 /* Modify last tetra */
4307 pt0->v[0] = vx[2]; pt0->v[1] = vx[3]; pt0->v[2] = vx[5];
4308 pt0->v[3] = vx[4];
4309 vnew = MMG5_orvol(mesh->point,pt0->v);
4310 if ( vnew < MMG5_EPSOK ) return 0;
4311
4312 return 1;
4313}
4314
4327int MMG5_split6(MMG5_pMesh mesh,MMG5_pSol met,MMG5_int k,MMG5_int vx[6],int8_t metRidTyp) {
4328 MMG5_pTetra pt[8];
4329 MMG5_xTetra xt0,xt;
4330 MMG5_pxTetra pxt;
4331 int i,j;
4332 MMG5_int iel,newtet[8],nxt0;
4333 int8_t isxt0,isxt;
4334 const int8_t ne=8;
4335
4336 pt[0] = &mesh->tetra[k];
4337 pt[0]->flag = 0;
4338 newtet[0]=k;
4339
4340 nxt0 = pt[0]->xt;
4341 pxt = &mesh->xtetra[nxt0];
4342 memcpy(&xt0,pxt,sizeof(MMG5_xTetra));
4343
4344 /* create 7 new tetras */
4345 for (i=1; i<ne; i++) {
4346 iel = MMG3D_newElt(mesh);
4347 if ( !iel ) {
4349 fprintf(stderr,"\n ## Error: %s: unable to allocate"
4350 " a new element.\n",__func__);
4352 fprintf(stderr," Exit program.\n");
4353 return 0);
4354 for ( j=0; j<i; j++ )
4355 pt[j] = &mesh->tetra[newtet[j]];
4356 }
4357 pt[i] = &mesh->tetra[iel];
4358 pt[i] = memcpy(pt[i],pt[0],sizeof(MMG5_Tetra));
4359 newtet[i]=iel;
4360 }
4361
4362 /* Modify first tetra */
4363 pt[0]->v[1] = vx[0] ; pt[0]->v[2] = vx[1]; pt[0]->v[3] = vx[2];
4364 if ( nxt0 ) {
4365 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4366 xt.tag[3] = 0; xt.tag[4] = 0;
4367 xt.tag[5] = 0; xt.edg[3] = 0;
4368 xt.edg[4] = 0; xt.edg[5] = 0;
4369 xt.ref[0] = 0; xt.ftag[0] = 0; MG_SET(xt.ori, 0);
4370 isxt0 = 0;
4371 for(i=0;i<4;i++ ) {
4372 if ( (xt.ref[i]) || xt.ftag[i] ) isxt0 = 1;
4373 }
4374
4375 if ( isxt0 ) {
4376 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4377 }
4378 else {
4379 pt[0]->xt = 0;
4380 }
4381 }
4382
4383 /* Modify second tetra */
4384 pt[1]->v[0] = vx[0] ; pt[1]->v[2] = vx[3]; pt[1]->v[3] = vx[4];
4385
4386 if ( nxt0 ) {
4387 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4388 xt.tag[1] = 0; xt.tag[2] = 0;
4389 xt.tag[5] = 0; xt.edg[1] = 0;
4390 xt.edg[2] = 0; xt.edg[5] = 0;
4391 xt.ref[1] = 0; xt.ftag[1] = 0; MG_SET(xt.ori, 1);
4392
4393 isxt = 0;
4394
4395 for (i=0; i<4; i++) {
4396 if ( (xt.ref[i]) || xt.ftag[i]) isxt = 1;
4397 }
4398
4399 pt[1]->xt = 0;
4400 if ( isxt ) {
4401 if ( !isxt0 ) {
4402 isxt0 = 1;
4403 pt[1]->xt = nxt0;
4404 pxt = &mesh->xtetra[pt[1]->xt];
4405 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4406 }
4407 else {
4408 mesh->xt++;
4409 if ( mesh->xt > mesh->xtmax ) {
4410 /* realloc of xtetras table */
4412 "larger xtetra table",
4413 mesh->xt--;
4414 fprintf(stderr," Exit program.\n");
4415 return 0);
4416 }
4417 pt[1]->xt = mesh->xt;
4418 pxt = &mesh->xtetra[pt[1]->xt];
4419 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4420 }
4421 }
4422 }
4423
4424 /* Modify 3rd tetra */
4425 pt[2]->v[0] = vx[1] ; pt[2]->v[1] = vx[3]; pt[2]->v[3] = vx[5];
4426
4427 if ( nxt0 ) {
4428 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4429 xt.tag[0] = 0; xt.tag[2] = 0;
4430 xt.tag[4] = 0; xt.edg[0] = 0;
4431 xt.edg[2] = 0; xt.edg[4] = 0;
4432 xt.ref[2] = 0; xt.ftag[2] = 0; MG_SET(xt.ori, 2);
4433 isxt = 0;
4434
4435 for (i=0; i<4;i++) {
4436 if ( (xt.ref[i]) || xt.ftag[i]) isxt = 1;
4437 }
4438
4439 pt[2]->xt = 0;
4440 if ( isxt ) {
4441 if ( !isxt0 ) {
4442 isxt0 = 1;
4443 pt[2]->xt = nxt0;
4444 pxt = &mesh->xtetra[pt[2]->xt];
4445 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4446 }
4447 else {
4448 mesh->xt++;
4449 if ( mesh->xt > mesh->xtmax ) {
4450 /* realloc of xtetras table */
4452 "larger xtetra table",
4453 mesh->xt--;
4454 fprintf(stderr," Exit program.\n");
4455 return 0);
4456 }
4457 pt[2]->xt = mesh->xt;
4458 pxt = &mesh->xtetra[pt[2]->xt];
4459 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4460 }
4461 }
4462 }
4463
4464 /* Modify 4th tetra */
4465 pt[3]->v[0] = vx[2] ; pt[3]->v[1] = vx[4]; pt[3]->v[2] = vx[5];
4466
4467 if ( nxt0 ) {
4468 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4469 xt.tag[0] = 0; xt.tag[1] = 0;
4470 xt.tag[3] = 0; xt.edg[0] = 0;
4471 xt.edg[1] = 0; xt.edg[3] = 0;
4472 xt.ref[3] = 0; xt.ftag[3] = 0; MG_SET(xt.ori, 3);
4473
4474 isxt = 0;
4475
4476 for (i=0; i<4; i++) {
4477 if ( (xt.ref[i]) || xt.ftag[i]) isxt = 1;
4478 }
4479
4480 pt[3]->xt = 0;
4481 if ( isxt ) {
4482 if ( !isxt0 ) {
4483 isxt0 = 1;
4484 pt[3]->xt = nxt0;
4485 pxt = &mesh->xtetra[pt[3]->xt];
4486 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4487 }
4488 else {
4489 mesh->xt++;
4490 if ( mesh->xt > mesh->xtmax ) {
4491 /* realloc of xtetras table */
4493 "larger xtetra table",
4494 mesh->xt--;
4495 fprintf(stderr," Exit program.\n");
4496 return 0);
4497 }
4498 pt[3]->xt = mesh->xt;
4499 pxt = &mesh->xtetra[pt[3]->xt];
4500 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4501 }
4502 }
4503 }
4504
4505 /* Modify 5th tetra */
4506 pt[4]->v[0] = vx[0] ; pt[4]->v[1] = vx[3]; pt[4]->v[2] = vx[1] ; pt[4]->v[3] = vx[2];
4507
4508 if ( nxt0 ) {
4509 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4510 xt.tag[0] = 0; xt.tag[1] = 0;
4511 xt.tag[2] = 0; xt.tag[3] = 0;
4512 xt.edg[0] = 0; xt.edg[1] = 0;
4513 xt.edg[2] = 0; xt.edg[3] = 0;
4514 xt.tag[4] = 0; xt.edg[4] = 0;
4515 xt.tag[5] = 0; xt.edg[5] = 0;
4516 xt.ref [0] = 0 ; xt.ref [1] = 0 ; xt.ref [2] = 0;
4517 xt.ftag[0] = 0 ; xt.ftag[1] = 0 ; xt.ftag[2] = 0;
4518 MG_SET(xt.ori, 0); MG_SET(xt.ori, 1); MG_SET(xt.ori, 2);
4519
4520 isxt = 0;
4521
4522 if ( (xt.ref[3]) || xt.ftag[3]) isxt = 1;
4523
4524 pt[4]->xt = 0;
4525 if ( isxt ) {
4526 if ( !isxt0 ) {
4527 isxt0 = 1;
4528 pt[4]->xt = nxt0;
4529 pxt = &mesh->xtetra[(pt[4])->xt];
4530 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4531 }
4532 else {
4533 mesh->xt++;
4534 if ( mesh->xt > mesh->xtmax ) {
4535 /* realloc of xtetras table */
4537 "larger xtetra table",
4538 mesh->xt--;
4539 fprintf(stderr," Exit program.\n");
4540 return 0);
4541 }
4542 pt[4]->xt = mesh->xt;
4543 pxt = &mesh->xtetra[pt[4]->xt];
4544 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4545 }
4546 }
4547 }
4548
4549 /* Modify 6th tetra */
4550 pt[5]->v[0] = vx[2] ; pt[5]->v[1] = vx[0]; pt[5]->v[2] = vx[3] ; pt[5]->v[3] = vx[4];
4551
4552 if ( nxt0 ) {
4553 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4554 xt.tag[0] = 0; xt.tag[1] = 0;
4555 xt.tag[2] = 0; xt.tag[3] = 0;
4556 xt.tag[4] = 0; xt.tag[5] = 0;
4557 xt.edg[0] = 0; xt.edg[1] = 0;
4558 xt.edg[2] = 0; xt.edg[3] = 0;
4559 xt.edg[4] = 0; xt.edg[5] = 0;
4560 xt.ref [0] = 0 ; xt.ref [1] = 0 ; xt.ref [3] = 0;
4561 xt.ftag[0] = 0 ; xt.ftag[1] = 0 ; xt.ftag[3] = 0;
4562 MG_SET(xt.ori, 0); MG_SET(xt.ori, 1); MG_SET(xt.ori, 3);
4563
4564 isxt = 0;
4565
4566 if ( (xt.ref[2]) || xt.ftag[2]) isxt = 1;
4567
4568 pt[5]->xt = 0;
4569 if ( isxt ) {
4570 if ( !isxt0 ) {
4571 isxt0 = 1;
4572 pt[5]->xt = nxt0;
4573 pxt = &mesh->xtetra[pt[5]->xt];
4574 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4575 }
4576 else {
4577 mesh->xt++;
4578 if ( mesh->xt > mesh->xtmax ) {
4579 /* realloc of xtetras table */
4581 "larger xtetra table",
4582 mesh->xt--;
4583 fprintf(stderr," Exit program.\n");
4584 return 0);
4585 }
4586 pt[5]->xt = mesh->xt;
4587 pxt = &mesh->xtetra[pt[5]->xt];
4588 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4589 }
4590 }
4591 }
4592
4593 /* Modify 7th tetra */
4594 pt[6]->v[0] = vx[2] ; pt[6]->v[1] = vx[3]; pt[6]->v[2] = vx[1] ; pt[6]->v[3] = vx[5];
4595
4596 if ( nxt0 ) {
4597 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4598 xt.tag[0] = 0; xt.edg[0] = 0;
4599 xt.tag[1] = 0; xt.tag[2] = 0;
4600 xt.tag[3] = 0; xt.tag[4] = 0;
4601 xt.edg[1] = 0; xt.edg[2] = 0;
4602 xt.edg[3] = 0; xt.edg[4] = 0;
4603 xt.tag[5] = 0; xt.edg[5] = 0;
4604 xt.ref [0] = 0 ; xt.ref [2] = 0 ; xt.ref [3] = 0;
4605 xt.ftag[0] = 0 ; xt.ftag[2] = 0 ; xt.ftag[3] = 0;
4606 MG_SET(xt.ori, 0); MG_SET(xt.ori, 2); MG_SET(xt.ori, 3);
4607
4608 isxt = 0;
4609
4610 if ( (xt.ref[1]) || xt.ftag[1]) isxt = 1;
4611
4612 pt[6]->xt = 0;
4613 if ( isxt ) {
4614 if ( !isxt0 ) {
4615 isxt0 = 1;
4616 pt[6]->xt = nxt0;
4617 pxt = &mesh->xtetra[pt[6]->xt];
4618 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4619 }
4620 else {
4621 mesh->xt++;
4622 if ( mesh->xt > mesh->xtmax ) {
4623 /* realloc of xtetras table */
4625 "larger xtetra table",
4626 mesh->xt--;
4627 fprintf(stderr," Exit program.\n");
4628 return 0);
4629 }
4630 pt[6]->xt = mesh->xt;
4631 pxt = &mesh->xtetra[pt[6]->xt];
4632 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4633 }
4634 }
4635 }
4636
4637 /* Modify last tetra */
4638 pt[7]->v[0] = vx[2] ; pt[7]->v[1] = vx[3]; pt[7]->v[2] = vx[5] ; pt[7]->v[3] = vx[4];
4639
4640 if ( nxt0 ) {
4641 memcpy(&xt,&xt0,sizeof(MMG5_xTetra));
4642 xt.tag[0] = 0; xt.tag[1] = 0;
4643 xt.tag[2] = 0; xt.tag[3] = 0;
4644 xt.tag[4] = 0; xt.tag[5] = 0;
4645 xt.edg[0] = 0; xt.edg[1] = 0;
4646 xt.edg[2] = 0; xt.edg[3] = 0;
4647 xt.edg[4] = 0; xt.edg[5] = 0;
4648 xt.ref [1] = 0 ; xt.ref [2] = 0 ; xt.ref [3] = 0;
4649 xt.ftag[1] = 0 ; xt.ftag[2] = 0 ; xt.ftag[3] = 0;
4650 MG_SET(xt.ori, 1); MG_SET(xt.ori, 2); MG_SET(xt.ori, 3);
4651
4652 isxt = 0;
4653
4654 if ( (xt.ref[0]) || xt.ftag[0]) isxt = 1;
4655
4656 pt[7]->xt = 0;
4657 if ( isxt ) {
4658 if ( !isxt0 ) {
4659 pt[7]->xt = nxt0;
4660 pxt = &mesh->xtetra[pt[7]->xt];
4661 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4662 }
4663 else {
4664 mesh->xt++;
4665 if ( mesh->xt > mesh->xtmax ) {
4666 /* realloc of xtetras table */
4668 "larger xtetra table",
4669 mesh->xt--;
4670 fprintf(stderr," Exit program.\n");
4671 return 0);
4672 }
4673 pt[7]->xt = mesh->xt;
4674 pxt = &mesh->xtetra[pt[7]->xt];
4675 memcpy(pxt,&xt,sizeof(MMG5_xTetra));
4676 }
4677 }
4678 }
4679
4680 /* Quality update */
4681 MMG3D_update_qual(mesh,met,ne,newtet,pt,metRidTyp);
4682
4683 return 1;
4684}
4685
4686
4699static inline
4701 int64_t* list,int ret,double crit) {
4702 MMG5_pTetra pt0,pt1;
4703 double cal,critloc;
4704 int l,ipb,lon;
4705 MMG5_int jel,na;
4706
4707 lon = ret/2;
4708 critloc = 1.;
4709 for (l=0; l<lon; l++) {
4710 jel = list[l] / 6;
4711 pt1 = &mesh->tetra[jel];
4712 if(pt1->qual < critloc) critloc = pt1->qual;
4713 }
4714 critloc *= crit;
4715
4716 pt0 = &mesh->tetra[0];
4717 for (l=0; l<lon; l++) {
4718 jel = list[l] / 6;
4719 na = list[l] % 6;
4720 pt1 = &mesh->tetra[jel];
4721
4722 memcpy(pt0->v,pt1->v,4*sizeof(MMG5_int));
4723 ipb = MMG5_iare[na][0];
4724 pt0->v[ipb] = ip;
4725 cal = MMG5_caltet(mesh,met,pt0);
4726 if ( cal < critloc ) {
4727 MMG3D_delPt(mesh,ip);
4728 return 0;
4729 }
4730
4731 memcpy(pt0->v,pt1->v,4*sizeof(MMG5_int));
4732 ipb = MMG5_iare[na][1];
4733 pt0->v[ipb] = ip;
4734 cal = MMG5_caltet(mesh,met,pt0);
4735 if ( cal < critloc ) {
4736 MMG3D_delPt(mesh,ip);
4737 return 0;
4738 }
4739 }
4740 return 1;
4741}
4753MMG5_int MMG5_splitedg(MMG5_pMesh mesh, MMG5_pSol met,MMG5_int iel, int iar, double crit){
4754 MMG5_pTetra pt;
4755 MMG5_pxTetra pxt;
4756 MMG5_pPoint p0,p1;
4757 double o[3];
4758 int warn,lon,ier;
4759 int64_t list[MMG3D_LMAX+2];
4760 MMG5_int src,i0,i1,ip;
4761 int16_t tag;
4762
4763 warn = 0;
4764 pt = &mesh->tetra[iel];
4765
4766 int8_t isbdy;
4767 lon = MMG5_coquil(mesh,iel,iar,list,&isbdy);
4768 if ( (!lon || lon<0) )
4769 return 0;
4770
4771 /* Skip edges along an external boundary (test on open shell) */
4772 if(lon%2) return 0;
4773
4774 i0 = pt->v[MMG5_iare[iar][0]];
4775 i1 = pt->v[MMG5_iare[iar][1]];
4776 p0 = &mesh->point[i0];
4777 p1 = &mesh->point[i1];
4778
4779 tag = MG_NOTAG;
4780 if ( pt->xt ){
4781 pxt = &mesh->xtetra[pt->xt];
4782 if ( (pxt->ftag[MMG5_ifar[iar][0]] & MG_BDY) ||
4783 (pxt->ftag[MMG5_ifar[iar][1]] & MG_BDY) ) {
4784 tag = pxt->tag[iar];
4785 tag |= MG_BDY;
4786 }
4787 }
4788
4789 /* Do not split a required edge */
4790 if ( pt->tag & MG_REQ || tag & MG_REQ ) {
4791 return 0;
4792 }
4793
4794 /* Skip edge if it connects bdy point (edge can be internal or external) */
4795 if ( isbdy ) {
4796 return 0;
4797 }
4798
4799 o[0] = 0.5*(p0->c[0] + p1->c[0]);
4800 o[1] = 0.5*(p0->c[1] + p1->c[1]);
4801 o[2] = 0.5*(p0->c[2] + p1->c[2]);
4802
4803#ifdef USE_POINTMAP
4804 src = mesh->point[i0].src;
4805#else
4806 src = 1;
4807#endif
4808 ip = MMG3D_newPt(mesh,o,tag,src);
4809
4810 if ( !ip ) {
4811 assert ( mesh );
4812 /* reallocation of point table */
4814 warn=1;
4815 break
4816 ,o,tag,src);
4817 }
4818
4819 if ( warn ) {
4820 fprintf(stderr,"\n ## Warning: %s:",__func__);
4821 fprintf(stderr," unable to allocate a new point in last call"
4822 " of MMG5_adpspl.\n");
4824 }
4825
4826 ier = MMG5_intmet(mesh,met,iel,iar,ip,0.5);
4827 if ( !ier ) {
4828 MMG3D_delPt(mesh,ip);
4829 return 0;
4830 }
4831 else if (ier < 0 ) {
4832 MMG3D_delPt(mesh,ip);
4833 return 0;
4834 }
4835
4836 ier = MMG3D_simbulgept(mesh,met,list,lon,ip);
4837 assert ( (!mesh->info.ddebug) || (mesh->info.ddebug && ier != -1) );
4838 if ( ier <= 0 || ier == 2 ) return 0;
4839
4840 ier = MMG3D_chksplit(mesh,met,ip,&list[0],lon,crit);
4841 if(!ier) return 0;
4842 ier = MMG5_split1b(mesh,met,list,lon,ip,0,1,0);
4843 if ( ier < 0 ) {
4844 fprintf(stderr,"\n ## Error: %s: unable to split.\n",__func__);
4845 return -1;
4846 }
4847 else if ( !ier ) {
4848 MMG3D_delPt(mesh,ip);
4849 return 0;
4850 }
4851
4852 return ip;
4853}
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:1843
int MMG5_coquil(MMG5_pMesh mesh, MMG5_int start, int ia, int64_t *list, int8_t *isbdy)
Definition: boulep_3d.c:1403
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:462
API headers for the mmg3d library.
#define MMG3D_LMAX
Definition: libmmg3d.h:58
MMG5_int MMG3D_newPt(MMG5_pMesh mesh, double c[3], int16_t tag, MMG5_int src)
Definition: zaldy_3d.c:39
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]
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)
static uint8_t MMG3D_split2sf_cfg(MMG5_int flag, uint8_t *tau, const uint8_t **taued, MMG5_pTetra pt)
Definition: split_3d.c:1005
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:1138
static void MMG3D_configSplit5(MMG5_pTetra pt, MMG5_int vx[6], uint8_t tau[4], const uint8_t **taued, uint8_t *imin)
Definition: split_3d.c:3913
int MMG3D_split6_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:4258
MMG5_int MMG5_splitedg(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int iel, int iar, double crit)
Definition: split_3d.c:4753
int MMG3D_split3_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:1571
int MMG3D_split3cone_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:1790
int MMG5_split6(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:4327
int MMG5_split4op(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:3676
int MMG3D_simbulgept(MMG5_pMesh mesh, MMG5_pSol met, int64_t *list, int ret, MMG5_int ip)
Definition: split_3d.c:324
static void MMG3D_configSplit3op(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:2286
static int MMG3D_chksplit(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int ip, int64_t *list, int ret, double crit)
Definition: split_3d.c:4700
int MMG5_split1(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:136
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:267
int MMG3D_normalAdjaTri(MMG5_pMesh mesh, MMG5_int start, int8_t iface, int ia, double n[3])
Definition: split_3d.c:466
int MMG3D_split2sf_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:1075
int MMG3D_split4op_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:3555
int MMG5_split2(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:1430
MMG5_int MMG5_split4bar(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, int8_t metRidTyp)
Definition: split_3d.c:2964
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:617
int MMG5_split2sf(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:1228
int8_t ddb
Definition: mmg3d1_delone.c:42
int MMG3D_split4sf_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:3251
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:1191
static void MMG3D_split1_cfg(MMG5_int flag, uint8_t *tau, const uint8_t **taued)
Definition: split_3d.c:53
int MMG3D_split5_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:3962
static void MMG3D_configSplit4sf(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:3174
int MMG5_split5(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:4053
int MMG5_split3op(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:2574
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:513
int MMG3D_split3op_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:2442
int MMG5_split3cone(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:1971
int MMG5_split3(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:1642
int MMG3D_split2_sim(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6])
Definition: split_3d.c:1368
int MMG5_split4sf(MMG5_pMesh mesh, MMG5_pSol met, MMG5_int k, MMG5_int vx[6], int8_t metRidTyp)
Definition: split_3d.c:3354
int8_t ddebug
Definition: libmmgtypes.h:532
double dhd
Definition: libmmgtypes.h:518
MMG mesh structure.
Definition: libmmgtypes.h:605
MMG5_Info info
Definition: libmmgtypes.h:651
MMG5_int xt
Definition: libmmgtypes.h:620
MMG5_pPoint point
Definition: libmmgtypes.h:641
MMG5_int mark
Definition: libmmgtypes.h:618
MMG5_int * adja
Definition: libmmgtypes.h:624
MMG5_int xtmax
Definition: libmmgtypes.h:612
double gap
Definition: libmmgtypes.h:608
MMG5_pTetra tetra
Definition: libmmgtypes.h:643
MMG5_pxTetra xtetra
Definition: libmmgtypes.h:644
Structure to store points of a MMG mesh.
Definition: libmmgtypes.h:270
int16_t tag
Definition: libmmgtypes.h:284
double c[3]
Definition: libmmgtypes.h:271
double * m
Definition: libmmgtypes.h:671
MMG5_int v[4]
Definition: libmmgtypes.h:403
MMG5_int xt
Definition: libmmgtypes.h:407
MMG5_int flag
Definition: libmmgtypes.h:409
MMG5_int mark
Definition: libmmgtypes.h:406
double qual
Definition: libmmgtypes.h:402
int16_t tag
Definition: libmmgtypes.h:410
int16_t tag[3]
Definition: libmmgtypes.h:342
MMG5_int v[3]
Definition: libmmgtypes.h:334
Structure to store the surface tetrahedra of a MMG mesh.
Definition: libmmgtypes.h:418
int16_t ftag[4]
Definition: libmmgtypes.h:423
int16_t tag[6]
Definition: libmmgtypes.h:425
int8_t ori
Definition: libmmgtypes.h:427
MMG5_int edg[6]
Definition: libmmgtypes.h:421
MMG5_int ref[4]
Definition: libmmgtypes.h:419