/** * \param mesh pointer toward the mesh structure. * \param met pointer toward the sol structure. * \param nconf configuration. * \param ilist number of tetrahedra in the shell of the edge that we want * to swap. * \param list pointer toward the shell of the edge that we want to swap. * \param bucket pointer toward the bucket structure in Delaunay mode, * NULL pointer in pattern mode. * \return -1 if lack of memory, 0 if fail to swap, 1 otherwise. * * Perform swap of edge whose shell is passed according to configuration nconf. * */ int _MMG5_swpgen(MMG5_pMesh mesh,MMG5_pSol met,int nconf,int ilist,int *list,_MMG5_pBucket bucket) { MMG5_pTetra pt; MMG5_pPoint p0,p1; int iel,na,nb,np,nball,ret,start; double m[3]; char ia,ip,iq; int ier; iel = list[0] / 6; ia = list[0] % 6; pt = &mesh->tetra[iel]; na = pt->v[_MMG5_iare[ia][0]]; nb = pt->v[_MMG5_iare[ia][1]]; p0 = &mesh->point[na]; p1 = &mesh->point[nb]; /* Temporarily create midpoint at swapped edge */ m[0] = 0.5*(p0->c[0] + p1->c[0]); m[1] = 0.5*(p0->c[1] + p1->c[1]); m[2] = 0.5*(p0->c[2] + p1->c[2]); np = _MMG5_newPt(mesh,m,0); if(!np){ if ( bucket ) { _MMG5_POINT_AND_BUCKET_REALLOC(mesh,met,np,mesh->gap, printf(" ## Error: unable to allocate a new point\n"); _MMG5_INCREASE_MEM_MESSAGE(); return(-1) ,m,0); } else { _MMG5_POINT_REALLOC(mesh,met,np,mesh->gap, printf(" ## Error: unable to allocate a new point\n"); _MMG5_INCREASE_MEM_MESSAGE(); return(-1) ,m,0); } }
/** * \param mesh pointer toward the mesh structure. * \param met pointer toward the metric structure. * \param *warn \a warn is set to 1 if we don't have enough memory to complete mesh. * \return -1 if failed. * \return number of new points. * * Split edges of length bigger than _MMG5_LOPTL. * */ static int _MMG5_adpspl(MMG5_pMesh mesh,MMG5_pSol met, int* warn) { MMG5_pTetra pt; MMG5_pxTetra pxt; MMG5_Tria ptt; MMG5_pPoint p0,p1,ppt; MMG5_pxPoint pxp; double dd,len,lmax,o[3],to[3],ro[3],no1[3],no2[3],v[3]; int k,ip,ip1,ip2,list[_MMG5_LMAX+2],ilist,ns,ref,ier; char imax,tag,j,i,i1,i2,ifa0,ifa1; *warn=0; ns = 0; for (k=1; k<=mesh->ne; k++) { pt = &mesh->tetra[k]; if ( !MG_EOK(pt) || (pt->tag & MG_REQ) ) continue; pxt = pt->xt ? &mesh->xtetra[pt->xt] : 0; /* find longest edge */ imax = -1; lmax = 0.0; for (i=0; i<6; i++) { if ( pt->xt && (pxt->tag[i] & MG_REQ) ) continue; ip1 = _MMG5_iare[i][0]; ip2 = _MMG5_iare[i][1]; len = _MMG5_lenedg(mesh,met,pt->v[ip1],pt->v[ip2]); if ( len > lmax ) { lmax = len; imax = i; } } if ( imax==-1 ) fprintf(stdout,"%s:%d: Warning: all edges of tetra %d are required or of length null.\n", __FILE__,__LINE__,k); if ( lmax < _MMG5_LOPTL ) continue; /* proceed edges according to lengths */ ifa0 = _MMG5_ifar[imax][0]; ifa1 = _MMG5_ifar[imax][1]; i = (pt->xt && (pxt->ftag[ifa1] & MG_BDY)) ? ifa1 : ifa0; j = _MMG5_iarfinv[i][imax]; i1 = _MMG5_idir[i][_MMG5_inxt2[j]]; i2 = _MMG5_idir[i][_MMG5_iprv2[j]]; ip1 = pt->v[i1]; ip2 = pt->v[i2]; p0 = &mesh->point[ip1]; p1 = &mesh->point[ip2]; /* Case of a boundary face */ if ( pt->xt && (pxt->ftag[i] & MG_BDY) ) { if ( !(MG_GET(pxt->ori,i)) ) continue; ref = pxt->edg[_MMG5_iarf[i][j]]; tag = pxt->tag[_MMG5_iarf[i][j]]; if ( tag & MG_REQ ) continue; tag |= MG_BDY; ilist = _MMG5_coquil(mesh,k,imax,list); if ( !ilist ) continue; else if ( ilist < 0 ) return(-1); if ( tag & MG_NOM ){ if( !_MMG5_BezierNom(mesh,ip1,ip2,0.5,o,no1,to) ) continue; else if ( MG_SIN(p0->tag) && MG_SIN(p1->tag) ) { _MMG5_tet2tri(mesh,k,i,&ptt); _MMG5_nortri(mesh,&ptt,no1); if ( !MG_GET(pxt->ori,i) ) { no1[0] *= -1.0; no1[1] *= -1.0; no1[2] *= -1.0; } } } else if ( tag & MG_GEO ) { if ( !_MMG5_BezierRidge(mesh,ip1,ip2,0.5,o,no1,no2,to) ) continue; if ( MG_SIN(p0->tag) && MG_SIN(p1->tag) ) { _MMG5_tet2tri(mesh,k,i,&ptt); _MMG5_nortri(mesh,&ptt,no1); no2[0] = to[1]*no1[2] - to[2]*no1[1]; no2[1] = to[2]*no1[0] - to[0]*no1[2]; no2[2] = to[0]*no1[1] - to[1]*no1[0]; dd = no2[0]*no2[0] + no2[1]*no2[1] + no2[2]*no2[2]; if ( dd > _MMG5_EPSD2 ) { dd = 1.0 / sqrt(dd); no2[0] *= dd; no2[1] *= dd; no2[2] *= dd; } } } else if ( tag & MG_REF ) { if ( !_MMG5_BezierRef(mesh,ip1,ip2,0.5,o,no1,to) ) continue; } else { if ( !_MMG5_norface(mesh,k,i,v) ) continue; if ( !_MMG5_BezierReg(mesh,ip1,ip2,0.5,v,o,no1) ) continue; } ier = _MMG5_simbulgept(mesh,list,ilist,o); if ( !ier ) { ier = _MMG5_dichoto1b(mesh,list,ilist,o,ro); memcpy(o,ro,3*sizeof(double)); } ip = _MMG5_newPt(mesh,o,tag); if ( !ip ) { /* reallocation of point table */ _MMG5_POINT_REALLOC(mesh,met,ip,mesh->gap, *warn=1; break ,o,tag); } //CECILE if ( met->m ) met->m[ip] = 0.5 * (met->m[ip1]+met->m[ip2]); //CECILE ier = _MMG5_split1b(mesh,met,list,ilist,ip,1); /* if we realloc memory in _MMG5_split1b pt and pxt pointers are not valid */ pt = &mesh->tetra[k]; pxt = pt->xt ? &mesh->xtetra[pt->xt] : 0; if ( ier < 0 ) { fprintf(stdout," ## Error: unable to split.\n"); return(-1); } else if ( !ier ) { _MMG5_delPt(mesh,ip); continue; } ns++; ppt = &mesh->point[ip]; if ( MG_EDG(tag) || (tag & MG_NOM) ) ppt->ref = ref; else ppt->ref = pxt->ref[i]; if ( met->m ) met->m[ip] = 0.5 * (met->m[ip1]+met->m[ip2]); pxp = &mesh->xpoint[ppt->xp]; if ( tag & MG_NOM ){ memcpy(pxp->n1,no1,3*sizeof(double)); memcpy(pxp->t,to,3*sizeof(double)); } else if ( tag & MG_GEO ) { memcpy(pxp->n1,no1,3*sizeof(double)); memcpy(pxp->n2,no2,3*sizeof(double)); memcpy(pxp->t,to,3*sizeof(double)); } else if ( tag & MG_REF ) { memcpy(pxp->n1,no1,3*sizeof(double)); memcpy(pxp->t,to,3*sizeof(double)); } else memcpy(pxp->n1,no1,3*sizeof(double)); } /* Case of an internal face */ else { if ( (p0->tag & MG_BDY) && (p1->tag & MG_BDY) ) continue;