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