/** * \param mesh pointer toward the mesh structure. * \param list pointer toward the ball of the point to collapse. * \return 1. * * Collapse edge \f$list[0]%3\f$ in tet \f$list[0]/3\f$ (\f$ ip->i1\f$ ) for a * ball of the collapsed point of size 3: the collapsed point is removed. * */ int colver3(MMG5_pMesh mesh,int* list) { MMG5_pTria pt,pt1,pt2; int *adja,iel,jel,kel,mel,ip; char i,i1,j,j1,j2,k,m; /* update of new point for triangle list[0] */ iel = list[0] / 3; i = list[0] % 3; i1 = _MMG5_inxt2[i]; pt = &mesh->tria[iel]; ip = pt->v[i]; jel = list[1] / 3; j = list[1] % 3; j1 = _MMG5_inxt2[j]; j2 = _MMG5_iprv2[j]; pt1 = &mesh->tria[jel]; kel = list[2] / 3; k = list[2] % 3; pt2 = &mesh->tria[kel]; /* update info */ pt1->v[j] = pt->v[i1]; pt1->tag[j1] |= pt2->tag[k]; pt1->edg[j1] = MG_MAX(pt1->edg[j1],pt2->edg[k]); pt1->tag[j2] |= pt->tag[i]; pt1->edg[j2] = MG_MAX(pt1->edg[j2],pt->edg[i]); pt1->base = mesh->base; /* update neighbours of new triangle */ adja = &mesh->adja[3*(jel-1)+1]; adja[j1] = mesh->adja[3*(kel-1)+1+k]; adja[j2] = mesh->adja[3*(iel-1)+1+i]; mel = adja[j2] / 3; if ( mel ) { m = adja[j2] % 3; pt = &mesh->tria[mel]; pt->tag[m] = pt1->tag[j2]; pt->edg[m] = pt1->edg[j2]; mesh->adja[3*(mel-1)+1+m] = 3*jel + j2; } mel = adja[j1] / 3; if ( mel ) { m = adja[j1] % 3; pt = &mesh->tria[mel]; pt->tag[m] = pt1->tag[j1]; pt->edg[m] = pt1->edg[j1]; mesh->adja[3*(mel-1)+1+m] = 3*jel + j1; } /* remove vertex + elements */ _MMG5_delPt(mesh,ip); _MMG5_delElt(mesh,iel); _MMG5_delElt(mesh,kel); return(1); }
/* collapse point along open ridge */ int colver2(MMG5_pMesh mesh,int* list) { MMG5_pTria pt,pt1; int *adja,iel,jel,kel,ip; char i1,i2,jj,j2,k; /* update of new point for triangle list[0] */ iel = list[0] / 3; i1 = list[0] % 3; i2 = _MMG5_inxt2[i1]; pt = &mesh->tria[iel]; ip = pt->v[i1]; jel = list[1] / 3; j2 = list[1] % 3; jj = _MMG5_iprv2[j2]; pt1 = &mesh->tria[jel]; /* update info */ pt->v[i1] = pt1->v[jj]; pt->tag[i2] |= pt1->tag[j2]; pt->edg[i2] = pt1->edg[j2]; pt->base = mesh->base; /* update neighbours of new triangle */ adja = &mesh->adja[3*(iel-1)+1]; adja[i2] = mesh->adja[3*(jel-1)+1+j2]; adja = &mesh->adja[3*(jel-1)+1]; kel = adja[j2] / 3; k = adja[j2] % 3; if ( kel ) mesh->adja[3*(kel-1)+1+k] = 3*iel + i2; /* remove vertex + element */ _MMG5_delPt(mesh,ip); _MMG5_delElt(mesh,jel); return(1); }
/** * \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;
/* collapse edge i of k, i1->i2 */ int colver(MMG5_pMesh mesh,int *list,int ilist) { MMG5_pTria pt,pt1,pt2; int *adja,k,iel,jel,kel,ip1,ip2; char i,i1,i2,j,jj,open; iel = list[0] / 3; i1 = list[0] % 3; i = _MMG5_iprv2[i1]; i2 = _MMG5_inxt2[i1]; pt = &mesh->tria[iel]; ip1 = pt->v[i1]; ip2 = pt->v[i2]; /* check for open ball */ adja = &mesh->adja[3*(iel-1)+1]; open = adja[i] == 0; /* update vertex ip1 -> ip2 */ for (k=1; k<ilist-1+open; k++) { jel = list[k] / 3; jj = list[k] % 3; pt1 = &mesh->tria[jel]; pt1->v[jj] = ip2; pt1->base = mesh->base; } /* update adjacent with 1st elt */ jel = list[1] / 3; jj = list[1] % 3; j = _MMG5_iprv2[jj]; pt1 = &mesh->tria[jel]; pt1->tag[j] = MG_MAX(pt->tag[i1],pt1->tag[j]); pt1->edg[j] = MG_MAX(pt->edg[i1],pt1->edg[j]); if ( adja[i1] ) { kel = adja[i1] / 3; k = adja[i1] % 3; mesh->adja[3*(kel-1)+1+k] = 3*jel + j; mesh->adja[3*(jel-1)+1+j] = 3*kel + k; pt2 = &mesh->tria[kel]; pt2->tag[k] = MG_MAX(pt1->tag[j],pt2->tag[k]); pt2->edg[k] = MG_MAX(pt1->edg[j],pt2->edg[k]); } else mesh->adja[3*(jel-1)+1+j] = 0; /* adjacent with last elt */ if ( !open ) { iel = list[ilist-1] / 3; i1 = list[ilist-1] % 3; pt = &mesh->tria[iel]; jel = list[ilist-2] / 3; jj = list[ilist-2] % 3; j = _MMG5_inxt2[jj]; pt1 = &mesh->tria[jel]; pt1->tag[j] = MG_MAX(pt->tag[i1],pt1->tag[j]); pt1->edg[j] = MG_MAX(pt->edg[i1],pt1->edg[j]); adja = &mesh->adja[3*(iel-1)+1]; if ( adja[i1] ) { kel = adja[i1] / 3; k = adja[i1] % 3; mesh->adja[3*(kel-1)+1+k] = 3*jel + j; mesh->adja[3*(jel-1)+1+j] = 3*kel + k; pt2 = &mesh->tria[kel]; pt2->tag[k] = MG_MAX(pt1->tag[j],pt2->tag[k]); pt2->edg[k] = MG_MAX(pt1->edg[j],pt2->edg[k]); } else mesh->adja[3*(jel-1)+1+j] = 0; } _MMG5_delPt(mesh,ip1); _MMG5_delElt(mesh,list[0] / 3); if ( !open ) _MMG5_delElt(mesh,list[ilist-1] / 3); return(1); }