/** Compute point located at parameter value step from point ip0, as well as interpolate of normals, tangent for a regular edge ; v = ref vector (normal) for choice of normals if need be */ inline int _MMG5_BezierReg(MMG5_pMesh mesh,int ip0, int ip1, double s, double v[3], double *o, double *no){ MMG5_pPoint p0,p1; double b0[3],b1[3],bn[3],t0[3],t1[3],np0[3],np1[3],alpha,ux,uy,uz,ps1,ps2,ll,il,dd,*n1,*n2; p0 = &mesh->point[ip0]; p1 = &mesh->point[ip1]; ux = p1->c[0] - p0->c[0]; uy = p1->c[1] - p0->c[1]; uz = p1->c[2] - p0->c[2]; ll = ux*ux + uy*uy + uz*uz; /* Pathological case : don't move in that case ! */ if(((MG_SIN(p0->tag)||(p0->tag & MG_NOM)) && (MG_SIN(p1->tag) || (p1->tag & MG_NOM)))||(ll<_MMG5_EPSD)){ o[0] = 0.5*( p0->c[0] + p1->c[0] ); o[1] = 0.5*( p0->c[1] + p1->c[1] ); o[2] = 0.5*( p0->c[2] + p1->c[2] ); memcpy(no,v,3*sizeof(double)); return(1); } il = 1.0 /sqrt(ll); /* Coordinates of the new tangent and normal */ if(MG_SIN(p0->tag)||(p0->tag & MG_NOM)){ if(p1->tag & MG_GEO){ n1 = &mesh->xpoint[p1->xp].n1[0]; n2 = &mesh->xpoint[p1->xp].n2[0]; ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2]; ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2]; if(fabs(ps1) < fabs(ps2)){ memcpy(np1,&mesh->xpoint[p1->xp].n2[0],3*sizeof(double)); } else{ memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double)); } } else{ memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double)); } memcpy(np0,np1,3*sizeof(double)); } else if(MG_SIN(p1->tag) || (p1->tag & MG_NOM)){ if(p0->tag & MG_GEO){ n1 = &mesh->xpoint[p0->xp].n1[0]; n2 = &mesh->xpoint[p0->xp].n2[0]; ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2]; ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2]; if(fabs(ps1) < fabs(ps2)){ memcpy(np0,&mesh->xpoint[p0->xp].n2[0],3*sizeof(double)); } else{ memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double)); } } else{ memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double)); } memcpy(np1,np0,3*sizeof(double)); } else{ if(p0->tag & MG_GEO){ n1 = &mesh->xpoint[p0->xp].n1[0]; n2 = &mesh->xpoint[p0->xp].n2[0]; ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2]; ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2]; if(fabs(ps1) < fabs(ps2)){ memcpy(np0,&mesh->xpoint[p0->xp].n2[0],3*sizeof(double)); } else{ memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double)); } } else{ memcpy(np0,&mesh->xpoint[p0->xp].n1[0],3*sizeof(double)); } if(p1->tag & MG_GEO){ n1 = &mesh->xpoint[p1->xp].n1[0]; n2 = &mesh->xpoint[p1->xp].n2[0]; ps1 = n1[0]*v[0] + n1[1]*v[1] + n1[2]*v[2]; ps2 = n2[0]*v[0] + n2[1]*v[1] + n2[2]*v[2]; if(fabs(ps1) < fabs(ps2)){ memcpy(np1,&mesh->xpoint[p1->xp].n2[0],3*sizeof(double)); } else{ memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double)); } } else{ memcpy(np1,&mesh->xpoint[p1->xp].n1[0],3*sizeof(double)); } } /* Normal interpolation */ ps1 = ux*(np0[0] + np1[0]) + uy*(np0[1] + np1[1]) + uz*(np0[2] + np1[2]); ps1 = 2.0*ps1/ll; bn[0] = np0[0] + np1[0] -ps1*ux; bn[1] = np0[1] + np1[1] -ps1*uy; bn[2] = np0[2] + np1[2] -ps1*uz; dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2]; if(dd > _MMG5_EPSD){ dd = 1.0/sqrt(dd); bn[0] *= dd; bn[1] *= dd; bn[2] *= dd; } no[0] = (1.0-s)*(1.0-s)*np0[0] + 2.0*s*(1.0-s)*bn[0] + s*s*np1[0]; no[1] = (1.0-s)*(1.0-s)*np0[1] + 2.0*s*(1.0-s)*bn[1] + s*s*np1[1]; no[2] = (1.0-s)*(1.0-s)*np0[2] + 2.0*s*(1.0-s)*bn[2] + s*s*np1[2]; dd = no[0]*no[0] + no[1]*no[1] + no[2]*no[2]; if(dd > _MMG5_EPSD){ dd = 1.0/sqrt(dd); no[0] *= dd; no[1] *= dd; no[2] *= dd; } /* vertex position interpolation */ if(!_MMG5_BezierTgt(p0->c,p1->c,np0,np1,t0,t1)){ t0[0] = ux * il; t0[1] = uy * il; t0[2] = uz * il; t1[0] = - ux * il; t1[1] = - uy * il; t1[2] = - uz * il; } alpha = _MMG5_BezierGeod(p0->c,p1->c,t0,t1); b0[0] = p0->c[0] + alpha * t0[0]; b0[1] = p0->c[1] + alpha * t0[1]; b0[2] = p0->c[2] + alpha * t0[2]; b1[0] = p1->c[0] + alpha * t1[0]; b1[1] = p1->c[1] + alpha * t1[1]; b1[2] = p1->c[2] + alpha * t1[2]; o[0] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[0] + 3.0*s*(1.0-s)*(1.0-s)*b0[0] + \ 3.0*s*s*(1.0-s)*b1[0] + s*s*s*p1->c[0]; o[1] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[1] + 3.0*s*(1.0-s)*(1.0-s)*b0[1] + \ 3.0*s*s*(1.0-s)*b1[1] + s*s*s*p1->c[1]; o[2] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[2] + 3.0*s*(1.0-s)*(1.0-s)*b0[2] + \ 3.0*s*s*(1.0-s)*b1[2] + s*s*s*p1->c[2]; return(1); }
/** Compute point located at parameter value step from point ip0, as well as interpolate of normals, tangent for a REF edge */ inline int _MMG5_BezierRef(MMG5_pMesh mesh,int ip0,int ip1,double s,double *o,double *no,double *to) { MMG5_pPoint p0,p1; double ux,uy,uz,n01[3],n02[3],n11[3],n12[3],ntemp[3],t0[3],t1[3]; double ps,b0[3],b1[3],bn[3],ll,il,dd,alpha,ps2; p0 = &mesh->point[ip0]; /* Ref point, from which step is counted */ p1 = &mesh->point[ip1]; ux = p1->c[0] - p0->c[0]; uy = p1->c[1] - p0->c[1]; uz = p1->c[2] - p0->c[2]; ll = ux*ux + uy*uy + uz*uz; if ( ll < _MMG5_EPSD2 ) return(0); il = 1.0 / sqrt(ll); assert( (MG_REF & p0->tag) && (MG_REF & p1->tag) ); /* Coordinates of the new point */ if ( MG_SIN(p0->tag) ) { t0[0] = ux * il; t0[1] = uy * il; t0[2] = uz * il; } else { memcpy(t0,&(mesh->xpoint[p0->xp].t[0]),3*sizeof(double)); ps = t0[0]*ux + t0[1]*uy + t0[2]*uz; if ( ps < 0.0 ) { t0[0] *= -1.0; t0[1] *= -1.0; t0[2] *= -1.0; } } if ( MG_SIN(p1->tag) ) { t1[0] = -ux * il; t1[1] = -uy * il; t1[2] = -uz * il; } else { memcpy(t1,&(mesh->xpoint[p1->xp].t[0]),3*sizeof(double)); ps = - ( t1[0]*ux + t1[1]*uy + t1[2]*uz ); if ( ps < 0.0 ) { t1[0] *= -1.0; t1[1] *= -1.0; t1[2] *= -1.0; } } alpha = _MMG5_BezierGeod(p0->c,p1->c,t0,t1); b0[0] = p0->c[0] + alpha * t0[0]; b0[1] = p0->c[1] + alpha * t0[1]; b0[2] = p0->c[2] + alpha * t0[2]; b1[0] = p1->c[0] + alpha * t1[0]; b1[1] = p1->c[1] + alpha * t1[1]; b1[2] = p1->c[2] + alpha * t1[2]; o[0] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[0] + 3.0*s*(1.0-s)*(1.0-s)*b0[0] + \ 3.0*s*s*(1.0-s)*b1[0] + s*s*s*p1->c[0]; o[1] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[1] + 3.0*s*(1.0-s)*(1.0-s)*b0[1] + \ 3.0*s*s*(1.0-s)*b1[1] + s*s*s*p1->c[1]; o[2] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[2] + 3.0*s*(1.0-s)*(1.0-s)*b0[2] + \ 3.0*s*s*(1.0-s)*b1[2] + s*s*s*p1->c[2]; /* Coordinates of the new tangent and normal */ if ( MG_SIN(p0->tag) && MG_SIN(p1->tag) ) { memcpy(to,t0,3*sizeof(double)); return(1); } else if ( MG_SIN(p0->tag) ) { memcpy(n11,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double)); memcpy(n01,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double)); memcpy(n12,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double)); memcpy(n02,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double)); } else if ( MG_SIN(p1->tag) ) { memcpy(n01,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double)); memcpy(n11,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double)); memcpy(n02,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double)); memcpy(n12,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double)); } else { memcpy(n01,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double)); memcpy(n11,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double)); memcpy(n02,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double)); memcpy(n12,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double)); } /* Switch normals of p1 for pairing */ ps = n01[0] * n11[0] + n01[1] * n11[1] + n01[2] * n11[2]; ps2 = n01[0] * n12[0] + n01[1] * n12[1] + n01[2] * n12[2]; if ( ps2 > ps ) { memcpy(ntemp,n11,3*sizeof(double)); memcpy(n11,n12,3*sizeof(double)); memcpy(n12,ntemp,3*sizeof(double)); } /* Normal interpolation */ ps = ux*(n01[0] + n11[0]) + uy*(n01[1] + n11[1]) + uz*(n01[2] + n11[2]); ps = 2.0*ps/ll; bn[0] = n01[0] + n11[0] -ps*ux; bn[1] = n01[1] + n11[1] -ps*uy; bn[2] = n01[2] + n11[2] -ps*uz; dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2]; if ( dd > _MMG5_EPSD ) { dd = 1.0 / sqrt(dd); bn[0] *= dd; bn[1] *= dd; bn[2] *= dd; } no[0] = (1.0-s)*(1.0-s)*n01[0] + 2.0*s*(1.0-s)*bn[0] + s*s*n11[0]; no[1] = (1.0-s)*(1.0-s)*n01[1] + 2.0*s*(1.0-s)*bn[1] + s*s*n11[1]; no[2] = (1.0-s)*(1.0-s)*n01[2] + 2.0*s*(1.0-s)*bn[2] + s*s*n11[2]; dd = no[0]*no[0] + no[1]*no[1] + no[2]*no[2]; if ( dd > _MMG5_EPSD2 ) { dd = 1.0/sqrt(dd); no[0] *= dd; no[1] *= dd; no[2] *= dd; } /* Tangent interpolation : possibly flip (back) t1 */ ps = t0[0]*t1[0] + t0[1]*t1[1] + t0[2]*t1[2]; if ( ps < 0.0 ) { t1[0] *= -1.0; t1[1] *= -1.0; t1[2] *= -1.0; } to[0] = (1.0-s)*t0[0] + s*t1[0]; to[1] = (1.0-s)*t0[1] + s*t1[1]; to[2] = (1.0-s)*t0[2] + s*t1[2]; /* Projection of the tangent in the tangent plane defined by no */ ps = to[0]*no[0] + to[1]*no[1] + to[2]*no[2]; to[0] = to[0] -ps*no[0]; to[1] = to[1] -ps*no[1]; to[2] = to[2] -ps*no[2]; dd = to[0]*to[0] + to[1]*to[1] + to[2]*to[2]; if ( dd > _MMG5_EPSD2) { dd = 1.0 / sqrt(dd); to[0] *= dd; to[1] *= dd; to[2] *= dd; } return(1); }
/** Compute point located at parameter value step from point ip0, as well as interpolate of normals, tangent for a NOM edge */ inline int _MMG5_BezierNom(MMG5_pMesh mesh,int ip0,int ip1,double s,double *o,double *no,double *to) { MMG5_pPoint p0,p1; double ux,uy,uz,il,ll,ps,alpha,dd; double t0[3],t1[3],b0[3],b1[3],n0[3],n1[3],bn[3]; p0 = &mesh->point[ip0]; p1 = &mesh->point[ip1]; ux = p1->c[0] - p0->c[0]; uy = p1->c[1] - p0->c[1]; uz = p1->c[2] - p0->c[2]; ll = ux*ux + uy*uy + uz*uz; if(ll < _MMG5_EPSD2) return(0); il = 1.0 / sqrt(ll); assert(( p0->tag & MG_NOM ) && ( p1->tag & MG_NOM )); /* Coordinates of the new point */ if ( MG_SIN(p0->tag) ) { t0[0] = ux * il; t0[1] = uy * il; t0[2] = uz * il; } else { memcpy(t0,&(mesh->xpoint[p0->xp].t[0]),3*sizeof(double)); ps = t0[0]*ux + t0[1]*uy + t0[2]*uz; if ( ps < 0.0 ) { t0[0] *= -1.0; t0[1] *= -1.0; t0[2] *= -1.0; } } if ( MG_SIN(p1->tag) ) { t1[0] = -ux * il; t1[1] = -uy * il; t1[2] = -uz * il; } else { memcpy(t1,&(mesh->xpoint[p1->xp].t[0]),3*sizeof(double)); ps = - ( t1[0]*ux + t1[1]*uy + t1[2]*uz ); if ( ps < 0.0 ) { t1[0] *= -1.0; t1[1] *= -1.0; t1[2] *= -1.0; } } alpha = _MMG5_BezierGeod(p0->c,p1->c,t0,t1); b0[0] = p0->c[0] + alpha * t0[0]; b0[1] = p0->c[1] + alpha * t0[1]; b0[2] = p0->c[2] + alpha * t0[2]; b1[0] = p1->c[0] + alpha * t1[0]; b1[1] = p1->c[1] + alpha * t1[1]; b1[2] = p1->c[2] + alpha * t1[2]; o[0] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[0] + 3.0*s*(1.0-s)*(1.0-s)*b0[0] + \ 3.0*s*s*(1.0-s)*b1[0] + s*s*s*p1->c[0]; o[1] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[1] + 3.0*s*(1.0-s)*(1.0-s)*b0[1] + \ 3.0*s*s*(1.0-s)*b1[1] + s*s*s*p1->c[1]; o[2] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[2] + 3.0*s*(1.0-s)*(1.0-s)*b0[2] + \ 3.0*s*s*(1.0-s)*b1[2] + s*s*s*p1->c[2]; /* Coordinates of the new tangent and normal */ if ( MG_SIN(p0->tag) && MG_SIN(p1->tag) ) { // function should not be used in that case memcpy(to,t0,3*sizeof(double)); return(1); } else if ( MG_SIN(p0->tag) ) { memcpy(n1,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double)); memcpy(n0,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double)); } else if ( MG_SIN(p1->tag) ) { memcpy(n0,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double)); memcpy(n1,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double)); } else { memcpy(n0,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double)); memcpy(n1,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double)); } /* Normal interpolation */ ps = ux*(n0[0] + n1[0]) + uy*(n0[1] + n1[1]) + uz*(n0[2] + n1[2]); ps = 2.0*ps/ll; bn[0] = n0[0] + n1[0] -ps*ux; bn[1] = n0[1] + n1[1] -ps*uy; bn[2] = n0[2] + n1[2] -ps*uz; dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2]; if ( dd > _MMG5_EPSD ) { dd = 1.0 / sqrt(dd); bn[0] *= dd; bn[1] *= dd; bn[2] *= dd; } no[0] = (1.0-s)*(1.0-s)*n0[0] + 2.0*s*(1.0-s)*bn[0] + s*s*n1[0]; no[1] = (1.0-s)*(1.0-s)*n0[1] + 2.0*s*(1.0-s)*bn[1] + s*s*n1[1]; no[2] = (1.0-s)*(1.0-s)*n0[2] + 2.0*s*(1.0-s)*bn[2] + s*s*n1[2]; dd = no[0]*no[0] + no[1]*no[1] + no[2]*no[2]; if ( dd > _MMG5_EPSD2 ) { dd = 1.0/sqrt(dd); no[0] *= dd; no[1] *= dd; no[2] *= dd; } /* Tangent interpolation : possibly flip (back) t1 */ ps = t0[0]*t1[0] + t0[1]*t1[1] + t0[2]*t1[2]; if ( ps < 0.0 ) { t1[0] *= -1.0; t1[1] *= -1.0; t1[2] *= -1.0; } to[0] = (1.0-s)*t0[0] + s*t1[0]; to[1] = (1.0-s)*t0[1] + s*t1[1]; to[2] = (1.0-s)*t0[2] + s*t1[2]; /* Projection of the tangent in the tangent plane defined by no */ ps = to[0]*no[0] + to[1]*no[1] + to[2]*no[2]; to[0] = to[0] -ps*no[0]; to[1] = to[1] -ps*no[1]; to[2] = to[2] -ps*no[2]; dd = to[0]*to[0] + to[1]*to[1] + to[2]*to[2]; if ( dd > _MMG5_EPSD2) { dd = 1.0 / sqrt(dd); to[0] *= dd; to[1] *= dd; to[2] *= dd; } return(1); }
/** Compute point located at parameter value step from point ip0, as well as interpolate of normals, tangent for a RIDGE edge */ inline int _MMG5_BezierRidge(MMG5_pMesh mesh,int ip0,int ip1,double s,double *o,double *no1,double *no2,double *to){ MMG5_pPoint p0,p1; double ux,uy,uz,n01[3],n02[3],n11[3],n12[3],t0[3],t1[3]; double ps,ps2,b0[3],b1[3],bn[3],ll,il,ntemp[3],dd,alpha; p0 = &mesh->point[ip0]; /* Ref point, from which step is counted */ p1 = &mesh->point[ip1]; if ( !p0->xp || !p1->xp ) return(0); else if ( !(MG_GEO & p0->tag) || !(MG_GEO & p1->tag) ) return(0); ux = p1->c[0] - p0->c[0]; uy = p1->c[1] - p0->c[1]; uz = p1->c[2] - p0->c[2]; ll = ux*ux + uy*uy + uz*uz; if ( ll < _MMG5_EPSD2 ) return(0); il = 1.0 / sqrt(ll); if ( MG_SIN(p0->tag) ) { t0[0] = ux * il; t0[1] = uy * il; t0[2] = uz * il; } else { memcpy(t0,&(mesh->xpoint[p0->xp].t[0]),3*sizeof(double)); ps = t0[0]*ux + t0[1]*uy + t0[2]*uz; if ( ps < 0.0 ) { t0[0] *= -1.0; t0[1] *= -1.0; t0[2] *= -1.0; } } if ( MG_SIN(p1->tag) ) { t1[0] = -ux * il; t1[1] = -uy * il; t1[2] = -uz * il; } else { memcpy(t1,&(mesh->xpoint[p1->xp].t[0]),3*sizeof(double)); ps = - ( t1[0]*ux + t1[1]*uy + t1[2]*uz ); if ( ps < 0.0 ) { t1[0] *= -1.0; t1[1] *= -1.0; t1[2] *= -1.0; } } alpha = _MMG5_BezierGeod(p0->c,p1->c,t0,t1); b0[0] = p0->c[0] + alpha * t0[0]; b0[1] = p0->c[1] + alpha * t0[1]; b0[2] = p0->c[2] + alpha * t0[2]; b1[0] = p1->c[0] + alpha * t1[0]; b1[1] = p1->c[1] + alpha * t1[1]; b1[2] = p1->c[2] + alpha * t1[2]; o[0] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[0] + 3.0*s*(1.0-s)*(1.0-s)*b0[0] + \ 3.0*s*s*(1.0-s)*b1[0] + s*s*s*p1->c[0]; o[1] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[1] + 3.0*s*(1.0-s)*(1.0-s)*b0[1] + \ 3.0*s*s*(1.0-s)*b1[1] + s*s*s*p1->c[1]; o[2] = (1.0-s)*(1.0-s)*(1.0-s)*p0->c[2] + 3.0*s*(1.0-s)*(1.0-s)*b0[2] + \ 3.0*s*s*(1.0-s)*b1[2] + s*s*s*p1->c[2]; if ( MG_SIN(p0->tag) && MG_SIN(p1->tag) ) { memcpy(to,t0,3*sizeof(double)); return(1); } else if ( MG_SIN(p0->tag) ) { memcpy(n11,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double)); memcpy(n12,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double)); memcpy(n01,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double)); memcpy(n02,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double)); } else if ( MG_SIN(p1->tag) ) { memcpy(n01,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double)); memcpy(n02,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double)); memcpy(n11,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double)); memcpy(n12,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double)); } else { memcpy(n01,&(mesh->xpoint[p0->xp].n1[0]),3*sizeof(double)); memcpy(n02,&(mesh->xpoint[p0->xp].n2[0]),3*sizeof(double)); memcpy(n11,&(mesh->xpoint[p1->xp].n1[0]),3*sizeof(double)); memcpy(n12,&(mesh->xpoint[p1->xp].n2[0]),3*sizeof(double)); /* Switch normals of p1 for pairing */ ps = n01[0] * n11[0] + n01[1] * n11[1] + n01[2] * n11[2]; ps2 = n01[0] * n12[0] + n01[1] * n12[1] + n01[2] * n12[2]; if ( ps2 > ps ) { memcpy(ntemp,n11,3*sizeof(double)); memcpy(n11,n12,3*sizeof(double)); memcpy(n12,ntemp,3*sizeof(double)); } } /* Normal n1 interpolation */ ps = ux*(n01[0] + n11[0]) + uy*(n01[1] + n11[1]) + uz*(n01[2] + n11[2]); ps = 2.0*ps / ll; bn[0] = n01[0] + n11[0] -ps*ux; bn[1] = n01[1] + n11[1] -ps*uy; bn[2] = n01[2] + n11[2] -ps*uz; dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2]; if ( dd > _MMG5_EPSD2 ) { dd = 1.0 / sqrt(dd); bn[0] *= dd; bn[1] *= dd; bn[2] *= dd; } no1[0] = (1.0-s)*(1.0-s)*n01[0] + 2.0*s*(1.0-s)*bn[0] + s*s*n11[0]; no1[1] = (1.0-s)*(1.0-s)*n01[1] + 2.0*s*(1.0-s)*bn[1] + s*s*n11[1]; no1[2] = (1.0-s)*(1.0-s)*n01[2] + 2.0*s*(1.0-s)*bn[2] + s*s*n11[2]; dd = no1[0]*no1[0] + no1[1]*no1[1] + no1[2]*no1[2]; if ( dd > _MMG5_EPSD2 ) { dd = 1.0 / sqrt(dd); no1[0] *= dd; no1[1] *= dd; no1[2] *= dd; } /* Normal n2 interpolation */ ps = ux*(n02[0] + n12[0]) + uy*(n02[1] + n12[1]) + uz*(n02[2] + n12[2]); ps = 2.0*ps/ll; bn[0] = n02[0] + n12[0] -ps*ux; bn[1] = n02[1] + n12[1] -ps*uy; bn[2] = n02[2] + n12[2] -ps*uz; dd = bn[0]*bn[0] + bn[1]*bn[1] + bn[2]*bn[2]; if ( dd > _MMG5_EPSD2 ) { dd = 1.0 / sqrt(dd); bn[0] *= dd; bn[1] *= dd; bn[2] *= dd; } no2[0] = (1.0-s)*(1.0-s)*n02[0] + 2.0*s*(1.0-s)*bn[0] + s*s*n12[0]; no2[1] = (1.0-s)*(1.0-s)*n02[1] + 2.0*s*(1.0-s)*bn[1] + s*s*n12[1]; no2[2] = (1.0-s)*(1.0-s)*n02[2] + 2.0*s*(1.0-s)*bn[2] + s*s*n12[2]; 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; } to[0] = no1[1]*no2[2] - no1[2]*no2[1]; to[1] = no1[2]*no2[0] - no1[0]*no2[2]; to[2] = no1[0]*no2[1] - no1[1]*no2[0]; dd = to[0]*to[0] + to[1]*to[1] + to[2]*to[2]; if ( dd > _MMG5_EPSD2 ) { dd = 1.0/sqrt(dd); to[0] *= dd; to[1] *= dd; to[2] *= dd; } return(1); }
/** * \param mesh pointer toward the mesh structure. * \param met pointer toward the metric structure. * \param nump index of point in which the size must be computed. * \param lists pointer toward the surfacic ball of \a nump. * \param ilists size of surfacic ball of \a nump. * \param hmin minimal edge size. * \param hmax maximal edge size. * \param hausd hausdorff value. * \return the isotropic size at the point. * * Define isotropic size at regular point nump, whose surfacic ball is provided. * */ static double _MMG5_defsizreg(MMG5_pMesh mesh,MMG5_pSol met,int nump,int *lists, int ilists, double hmin,double hmax,double hausd) { MMG5_pTetra pt; MMG5_pxTetra pxt; MMG5_pPoint p0,p1; MMG5_Tria tt; _MMG5_Bezier b; double ux,uy,uz,det2d,h,isqhmin,isqhmax,ll,lmin,lmax,hnm,s; double *n,*t,r[3][3],lispoi[3*MMG3D_LMAX+1],intm[3],b0[3],b1[3],c[3],tAA[6],tAb[3],d[3]; double kappa[2],vp[2][2]; int k,na,nb,ntempa,ntempb,iel,ip0; char iface,i,j,i0; p0 = &mesh->point[nump]; if ( !p0->xp || MG_EDG(p0->tag) || (p0->tag & MG_NOM) || (p0->tag & MG_REQ)) { fprintf(stdout," ## Func. _MMG5_defsizreg : wrong point qualification : xp ? %d\n",p0->xp); return(0); } isqhmin = 1.0 / (hmin*hmin); isqhmax = 1.0 / (hmax*hmax); n = &mesh->xpoint[p0->xp].n1[0]; /* Step 1 : rotation matrix that sends normal n to the third coordinate vector of R^3 */ if ( !_MMG5_rotmatrix(n,r) ) { fprintf(stdout,"%s:%d: Error: function _MMG5_rotmatrix return 0\n", __FILE__,__LINE__); exit(EXIT_FAILURE); } /* Step 2 : rotation of the oriented surfacic ball with r : lispoi[k] is the common edge between faces lists[k-1] and lists[k] */ iel = lists[0] / 4; iface = lists[0] % 4; pt = &mesh->tetra[iel]; lmin = MAXLEN; lmax = 0.0; na = nb = 0; for (i=0; i<3; i++) { if ( pt->v[_MMG5_idir[iface][i]] != nump ) { if ( !na ) na = pt->v[_MMG5_idir[iface][i]]; else nb = pt->v[_MMG5_idir[iface][i]]; } } for (k=1; k<ilists; k++) { iel = lists[k] / 4; iface = lists[k] % 4; pt = &mesh->tetra[iel]; ntempa = ntempb = 0; for (i=0; i<3; i++) { if ( pt->v[_MMG5_idir[iface][i]] != nump ) { if ( !ntempa ) ntempa = pt->v[_MMG5_idir[iface][i]]; else ntempb = pt->v[_MMG5_idir[iface][i]]; } } if ( ntempa == na ) p1 = &mesh->point[na]; else if ( ntempa == nb ) p1 = &mesh->point[nb]; else if ( ntempb == na ) p1 = &mesh->point[na]; else { assert(ntempb == nb); p1 = &mesh->point[nb]; } ux = p1->c[0] - p0->c[0]; uy = p1->c[1] - p0->c[1]; uz = p1->c[2] - p0->c[2]; lispoi[3*k+1] = r[0][0]*ux + r[0][1]*uy + r[0][2]*uz; lispoi[3*k+2] = r[1][0]*ux + r[1][1]*uy + r[1][2]*uz; lispoi[3*k+3] = r[2][0]*ux + r[2][1]*uy + r[2][2]*uz; ll = lispoi[3*k+1]*lispoi[3*k+1] + lispoi[3*k+2]*lispoi[3*k+2] + lispoi[3*k+3]*lispoi[3*k+3]; lmin = MG_MIN(lmin,ll); lmax = MG_MAX(lmax,ll); na = ntempa; nb = ntempb; } /* Finish with point 0 */ iel = lists[0] / 4; iface = lists[0] % 4; pt = &mesh->tetra[iel]; ntempa = ntempb = 0; for (i=0; i<3; i++) { if ( pt->v[_MMG5_idir[iface][i]] != nump ) { if ( !ntempa ) ntempa = pt->v[_MMG5_idir[iface][i]]; else ntempb = pt->v[_MMG5_idir[iface][i]]; } } if ( ntempa == na ) p1 = &mesh->point[na]; else if ( ntempa == nb ) p1 = &mesh->point[nb]; else if ( ntempb == na ) p1 = &mesh->point[na]; else { assert(ntempb == nb); p1 = &mesh->point[nb]; } ux = p1->c[0] - p0->c[0]; uy = p1->c[1] - p0->c[1]; uz = p1->c[2] - p0->c[2]; lispoi[1] = r[0][0]*ux + r[0][1]*uy + r[0][2]*uz; lispoi[2] = r[1][0]*ux + r[1][1]*uy + r[1][2]*uz; lispoi[3] = r[2][0]*ux + r[2][1]*uy + r[2][2]*uz; ll = lispoi[1]*lispoi[1] + lispoi[2]*lispoi[2] + lispoi[3]*lispoi[3]; lmin = MG_MIN(lmin,ll); lmax = MG_MAX(lmax,ll); /* list goes modulo ilist */ lispoi[3*ilists+1] = lispoi[1]; lispoi[3*ilists+2] = lispoi[2]; lispoi[3*ilists+3] = lispoi[3]; /* At this point, lispoi contains the oriented surface ball of point p0, that has been rotated through r, with the convention that triangle l has edges lispoi[l]; lispoi[l+1] */ if ( lmax/lmin > 4.0*hmax*hmax/ (hmin*hmin) ) return(hmax); /* Check all projections over tangent plane. */ for (k=0; k<ilists-1; k++) { det2d = lispoi[3*k+1]*lispoi[3*(k+1)+2] - lispoi[3*k+2]*lispoi[3*(k+1)+1]; if ( det2d < 0.0 ) return(hmax); } det2d = lispoi[3*(ilists-1)+1]*lispoi[3*0+2] - lispoi[3*(ilists-1)+2]*lispoi[3*0+1]; if ( det2d < 0.0 ) return(hmax); /* Reconstitution of the curvature tensor at p0 in the tangent plane, with a quadric fitting approach */ memset(intm,0.0,3*sizeof(double)); memset(tAA,0.0,6*sizeof(double)); memset(tAb,0.0,3*sizeof(double)); for (k=0; k<ilists; k++) { iel = lists[k] / 4; iface = lists[k] % 4; _MMG5_tet2tri(mesh,iel,iface,&tt); pxt = &mesh->xtetra[mesh->tetra[iel].xt]; if ( !_MMG5_bezierCP(mesh,&tt,&b,MG_GET(pxt->ori,iface)) ) { fprintf(stdout,"%s:%d: Error: function _MMG5_bezierCP return 0\n", __FILE__,__LINE__); exit(EXIT_FAILURE); } for (i0=0; i0<3; i0++) { if ( tt.v[i0] == nump ) break; } assert(i0 < 3); for (j=0; j<10; j++) { c[0] = b.b[j][0] - p0->c[0]; c[1] = b.b[j][1] - p0->c[1]; c[2] = b.b[j][2] - p0->c[2]; b.b[j][0] = r[0][0]*c[0] + r[0][1]*c[1] + r[0][2]*c[2]; b.b[j][1] = r[1][0]*c[0] + r[1][1]*c[1] + r[1][2]*c[2]; b.b[j][2] = r[2][0]*c[0] + r[2][1]*c[1] + r[2][2]*c[2]; } /* Mid-point along left edge and endpoint in the rotated frame */ if ( i0 == 0 ) { memcpy(b0,&(b.b[7][0]),3*sizeof(double)); memcpy(b1,&(b.b[8][0]),3*sizeof(double)); } else if ( i0 == 1 ) { memcpy(b0,&(b.b[3][0]),3*sizeof(double)); memcpy(b1,&(b.b[4][0]),3*sizeof(double)); } else { memcpy(b0,&(b.b[5][0]),3*sizeof(double)); memcpy(b1,&(b.b[6][0]),3*sizeof(double)); } s = 0.5; /* At this point, the two control points are expressed in the rotated frame */ c[0] = 3.0*s*(1.0-s)*(1.0-s)*b0[0] + 3.0*s*s*(1.0-s)*b1[0] + s*s*s*lispoi[3*k+1]; c[1] = 3.0*s*(1.0-s)*(1.0-s)*b0[1] + 3.0*s*s*(1.0-s)*b1[1] + s*s*s*lispoi[3*k+2]; c[2] = 3.0*s*(1.0-s)*(1.0-s)*b0[2] + 3.0*s*s*(1.0-s)*b1[2] + s*s*s*lispoi[3*k+3]; /* Fill matric tAA and second member tAb*/ tAA[0] += c[0]*c[0]*c[0]*c[0]; tAA[1] += c[0]*c[0]*c[1]*c[1]; tAA[2] += c[0]*c[0]*c[0]*c[1]; tAA[3] += c[1]*c[1]*c[1]*c[1]; tAA[4] += c[0]*c[1]*c[1]*c[1]; tAA[5] += c[0]*c[0]*c[1]*c[1]; tAb[0] += c[0]*c[0]*c[2]; tAb[1] += c[1]*c[1]*c[2]; tAb[2] += c[0]*c[1]*c[2]; s = 1.0; /* At this point, the two control points are expressed in the rotated frame */ c[0] = 3.0*s*(1.0-s)*(1.0-s)*b0[0] + 3.0*s*s*(1.0-s)*b1[0] + s*s*s*lispoi[3*k+1]; c[1] = 3.0*s*(1.0-s)*(1.0-s)*b0[1] + 3.0*s*s*(1.0-s)*b1[1] + s*s*s*lispoi[3*k+2]; c[2] = 3.0*s*(1.0-s)*(1.0-s)*b0[2] + 3.0*s*s*(1.0-s)*b1[2] + s*s*s*lispoi[3*k+3]; /* Fill matric tAA and second member tAb*/ tAA[0] += c[0]*c[0]*c[0]*c[0]; tAA[1] += c[0]*c[0]*c[1]*c[1]; tAA[2] += c[0]*c[0]*c[0]*c[1]; tAA[3] += c[1]*c[1]*c[1]*c[1]; tAA[4] += c[0]*c[1]*c[1]*c[1]; tAA[5] += c[0]*c[0]*c[1]*c[1]; tAb[0] += c[0]*c[0]*c[2]; tAb[1] += c[1]*c[1]*c[2]; tAb[2] += c[0]*c[1]*c[2]; /* Mid-point along median edge and endpoint in the rotated frame */ if ( i0 == 0 ) { c[0] = A64TH*(b.b[1][0] + b.b[2][0] + 3.0*(b.b[3][0] + b.b[4][0])) \ + 3.0*A16TH*(b.b[6][0] + b.b[7][0] + b.b[9][0]) + A32TH*(b.b[5][0] + b.b[8][0]); c[1] = A64TH*(b.b[1][1] + b.b[2][1] + 3.0*(b.b[3][1] + b.b[4][1])) \ + 3.0*A16TH*(b.b[6][1] + b.b[7][1] + b.b[9][1]) + A32TH*(b.b[5][1] + b.b[8][1]); c[2] = A64TH*(b.b[1][2] + b.b[2][2] + 3.0*(b.b[3][2] + b.b[4][2])) \ + 3.0*A16TH*(b.b[6][2] + b.b[7][2] + b.b[9][2]) + A32TH*(b.b[5][2] + b.b[8][2]); d[0] = 0.125*b.b[1][0] + 0.375*(b.b[3][0] + b.b[4][0]) + 0.125*b.b[2][0]; d[1] = 0.125*b.b[1][1] + 0.375*(b.b[3][1] + b.b[4][1]) + 0.125*b.b[2][1]; d[2] = 0.125*b.b[1][2] + 0.375*(b.b[3][2] + b.b[4][2]) + 0.125*b.b[2][2]; } else if (i0 == 1) { c[0] = A64TH*(b.b[0][0] + b.b[2][0] + 3.0*(b.b[5][0] + b.b[6][0])) \ + 3.0*A16TH*(b.b[3][0] + b.b[8][0] + b.b[9][0]) + A32TH*(b.b[4][0] + b.b[7][0]); c[1] = A64TH*(b.b[0][1] + b.b[2][1] + 3.0*(b.b[5][1] + b.b[6][1])) \ + 3.0*A16TH*(b.b[3][1] + b.b[8][1] + b.b[9][1]) + A32TH*(b.b[4][1] + b.b[7][1]); c[2] = A64TH*(b.b[0][2] + b.b[2][2] + 3.0*(b.b[5][2] + b.b[6][2])) \ + 3.0*A16TH*(b.b[3][2] + b.b[8][2] + b.b[9][2]) + A32TH*(b.b[4][2] + b.b[7][2]); d[0] = 0.125*b.b[2][0] + 0.375*(b.b[5][0] + b.b[6][0]) + 0.125*b.b[0][0]; d[1] = 0.125*b.b[2][1] + 0.375*(b.b[5][1] + b.b[6][1]) + 0.125*b.b[0][1]; d[2] = 0.125*b.b[2][2] + 0.375*(b.b[5][2] + b.b[6][2]) + 0.125*b.b[0][2]; } else { c[0] = A64TH*(b.b[0][0] + b.b[1][0] + 3.0*(b.b[7][0] + b.b[8][0])) \ + 3.0*A16TH*(b.b[4][0] + b.b[5][0] + b.b[9][0]) + A32TH*(b.b[3][0] + b.b[6][0]); c[1] = A64TH*(b.b[0][1] + b.b[1][1] + 3.0*(b.b[7][1] + b.b[8][1])) \ + 3.0*A16TH*(b.b[4][1] + b.b[5][1] + b.b[9][1]) + A32TH*(b.b[3][1] + b.b[6][1]); c[2] = A64TH*(b.b[0][2] + b.b[1][2] + 3.0*(b.b[7][2] + b.b[8][2])) \ + 3.0*A16TH*(b.b[4][2] + b.b[5][2] + b.b[9][2]) + A32TH*(b.b[3][2] + b.b[6][2]); d[0] = 0.125*b.b[0][0] + 0.375*(b.b[7][0] + b.b[8][0]) + 0.125*b.b[1][0]; d[1] = 0.125*b.b[0][1] + 0.375*(b.b[7][1] + b.b[8][1]) + 0.125*b.b[1][1]; d[2] = 0.125*b.b[0][2] + 0.375*(b.b[7][2] + b.b[8][2]) + 0.125*b.b[1][2]; } /* Fill matric tAA and second member tAb*/ tAA[0] += c[0]*c[0]*c[0]*c[0]; tAA[1] += c[0]*c[0]*c[1]*c[1]; tAA[2] += c[0]*c[0]*c[0]*c[1]; tAA[3] += c[1]*c[1]*c[1]*c[1]; tAA[4] += c[0]*c[1]*c[1]*c[1]; tAA[5] += c[0]*c[0]*c[1]*c[1]; tAb[0] += c[0]*c[0]*c[2]; tAb[1] += c[1]*c[1]*c[2]; tAb[2] += c[0]*c[1]*c[2]; tAA[0] += d[0]*d[0]*d[0]*d[0]; tAA[1] += d[0]*d[0]*d[1]*d[1]; tAA[2] += d[0]*d[0]*d[0]*d[1]; tAA[3] += d[1]*d[1]*d[1]*d[1]; tAA[4] += d[0]*d[1]*d[1]*d[1]; tAA[5] += d[0]*d[0]*d[1]*d[1]; tAb[0] += d[0]*d[0]*d[2]; tAb[1] += d[1]*d[1]*d[2]; tAb[2] += d[0]*d[1]*d[2]; } /* solve now (a b c) = tAA^{-1} * tAb */ if ( !_MMG5_sys33sym(tAA,tAb,c) ) return(hmax); intm[0] = 2.0*c[0]; intm[1] = c[2]; intm[2] = 2.0*c[1]; /* At this point, intm stands for the integral matrix of Taubin's approach : vp[0] and vp[1] are the two pr. directions of curvature, and the two curvatures can be inferred from lambdas*/ if( !_MMG5_eigensym(intm,kappa,vp) ){ fprintf(stdout,"%s:%d: Error: function _MMG5_eigensym return 0\n", __FILE__,__LINE__); exit(EXIT_FAILURE); } /* h computation : h(x) = sqrt( 9*hausd / (2 * max(kappa1(x),kappa2(x)) ) */ kappa[0] = 2.0/9.0 * fabs(kappa[0]) / hausd; kappa[0] = MG_MIN(kappa[0],isqhmin); kappa[0] = MG_MAX(kappa[0],isqhmax); kappa[1] = 2.0/9.0 * fabs(kappa[1]) / hausd; kappa[1] = MG_MIN(kappa[1],isqhmin); kappa[1] = MG_MAX(kappa[1],isqhmax); kappa[0] = 1.0 / sqrt(kappa[0]); kappa[1] = 1.0 / sqrt(kappa[1]); h = MG_MIN(kappa[0],kappa[1]); /* Travel surfacic ball one last time and update non manifold point metric */ for (k=0; k<ilists; k++) { iel = lists[k] / 4; iface = lists[k] % 4; for (j=0; j<3; j++) { i0 = _MMG5_idir[iface][j]; ip0 = pt->v[i0]; p1 = &mesh->point[ip0]; if( !(p1->tag & MG_NOM) || MG_SIN(p1->tag) ) continue; assert(p1->xp); t = &p1->n[0]; memcpy(c,t,3*sizeof(double)); d[0] = r[0][0]*c[0] + r[0][1]*c[1] + r[0][2]*c[2]; d[1] = r[1][0]*c[0] + r[1][1]*c[1] + r[1][2]*c[2]; hnm = intm[0]*d[0]*d[0] + 2.0*intm[1]*d[0]*d[1] + intm[2]*d[1]*d[1]; hnm = 2.0/9.0 * fabs(hnm) / hausd; hnm = MG_MIN(hnm,isqhmin); hnm = MG_MAX(hnm,isqhmax); hnm = 1.0 / sqrt(hnm); met->m[ip0] = MG_MIN(met->m[ip0],hnm); } } return(h); }
/** * \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;
/** * \param pb pointer toward the Bezier structure. * \param uv coordinates of the point in the parametric space. * \param o computed coordinates of the point in the real space. * \param no computed normal. * \param to computed tangent. * \return 1. * * Compute \a o, \a no and \a to at \f$(u,v)\f$ in Bezier patch. * */ int _MMG5_bezierInt(_MMG5_pBezier pb,double uv[2],double o[3],double no[3],double to[3]) { double dd,u,v,w,ps,ux,uy,uz; char i; memset(to,0,3*sizeof(double)); u = uv[0]; v = uv[1]; w = 1 - u - v; /* coordinates + normals */ for (i=0; i<3; i++) { o[i] = pb->b[0][i]*w*w*w + pb->b[1][i]*u*u*u + pb->b[2][i]*v*v*v \ + 3.0 * (pb->b[3][i]*u*u*v + pb->b[4][i]*u*v*v + pb->b[5][i]*w*v*v \ + pb->b[6][i]*w*w*v + pb->b[7][i]*w*w*u + pb->b[8][i]*w*u*u)\ + 6.0 * pb->b[9][i]*u*v*w; /* quadratic interpolation of normals */ no[i] = pb->n[0][i]*w*w + pb->n[1][i]*u*u + pb->n[2][i]*v*v \ + 2.0 * (pb->n[3][i]*u*v + pb->n[4][i]*v*w + pb->n[5][i]*u*w); /* linear interpolation, not used here no[i] = pb->n[0][i]*w + pb->n[1][i]*u + pb->n[2][i]*v; */ } /* tangent */ if ( w < _MMG5_EPSD2 ) { ux = pb->b[2][0] - pb->b[1][0]; uy = pb->b[2][1] - pb->b[1][1]; uz = pb->b[2][2] - pb->b[1][2]; dd = ux*ux + uy*uy + uz*uz; if ( dd > _MMG5_EPSD2 ) { dd = 1.0 / sqrt(dd); ux *= dd; uy *= dd; uz *= dd; } /* corners */ if ( MG_SIN(pb->p[1]->tag) ) { pb->t[1][0] = ux; pb->t[1][1] = uy; pb->t[1][2] = uz; } if ( MG_SIN(pb->p[2]->tag) ) { pb->t[2][0] = ux; pb->t[2][1] = uy; pb->t[2][2] = uz; } ps = pb->t[1][0]* pb->t[2][0] + pb->t[1][1]* pb->t[2][1] + pb->t[1][2]* pb->t[2][2]; if ( ps > 0.0 ) { to[0] = pb->t[1][0]*u + pb->t[2][0]*v; to[1] = pb->t[1][1]*u + pb->t[2][1]*v; to[2] = pb->t[1][2]*u + pb->t[2][2]*v; } else { to[0] = -pb->t[1][0]*u + pb->t[2][0]*v; to[1] = -pb->t[1][1]*u + pb->t[2][1]*v; to[2] = -pb->t[1][2]*u + pb->t[2][2]*v; } } if ( u < _MMG5_EPSD2 ) { ux = pb->b[2][0] - pb->b[0][0]; uy = pb->b[2][1] - pb->b[0][1]; uz = pb->b[2][2] - pb->b[0][2]; dd = ux*ux + uy*uy + uz*uz; if ( dd > _MMG5_EPSD2 ) { dd = 1.0 / sqrt(dd); ux *= dd; uy *= dd; uz *= dd; } /* corners */ if ( MG_SIN(pb->p[0]->tag) ) { pb->t[0][0] = ux; pb->t[0][1] = uy; pb->t[0][2] = uz; } if ( MG_SIN(pb->p[2]->tag) ) { pb->t[2][0] = ux; pb->t[2][1] = uy; pb->t[2][2] = uz; } ps = pb->t[0][0]* pb->t[2][0] + pb->t[0][1]* pb->t[2][1] + pb->t[0][2]* pb->t[2][2]; if ( ps > 0.0 ) { to[0] = pb->t[0][0]*w + pb->t[2][0]*v; to[1] = pb->t[0][1]*w + pb->t[2][1]*v; to[2] = pb->t[0][2]*w + pb->t[2][2]*v; } else { to[0] = -pb->t[0][0]*w + pb->t[2][0]*v; to[1] = -pb->t[0][1]*w + pb->t[2][1]*v; to[2] = -pb->t[0][2]*w + pb->t[2][2]*v; } } if ( v < _MMG5_EPSD2 ) { ux = pb->b[1][0] - pb->b[0][0]; uy = pb->b[1][1] - pb->b[0][1]; uz = pb->b[1][2] - pb->b[0][2]; dd = ux*ux + uy*uy + uz*uz; if ( dd > _MMG5_EPSD2 ) { dd = 1.0 / sqrt(dd); ux *= dd; uy *= dd; uz *= dd; } /* corners */ if ( MG_SIN(pb->p[0]->tag) ) { pb->t[0][0] = ux; pb->t[0][1] = uy; pb->t[0][2] = uz; } if ( MG_SIN(pb->p[1]->tag) ) { pb->t[1][0] = ux; pb->t[1][1] = uy; pb->t[1][2] = uz; } ps = pb->t[0][0]* pb->t[1][0] + pb->t[0][1]* pb->t[1][1] + pb->t[0][2]* pb->t[1][2]; if ( ps > 0.0 ) { to[0] = pb->t[0][0]*w + pb->t[1][0]*u; to[1] = pb->t[0][1]*w + pb->t[1][1]*u; to[2] = pb->t[0][2]*w + pb->t[1][2]*u; } else { to[0] = -pb->t[0][0]*w + pb->t[1][0]*u; to[1] = -pb->t[0][1]*w + pb->t[1][1]*u; to[2] = -pb->t[0][2]*w + pb->t[1][2]*u; } } dd = no[0]*no[0] + no[1]*no[1] + no[2]*no[2]; if ( dd > _MMG5_EPSD2 ) { dd = 1.0 / sqrt(dd); no[0] *= dd; no[1] *= dd; no[2] *= dd; } dd = to[0]*to[0] + to[1]*to[1] + to[2]*to[2]; if ( dd > _MMG5_EPSD2 ) { dd = 1.0 / sqrt(dd); to[0] *= dd; to[1] *= dd; to[2] *= dd; } return(1); }
/** check for singularities */ static int _MMG5_singul(MMG5_pMesh mesh) { MMG5_pTria pt; MMG5_pPoint ppt,p1,p2; double ux,uy,uz,vx,vy,vz,dd; int list[_MMG5_LMAX+2],k,nc,ng,nr,ns,nre; char i; nre = nc = 0; for (k=1; k<=mesh->nt; k++) { pt = &mesh->tria[k]; if ( !MG_EOK(pt) ) continue; for (i=0; i<3; i++) { ppt = &mesh->point[pt->v[i]]; if ( !MG_VOK(ppt) || MG_SIN(ppt->tag) || ppt->tag & MG_NOM ) continue; else if ( MG_EDG(ppt->tag) ) { ns = _MMG5_bouler(mesh,k,i,list,&ng,&nr); if ( !ns ) continue; if ( (ng+nr) > 2 ) { ppt->tag |= MG_CRN + MG_REQ; nre++; nc++; } else if ( (ng == 1) && (nr == 1) ) { ppt->tag |= MG_REQ; nre++; } else if ( ng == 1 && !nr ){ ppt->tag |= MG_CRN + MG_REQ; nre++; nc++; } else if ( nr == 1 && !ng ){ ppt->tag |= MG_CRN + MG_REQ; nre++; nc++; } /* check ridge angle */ else { p1 = &mesh->point[list[1]]; p2 = &mesh->point[list[2]]; ux = p1->c[0] - ppt->c[0]; uy = p1->c[1] - ppt->c[1]; uz = p1->c[2] - ppt->c[2]; vx = p2->c[0] - ppt->c[0]; vy = p2->c[1] - ppt->c[1]; vz = p2->c[2] - ppt->c[2]; dd = (ux*ux + uy*uy + uz*uz) * (vx*vx + vy*vy + vz*vz); if ( fabs(dd) > _MMG5_EPSD ) { dd = (ux*vx + uy*vy + uz*vz) / sqrt(dd); if ( dd > -mesh->info.dhd ) { ppt->tag |= MG_CRN; nc++; } } } } } } if ( abs(mesh->info.imprim) > 3 && nre > 0 ) fprintf(stdout," %d corners, %d singular points detected\n",nc,nre); return(1); }