예제 #1
0
파일: tools.c 프로젝트: XL64/mmg
/** 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);
}
예제 #2
0
파일: tools.c 프로젝트: XL64/mmg
/** 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);
}
예제 #3
0
파일: tools.c 프로젝트: XL64/mmg
/** 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);
}
예제 #4
0
파일: tools.c 프로젝트: XL64/mmg
/** 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);
}
예제 #5
0
파일: isosiz_3d.c 프로젝트: BijanZarif/mmg
/**
 * \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);
}
예제 #6
0
파일: mmg3d1_pattern.c 프로젝트: XL64/mmg
/**
 * \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;
예제 #7
0
파일: bezier.c 프로젝트: arthurlevy/mmg
/**
 * \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);
}
예제 #8
0
파일: analys.c 프로젝트: XL64/mmg
/** 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);
}